Merge "Add ability to add existing connection AND set parent at the same time." into oc-dev
diff --git a/apct-tests/perftests/core/res/font/samplefont.ttf b/apct-tests/perftests/core/res/font/samplefont.ttf
new file mode 100644
index 0000000..b8302d4
--- /dev/null
+++ b/apct-tests/perftests/core/res/font/samplefont.ttf
Binary files differ
diff --git a/apct-tests/perftests/core/res/font/samplefont_source.ttx b/apct-tests/perftests/core/res/font/samplefont_source.ttx
new file mode 100644
index 0000000..40fa268
--- /dev/null
+++ b/apct-tests/perftests/core/res/font/samplefont_source.ttx
@@ -0,0 +1,177 @@
+<?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.
+-->
+<ttFont sfntVersion="\x00\x01\x00\x00" ttLibVersion="3.0">
+
+  <GlyphOrder>
+    <GlyphID id="0" name=".notdef"/>
+    <GlyphID id="1" name="a"/>
+  </GlyphOrder>
+
+  <head>
+    <tableVersion value="1.0"/>
+    <fontRevision value="1.0"/>
+    <checkSumAdjustment value="0x640cdb2f"/>
+    <magicNumber value="0x5f0f3cf5"/>
+    <flags value="00000000 00000011"/>
+    <unitsPerEm value="1000"/>
+    <created value="Fri Mar 17 07:26:00 2017"/>
+    <macStyle value="00000000 00000000"/>
+    <lowestRecPPEM value="7"/>
+    <fontDirectionHint value="2"/>
+    <glyphDataFormat value="0"/>
+  </head>
+
+  <hhea>
+    <tableVersion value="1.0"/>
+    <ascent value="1000"/>
+    <descent value="-200"/>
+    <lineGap value="0"/>
+    <caretSlopeRise value="1"/>
+    <caretSlopeRun value="0"/>
+    <caretOffset value="0"/>
+    <reserved0 value="0"/>
+    <reserved1 value="0"/>
+    <reserved2 value="0"/>
+    <reserved3 value="0"/>
+    <metricDataFormat value="0"/>
+  </hhea>
+
+  <maxp>
+    <tableVersion value="0x10000"/>
+    <maxZones value="0"/>
+    <maxTwilightPoints value="0"/>
+    <maxStorage value="0"/>
+    <maxFunctionDefs value="0"/>
+    <maxInstructionDefs value="0"/>
+    <maxStackElements value="0"/>
+    <maxSizeOfInstructions value="0"/>
+    <maxComponentElements value="0"/>
+  </maxp>
+
+  <OS_2>
+    <!-- The fields 'usFirstCharIndex' and 'usLastCharIndex'
+         will be recalculated by the compiler -->
+    <version value="3"/>
+    <xAvgCharWidth value="594"/>
+    <usWeightClass value="400"/>
+    <usWidthClass value="5"/>
+    <fsType value="00000000 00001000"/>
+    <ySubscriptXSize value="650"/>
+    <ySubscriptYSize value="600"/>
+    <ySubscriptXOffset value="0"/>
+    <ySubscriptYOffset value="75"/>
+    <ySuperscriptXSize value="650"/>
+    <ySuperscriptYSize value="600"/>
+    <ySuperscriptXOffset value="0"/>
+    <ySuperscriptYOffset value="350"/>
+    <yStrikeoutSize value="50"/>
+    <yStrikeoutPosition value="300"/>
+    <sFamilyClass value="0"/>
+    <panose>
+      <bFamilyType value="0"/>
+      <bSerifStyle value="0"/>
+      <bWeight value="5"/>
+      <bProportion value="0"/>
+      <bContrast value="0"/>
+      <bStrokeVariation value="0"/>
+      <bArmStyle value="0"/>
+      <bLetterForm value="0"/>
+      <bMidline value="0"/>
+      <bXHeight value="0"/>
+    </panose>
+    <ulUnicodeRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulUnicodeRange2 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange3 value="00000000 00000000 00000000 00000000"/>
+    <ulUnicodeRange4 value="00000000 00000000 00000000 00000000"/>
+    <achVendID value="UKWN"/>
+    <fsSelection value="00000000 01000000"/>
+    <usFirstCharIndex value="32"/>
+    <usLastCharIndex value="122"/>
+    <sTypoAscender value="800"/>
+    <sTypoDescender value="-200"/>
+    <sTypoLineGap value="200"/>
+    <usWinAscent value="1000"/>
+    <usWinDescent value="200"/>
+    <ulCodePageRange1 value="00000000 00000000 00000000 00000001"/>
+    <ulCodePageRange2 value="00000000 00000000 00000000 00000000"/>
+    <sxHeight value="500"/>
+    <sCapHeight value="700"/>
+    <usDefaultChar value="0"/>
+    <usBreakChar value="32"/>
+    <usMaxContext value="0"/>
+  </OS_2>
+
+  <hmtx>
+    <mtx name=".notdef" width="500" lsb="93"/>
+    <mtx name="a" width="500" lsb="93"/>
+  </hmtx>
+
+  <cmap>
+    <tableVersion version="0"/>
+    <cmap_format_4 platformID="3" platEncID="10" language="0">
+      <map code="0x0061" name="a" />
+    </cmap_format_4>
+  </cmap>
+
+  <loca>
+    <!-- The 'loca' table will be calculated by the compiler -->
+  </loca>
+
+  <glyf>
+    <TTGlyph name=".notdef" xMin="0" yMin="0" xMax="0" yMax="0" />
+    <TTGlyph name="a" xMin="0" yMin="0" xMax="0" yMax="0" />
+  </glyf>
+
+  <name>
+    <namerecord nameID="1" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="1" platEncID="0" langID="0x0" unicode="True">
+      SampleFont-Regular
+    </namerecord>
+    <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
+      Regular
+    </namerecord>
+    <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
+      Sample Font
+    </namerecord>
+    <namerecord nameID="6" platformID="3" platEncID="1" langID="0x409">
+      SampleFont-Regular
+    </namerecord>
+  </name>
+
+  <post>
+    <formatType value="3.0"/>
+    <italicAngle value="0.0"/>
+    <underlinePosition value="-75"/>
+    <underlineThickness value="50"/>
+    <isFixedPitch value="0"/>
+    <minMemType42 value="0"/>
+    <maxMemType42 value="0"/>
+    <minMemType1 value="0"/>
+    <maxMemType1 value="0"/>
+  </post>
+
+</ttFont>
diff --git a/apct-tests/perftests/core/res/font/samplexmlfont.xml b/apct-tests/perftests/core/res/font/samplexmlfont.xml
new file mode 100644
index 0000000..b226446
--- /dev/null
+++ b/apct-tests/perftests/core/res/font/samplexmlfont.xml
@@ -0,0 +1,19 @@
+<?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
+-->
+<font-family xmlns:android="http://schemas.android.com/apk/res/android">
+    <font android:font="@font/samplefont" />
+</font-family>
diff --git a/apct-tests/perftests/core/res/layout/test_textview_font_family_file.xml b/apct-tests/perftests/core/res/layout/test_textview_font_family_file.xml
new file mode 100644
index 0000000..3689a64
--- /dev/null
+++ b/apct-tests/perftests/core/res/layout/test_textview_font_family_file.xml
@@ -0,0 +1,20 @@
+<!--
+ 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
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:layout_width="100dp"
+          android:layout_height="100dp"
+          android:text="@string/short_text"
+          android:fontFamily="@font/samplefont" />
diff --git a/apct-tests/perftests/core/res/layout/test_textview_font_family_string.xml b/apct-tests/perftests/core/res/layout/test_textview_font_family_string.xml
new file mode 100644
index 0000000..5f236f5
--- /dev/null
+++ b/apct-tests/perftests/core/res/layout/test_textview_font_family_string.xml
@@ -0,0 +1,20 @@
+<!--
+ 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
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:layout_width="100dp"
+          android:layout_height="100dp"
+          android:text="@string/short_text"
+          android:fontFamily="sans-serif" />
diff --git a/apct-tests/perftests/core/res/layout/test_textview_font_family_xml.xml b/apct-tests/perftests/core/res/layout/test_textview_font_family_xml.xml
new file mode 100644
index 0000000..0331fa5
--- /dev/null
+++ b/apct-tests/perftests/core/res/layout/test_textview_font_family_xml.xml
@@ -0,0 +1,20 @@
+<!--
+ 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
+-->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:layout_width="100dp"
+          android:layout_height="100dp"
+          android:text="@string/short_text"
+          android:fontFamily="@font/samplexmlfont" />
diff --git a/apct-tests/perftests/core/res/values/strings.xml b/apct-tests/perftests/core/res/values/strings.xml
index 5d1f6f0..7ab325f 100644
--- a/apct-tests/perftests/core/res/values/strings.xml
+++ b/apct-tests/perftests/core/res/values/strings.xml
@@ -28,4 +28,5 @@
         text text text text text text text text text text text text text text text text
         text text text text text text text text text text text text text text text text
         text text text text text text text text text text text text </string>
+    <string name="short_text">text text</string>
 </resources>
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewFontFamilyLayoutPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewFontFamilyLayoutPerfTest.java
new file mode 100644
index 0000000..4b6da6b
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/widget/TextViewFontFamilyLayoutPerfTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.widget;
+
+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 android.view.LayoutInflater;
+
+import com.android.perftests.core.R;
+
+import java.util.Collection;
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.junit.Rule;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertTrue;
+
+@LargeTest
+@RunWith(Parameterized.class)
+public class TextViewFontFamilyLayoutPerfTest {
+    @Parameters(name = "{0}")
+    public static Collection layouts() {
+        return Arrays.asList(new Object[][] {
+                { "String fontFamily attribute", R.layout.test_textview_font_family_string},
+                { "File fontFamily attribute", R.layout.test_textview_font_family_file},
+                { "XML fontFamily attribute", R.layout.test_textview_font_family_xml},
+        });
+    }
+
+    private int mLayoutId;
+
+    public TextViewFontFamilyLayoutPerfTest(String key, int layoutId) {
+        mLayoutId = layoutId;
+    }
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void testConstruction() throws Throwable {
+        final Context context = InstrumentationRegistry.getTargetContext();
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final LayoutInflater inflator =
+                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        while (state.keepRunning()) {
+            inflator.inflate(mLayoutId, null, false);
+        }
+    }
+}
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index dca7ea6..3689d5e 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -16,12 +16,16 @@
 
 #define LOG_TAG "BootAnimation"
 
+#include <stdint.h>
+#include <inttypes.h>
+
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <cutils/properties.h>
 #include <sys/resource.h>
 #include <utils/Log.h>
+#include <utils/SystemClock.h>
 #include <utils/threads.h>
 
 #include "BootAnimation.h"
@@ -47,6 +51,26 @@
         sp<ProcessState> proc(ProcessState::self());
         ProcessState::self()->startThreadPool();
 
+        // TODO: replace this with better waiting logic in future, b/35253872
+        int64_t waitStartTime = elapsedRealtime();
+        sp<IServiceManager> sm = defaultServiceManager();
+        const String16 name("SurfaceFlinger");
+        const int SERVICE_WAIT_SLEEP_MS = 100;
+        const int LOG_PER_RETRIES = 10;
+        int retry = 0;
+        while (sm->checkService(name) == nullptr) {
+            retry++;
+            if ((retry % LOG_PER_RETRIES) == 0) {
+                ALOGW("Waiting for SurfaceFlinger, waited for %" PRId64 " ms",
+                      elapsedRealtime() - waitStartTime);
+            }
+            usleep(SERVICE_WAIT_SLEEP_MS * 1000);
+        };
+        int64_t totalWaited = elapsedRealtime() - waitStartTime;
+        if (totalWaited > SERVICE_WAIT_SLEEP_MS) {
+            ALOGI("Waiting for SurfaceFlinger took %" PRId64 " ms", totalWaited);
+        }
+
         // create the boot animation object
         sp<BootAnimation> boot = new BootAnimation();
 
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ab03556..b439c1d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4719,7 +4719,9 @@
                 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
             }
             int result = ActivityManager.getService()
-                .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
+                .startActivityIntentSender(mMainThread.getApplicationThread(),
+                        intent != null ? intent.getTarget() : null,
+                        intent != null ? intent.getWhitelistToken() : null,
                         fillInIntent, resolvedType, mToken, who,
                         requestCode, flagsMask, flagsValues, options);
             if (result == ActivityManager.START_CANCELED) {
@@ -7447,6 +7449,7 @@
     }
 
     /** @hide */
+    @Override
     @NonNull public View[] findViewsByAccessibilityIdTraversal(@NonNull int[] viewIds) {
         final View[] views = new View[viewIds.length];
         final ArrayList<ViewRootImpl> roots =
@@ -7470,6 +7473,25 @@
 
     /** @hide */
     @Override
+    @Nullable public View findViewByAccessibilityIdTraversal(int viewId) {
+        final ArrayList<ViewRootImpl> roots =
+                WindowManagerGlobal.getInstance().getRootViews(getActivityToken());
+        for (int rootNum = 0; rootNum < roots.size(); rootNum++) {
+            final View rootView = roots.get(rootNum).getView();
+
+            if (rootView != null) {
+                final View view = rootView.findViewByAccessibilityIdTraversal(viewId);
+                if (view != null) {
+                    return view;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /** @hide */
+    @Override
     @NonNull public boolean[] getViewVisibility(@NonNull int[] viewIds) {
         final boolean[] isVisible = new boolean[viewIds.length];
         final View views[] = findViewsByAccessibilityIdTraversal(viewIds);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 928ef7e..01e4cceb 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3567,6 +3567,7 @@
             try {
                 if (localLOGV) Slog.v(TAG, "Destroying service " + s);
                 s.onDestroy();
+                s.detachAndCleanUp();
                 Context context = s.getBaseContext();
                 if (context instanceof ContextImpl) {
                     final String who = s.getClassName();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 2de205b..268a105b 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -925,7 +925,9 @@
                 resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
             }
             int result = ActivityManager.getService()
-                .startActivityIntentSender(mMainThread.getApplicationThread(), intent,
+                .startActivityIntentSender(mMainThread.getApplicationThread(),
+                        intent != null ? intent.getTarget() : null,
+                        intent != null ? intent.getWhitelistToken() : null,
                         fillInIntent, resolvedType, null, null,
                         0, flagsMask, flagsValues, options);
             if (result == ActivityManager.START_CANCELED) {
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 95d55dc..3e26e0f 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2603,23 +2603,25 @@
                         f.mTargetIndex = f.mTarget != null ? f.mTarget.mIndex : -1;
                         if (DEBUG) Log.v(TAG, "retainNonConfig: keeping retained " + f);
                     }
-                    boolean addedChild = false;
+                    FragmentManagerNonConfig child;
                     if (f.mChildFragmentManager != null) {
                         f.mChildFragmentManager.saveNonConfig();
-                        FragmentManagerNonConfig child = f.mChildFragmentManager.mSavedNonConfig;
-                        if (child != null) {
-                            if (childFragments == null) {
-                                childFragments = new ArrayList<>();
-                                for (int j = 0; j < i; j++) {
-                                    childFragments.add(null);
-                                }
-                            }
-                            childFragments.add(child);
-                            addedChild = true;
+                        child = f.mChildFragmentManager.mSavedNonConfig;
+                    } else {
+                        // f.mChildNonConfig may be not null, when the parent fragment is
+                        // in the backstack.
+                        child = f.mChildNonConfig;
+                    }
+
+                    if (childFragments == null && child != null) {
+                        childFragments = new ArrayList<>(mActive.size());
+                        for (int j = 0; j < i; j++) {
+                            childFragments.add(null);
                         }
                     }
-                    if (childFragments != null && !addedChild) {
-                        childFragments.add(null);
+
+                    if (childFragments != null) {
+                        childFragments.add(child);
                     }
                 }
             }
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 9552d17..3ac026d 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -236,8 +236,8 @@
     Debug.MemoryInfo[] getProcessMemoryInfo(in int[] pids);
     void killApplicationProcess(in String processName, int uid);
     int startActivityIntentSender(in IApplicationThread caller,
-            in IntentSender intent, in Intent fillInIntent, in String resolvedType,
-            in IBinder resultTo, in String resultWho, int requestCode,
+            in IIntentSender target, in IBinder whitelistToken, in Intent fillInIntent,
+            in String resolvedType, in IBinder resultTo, in String resultWho, int requestCode,
             int flagsMask, int flagsValues, in Bundle options);
     void overridePendingTransition(in IBinder token, in String packageName,
             int enterAnim, int exitAnim);
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 4994fbb..b5b1017 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -30,7 +30,7 @@
     void onTaskStackChanged();
 
     /** Called whenever an Activity is moved to the pinned stack from another stack. */
-    void onActivityPinned(String packageName);
+    void onActivityPinned(String packageName, int taskId);
 
     /** Called whenever an Activity is moved from the pinned stack to another stack. */
     void onActivityUnpinned();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8a15b1f..3ed174b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1112,6 +1112,16 @@
     @SystemApi
     public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
 
+    /**
+     * This is set on the notification shown by the activity manager about all apps
+     * running in the background.  It indicates that the notification should be shown
+     * only if any of the given apps do not already have a {@link #FLAG_FOREGROUND_SERVICE}
+     * notification currently visible to the user.  This is a string array of all
+     * package names of the apps.
+     * @hide
+     */
+    public static final String EXTRA_FOREGROUND_APPS = "android.foregroundApps";
+
     private Icon mSmallIcon;
     private Icon mLargeIcon;
 
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 10d6a7b..256c479 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -767,7 +767,15 @@
         mStartCompatibility = getApplicationInfo().targetSdkVersion
                 < Build.VERSION_CODES.ECLAIR;
     }
-    
+
+    /**
+     * @hide
+     * Clean up any references to avoid leaks.
+     */
+    public final void detachAndCleanUp() {
+        mToken = null;
+    }
+
     final String getClassName() {
         return mClassName;
     }
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 2df011f..a52ca0a 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -31,7 +31,7 @@
     }
 
     @Override
-    public void onActivityPinned(String packageName) throws RemoteException {
+    public void onActivityPinned(String packageName, int taskId) throws RemoteException {
     }
 
     @Override
diff --git a/core/java/android/app/job/JobServiceEngine.java b/core/java/android/app/job/JobServiceEngine.java
index b7d759b..b0ec650 100644
--- a/core/java/android/app/job/JobServiceEngine.java
+++ b/core/java/android/app/job/JobServiceEngine.java
@@ -55,21 +55,12 @@
      */
     private static final int MSG_JOB_FINISHED = 2;
 
-    /**
-     * Context we are running in.
-     */
-    private final Service mService;
-
     private final IJobService mBinder;
 
-    /** Lock object for {@link #mHandler}. */
-    private final Object mHandlerLock = new Object();
-
     /**
      * Handler we post jobs to. Responsible for calling into the client logic, and handling the
      * callback to the system.
      */
-    @GuardedBy("mHandlerLock")
     JobHandler mHandler;
 
     static final class JobInterface extends IJobService.Stub {
@@ -189,9 +180,8 @@
      * @param service The {@link Service} that is creating this engine and in which it will run.
      */
     public JobServiceEngine(Service service) {
-        mService = service;
         mBinder = new JobInterface(this);
-        mHandler = new JobHandler(mService.getMainLooper());
+        mHandler = new JobHandler(service.getMainLooper());
     }
 
     /**
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index ce8b05a..0d7a941 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -15,10 +15,13 @@
  */
 package android.app.usage;
 
+import android.annotation.IntDef;
 import android.content.res.Configuration;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.List;
 
@@ -28,6 +31,12 @@
  */
 public final class UsageEvents implements Parcelable {
 
+    /** @hide */
+    public static final String INSTANT_APP_PACKAGE_NAME = "android.instant_app";
+
+    /** @hide */
+    public static final String INSTANT_APP_CLASS_NAME = "android.instant_class";
+
     /**
      * An event representing a state change for a component.
      */
@@ -91,6 +100,17 @@
          */
         public static final int CHOOSER_ACTION = 9;
 
+        /** @hide */
+        public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
+
+        /** @hide */
+        @IntDef(flag = true,
+                value = {
+                        FLAG_IS_PACKAGE_INSTANT_APP,
+                })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface EventFlags {}
+
         /**
          * {@hide}
          */
@@ -145,6 +165,27 @@
          */
         public String[] mContentAnnotations;
 
+        /** @hide */
+        @EventFlags
+        public int mFlags;
+
+        public Event() {
+        }
+
+        /** @hide */
+        public Event(Event orig) {
+            mPackage = orig.mPackage;
+            mClass = orig.mClass;
+            mTimeStamp = orig.mTimeStamp;
+            mEventType = orig.mEventType;
+            mConfiguration = orig.mConfiguration;
+            mShortcutId = orig.mShortcutId;
+            mAction = orig.mAction;
+            mContentType = orig.mContentType;
+            mContentAnnotations = orig.mContentAnnotations;
+            mFlags = orig.mFlags;
+        }
+
         /**
          * The package name of the source of this event.
          */
@@ -196,6 +237,20 @@
         public String getShortcutId() {
             return mShortcutId;
         }
+
+        /** @hide */
+        public Event getObfuscatedIfInstantApp() {
+            if ((mFlags & FLAG_IS_PACKAGE_INSTANT_APP) == 0) {
+                return this;
+            }
+            final Event ret = new Event(this);
+            ret.mPackage = INSTANT_APP_PACKAGE_NAME;
+            ret.mClass = INSTANT_APP_CLASS_NAME;
+
+            // Note there are other string fields too, but they're for app shortcuts and choosers,
+            // which instant apps can't use anyway, so there's no need to hide them.
+            return ret;
+        }
     }
 
     // Only used when creating the resulting events. Not used for reading/unparceling.
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 0874095..7eef85c 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -85,6 +85,17 @@
         mChooserCounts = stats.mChooserCounts;
     }
 
+    /**
+     * {@hide}
+     */
+    public UsageStats getObfuscatedForInstantApp() {
+        final UsageStats ret = new UsageStats(this);
+
+        ret.mPackageName = UsageEvents.INSTANT_APP_PACKAGE_NAME;
+
+        return ret;
+    }
+
     public String getPackageName() {
         return mPackageName;
     }
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 08595dd..dbaace2 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -127,7 +127,12 @@
 
     public abstract void applyRestoredPayload(int user, String key, byte[] payload);
 
-    /* Cache Quota Service API */
+    /**
+     * Return usage stats.
+     *
+     * @param obfuscateInstantApps whether instant app package names need to be obfuscated in the
+     *     result.
+     */
     public abstract List<UsageStats> queryUsageStatsForUser(
-            int userId, int interval, long beginTime, long endTime);
+            int userId, int interval, long beginTime, long endTime, boolean obfuscateInstantApps);
 }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 5fabbb6..a3d6e9f 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,7 +16,6 @@
 
 package android.bluetooth;
 
-import android.content.Context;
 import android.os.Handler;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
@@ -927,6 +926,31 @@
     }
 
     /**
+     * Discovers a service by UUID. This is exposed only for passing PTS tests.
+     * It should never be used by real applications. The service is not searched
+     * for characteristics and descriptors, or returned in any callback.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     *
+     * @return true, if the remote service discovery has been started
+     * @hide
+     */
+    public boolean discoverServiceByUuid(UUID uuid) {
+        if (DBG) Log.d(TAG, "discoverServiceByUuid() - device: " + mDevice.getAddress());
+        if (mService == null || mClientIf == 0) return false;
+
+        mServices.clear();
+
+        try {
+            mService.discoverServiceByUuid(mClientIf, mDevice.getAddress(), new ParcelUuid(uuid));
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
      * Returns a list of GATT services offered by the remote device.
      *
      * <p>This function requires that service discovery has been completed
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index dc5c7b6..167f5e9 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -80,6 +80,7 @@
     void clientReadPhy(in int clientIf, in String address);
     void refreshDevice(in int clientIf, in String address);
     void discoverServices(in int clientIf, in String address);
+    void discoverServiceByUuid(in int clientIf, in String address, in ParcelUuid uuid);
     void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
     void readUsingCharacteristicUuid(in int clientIf, in String address, in ParcelUuid uuid,
                            in int startHandle, in int endHandle, in int authReq);
diff --git a/core/java/android/content/IntentSender.java b/core/java/android/content/IntentSender.java
index 0a456b5..ff127df 100644
--- a/core/java/android/content/IntentSender.java
+++ b/core/java/android/content/IntentSender.java
@@ -361,6 +361,11 @@
     }
 
     /** @hide */
+    public IBinder getWhitelistToken() {
+        return mWhitelistToken;
+    }
+
+    /** @hide */
     public IntentSender(IIntentSender target) {
         mTarget = target;
     }
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 426f3cf..4cee2df 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -341,4 +341,7 @@
      * Return the taget SDK version for the app with the given UID.
      */
     public abstract int getUidTargetSdkVersion(int uid);
+
+    /** Whether the binder caller can access instant apps. */
+    public abstract boolean canAccessInstantApps(int callingUid, int userId);
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index b559604..e525ab3 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1760,7 +1760,9 @@
     public final Theme newTheme() {
         Theme theme = new Theme();
         theme.setImpl(mResourcesImpl.newThemeImpl());
-        mThemeRefs.add(new WeakReference<>(theme));
+        synchronized (mThemeRefs) {
+            mThemeRefs.add(new WeakReference<>(theme));
+        }
         return theme;
     }
 
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index bdfef83..b3adf82 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -772,6 +772,10 @@
         }
 
         final String file = value.string.toString();
+        if (!file.startsWith("res/")) {
+            return null;
+        }
+
         Typeface cached = Typeface.findFromCache(mAssets, file);
         if (cached != null) {
             return cached;
diff --git a/core/java/android/hardware/camera2/impl/CallbackProxies.java b/core/java/android/hardware/camera2/impl/CallbackProxies.java
index e6e448e..c9eecf1 100644
--- a/core/java/android/hardware/camera2/impl/CallbackProxies.java
+++ b/core/java/android/hardware/camera2/impl/CallbackProxies.java
@@ -88,7 +88,7 @@
     }
 
     @SuppressWarnings("deprecation")
-    public static class DeviceCaptureCallbackProxy extends CameraDeviceImpl.CaptureCallback {
+    public static class DeviceCaptureCallbackProxy implements CameraDeviceImpl.CaptureCallback {
         private final MethodNameInvoker<CameraDeviceImpl.CaptureCallback> mProxy;
 
         public DeviceCaptureCallbackProxy(
@@ -138,6 +138,13 @@
                 int sequenceId) {
             mProxy.invoke("onCaptureSequenceAborted", camera, sequenceId);
         }
+
+        @Override
+        public void onCaptureBufferLost(CameraDevice camera,
+                CaptureRequest request, Surface target, long frameNumber) {
+            mProxy.invoke("onCaptureBufferLost", camera, request, target, frameNumber);
+        }
+
     }
 
     public static class SessionStateCallbackProxy
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index 16ffee0..b3938cb 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -452,6 +452,37 @@
     private CameraDeviceImpl.CaptureCallback createCaptureCallbackProxy(
             Handler handler, CaptureCallback callback) {
         CameraDeviceImpl.CaptureCallback localCallback = new CameraDeviceImpl.CaptureCallback() {
+
+            @Override
+            public void onCaptureStarted(CameraDevice camera,
+                    CaptureRequest request, long timestamp, long frameNumber) {
+                // Do nothing
+            }
+
+            @Override
+            public void onCapturePartial(CameraDevice camera,
+                    CaptureRequest request, android.hardware.camera2.CaptureResult result) {
+                // Do nothing
+            }
+
+            @Override
+            public void onCaptureProgressed(CameraDevice camera,
+                    CaptureRequest request, android.hardware.camera2.CaptureResult partialResult) {
+                // Do nothing
+            }
+
+            @Override
+            public void onCaptureCompleted(CameraDevice camera,
+                    CaptureRequest request, android.hardware.camera2.TotalCaptureResult result) {
+                // Do nothing
+            }
+
+            @Override
+            public void onCaptureFailed(CameraDevice camera,
+                    CaptureRequest request, android.hardware.camera2.CaptureFailure failure) {
+                // Do nothing
+            }
+
             @Override
             public void onCaptureSequenceCompleted(CameraDevice camera,
                     int sequenceId, long frameNumber) {
@@ -463,6 +494,13 @@
                     int sequenceId) {
                 finishPendingSequence(sequenceId);
             }
+
+            @Override
+            public void onCaptureBufferLost(CameraDevice camera,
+                    CaptureRequest request, Surface target, long frameNumber) {
+                // Do nothing
+            }
+
         };
 
         /*
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index ab87f15..0d5c5e3 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1112,8 +1112,11 @@
      * <p>A callback for tracking the progress of a {@link CaptureRequest}
      * submitted to the camera device.</p>
      *
+     * An interface instead of an abstract class because this is internal and
+     * we want to make sure we always implement all its callbacks until we reach
+     * the public layer.
      */
-    public static abstract class CaptureCallback {
+    public interface CaptureCallback {
 
         /**
          * This constant is used to indicate that no images were captured for
@@ -1130,9 +1133,7 @@
          * @see android.media.MediaActionSound
          */
         public void onCaptureStarted(CameraDevice camera,
-                CaptureRequest request, long timestamp, long frameNumber) {
-            // default empty implementation
-        }
+                CaptureRequest request, long timestamp, long frameNumber);
 
         /**
          * This method is called when some results from an image capture are
@@ -1141,9 +1142,7 @@
          * @hide
          */
         public void onCapturePartial(CameraDevice camera,
-                CaptureRequest request, CaptureResult result) {
-            // default empty implementation
-        }
+                CaptureRequest request, CaptureResult result);
 
         /**
          * This method is called when an image capture makes partial forward progress; some
@@ -1151,18 +1150,14 @@
          *
          */
         public void onCaptureProgressed(CameraDevice camera,
-                CaptureRequest request, CaptureResult partialResult) {
-            // default empty implementation
-        }
+                CaptureRequest request, CaptureResult partialResult);
 
         /**
          * This method is called when an image capture has fully completed and all the
          * result metadata is available.
          */
         public void onCaptureCompleted(CameraDevice camera,
-                CaptureRequest request, TotalCaptureResult result) {
-            // default empty implementation
-        }
+                CaptureRequest request, TotalCaptureResult result);
 
         /**
          * This method is called instead of {@link #onCaptureCompleted} when the
@@ -1170,9 +1165,7 @@
          * request.
          */
         public void onCaptureFailed(CameraDevice camera,
-                CaptureRequest request, CaptureFailure failure) {
-            // default empty implementation
-        }
+                CaptureRequest request, CaptureFailure failure);
 
         /**
          * This method is called independently of the others in CaptureCallback,
@@ -1180,9 +1173,7 @@
          * or {@link CaptureFailure} for it have been returned via this callback.
          */
         public void onCaptureSequenceCompleted(CameraDevice camera,
-                int sequenceId, long frameNumber) {
-            // default empty implementation
-        }
+                int sequenceId, long frameNumber);
 
         /**
          * This method is called independently of the others in CaptureCallback,
@@ -1190,14 +1181,16 @@
          * or {@link CaptureFailure} for it have been returned via this callback.
          */
         public void onCaptureSequenceAborted(CameraDevice camera,
-                int sequenceId) {
-            // default empty implementation
-        }
+                int sequenceId);
 
+        /**
+         * This method is called independently of the others in CaptureCallback, if an output buffer
+         * is dropped for a particular capture request.
+         *
+         * Loss of metadata is communicated via onCaptureFailed, independently of any buffer loss.
+         */
         public void onCaptureBufferLost(CameraDevice camera,
-                CaptureRequest request, Surface target, long frameNumber) {
-            // default empty implementation
-        }
+                CaptureRequest request, Surface target, long frameNumber);
     }
 
     /**
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 8e57e85..324a08c 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -100,8 +100,8 @@
     public static final int FINGERPRINT_ERROR_CANCELED = 5;
 
     /**
-     * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically
-     * this will happen when the provided fingerprint id was incorrect.
+     * The {@link FingerprintManager#remove} call failed. Typically this will happen when the
+     * provided fingerprint id was incorrect.
      *
      * @hide
      */
@@ -398,10 +398,10 @@
     };
 
     /**
-     * Callback structure provided to {@link FingerprintManager#remove(int). Users of
-     * {@link #FingerprintManager()} may optionally provide an implementation of this to
-     * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
-     * fingerprint template removal events.
+     * Callback structure provided to {@link #remove}. Users of {@link FingerprintManager} may
+     * optionally provide an implementation of this to
+     * {@link #remove(Fingerprint, int, RemovalCallback)} for listening to fingerprint template
+     * removal events.
      *
      * @hide
      */
@@ -416,9 +416,13 @@
 
         /**
          * Called when a given fingerprint is successfully removed.
-         * @param fingerprint the fingerprint template that was removed.
+         * @param fp The fingerprint template that was removed.
+         * @param remaining The number of fingerprints yet to be removed in this operation. If
+         *         {@link #remove} is called on one fingerprint, this should be 0. If
+         *         {@link #remove} is called on a group, this should be the number of remaining
+         *         fingerprints in the group, and 0 after the last fingerprint is removed.
          */
-        public void onRemovalSucceeded(Fingerprint fingerprint) { }
+        public void onRemovalSucceeded(Fingerprint fp, int remaining) { }
     };
 
     /**
@@ -878,8 +882,7 @@
                             msg.arg2 /* vendorCode */);
                     break;
                 case MSG_REMOVED:
-                    sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
-                            msg.arg2 /* groupId */);
+                    sendRemovedResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
                     break;
                 case MSG_ENUMERATED:
                     sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
@@ -888,21 +891,29 @@
             }
         }
 
-        private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
-            if (mRemovalCallback != null) {
-                int reqFingerId = mRemovalFingerprint.getFingerId();
-                int reqGroupId = mRemovalFingerprint.getGroupId();
-                if (reqFingerId != 0 && fingerId != 0  &&  fingerId != reqFingerId) {
-                    Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
-                    return;
-                }
-                if (groupId != reqGroupId) {
-                    Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
-                    return;
-                }
-                mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
-                        deviceId));
+        private void sendRemovedResult(Fingerprint fingerprint, int remaining) {
+            if (mRemovalCallback == null) {
+                return;
             }
+            if (fingerprint == null) {
+                Log.e(TAG, "Received MSG_REMOVED, but fingerprint is null");
+                return;
+            }
+
+            int fingerId = fingerprint.getFingerId();
+            int reqFingerId = mRemovalFingerprint.getFingerId();
+            if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
+                Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
+                return;
+            }
+            int groupId = fingerprint.getGroupId();
+            int reqGroupId = mRemovalFingerprint.getGroupId();
+            if (groupId != reqGroupId) {
+                Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
+                return;
+            }
+
+            mRemovalCallback.onRemovalSucceeded(fingerprint, remaining);
         }
 
         private void sendEnumeratedResult(long deviceId, int fingerId, int groupId) {
@@ -921,7 +932,6 @@
             } else if (mAuthenticationCallback != null) {
                 mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
                         getErrorString(errMsgId, vendorCode));
-                mAuthenticationCallback = null;
             } else if (mRemovalCallback != null) {
                 mRemovalCallback.onRemovalError(mRemovalFingerprint, clientErrMsgId,
                         getErrorString(errMsgId, vendorCode));
@@ -942,7 +952,6 @@
                 final AuthenticationResult result =
                         new AuthenticationResult(mCryptoObject, fp, userId);
                 mAuthenticationCallback.onAuthenticationSucceeded(result);
-                mAuthenticationCallback = null;
             }
         }
 
@@ -1100,8 +1109,8 @@
 
         @Override // binder call
         public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
-            // TODO: propagate remaining
-            mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
+            mHandler.obtainMessage(MSG_REMOVED, remaining, 0,
+                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
         }
 
         @Override // binder call
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 3eea72d..499d6bb 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -157,6 +157,11 @@
     public static final int BLUETOOTH_SCAN_ON = 19;
 
     /**
+     * A constant indicating an aggregated partial wake lock timer.
+     */
+    public static final int AGGREGATED_WAKE_TYPE_PARTIAL = 20;
+
+    /**
      * Include all of the data in the stats, including previously saved data.
      */
     public static final int STATS_SINCE_CHARGED = 0;
@@ -185,6 +190,7 @@
      *   - Background timers and counters for: Sensor, BluetoothScan, WifiScan, Jobs, Syncs.
      * New in version 21:
      *   - Actual (not just apportioned) Wakelock time is also recorded.
+     *   - Aggregated partial wakelock time (per uid, instead of per wakelock) is recorded.
      */
     static final String CHECKIN_VERSION = "21";
 
@@ -216,6 +222,10 @@
     // window totalTime,  'w', count, current duration, max duration, total duration
     // [Currently, full and window wakelocks have durations current = max = total = -1]
     private static final String WAKELOCK_DATA = "wl";
+    // awl line is:
+    // BATTERY_STATS_CHECKIN_VERSION, uid, which, "awl",
+    // cumulative partial wakelock duration, cumulative background partial wakelock duration
+    private static final String AGGREGATED_WAKELOCK_DATA = "awl";
     private static final String SYNC_DATA = "sy";
     private static final String JOB_DATA = "jb";
     private static final String KERNEL_WAKELOCK_DATA = "kwl";
@@ -485,6 +495,13 @@
         }
 
         /**
+         * The cumulative time the uid spent holding any partial wakelocks. This will generally
+         * differ from summing over the Wakelocks in getWakelockStats since the latter may have
+         * wakelocks that overlap in time (and therefore over-counts).
+         */
+        public abstract Timer getAggregatedPartialWakelockTimer();
+
+        /**
          * Returns a mapping containing sensor statistics.
          *
          * @return a Map from Integer sensor ids to Uid.Sensor objects.
@@ -495,7 +512,7 @@
          * Returns a mapping containing active process data.
          */
         public abstract SparseArray<? extends Pid> getPidStats();
-        
+
         /**
          * Returns a mapping containing process statistics.
          *
@@ -609,7 +626,7 @@
         static final String[] USER_ACTIVITY_TYPES = {
             "other", "button", "touch", "accessibility"
         };
-        
+
         public static final int NUM_USER_ACTIVITY_TYPES = 4;
 
         public abstract void noteUserActivityLocked(int type);
@@ -1259,7 +1276,7 @@
         public static final byte CMD_SHUTDOWN = 8;
 
         public byte cmd = CMD_NULL;
-        
+
         /**
          * Return whether the command code is a delta data update.
          */
@@ -1271,13 +1288,13 @@
         public byte batteryStatus;
         public byte batteryHealth;
         public byte batteryPlugType;
-        
+
         public short batteryTemperature;
         public char batteryVoltage;
 
         // The charge of the battery in micro-Ampere-hours.
         public int batteryChargeUAh;
-        
+
         // Constants from SCREEN_BRIGHTNESS_*
         public static final int STATE_BRIGHTNESS_SHIFT = 0;
         public static final int STATE_BRIGHTNESS_MASK = 0x7;
@@ -1458,13 +1475,13 @@
 
         public HistoryItem() {
         }
-        
+
         public HistoryItem(long time, Parcel src) {
             this.time = time;
             numReadInts = 2;
             readFromParcel(src);
         }
-        
+
         public int describeContents() {
             return 0;
         }
@@ -1560,7 +1577,7 @@
             eventCode = EVENT_NONE;
             eventTag = null;
         }
-        
+
         public void setTo(HistoryItem o) {
             time = o.time;
             cmd = o.cmd;
@@ -1714,7 +1731,7 @@
         public final String shortName;
         public final String[] values;
         public final String[] shortValues;
-        
+
         public BitDescription(int mask, String name, String shortName) {
             this.mask = mask;
             this.shift = -1;
@@ -1723,7 +1740,7 @@
             this.values = null;
             this.shortValues = null;
         }
-        
+
         public BitDescription(int mask, int shift, String name, String shortName,
                 String[] values, String[] shortValues) {
             this.mask = mask;
@@ -1771,20 +1788,20 @@
      * Return the base time offset for the battery history.
      */
     public abstract long getHistoryBaseTime();
-    
+
     /**
      * Returns the number of times the device has been started.
      */
     public abstract int getStartCount();
-    
+
     /**
      * Returns the time in microseconds that the screen has been on while the device was
      * running on battery.
-     * 
+     *
      * {@hide}
      */
     public abstract long getScreenOnTime(long elapsedRealtimeUs, int which);
-    
+
     /**
      * Returns the number of times the screen was turned on.
      *
@@ -1799,11 +1816,11 @@
     public static final int SCREEN_BRIGHTNESS_MEDIUM = 2;
     public static final int SCREEN_BRIGHTNESS_LIGHT = 3;
     public static final int SCREEN_BRIGHTNESS_BRIGHT = 4;
-    
+
     static final String[] SCREEN_BRIGHTNESS_NAMES = {
         "dark", "dim", "medium", "light", "bright"
     };
-    
+
     static final String[] SCREEN_BRIGHTNESS_SHORT_NAMES = {
         "0", "1", "2", "3", "4"
     };
@@ -1813,7 +1830,7 @@
     /**
      * Returns the time in microseconds that the screen has been on with
      * the given brightness
-     * 
+     *
      * {@hide}
      */
     public abstract long getScreenBrightnessTime(int brightnessBin,
@@ -1897,11 +1914,11 @@
     /**
      * Returns the time in microseconds that the phone has been on while the device was
      * running on battery.
-     * 
+     *
      * {@hide}
      */
     public abstract long getPhoneOnTime(long elapsedRealtimeUs, int which);
-    
+
     /**
      * Returns the number of times a phone call was activated.
      *
@@ -1912,7 +1929,7 @@
     /**
      * Returns the time in microseconds that the phone has been running with
      * the given signal strength.
-     * 
+     *
      * {@hide}
      */
     public abstract long getPhoneSignalStrengthTime(int strengthBin,
@@ -1929,7 +1946,7 @@
 
     /**
      * Returns the number of times the phone has entered the given signal strength.
-     * 
+     *
      * {@hide}
      */
     public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
@@ -1997,13 +2014,13 @@
         "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
         "ehrpd", "hspap", "other"
     };
-    
+
     public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
-    
+
     /**
      * Returns the time in microseconds that the phone has been running with
      * the given data connection.
-     * 
+     *
      * {@hide}
      */
     public abstract long getPhoneDataConnectionTime(int dataType,
@@ -2012,7 +2029,7 @@
     /**
      * Returns the number of times the phone has entered the given data
      * connection type.
-     * 
+     *
      * {@hide}
      */
     public abstract int getPhoneDataConnectionCount(int dataType, int which);
@@ -2131,7 +2148,7 @@
     /**
      * Returns the time in microseconds that wifi has been on while the device was
      * running on battery.
-     * 
+     *
      * {@hide}
      */
     public abstract long getWifiOnTime(long elapsedRealtimeUs, int which);
@@ -2322,7 +2339,7 @@
      * Return whether we are currently running on battery.
      */
     public abstract boolean getIsOnBattery();
-    
+
     /**
      * Returns a SparseArray containing the statistics for each uid.
      */
@@ -2341,13 +2358,13 @@
      * @param curTime the amount of elapsed realtime in microseconds.
      */
     public abstract long getBatteryRealtime(long curTime);
-    
+
     /**
      * Returns the battery percentage level at the last time the device was unplugged from power, or
-     * the last time it booted on battery power. 
+     * the last time it booted on battery power.
      */
     public abstract int getDischargeStartLevel();
-    
+
     /**
      * Returns the current battery percentage level if we are in a discharge cycle, otherwise
      * returns the level at the last plug event.
@@ -2643,7 +2660,7 @@
 
     final String formatBytesLocked(long bytes) {
         mFormatBuilder.setLength(0);
-        
+
         if (bytes < BYTES_PER_KB) {
             return bytes + "B";
         } else if (bytes < BYTES_PER_MB) {
@@ -2773,10 +2790,10 @@
         }
         return false;
     }
-    
+
     /**
      * Checkin version of wakelock printer. Prints simple comma-separated list.
-     * 
+     *
      * @param sb a StringBuilder object.
      * @param timer a Timer object contining the wakelock times.
      * @param elapsedRealtimeUs the current time in microseconds.
@@ -2831,13 +2848,13 @@
 
     /**
      * Dump a comma-separated line of values for terse checkin mode.
-     * 
+     *
      * @param pw the PageWriter to dump log to
      * @param category category of data (e.g. "total", "last", "unplugged", "current" )
      * @param type type of data (e.g. "wakelock", "sensor", "process", "apk" ,  "process", "network")
      * @param args type-dependent data arguments
      */
-    private static final void dumpLine(PrintWriter pw, int uid, String category, String type, 
+    private static final void dumpLine(PrintWriter pw, int uid, String category, String type,
            Object... args ) {
         dumpLineHeader(pw, uid, category, type);
         for (Object arg : args) {
@@ -3014,7 +3031,7 @@
 
     /**
      * Checkin server version of dump to produce more compact, computer-readable log.
-     * 
+     *
      * NOTE: all times are expressed in 'ms'.
      */
     public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid,
@@ -3047,10 +3064,10 @@
                 .getCountLocked(which);
 
         final StringBuilder sb = new StringBuilder(128);
-        
+
         final SparseArray<? extends Uid> uidStats = getUidStats();
         final int NU = uidStats.size();
-        
+
         final String category = STAT_NAMES[which];
 
         // Dump "battery" stat
@@ -3063,11 +3080,11 @@
                 getEstimatedBatteryCapacity(),
                 getMinLearnedBatteryCapacity(), getMaxLearnedBatteryCapacity());
 
-        
+
         // Calculate wakelock times across all uids.
         long fullWakeLockTimeTotal = 0;
         long partialWakeLockTimeTotal = 0;
-        
+
         for (int iu = 0; iu < NU; iu++) {
             final Uid u = uidStats.valueAt(iu);
 
@@ -3138,14 +3155,14 @@
                 getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which),
                 getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT),
                 getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP));
-        
+
         // Dump screen brightness stats
         Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS];
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
             args[i] = getScreenBrightnessTime(i, rawRealtime, which) / 1000;
         }
         dumpLine(pw, 0 /* uid */, category, SCREEN_BRIGHTNESS_DATA, args);
-        
+
         // Dump signal strength stats
         args = new Object[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
         for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) {
@@ -3207,7 +3224,7 @@
             dumpLine(pw, 0 /* uid */, category, BATTERY_LEVEL_DATA, getDischargeStartLevel(),
                     getDischargeCurrentLevel());
         }
-        
+
         if (which == STATS_SINCE_UNPLUGGED) {
             dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
                     getDischargeStartLevel()-getDischargeCurrentLevel(),
@@ -3221,7 +3238,7 @@
                     getDischargeAmountScreenOffSinceCharge(),
                     dischargeCount / 1000, dischargeScreenOffCount / 1000);
         }
-        
+
         if (reqUid < 0) {
             final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
             if (kernelWakelocks.size() > 0) {
@@ -3244,7 +3261,7 @@
                 }
             }
         }
-        
+
         final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
         helper.create(this);
         helper.refreshStats(which, UserHandle.USER_ALL);
@@ -3434,7 +3451,17 @@
                     dumpLine(pw, uid /* uid */, category, USER_ACTIVITY_DATA, args);
                 }
             }
-            
+
+            if (u.getAggregatedPartialWakelockTimer() != null) {
+                final Timer timer = u.getAggregatedPartialWakelockTimer();
+                // Convert from microseconds to milliseconds with rounding
+                final long totTimeMs = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                final Timer bgTimer = timer.getSubTimer();
+                final long bgTimeMs = bgTimer != null ?
+                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+                dumpLine(pw, uid, category, AGGREGATED_WAKELOCK_DATA, totTimeMs, bgTimeMs);
+            }
+
             final ArrayMap<String, ? extends Uid.Wakelock> wakelocks = u.getWakelockStats();
             for (int iw=wakelocks.size()-1; iw>=0; iw--) {
                 final Uid.Wakelock wl = wakelocks.valueAt(iw);
@@ -3666,7 +3693,7 @@
         final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
 
         final StringBuilder sb = new StringBuilder(128);
-        
+
         final SparseArray<? extends Uid> uidStats = getUidStats();
         final int NU = uidStats.size();
 
@@ -3932,7 +3959,7 @@
                 }
             }
         }
-        
+
         final long mobileRxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which);
         final long mobileTxTotalBytes = getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which);
         final long wifiRxTotalBytes = getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which);
@@ -4161,15 +4188,15 @@
         if (which == STATS_SINCE_UNPLUGGED) {
             if (getIsOnBattery()) {
                 pw.print(prefix); pw.println("  Device is currently unplugged");
-                pw.print(prefix); pw.print("    Discharge cycle start level: "); 
+                pw.print(prefix); pw.print("    Discharge cycle start level: ");
                         pw.println(getDischargeStartLevel());
                 pw.print(prefix); pw.print("    Discharge cycle current level: ");
                         pw.println(getDischargeCurrentLevel());
             } else {
                 pw.print(prefix); pw.println("  Device is currently plugged into power");
-                pw.print(prefix); pw.print("    Last discharge cycle start level: "); 
+                pw.print(prefix); pw.print("    Last discharge cycle start level: ");
                         pw.println(getDischargeStartLevel());
-                pw.print(prefix); pw.print("    Last discharge cycle end level: "); 
+                pw.print(prefix); pw.print("    Last discharge cycle end level: ");
                         pw.println(getDischargeCurrentLevel());
             }
             pw.print(prefix); pw.print("    Amount discharged while screen on: ");
@@ -4450,7 +4477,7 @@
             if (reqUid >= 0 && uid != reqUid && uid != Process.SYSTEM_UID) {
                 continue;
             }
-            
+
             final Uid u = uidStats.valueAt(iu);
 
             pw.print(prefix);
@@ -4538,7 +4565,7 @@
                         formatTimeMs(sb, uidWifiRunningTime / 1000);
                         sb.append("("); sb.append(formatRatioLocked(uidWifiRunningTime,
                                 whichBatteryRealtime)); sb.append(")\n");
-                sb.append(prefix); sb.append("    Full Wifi Lock: "); 
+                sb.append(prefix); sb.append("    Full Wifi Lock: ");
                         formatTimeMs(sb, fullWifiLockOnTime / 1000);
                         sb.append("("); sb.append(formatRatioLocked(fullWifiLockOnTime,
                                 whichBatteryRealtime)); sb.append(")\n");
@@ -4690,8 +4717,23 @@
                         rawRealtime, which);
             }
             if (countWakelock > 1) {
-                if (totalFullWakelock != 0 || totalPartialWakelock != 0
-                        || totalWindowWakelock != 0) {
+                // get unpooled partial wakelock quantities (unlike totalPartialWakelock, which is
+                // pooled and therefore just a lower bound)
+                long actualTotalPartialWakelock = 0;
+                long actualBgPartialWakelock = 0;
+                if (u.getAggregatedPartialWakelockTimer() != null) {
+                    final Timer aggTimer = u.getAggregatedPartialWakelockTimer();
+                    // Convert from microseconds to milliseconds with rounding
+                    actualTotalPartialWakelock =
+                            (aggTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                    final Timer bgAggTimer = aggTimer.getSubTimer();
+                    actualBgPartialWakelock = bgAggTimer != null ?
+                            (bgAggTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+                }
+
+                if (actualTotalPartialWakelock != 0 || actualBgPartialWakelock != 0 ||
+                        totalFullWakelock != 0 || totalPartialWakelock != 0 ||
+                        totalWindowWakelock != 0) {
                     sb.setLength(0);
                     sb.append(prefix);
                     sb.append("    TOTAL wake: ");
@@ -4707,7 +4749,23 @@
                         }
                         needComma = true;
                         formatTimeMs(sb, totalPartialWakelock);
-                        sb.append("partial");
+                        sb.append("blamed partial");
+                    }
+                    if (actualTotalPartialWakelock != 0) {
+                        if (needComma) {
+                            sb.append(", ");
+                        }
+                        needComma = true;
+                        formatTimeMs(sb, actualTotalPartialWakelock);
+                        sb.append("actual partial");
+                    }
+                    if (actualBgPartialWakelock != 0) {
+                        if (needComma) {
+                            sb.append(", ");
+                        }
+                        needComma = true;
+                        formatTimeMs(sb, actualBgPartialWakelock);
+                        sb.append("actual background partial");
                     }
                     if (totalWindowWakelock != 0) {
                         if (needComma) {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 4bad7ab..a2fb9db 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -807,8 +807,20 @@
     }
 
     /**
-     * Verifies the the current flash of the device is consistent with what
+     * True if Treble is enabled and required for this device.
+     *
+     * @hide
+     */
+    public static final boolean IS_TREBLE_ENABLED =
+        SystemProperties.getBoolean("ro.treble.enabled", false);
+
+    /**
+     * Verifies the current flash of the device is consistent with what
      * was expected at build time.
+     *
+     * Treble devices will verify the Vendor Interface (VINTF). A device
+     * launched without Treble:
+     *
      * 1) Checks that device fingerprint is defined and that it matches across
      *    various partitions.
      * 2) Verifies radio and bootloader partitions are those expected in the build.
@@ -819,6 +831,17 @@
         // Don't care on eng builds.  Incremental build may trigger false negative.
         if (IS_ENG) return true;
 
+        if (IS_TREBLE_ENABLED) {
+            int result = VintfObject.verify(new String[0]);
+
+            if (result != 0) {
+                Slog.e(TAG, "Vendor interface is incompatible, error="
+                        + String.valueOf(result));
+            }
+
+            return result == 0;
+        }
+
         final String system = SystemProperties.get("ro.build.fingerprint");
         final String vendor = SystemProperties.get("ro.vendor.build.fingerprint");
         final String bootimage = SystemProperties.get("ro.bootimage.build.fingerprint");
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 38a5395..0a5e9a8 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -429,13 +429,7 @@
      * @param size The new number of bytes in the Parcel.
      */
     public final void setDataSize(int size) {
-        // STOPSHIP: Try/catch for exception is for temporary debug. Remove once bug resolved
-        try {
-            updateNativeSize(nativeSetDataSize(mNativePtr, size));
-        } catch (IllegalArgumentException iae) {
-            Log.e(TAG,"Caught Exception representing a known bug in Parcel",iae);
-            Log.wtfStack(TAG, "This flow is using SetDataSize incorrectly");
-        }
+        updateNativeSize(nativeSetDataSize(mNativePtr, size));
     }
 
     /**
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 3212139..c091420 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -547,7 +547,8 @@
      * Converts a string representing a file mode, such as "rw", into a bitmask suitable for use
      * with {@link #open}.
      * <p>
-     * @param mode The string representation of the file mode.
+     * @param mode The string representation of the file mode. Can be "r", "w", "wt", "wa", "rw"
+     *             or "rwt".
      * @return A bitmask representing the given file mode.
      * @throws IllegalArgumentException if the given string does not match a known file mode.
      */
diff --git a/core/java/android/os/ProxyFileDescriptorCallback.java b/core/java/android/os/ProxyFileDescriptorCallback.java
index e69fb55..9f56802 100644
--- a/core/java/android/os/ProxyFileDescriptorCallback.java
+++ b/core/java/android/os/ProxyFileDescriptorCallback.java
@@ -22,7 +22,23 @@
 /**
  * Callback that handles file system requests from ProxyFileDescriptor.
  *
- * @see android.os.storage.StorageManager#openProxyFileDescriptor(int, ProxyFileDescriptorCallback)
+ * All callback methods except for onRelease should throw {@link android.system.ErrnoException}
+ * with proper errno on errors. See
+ * <a href="http://man7.org/linux/man-pages/man3/errno.3.html">errno(3)</a> and
+ * {@link android.system.OsConstants}.
+ *
+ * Typical errnos are
+ *
+ * <ul>
+ * <li>{@link android.system.OsConstants#EIO} for general I/O issues
+ * <li>{@link android.system.OsConstants#ENOENT} when the file is not found
+ * <li>{@link android.system.OsConstants#EBADF} if the file doesn't allow read/write operations
+ *     based on how it was opened.  (For example, trying to write a file that was opened read-only.)
+ * <li>{@link android.system.OsConstants#ENOSPC} if you cannot handle a write operation to
+ *     space/quota limitations.
+ * </ul>
+ * @see android.os.storage.StorageManager#openProxyFileDescriptor(int, ProxyFileDescriptorCallback,
+ *     Handler)
  */
 public abstract class ProxyFileDescriptorCallback {
     /**
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 447f280..d2598c7 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -22,9 +22,12 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.Display;
+import android.view.WindowManager;
 
 import libcore.io.Streams;
 
@@ -570,7 +573,16 @@
 
             // Having set up the BCB (bootloader control block), go ahead and reboot
             PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-            pm.reboot(PowerManager.REBOOT_RECOVERY_UPDATE);
+            String reason = PowerManager.REBOOT_RECOVERY_UPDATE;
+
+            // On TV, reboot quiescently if the screen is off
+            if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
+                WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+                if (wm.getDefaultDisplay().getState() != Display.STATE_ON) {
+                    reason += ",quiescent";
+                }
+            }
+            pm.reboot(reason);
 
             throw new IOException("Reboot failed (no permissions?)");
         }
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 97da588..17f00c2 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -167,4 +167,12 @@
      * Remove user's running state
      */
     public abstract void removeUserState(int userId);
+
+    /**
+     * Returns an array of user ids. This array is cached in UserManagerService and passed as a
+     * reference, so do not modify the returned array.
+     *
+     * @return the array of user ids.
+     */
+    public abstract int[] getUserIds();
 }
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 2a83c4b..3eef31a 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -655,8 +655,12 @@
      * <p>
      * Your provider should return a reliable {@link ParcelFileDescriptor} to
      * detect when the remote caller has finished reading or writing the
-     * document. You may return a pipe or socket pair if the mode is exclusively
-     * "r" or "w", but complex modes like "rw" imply a normal file on disk that
+     * document.
+     * <p>
+     * Mode "r" should always be supported. Provider should throw
+     * {@link UnsupportedOperationException} if the passing mode is not supported.
+     * You may return a pipe or socket pair if the mode is exclusively "r" or
+     * "w", but complex modes like "rw" imply a normal file on disk that
      * supports seeking.
      * <p>
      * If you block while downloading content, you should periodically check
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 2ade9b5..2c9b2e4 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -138,6 +138,8 @@
                 case DRAW_FINISHED_MSG: {
                     mDrawFinished = true;
                     if (mAttachedToWindow) {
+                        mParent.requestTransparentRegion(SurfaceView.this);
+
                         notifyDrawFinished();
                         invalidate();
                     }
@@ -245,8 +247,8 @@
         super.onAttachedToWindow();
 
         getViewRootImpl().addWindowStoppedCallback(this);
+        mWindowStopped = false;
 
-        mParent.requestTransparentRegion(this);
         mViewVisibility = getVisibility() == VISIBLE;
         updateRequestedVisibility();
 
@@ -351,7 +353,7 @@
 
     @Override
     public boolean gatherTransparentRegion(Region region) {
-        if (isAboveParent()) {
+        if (isAboveParent() || !mDrawFinished) {
             return super.gatherTransparentRegion(region);
         }
 
@@ -677,9 +679,16 @@
                 } finally {
                     mIsCreating = false;
                     if (mSurfaceControl != null && !mSurfaceCreated) {
-                        mSurfaceControl.destroy();
                         mSurface.release();
-                        mSurfaceControl = null;
+                        // If we are not in the stopped state, then the destruction of the Surface
+                        // represents a visual change we need to display, and we should go ahead
+                        // and destroy the SurfaceControl. However if we are in the stopped state,
+                        // we can just leave the Surface around so it can be a part of animations,
+                        // and we let the life-time be tied to the parent surface.
+                        if (!mWindowStopped) {
+                            mSurfaceControl.destroy();
+                            mSurfaceControl = null;
+                        }
                     }
                 }
             } catch (Exception ex) {
@@ -855,7 +864,7 @@
      */
     @Deprecated
     public void setWindowType(int type) {
-        if (getContext().getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+        if (getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O) {
             throw new UnsupportedOperationException(
                     "SurfaceView#setWindowType() has never been a public API.");
         }
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index c66bf874..25a58e6 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -872,6 +872,15 @@
         }
     }
 
+    /**
+     * Creates a {@link android.graphics.Bitmap.Config#HARDWARE} bitmap from the given
+     * RenderNode. Note that the RenderNode should be created as a root node (so x/y of 0,0), and
+     * not the RenderNode from a View.
+     **/
+    public static Bitmap createHardwareBitmap(RenderNode node, int width, int height) {
+        return nCreateHardwareBitmap(node.getNativeDisplayList(), width, height);
+    }
+
     @Override
     protected void finalize() throws Throwable {
         try {
@@ -1015,4 +1024,6 @@
 
     private static native int nCopySurfaceInto(Surface surface,
             int srcLeft, int srcTop, int srcRight, int srcBottom, Bitmap bitmap);
+
+    private static native Bitmap nCreateHardwareBitmap(long renderNode, int width, int height);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2d48295..11b55a8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -593,12 +593,12 @@
  * a single tag using the {@link android.R.styleable#View_tag android:tag}
  * attribute or multiple tags using the {@code <tag>} child element:
  * <pre>
- *     &ltView ...
+ *     &lt;View ...
  *           android:tag="@string/mytag_value" /&gt;
- *     &ltView ...&gt;
- *         &lttag android:id="@+id/mytag"
+ *     &lt;View ...&gt;
+ *         &lt;tag android:id="@+id/mytag"
  *              android:value="@string/mytag_value" /&gt;
- *     &lt/View>
+ *     &lt;/View>
  * </pre>
  * </p>
  * <p>
@@ -628,11 +628,11 @@
  * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
  * the inflation context's theme (e.g. the Activity theme) will be preserved.
  * <pre>
- *     &ltLinearLayout
+ *     &lt;LinearLayout
  *             ...
  *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
- *         &ltView ...&gt;
- *     &lt/LinearLayout&gt;
+ *         &lt;View ...&gt;
+ *     &lt;/LinearLayout&gt;
  * </pre>
  * </p>
  *
@@ -7516,15 +7516,22 @@
      * <li>Passing the actual value to the equivalent setter in the view.
      * </ol>
      *
-     * <p>For example, a text-field view would call:
+     * <p>For example, a text-field view could implement the method this way:
+     *
      * <pre class="prettyprint">
-     * CharSequence text = value.getTextValue();
-     * if (text != null) {
-     *     setText(text);
+     * &#64;Override
+     * public void autofill(AutofillValue value) {
+     *   if (!value.isText() || !this.isEditable()) {
+     *      return;
+     *   }
+     *   CharSequence text = value.getTextValue();
+     *   if (text != null) {
+     *     this.setText(text);
+     *   }
      * }
      * </pre>
      *
-     * <p>If the value is updated asyncronously the next call to
+     * <p>If the value is updated asynchronously the next call to
      * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
      * changed to the autofilled value. If not, the view will not be considered autofilled.
      *
@@ -19794,7 +19801,6 @@
                 && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
             mPrivateFlags |= PFLAG_SKIP_DRAW;
         }
-        requestLayout();
         invalidate();
     }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 511a279..28ded55 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2401,6 +2401,9 @@
     }
 
     private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
+        if (mView == null) {
+            return;
+        }
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
         try {
             mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index e4d4e7b..0973d0a 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -334,7 +334,7 @@
      */
     ViewTreeObserver(Context context) {
         sIllegalOnDrawModificationIsFatal =
-                context.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.N_MR1;
+                context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.O;
     }
 
     /**
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 030c78b..13ffeec 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -401,6 +401,13 @@
         boolean isAnimatingLw();
 
         /**
+         * @return Whether the window can affect SystemUI flags, meaning that SystemUI (system bars,
+         *         for example) will be  affected by the flags specified in this window. This is the
+         *         case when the surface is on screen but not exiting.
+         */
+        boolean canAffectSystemUiFlags();
+
+        /**
          * Is this window considered to be gone for purposes of layout?
          */
         boolean isGoneForLayoutLw();
@@ -589,6 +596,13 @@
          * Notifies window manager that {@link #isKeyguardTrustedLw} has changed.
          */
         void notifyKeyguardTrustedChanged();
+
+        /**
+         * Notifies the window manager that screen is being turned off.
+         *
+         * @param listener callback to call when display can be turned off
+         */
+        void screenTurningOff(ScreenOffListener listener);
     }
 
     public interface PointerEventListener {
@@ -1267,6 +1281,15 @@
     public void screenTurnedOn();
 
     /**
+     * Called when the display would like to be turned off. This gives policy a chance to do some
+     * things before the display power state is actually changed to off.
+     *
+     * @param screenOffListener Must be called to tell that the display power state can actually be
+     *                          changed now after policy has done its work.
+     */
+    public void screenTurningOff(ScreenOffListener screenOffListener);
+
+    /**
      * Called when the device has turned the screen off.
      */
     public void screenTurnedOff();
@@ -1276,6 +1299,13 @@
     }
 
     /**
+     * See {@link #screenTurnedOff}
+     */
+    public interface ScreenOffListener {
+        void onScreenOff();
+    }
+
+    /**
      * Return whether the default display is on and not blocked by a black surface.
      */
     public boolean isScreenOn();
@@ -1661,4 +1691,16 @@
     public void onConfigurationChanged();
 
     public boolean shouldRotateSeamlessly(int oldRotation, int newRotation);
+
+    /**
+     * Called when System UI has been started.
+     */
+    void onSystemUiStarted();
+
+    /**
+     * Checks whether the policy is ready for dismissing the boot animation and completing the boot.
+     *
+     * @return true if ready; false otherwise.
+     */
+    boolean canDismissBootAnimation();
 }
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 8a13c0c..eecfdca 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -618,8 +618,7 @@
     public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
 
     /**
-     * Represents the event of scrolling a view. This event type is generally not sent directly.
-     * @see View#onScrollChanged(int, int, int, int)
+     * Represents the event of scrolling a view.
      */
     public static final int TYPE_VIEW_SCROLLED = 0x00001000;
 
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 39ac399..d8b316e 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -186,6 +186,10 @@
     @GuardedBy("mLock")
     @Nullable private TrackedViews mTrackedViews;
 
+    /** Views that are only tracked because they are fillable and could be anchoring the UI. */
+    @GuardedBy("mLock")
+    @Nullable private ArraySet<AutofillId> mFillableIds;
+
     /** @hide */
     public interface AutofillClient {
         /**
@@ -238,13 +242,22 @@
         boolean isVisibleForAutofill();
 
         /**
-         * Find views by traversing the hierarchies of the client.
+         * Finds views by traversing the hierarchies of the client.
          *
          * @param viewIds The accessibility ids of the views to find
          *
-         * @return And array containing the views, or {@code null} if not found
+         * @return And array containing the views (empty if no views found).
          */
         @NonNull View[] findViewsByAccessibilityIdTraversal(@NonNull int[] viewIds);
+
+        /**
+         * Finds a view by traversing the hierarchies of the client.
+         *
+         * @param viewId The accessibility id of the views to find
+         *
+         * @return The view, or {@code null} if not found
+         */
+        @Nullable View findViewByAccessibilityIdTraversal(int viewId);
     }
 
     /**
@@ -471,8 +484,17 @@
      */
     public void notifyViewVisibilityChange(@NonNull View view, boolean isVisible) {
         synchronized (mLock) {
-            if (mEnabled && mSessionId != NO_SESSION && mTrackedViews != null) {
-                mTrackedViews.notifyViewVisibilityChange(view, isVisible);
+            if (mEnabled && mSessionId != NO_SESSION) {
+                if (!isVisible && mFillableIds != null) {
+                    final AutofillId id = view.getAutofillId();
+                    if (mFillableIds.contains(id)) {
+                        if (sDebug) Log.d(TAG, "Hidding UI when view " + id + " became invisible");
+                        requestHideFillUi(id, view);
+                    }
+                }
+                if (mTrackedViews != null) {
+                    mTrackedViews.notifyViewVisibilityChange(view, isVisible);
+                }
             }
         }
     }
@@ -1048,9 +1070,10 @@
      *
      * @param trackedIds The views to be tracked
      * @param saveOnAllViewsInvisible Finish the session once all tracked views are invisible.
+     * @param fillableIds Views that might anchor FillUI.
      */
-    private void setTrackedViews(int sessionId, List<AutofillId> trackedIds,
-            boolean saveOnAllViewsInvisible) {
+    private void setTrackedViews(int sessionId, @Nullable AutofillId[] trackedIds,
+            boolean saveOnAllViewsInvisible, @Nullable AutofillId[] fillableIds) {
         synchronized (mLock) {
             if (mEnabled && mSessionId == sessionId) {
                 if (saveOnAllViewsInvisible) {
@@ -1058,15 +1081,32 @@
                 } else {
                     mTrackedViews = null;
                 }
+                if (fillableIds != null) {
+                    if (mFillableIds == null) {
+                        mFillableIds = new ArraySet<>(fillableIds.length);
+                    }
+                    for (AutofillId id : fillableIds) {
+                        mFillableIds.add(id);
+                    }
+                    if (sVerbose) {
+                        Log.v(TAG, "setTrackedViews(): fillableIds=" + fillableIds
+                                + ", mFillableIds" + mFillableIds);
+                    }
+                }
             }
         }
     }
 
-    private void requestHideFillUi(int sessionId, AutofillId id) {
+    private void requestHideFillUi(AutofillId id) {
         final View anchor = findView(id);
+        if (sVerbose) Log.v(TAG, "requestHideFillUi(" + id + "): anchor = " + anchor);
         if (anchor == null) {
             return;
         }
+        requestHideFillUi(id, anchor);
+    }
+
+    private void requestHideFillUi(AutofillId id, View anchor) {
 
         AutofillCallback callback = null;
         synchronized (mLock) {
@@ -1123,6 +1163,18 @@
      *
      * @return The array of viewIds.
      */
+    // TODO: move to Helper as static method
+    @NonNull private int[] getViewIds(@NonNull AutofillId[] autofillIds) {
+        final int numIds = autofillIds.length;
+        final int[] viewIds = new int[numIds];
+        for (int i = 0; i < numIds; i++) {
+            viewIds[i] = autofillIds[i].getViewId();
+        }
+
+        return viewIds;
+    }
+
+    // TODO: move to Helper as static method
     @NonNull private int[] getViewIds(@NonNull List<AutofillId> autofillIds) {
         final int numIds = autofillIds.size();
         final int[] viewIds = new int[numIds];
@@ -1147,7 +1199,7 @@
             return null;
         }
 
-        return client.findViewsByAccessibilityIdTraversal(new int[]{autofillId.getViewId()})[0];
+        return client.findViewByAccessibilityIdTraversal(autofillId.getViewId());
     }
 
     /** @hide */
@@ -1173,6 +1225,7 @@
          *
          * @return {@code true} iff set is not empty and value is in set
          */
+        // TODO: move to Helper as static method
         private <T> boolean isInSet(@Nullable ArraySet<T> set, T value) {
             return set != null && set.contains(value);
         }
@@ -1186,6 +1239,7 @@
          * @return The set including the new value. If set was {@code null}, a set containing only
          *         the new value.
          */
+        // TODO: move to Helper as static method
         @NonNull
         private <T> ArraySet<T> addToSet(@Nullable ArraySet<T> set, T valueToAdd) {
             if (set == null) {
@@ -1206,6 +1260,7 @@
          * @return The set without the removed value. {@code null} if set was null, or is empty
          *         after removal.
          */
+        // TODO: move to Helper as static method
         @Nullable
         private <T> ArraySet<T> removeFromSet(@Nullable ArraySet<T> set, T valueToRemove) {
             if (set == null) {
@@ -1226,11 +1281,8 @@
          *
          * @param trackedIds The views to be tracked
          */
-        TrackedViews(List<AutofillId> trackedIds) {
-            mVisibleTrackedIds = null;
-            mInvisibleTrackedIds = null;
-
-            AutofillClient client = getClientLocked();
+        TrackedViews(@Nullable AutofillId[] trackedIds) {
+            final AutofillClient client = getClientLocked();
             if (trackedIds != null && client != null) {
                 final boolean[] isVisible;
 
@@ -1238,12 +1290,12 @@
                     isVisible = client.getViewVisibility(getViewIds(trackedIds));
                 } else {
                     // All false
-                    isVisible = new boolean[trackedIds.size()];
+                    isVisible = new boolean[trackedIds.length];
                 }
 
-                final int numIds = trackedIds.size();
+                final int numIds = trackedIds.length;
                 for (int i = 0; i < numIds; i++) {
-                    final AutofillId id = trackedIds.get(i);
+                    final AutofillId id = trackedIds[i];
 
                     if (isVisible[i]) {
                         mVisibleTrackedIds = addToSet(mVisibleTrackedIds, id);
@@ -1294,6 +1346,9 @@
             }
 
             if (mVisibleTrackedIds == null) {
+                if (sVerbose) {
+                    Log.v(TAG, "No more visible ids. Invisibile = " + mInvisibleTrackedIds);
+                }
                 finishSessionLocked();
             }
         }
@@ -1473,8 +1528,7 @@
         public void requestHideFillUi(int sessionId, AutofillId id) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(
-                        () -> afm.requestHideFillUi(sessionId, id));
+                afm.mContext.getMainThreadHandler().post(() -> afm.requestHideFillUi(id));
             }
         }
 
@@ -1501,12 +1555,12 @@
         }
 
         @Override
-        public void setTrackedViews(int sessionId, List<AutofillId> ids,
-                boolean saveOnAllViewsInvisible) {
+        public void setTrackedViews(int sessionId, AutofillId[] ids,
+                boolean saveOnAllViewsInvisible, AutofillId[] fillableIds) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(
-                        () -> afm.setTrackedViews(sessionId, ids, saveOnAllViewsInvisible)
+                afm.mContext.getMainThreadHandler().post(() ->
+                        afm.setTrackedViews(sessionId, ids, saveOnAllViewsInvisible, fillableIds)
                 );
             }
         }
diff --git a/core/java/android/view/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
index 1d66f7f..d18b181 100644
--- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl
+++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl
@@ -52,8 +52,8 @@
       * Sets the views to track. If saveOnAllViewsInvisible is set and all these view are invisible
       * the session is finished automatically.
       */
-    void setTrackedViews(int sessionId, in List<AutofillId> ids,
-            boolean saveOnAllViewsInvisible);
+    void setTrackedViews(int sessionId, in @nullable AutofillId[] savableIds,
+            boolean saveOnAllViewsInvisible, in @nullable AutofillId[] fillableIds);
 
     /**
      * Requests showing the fill UI.
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 32fae73..ab1d034 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -67,11 +67,6 @@
                 CharSequence text, int startIndex, int endIndex, LocaleList defaultLocales) {
             return TextClassification.EMPTY;
         }
-
-        @Override
-        public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
-            return LinksInfo.NO_OP;
-        }
     };
 
     /**
@@ -138,8 +133,10 @@
      * @hide
      */
     @WorkerThread
-    LinksInfo getLinks(
-            @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales);
+    default LinksInfo getLinks(
+            @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales) {
+        return LinksInfo.NO_OP;
+    }
 
     /**
      * Logs a TextClassifier event.
diff --git a/core/java/android/webkit/UserPackage.java b/core/java/android/webkit/UserPackage.java
index f53b5d6..8920089 100644
--- a/core/java/android/webkit/UserPackage.java
+++ b/core/java/android/webkit/UserPackage.java
@@ -83,8 +83,7 @@
      * supported by the current framework version.
      */
     public static boolean hasCorrectTargetSdkVersion(PackageInfo packageInfo) {
-        // TODO(gsennton) use Build.VERSION_CODES.O when that has been updated.
-        return packageInfo.applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1;
+        return packageInfo.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O;
     }
 
     public UserInfo getUserInfo() {
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index ca1bf58..636519b 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -112,6 +112,7 @@
 
         // Set up and attach container.
         mContainer = (ViewGroup) inflater.inflate(layoutResourceId, mDelegator, false);
+        mContainer.setSaveFromParentEnabled(false);
         mDelegator.addView(mContainer);
 
         // Set up header views.
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index fc2d1fa..4f9316f 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -115,7 +115,8 @@
 
         LayoutInflater inflater = (LayoutInflater) context
                 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        inflater.inflate(layoutResourceId, mDelegator, true);
+        final View view = inflater.inflate(layoutResourceId, mDelegator, true);
+        view.setSaveFromParentEnabled(false);
 
         OnValueChangeListener onChangeListener = new OnValueChangeListener() {
             public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index be0967f..cfd1445 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -16,7 +16,7 @@
 
 package android.widget;
 
-import static android.os.Build.VERSION_CODES.N_MR1;
+import static android.os.Build.VERSION_CODES.O;
 
 import android.annotation.Nullable;
 import android.content.Context;
@@ -302,7 +302,7 @@
         getTempCalendarForTime(timeInMillis);
 
         final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
-        if (targetSdkVersion > N_MR1) {
+        if (targetSdkVersion >= O) {
             if (mTempCalendar.before(mMinDate) || mTempCalendar.after(mMaxDate)) {
                 throw new IllegalArgumentException("timeInMillis must be between the values of "
                         + "getMinDate() and getMaxDate()");
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index d456989..7bdd6da 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -737,7 +737,6 @@
         mInputText.setFilters(new InputFilter[] {
             new InputTextFilter()
         });
-        mInputText.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
 
         mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
         mInputText.setImeOptions(EditorInfo.IME_ACTION_DONE);
@@ -771,12 +770,6 @@
         if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
         }
-
-        // Should be focusable by default, as the text view whose visibility changes is focusable
-        if (getFocusable() == View.FOCUSABLE_AUTO) {
-            setFocusable(View.FOCUSABLE);
-            setFocusableInTouchMode(true);
-        }
     }
 
     @Override
@@ -863,7 +856,7 @@
         switch (action) {
             case MotionEvent.ACTION_DOWN: {
                 removeAllCallbacks();
-                hideSoftInput();
+                mInputText.setVisibility(View.INVISIBLE);
                 mLastDownOrMoveEventY = mLastDownEventY = event.getY();
                 mLastDownEventTime = event.getEventTime();
                 mIgnoreMoveEvents = false;
@@ -890,9 +883,11 @@
                     mFlingScroller.forceFinished(true);
                     mAdjustScroller.forceFinished(true);
                 } else if (mLastDownEventY < mTopSelectionDividerTop) {
+                    hideSoftInput();
                     postChangeCurrentByOneFromLongPress(
                             false, ViewConfiguration.getLongPressTimeout());
                 } else if (mLastDownEventY > mBottomSelectionDividerBottom) {
+                    hideSoftInput();
                     postChangeCurrentByOneFromLongPress(
                             true, ViewConfiguration.getLongPressTimeout());
                 } else {
@@ -1125,7 +1120,6 @@
     @Override
     public void scrollBy(int x, int y) {
         int[] selectorIndices = mSelectorIndices;
-        int startScrollOffset = mCurrentScrollOffset;
         if (!mWrapSelectorWheel && y > 0
                 && selectorIndices[SELECTOR_MIDDLE_ITEM_INDEX] <= mMinValue) {
             mCurrentScrollOffset = mInitialScrollOffset;
@@ -1153,9 +1147,6 @@
                 mCurrentScrollOffset = mInitialScrollOffset;
             }
         }
-        if (startScrollOffset != mCurrentScrollOffset) {
-            onScrollChanged(0, mCurrentScrollOffset, 0, startScrollOffset);
-        }
     }
 
     @Override
@@ -1744,10 +1735,7 @@
         }
         int previous = mValue;
         mValue = current;
-        // If we're flinging, we'll update the text view at the end when it becomes visible
-        if (mScrollState != OnScrollListener.SCROLL_STATE_FLING) {
-            updateInputTextView();
-        }
+        updateInputTextView();
         if (notifyChange) {
             notifyChange(previous, current);
         }
@@ -1764,7 +1752,7 @@
      */
      private void changeValueByOne(boolean increment) {
         if (mHasSelectorWheel) {
-            hideSoftInput();
+            mInputText.setVisibility(View.INVISIBLE);
             if (!moveToFinalScrollerPosition(mFlingScroller)) {
                 moveToFinalScrollerPosition(mAdjustScroller);
             }
@@ -1811,8 +1799,9 @@
      */
     private void onScrollerFinished(Scroller scroller) {
         if (scroller == mFlingScroller) {
-            ensureScrollWheelAdjusted();
-            updateInputTextView();
+            if (!ensureScrollWheelAdjusted()) {
+                updateInputTextView();
+            }
             onScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
         } else {
             if (mScrollState != OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
@@ -1948,25 +1937,9 @@
          */
         String text = (mDisplayedValues == null) ? formatNumber(mValue)
                 : mDisplayedValues[mValue - mMinValue];
-        if (!TextUtils.isEmpty(text)) {
-            CharSequence beforeText = mInputText.getText();
-            if (!text.equals(beforeText.toString())) {
-                mInputText.setText(text);
-                if (mAccessibilityNodeProvider != null) {
-                    AccessibilityEvent event = AccessibilityEvent.obtain(
-                            AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
-                    mInputText.onInitializeAccessibilityEvent(event);
-                    mInputText.onPopulateAccessibilityEvent(event);
-                    event.setFromIndex(0);
-                    event.setRemovedCount(beforeText.length());
-                    event.setAddedCount(text.length());
-                    event.setBeforeText(beforeText);
-                    event.setSource(NumberPicker.this,
-                            AccessibilityNodeProviderImpl.VIRTUAL_VIEW_ID_INPUT);
-                    requestSendAccessibilityEvent(NumberPicker.this, event);
-                }
-                return true;
-            }
+        if (!TextUtils.isEmpty(text) && !text.equals(mInputText.getText().toString())) {
+            mInputText.setText(text);
+            return true;
         }
 
         return false;
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 3d54fe7..6657c3a 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -73,7 +73,7 @@
             // Do not call the TextClassifier if there is no selection.
             startActionMode(null);
         } else {
-            resetTextClassificationHelper();
+            resetTextClassificationHelper(true /* resetSelectionTag */);
             mTextClassificationAsyncTask = new TextClassificationAsyncTask(
                     mEditor.getTextView(),
                     TIMEOUT_DURATION,
@@ -92,7 +92,7 @@
             // Do not call the TextClassifier if there is no selection.
             invalidateActionMode(null);
         } else {
-            resetTextClassificationHelper();
+            resetTextClassificationHelper(false /* resetSelectionTag */);
             mTextClassificationAsyncTask = new TextClassificationAsyncTask(
                     mEditor.getTextView(), TIMEOUT_DURATION,
                     mTextClassificationHelper::classifyText, this::invalidateActionMode)
@@ -101,12 +101,12 @@
     }
 
     public void onSelectionAction() {
-        mSelectionTracker.onSelectionAction(mTextClassificationHelper.getClassifierTag());
+        mSelectionTracker.onSelectionAction(mTextClassificationHelper.getSelectionTag());
     }
 
     public boolean resetSelection(int textIndex) {
         if (mSelectionTracker.resetSelection(
-                textIndex, mEditor, mTextClassificationHelper.getClassifierTag())) {
+                textIndex, mEditor, mTextClassificationHelper.getSelectionTag())) {
             invalidateActionModeAsync();
             return true;
         }
@@ -158,7 +158,7 @@
             }
             if (result != null) {
                 mSelectionTracker.onSelectionStarted(
-                        result.mStart, result.mEnd, mTextClassificationHelper.getClassifierTag());
+                        result.mStart, result.mEnd, mTextClassificationHelper.getSelectionTag());
             }
         }
         mEditor.setRestartActionModeOnNextRefresh(false);
@@ -174,15 +174,15 @@
         final TextView textView = mEditor.getTextView();
         mSelectionTracker.onSelectionUpdated(
                 textView.getSelectionStart(), textView.getSelectionEnd(),
-                mTextClassificationHelper.getClassifierTag());
+                mTextClassificationHelper.getSelectionTag());
         mTextClassificationAsyncTask = null;
     }
 
-    private void resetTextClassificationHelper() {
+    private void resetTextClassificationHelper(boolean resetSelectionTag) {
         final TextView textView = mEditor.getTextView();
         mTextClassificationHelper.reset(textView.getTextClassifier(), textView.getText(),
                 textView.getSelectionStart(), textView.getSelectionEnd(),
-                textView.getTextLocales());
+                resetSelectionTag, textView.getTextLocales());
     }
 
     /**
@@ -195,10 +195,14 @@
         // Log event: Smart selection happened.
         private static final String LOG_EVENT_MULTI_SELECTION =
                 "textClassifier_multiSelection";
+        private static final String LOG_EVENT_SINGLE_SELECTION =
+                "textClassifier_singleSelection";
 
         // Log event: Smart selection acted upon.
         private static final String LOG_EVENT_MULTI_SELECTION_ACTION =
                 "textClassifier_multiSelection_action";
+        private static final String LOG_EVENT_SINGLE_SELECTION_ACTION =
+                "textClassifier_singleSelection_action";
 
         // Log event: Smart selection was reset to original selection.
         private static final String LOG_EVENT_MULTI_SELECTION_RESET =
@@ -207,6 +211,8 @@
         // Log event: Smart selection was user modified.
         private static final String LOG_EVENT_MULTI_SELECTION_MODIFIED =
                 "textClassifier_multiSelection_modified";
+        private static final String LOG_EVENT_SINGLE_SELECTION_MODIFIED =
+                "textClassifier_singleSelection_modified";
 
         private final TextClassifier mClassifier;
 
@@ -215,7 +221,8 @@
         private int mSelectionStart;
         private int mSelectionEnd;
 
-        private boolean mSmartSelectionActive;
+        private boolean mMultiSelection;
+        private boolean mClassifierSelection;
 
         SelectionTracker(TextClassifier classifier) {
             mClassifier = classifier;
@@ -227,23 +234,26 @@
         public void setOriginalSelection(int selectionStart, int selectionEnd) {
             mOriginalStart = selectionStart;
             mOriginalEnd = selectionEnd;
-            mSmartSelectionActive = false;
+            resetSelectionFlags();
         }
 
         /**
-         * Called when selection action mode is started.
+         * Called when selection action mode is started and the results come from a classifier.
          * If the selection indices are different from the original selection indices, we have a
          * smart selection.
          */
         public void onSelectionStarted(int selectionStart, int selectionEnd, String logTag) {
+            mClassifierSelection = !logTag.isEmpty();
             mSelectionStart = selectionStart;
             mSelectionEnd = selectionEnd;
             // If the started selection is different from the original selection, we have a
             // smart selection.
-            mSmartSelectionActive =
+            mMultiSelection =
                     mSelectionStart != mOriginalStart || mSelectionEnd != mOriginalEnd;
-            if (mSmartSelectionActive) {
+            if (mMultiSelection) {
                 mClassifier.logEvent(logTag, LOG_EVENT_MULTI_SELECTION);
+            } else if (mClassifierSelection) {
+                mClassifier.logEvent(logTag, LOG_EVENT_SINGLE_SELECTION);
             }
         }
 
@@ -254,10 +264,12 @@
             final boolean selectionChanged =
                     selectionStart != mSelectionStart || selectionEnd != mSelectionEnd;
             if (selectionChanged) {
-                if (mSmartSelectionActive) {
+                if (mMultiSelection) {
                     mClassifier.logEvent(logTag, LOG_EVENT_MULTI_SELECTION_MODIFIED);
+                } else if (mClassifierSelection) {
+                    mClassifier.logEvent(logTag, LOG_EVENT_SINGLE_SELECTION_MODIFIED);
                 }
-                mSmartSelectionActive = false;
+                resetSelectionFlags();
             }
         }
 
@@ -265,15 +277,17 @@
          * Called when the selection action mode is destroyed.
          */
         public void onSelectionDestroyed() {
-            mSmartSelectionActive = false;
+            resetSelectionFlags();
         }
 
         /**
          * Logs if the action was taken on a smart selection.
          */
         public void onSelectionAction(String logTag) {
-            if (mSmartSelectionActive) {
+            if (mMultiSelection) {
                 mClassifier.logEvent(logTag, LOG_EVENT_MULTI_SELECTION_ACTION);
+            } else if (mClassifierSelection) {
+                mClassifier.logEvent(logTag, LOG_EVENT_SINGLE_SELECTION_ACTION);
             }
         }
 
@@ -285,16 +299,21 @@
          */
         public boolean resetSelection(int textIndex, Editor editor, String logTag) {
             final CharSequence text = editor.getTextView().getText();
-            if (mSmartSelectionActive
+            if (mMultiSelection
                     && textIndex >= mSelectionStart && textIndex <= mSelectionEnd
                     && text instanceof Spannable) {
                 // Only allow a reset once.
-                mSmartSelectionActive = false;
+                resetSelectionFlags();
                 mClassifier.logEvent(logTag, LOG_EVENT_MULTI_SELECTION_RESET);
                 return editor.selectCurrentWord();
             }
             return false;
         }
+
+        private void resetSelectionFlags() {
+            mMultiSelection = false;
+            mClassifierSelection = false;
+        }
     }
 
     /**
@@ -372,7 +391,8 @@
         /** End index relative to mText. */
         private int mSelectionEnd;
         private LocaleList mLocales;
-        private String mClassifierTag = "";
+        /** A tag for the classifier that returned the latest smart selection. */
+        private String mSelectionTag = "";
 
         /** Trimmed text starting from mTrimStart in mText. */
         private CharSequence mTrimmedText;
@@ -392,12 +412,13 @@
 
         TextClassificationHelper(TextClassifier textClassifier,
                 CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
-            reset(textClassifier, text, selectionStart, selectionEnd, locales);
+            reset(textClassifier, text, selectionStart, selectionEnd, true, locales);
         }
 
         @UiThread
         public void reset(TextClassifier textClassifier,
-                CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
+                CharSequence text, int selectionStart, int selectionEnd,
+                boolean resetSelectionTag, LocaleList locales) {
             mTextClassifier = Preconditions.checkNotNull(textClassifier);
             mText = Preconditions.checkNotNull(text).toString();
             mLastClassificationText = null; // invalidate.
@@ -405,6 +426,9 @@
             mSelectionStart = selectionStart;
             mSelectionEnd = selectionEnd;
             mLocales = locales;
+            if (resetSelectionTag) {
+                mSelectionTag = "";
+            }
         }
 
         @WorkerThread
@@ -437,12 +461,12 @@
                     mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
             mSelectionStart = Math.max(0, sel.getSelectionStartIndex() + mTrimStart);
             mSelectionEnd = Math.min(mText.length(), sel.getSelectionEndIndex() + mTrimStart);
-            mClassifierTag = sel.getSourceClassifier();
+            mSelectionTag = sel.getSourceClassifier();
             return classifyText();
         }
 
-        String getClassifierTag() {
-            return mClassifierTag;
+        String getSelectionTag() {
+            return mSelectionTag;
         }
 
         private void trimText() {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 77f27d9..2f1f890 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -746,17 +746,17 @@
     // Default value for the step size in pixels.
     private static final int DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX = 1;
     // Use this to specify that any of the auto-size configuration int values have not been set.
-    private static final int UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE = -1;
+    private static final float UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE = -1f;
     // Auto-size text type.
     private int mAutoSizeTextType = AUTO_SIZE_TEXT_TYPE_NONE;
     // Specify if auto-size text is needed.
     private boolean mNeedsAutoSizeText = false;
     // Step size for auto-sizing in pixels.
-    private int mAutoSizeStepGranularityInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+    private float mAutoSizeStepGranularityInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
     // Minimum text size for auto-sizing in pixels.
-    private int mAutoSizeMinTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+    private float mAutoSizeMinTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
     // Maximum text size for auto-sizing in pixels.
-    private int mAutoSizeMaxTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+    private float mAutoSizeMaxTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
     // Contains a (specified or computed) distinct sorted set of text sizes in pixels to pick from
     // when auto-sizing text.
     private int[] mAutoSizeTextSizesInPx = EmptyArray.INT;
@@ -987,9 +987,9 @@
         CharSequence text = "";
         CharSequence hint = null;
         boolean password = false;
-        int autoSizeMinTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
-        int autoSizeMaxTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
-        int autoSizeStepGranularityInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+        float autoSizeMinTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+        float autoSizeMaxTextSizeInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
+        float autoSizeStepGranularityInPx = UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE;
         int inputType = EditorInfo.TYPE_NULL;
         a = theme.obtainStyledAttributes(
                     attrs, com.android.internal.R.styleable.TextView, defStyleAttr, defStyleRes);
@@ -1363,17 +1363,17 @@
                     break;
 
                 case com.android.internal.R.styleable.TextView_autoSizeStepGranularity:
-                    autoSizeStepGranularityInPx = a.getDimensionPixelSize(attr,
+                    autoSizeStepGranularityInPx = a.getDimension(attr,
                         UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE);
                     break;
 
                 case com.android.internal.R.styleable.TextView_autoSizeMinTextSize:
-                    autoSizeMinTextSizeInPx = a.getDimensionPixelSize(attr,
+                    autoSizeMinTextSizeInPx = a.getDimension(attr,
                         UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE);
                     break;
 
                 case com.android.internal.R.styleable.TextView_autoSizeMaxTextSize:
-                    autoSizeMaxTextSizeInPx = a.getDimensionPixelSize(attr,
+                    autoSizeMaxTextSizeInPx = a.getDimension(attr,
                         UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE);
                     break;
 
@@ -1653,6 +1653,7 @@
                                 ? (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE)
                                 : val.data;
                     }
+                    break;
 
                 case com.android.internal.R.styleable.View_clickable:
                     clickable = a.getBoolean(attr, clickable);
@@ -1691,14 +1692,14 @@
                     final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
 
                     if (autoSizeMinTextSizeInPx == UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE) {
-                        autoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
+                        autoSizeMinTextSizeInPx = TypedValue.applyDimension(
                                 TypedValue.COMPLEX_UNIT_SP,
                                 DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP,
                                 displayMetrics);
                     }
 
                     if (autoSizeMaxTextSizeInPx == UNSET_AUTO_SIZE_UNIFORM_CONFIGURATION_VALUE) {
-                        autoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
+                        autoSizeMaxTextSizeInPx = TypedValue.applyDimension(
                                 TypedValue.COMPLEX_UNIT_SP,
                                 DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP,
                                 displayMetrics);
@@ -1743,11 +1744,11 @@
                     break;
                 case AUTO_SIZE_TEXT_TYPE_UNIFORM:
                     final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
-                    final int autoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
+                    final float autoSizeMinTextSizeInPx = TypedValue.applyDimension(
                             TypedValue.COMPLEX_UNIT_SP,
                             DEFAULT_AUTO_SIZE_MIN_TEXT_SIZE_IN_SP,
                             displayMetrics);
-                    final int autoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
+                    final float autoSizeMaxTextSizeInPx = TypedValue.applyDimension(
                             TypedValue.COMPLEX_UNIT_SP,
                             DEFAULT_AUTO_SIZE_MAX_TEXT_SIZE_IN_SP,
                             displayMetrics);
@@ -1796,11 +1797,11 @@
             int autoSizeMaxTextSize, int autoSizeStepGranularity, int unit) {
         if (supportsAutoSizeText()) {
             final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
-            final int autoSizeMinTextSizeInPx = (int) TypedValue.applyDimension(
+            final float autoSizeMinTextSizeInPx = TypedValue.applyDimension(
                     unit, autoSizeMinTextSize, displayMetrics);
-            final int autoSizeMaxTextSizeInPx = (int) TypedValue.applyDimension(
+            final float autoSizeMaxTextSizeInPx = TypedValue.applyDimension(
                     unit, autoSizeMaxTextSize, displayMetrics);
-            final int autoSizeStepGranularityInPx = (int) TypedValue.applyDimension(
+            final float autoSizeStepGranularityInPx = TypedValue.applyDimension(
                     unit, autoSizeStepGranularity, displayMetrics);
 
             validateAndSetAutoSizeTextTypeUniformConfiguration(autoSizeMinTextSizeInPx,
@@ -1842,8 +1843,8 @@
                     final DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
                     // Convert all to sizes to pixels.
                     for (int i = 0; i < presetSizesLength; i++) {
-                        presetSizesInPx[i] = (int) TypedValue.applyDimension(unit, presetSizes[i],
-                            displayMetrics);
+                        presetSizesInPx[i] = Math.round(TypedValue.applyDimension(unit,
+                            presetSizes[i], displayMetrics));
                     }
                 }
 
@@ -1885,7 +1886,7 @@
      * @see #setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int)
      */
     public int getAutoSizeStepGranularity() {
-        return mAutoSizeStepGranularityInPx;
+        return Math.round(mAutoSizeStepGranularityInPx);
     }
 
     /**
@@ -1898,7 +1899,7 @@
      * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int)
      */
     public int getAutoSizeMinTextSize() {
-        return mAutoSizeMinTextSizeInPx;
+        return Math.round(mAutoSizeMinTextSizeInPx);
     }
 
     /**
@@ -1911,7 +1912,7 @@
      * @see #setAutoSizeTextTypeUniformWithPresetSizes(int[], int)
      */
     public int getAutoSizeMaxTextSize() {
-        return mAutoSizeMaxTextSizeInPx;
+        return Math.round(mAutoSizeMaxTextSizeInPx);
     }
 
     /**
@@ -1954,8 +1955,8 @@
      *
      * @throws IllegalArgumentException if any of the params are invalid
      */
-    private void validateAndSetAutoSizeTextTypeUniformConfiguration(int autoSizeMinTextSizeInPx,
-            int autoSizeMaxTextSizeInPx, int autoSizeStepGranularityInPx) {
+    private void validateAndSetAutoSizeTextTypeUniformConfiguration(float autoSizeMinTextSizeInPx,
+            float autoSizeMaxTextSizeInPx, float autoSizeStepGranularityInPx) {
         // First validate.
         if (autoSizeMinTextSizeInPx <= 0) {
             throw new IllegalArgumentException("Minimum auto-size text size ("
@@ -2021,18 +2022,19 @@
                 // Calculate sizes to choose from based on the current auto-size configuration.
                 int autoSizeValuesLength = (int) Math.ceil(
                         (mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
-                                / (float) mAutoSizeStepGranularityInPx);
+                                / mAutoSizeStepGranularityInPx);
                 // Also reserve a slot for the max size if it fits.
                 if ((mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
                         % mAutoSizeStepGranularityInPx == 0) {
                     autoSizeValuesLength++;
                 }
-                mAutoSizeTextSizesInPx = new int[autoSizeValuesLength];
-                int sizeToAdd = mAutoSizeMinTextSizeInPx;
+                int[] autoSizeTextSizesInPx = new int[autoSizeValuesLength];
+                float sizeToAdd = mAutoSizeMinTextSizeInPx;
                 for (int i = 0; i < autoSizeValuesLength; i++) {
-                    mAutoSizeTextSizesInPx[i] = sizeToAdd;
+                    autoSizeTextSizesInPx[i] = Math.round(sizeToAdd);
                     sizeToAdd += mAutoSizeStepGranularityInPx;
                 }
+                mAutoSizeTextSizesInPx = cleanupAutoSizePresetSizes(autoSizeTextSizesInPx);
             }
 
             mNeedsAutoSizeText = true;
@@ -11227,8 +11229,10 @@
                 return true;
 
             case DragEvent.ACTION_DRAG_LOCATION:
-                final int offset = getOffsetForPosition(event.getX(), event.getY());
-                Selection.setSelection((Spannable) mText, offset);
+                if (mText instanceof Spannable) {
+                    final int offset = getOffsetForPosition(event.getX(), event.getY());
+                    Selection.setSelection((Spannable) mText, offset);
+                }
                 return true;
 
             case DragEvent.ACTION_DROP:
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 05d0f96..d3c83ee 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -137,6 +137,7 @@
         final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
                 R.layout.time_picker_material);
         final View mainView = inflater.inflate(layoutResourceId, delegator);
+        mainView.setSaveFromParentEnabled(false);
         mRadialTimePickerHeader = mainView.findViewById(R.id.time_header);
         mRadialTimePickerHeader.setOnTouchListener(new NearestTouchDelegate());
 
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index 813c30e3..7a7d9a9 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -83,7 +83,8 @@
         a.recycle();
 
         final LayoutInflater inflater = LayoutInflater.from(mContext);
-        inflater.inflate(layoutResourceId, mDelegator, true);
+        final View view = inflater.inflate(layoutResourceId, mDelegator, true);
+        view.setSaveFromParentEnabled(false);
 
         // hour
         mHourSpinner = delegator.findViewById(R.id.hour);
diff --git a/core/java/com/android/internal/notification/SystemNotificationChannels.java b/core/java/com/android/internal/notification/SystemNotificationChannels.java
index d279746..797cf2b 100644
--- a/core/java/com/android/internal/notification/SystemNotificationChannels.java
+++ b/core/java/com/android/internal/notification/SystemNotificationChannels.java
@@ -47,7 +47,6 @@
     public static String RETAIL_MODE = "RETAIL_MODE";
     public static String USB = "USB";
     public static String FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
-    public static String ALERT_WINDOW = "ALERT_WINDOW";
 
     public static void createAll(Context context) {
         final NotificationManager nm = context.getSystemService(NotificationManager.class);
@@ -138,11 +137,6 @@
                 context.getString(R.string.notification_channel_foreground_service),
                 NotificationManager.IMPORTANCE_MIN));
 
-        channelsList.add(new NotificationChannel(
-                ALERT_WINDOW,
-                context.getString(R.string.alert_windows_notification_channel_name),
-                NotificationManager.IMPORTANCE_MIN));
-
         nm.createNotificationChannels(channelsList);
     }
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b9d3a30..17ef77c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -116,7 +116,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 157 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 158 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -185,7 +185,7 @@
             switch (msg.what) {
                 case MSG_UPDATE_WAKELOCKS:
                     synchronized (BatteryStatsImpl.this) {
-                        updateCpuTimeLocked();
+                        updateCpuTimeLocked(false /* updateCpuFreqData */);
                     }
                     if (cb != null) {
                         cb.batteryNeedsCpuUpdate();
@@ -967,14 +967,15 @@
         }
     }
 
+    @VisibleForTesting
     public static class LongSamplingCounterArray extends LongCounterArray implements TimeBaseObs {
         final TimeBase mTimeBase;
-        long[] mCounts;
-        long[] mLoadedCounts;
-        long[] mUnpluggedCounts;
-        long[] mPluggedCounts;
+        public long[] mCounts;
+        public long[] mLoadedCounts;
+        public long[] mUnpluggedCounts;
+        public long[] mPluggedCounts;
 
-        LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
+        private LongSamplingCounterArray(TimeBase timeBase, Parcel in) {
             mTimeBase = timeBase;
             mPluggedCounts = in.createLongArray();
             mCounts = copyArray(mPluggedCounts, mCounts);
@@ -983,12 +984,12 @@
             timeBase.add(this);
         }
 
-        LongSamplingCounterArray(TimeBase timeBase) {
+        public LongSamplingCounterArray(TimeBase timeBase) {
             mTimeBase = timeBase;
             timeBase.add(this);
         }
 
-        public void writeToParcel(Parcel out) {
+        private void writeToParcel(Parcel out) {
             out.writeLongArray(mCounts);
             out.writeLongArray(mLoadedCounts);
             out.writeLongArray(mUnpluggedCounts);
@@ -1024,7 +1025,7 @@
                     + " mPluggedCounts=" + Arrays.toString(mPluggedCounts));
         }
 
-        void addCountLocked(long[] counts) {
+        public void addCountLocked(long[] counts) {
             if (counts == null) {
                 return;
             }
@@ -1039,7 +1040,7 @@
         /**
          * Clear state of this counter.
          */
-        void reset(boolean detachIfReset) {
+        public void reset(boolean detachIfReset) {
             fillArray(mCounts, 0);
             fillArray(mLoadedCounts, 0);
             fillArray(mPluggedCounts, 0);
@@ -1049,21 +1050,60 @@
             }
         }
 
-        void detach() {
+        public void detach() {
             mTimeBase.remove(this);
         }
 
-        void writeSummaryFromParcelLocked(Parcel out) {
+        private void writeSummaryToParcelLocked(Parcel out) {
             out.writeLongArray(mCounts);
         }
 
-        void readSummaryFromParcelLocked(Parcel in) {
+        private void readSummaryFromParcelLocked(Parcel in) {
             mCounts = in.createLongArray();
             mLoadedCounts = copyArray(mCounts, mLoadedCounts);
             mUnpluggedCounts = copyArray(mCounts, mUnpluggedCounts);
             mPluggedCounts = copyArray(mCounts, mPluggedCounts);
         }
 
+        public static void writeToParcel(Parcel out, LongSamplingCounterArray counterArray) {
+            if (counterArray != null) {
+                out.writeInt(1);
+                counterArray.writeToParcel(out);
+            } else {
+                out.writeInt(0);
+            }
+        }
+
+        public static LongSamplingCounterArray readFromParcel(Parcel in, TimeBase timeBase) {
+            if (in.readInt() != 0) {
+                return new LongSamplingCounterArray(timeBase, in);
+            } else {
+                return null;
+            }
+        }
+
+        public static void writeSummaryToParcelLocked(Parcel out,
+                LongSamplingCounterArray counterArray) {
+            if (counterArray != null) {
+                out.writeInt(1);
+                counterArray.writeSummaryToParcelLocked(out);
+            } else {
+                out.writeInt(0);
+            }
+        }
+
+        public static LongSamplingCounterArray readSummaryFromParcelLocked(Parcel in,
+                TimeBase timeBase) {
+            if (in.readInt() != 0) {
+                final LongSamplingCounterArray counterArray
+                        = new LongSamplingCounterArray(timeBase);
+                counterArray.readSummaryFromParcelLocked(in);
+                return counterArray;
+            } else {
+                return null;
+            }
+        }
+
         private void fillArray(long[] a, long val) {
             if (a != null) {
                 Arrays.fill(a, val);
@@ -3427,8 +3467,8 @@
         boolean batteryStatusChanged = mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime);
 
         if (batteryStatusChanged) {
-            for (int i=0; i<mUidStats.size(); i++) {
-                mUidStats.valueAt(i).updateBgTimeBase(uptime, realtime);
+            for (int i = 0; i < mUidStats.size(); i++) {
+                mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime);
             }
         }
 
@@ -3440,8 +3480,11 @@
                 Slog.d(TAG, "Updating cpu time because screen is now " +
                         (unpluggedScreenOff ? "off" : "on"));
             }
-            updateCpuTimeLocked();
+            updateCpuTimeLocked(true /* updateCpuFreqData */);
             mOnBatteryScreenOffTimeBase.setRunning(unpluggedScreenOff, uptime, realtime);
+            for (int i = 0; i < mUidStats.size(); i++) {
+                mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime);
+            }
         }
     }
 
@@ -5541,6 +5584,8 @@
         /** TimeBase for when uid is in background and device is on battery. */
         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
         public final TimeBase mOnBatteryBackgroundTimeBase;
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+        public final TimeBase mOnBatteryScreenOffBackgroundTimeBase;
 
         boolean mWifiRunning;
         StopwatchTimer mWifiRunningTimer;
@@ -5563,6 +5608,8 @@
         StopwatchTimer mFlashlightTurnedOnTimer;
         StopwatchTimer mCameraTurnedOnTimer;
         StopwatchTimer mForegroundActivityTimer;
+        /** Total time spent by the uid holding any partial wakelocks. */
+        DualTimer mAggregatedPartialWakelockTimer;
         DualTimer mBluetoothScanTimer;
         Counter mBluetoothScanResultCounter;
 
@@ -5664,6 +5711,10 @@
             mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
                     mBsi.mClocks.elapsedRealtime() * 1000);
 
+            mOnBatteryScreenOffBackgroundTimeBase = new TimeBase();
+            mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000,
+                    mBsi.mClocks.elapsedRealtime() * 1000);
+
             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
 
@@ -5734,6 +5785,11 @@
         }
 
         @Override
+        public Timer getAggregatedPartialWakelockTimer() {
+            return mAggregatedPartialWakelockTimer;
+        }
+
+        @Override
         public ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> getWakelockStats() {
             return mWakelockStats.getMap();
         }
@@ -6022,6 +6078,15 @@
             return mForegroundActivityTimer;
         }
 
+        public DualTimer createAggregatedPartialWakelockTimerLocked() {
+            if (mAggregatedPartialWakelockTimer == null) {
+                mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
+                        AGGREGATED_WAKE_TYPE_PARTIAL, null,
+                        mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase);
+            }
+            return mAggregatedPartialWakelockTimer;
+        }
+
         public DualTimer createBluetoothScanTimerLocked() {
             if (mBluetoothScanTimer == null) {
                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
@@ -6464,6 +6529,7 @@
             active |= !resetTimerIfNotNull(mFlashlightTurnedOnTimer, false);
             active |= !resetTimerIfNotNull(mCameraTurnedOnTimer, false);
             active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
+            active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
             active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
             if (mBluetoothScanResultCounter != null) {
                 mBluetoothScanResultCounter.reset(false);
@@ -6616,6 +6682,8 @@
 
             mOnBatteryBackgroundTimeBase.reset(mBsi.mClocks.elapsedRealtime() * 1000,
                     mBsi.mClocks.uptimeMillis() * 1000);
+            mOnBatteryScreenOffBackgroundTimeBase.reset(mBsi.mClocks.elapsedRealtime() * 1000,
+                    mBsi.mClocks.uptimeMillis() * 1000);
 
             if (!active) {
                 if (mWifiRunningTimer != null) {
@@ -6655,6 +6723,10 @@
                     mForegroundActivityTimer.detach();
                     mForegroundActivityTimer = null;
                 }
+                if (mAggregatedPartialWakelockTimer != null) {
+                    mAggregatedPartialWakelockTimer.detach();
+                    mAggregatedPartialWakelockTimer = null;
+                }
                 if (mBluetoothScanTimer != null) {
                     mBluetoothScanTimer.detach();
                     mBluetoothScanTimer = null;
@@ -6720,6 +6792,7 @@
 
         void writeToParcelLocked(Parcel out, long uptimeUs, long elapsedRealtimeUs) {
             mOnBatteryBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
+            mOnBatteryScreenOffBackgroundTimeBase.writeToParcel(out, uptimeUs, elapsedRealtimeUs);
 
             final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap();
             int NW = wakeStats.size();
@@ -6834,6 +6907,12 @@
             } else {
                 out.writeInt(0);
             }
+            if (mAggregatedPartialWakelockTimer != null) {
+                out.writeInt(1);
+                mAggregatedPartialWakelockTimer.writeToParcel(out, elapsedRealtimeUs);
+            } else {
+                out.writeInt(0);
+            }
             if (mBluetoothScanTimer != null) {
                 out.writeInt(1);
                 mBluetoothScanTimer.writeToParcel(out, elapsedRealtimeUs);
@@ -6927,18 +7006,8 @@
                 out.writeInt(0);
             }
 
-            if (mCpuFreqTimeMs != null) {
-                out.writeInt(1);
-                mCpuFreqTimeMs.writeToParcel(out);
-            } else {
-                out.writeInt(0);
-            }
-            if (mScreenOffCpuFreqTimeMs != null) {
-                out.writeInt(1);
-                mScreenOffCpuFreqTimeMs.writeToParcel(out);
-            } else {
-                out.writeInt(0);
-            }
+            LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
+            LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
 
             if (mMobileRadioApWakeupCount != null) {
                 out.writeInt(1);
@@ -6957,6 +7026,7 @@
 
         void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
             mOnBatteryBackgroundTimeBase.readFromParcel(in);
+            mOnBatteryScreenOffBackgroundTimeBase.readFromParcel(in);
 
             int numWakelocks = in.readInt();
             mWakelockStats.clear();
@@ -7083,6 +7153,14 @@
                 mForegroundActivityTimer = null;
             }
             if (in.readInt() != 0) {
+                mAggregatedPartialWakelockTimer = new DualTimer(mBsi.mClocks, this,
+                        AGGREGATED_WAKE_TYPE_PARTIAL, null,
+                        mBsi.mOnBatteryScreenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase,
+                        in);
+            } else {
+                mAggregatedPartialWakelockTimer = null;
+            }
+            if (in.readInt() != 0) {
                 mBluetoothScanTimer = new DualTimer(mBsi.mClocks, Uid.this, BLUETOOTH_SCAN_ON,
                         mBsi.mBluetoothScanOnTimers, mBsi.mOnBatteryTimeBase,
                         mOnBatteryBackgroundTimeBase, in);
@@ -7187,17 +7265,9 @@
                 mCpuClusterSpeed = null;
             }
 
-            if (in.readInt() != 0) {
-                mCpuFreqTimeMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
-            } else {
-                mCpuFreqTimeMs = null;
-            }
-            if (in.readInt() != 0) {
-                mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
-                        mBsi.mOnBatteryScreenOffTimeBase, in);
-            } else {
-                mScreenOffCpuFreqTimeMs = null;
-            }
+            mCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(in, mBsi.mOnBatteryTimeBase);
+            mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
+                    in, mBsi.mOnBatteryScreenOffTimeBase);
 
             if (in.readInt() != 0) {
                 mMobileRadioApWakeupCount = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
@@ -8202,15 +8272,25 @@
                 mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtimeMs);
             }
 
-            updateBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
+            updateOnBatteryBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
+            updateOnBatteryScreenOffBgTimeBase(uptimeMs * 1000, elapsedRealtimeMs * 1000);
         }
 
-        public boolean updateBgTimeBase(long uptimeUs, long realtimeUs) {
+        /** Whether to consider Uid to be in the background for background timebase purposes. */
+        public boolean isInBackground() {
             // Note that PROCESS_STATE_CACHED and ActivityManager.PROCESS_STATE_NONEXISTENT is
             // also considered to be 'background' for our purposes, because it's not foreground.
-            boolean isBgAndUnplugged = mBsi.mOnBatteryTimeBase.isRunning()
-                    && mProcessState >= PROCESS_STATE_BACKGROUND;
-            return mOnBatteryBackgroundTimeBase.setRunning(isBgAndUnplugged, uptimeUs, realtimeUs);
+            return mProcessState >= PROCESS_STATE_BACKGROUND;
+        }
+
+        public boolean updateOnBatteryBgTimeBase(long uptimeUs, long realtimeUs) {
+            boolean on = mBsi.mOnBatteryTimeBase.isRunning() && isInBackground();
+            return mOnBatteryBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
+        }
+
+        public boolean updateOnBatteryScreenOffBgTimeBase(long uptimeUs, long realtimeUs) {
+            boolean on = mBsi.mOnBatteryScreenOffTimeBase.isRunning() && isInBackground();
+            return mOnBatteryScreenOffBackgroundTimeBase.setRunning(on, uptimeUs, realtimeUs);
         }
 
         public SparseArray<? extends Pid> getPidStats() {
@@ -8341,10 +8421,13 @@
             if (wl != null) {
                 wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs);
             }
-            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
-                Pid p = getPidStatsLocked(pid);
-                if (p.mWakeNesting++ == 0) {
-                    p.mWakeStartMs = elapsedRealtimeMs;
+            if (type == WAKE_TYPE_PARTIAL) {
+                createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
+                if (pid >= 0) {
+                    Pid p = getPidStatsLocked(pid);
+                    if (p.mWakeNesting++ == 0) {
+                        p.mWakeStartMs = elapsedRealtimeMs;
+                    }
                 }
             }
         }
@@ -8354,12 +8437,17 @@
             if (wl != null) {
                 wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs);
             }
-            if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
-                Pid p = mPids.get(pid);
-                if (p != null && p.mWakeNesting > 0) {
-                    if (p.mWakeNesting-- == 1) {
-                        p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
-                        p.mWakeStartMs = 0;
+            if (type == WAKE_TYPE_PARTIAL) {
+                if (mAggregatedPartialWakelockTimer != null) {
+                    mAggregatedPartialWakelockTimer.stopRunningLocked(elapsedRealtimeMs);
+                }
+                if (pid >= 0) {
+                    Pid p = mPids.get(pid);
+                    if (p != null && p.mWakeNesting > 0) {
+                        if (p.mWakeNesting-- == 1) {
+                            p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
+                            p.mWakeStartMs = 0;
+                        }
                     }
                 }
             }
@@ -9914,7 +10002,7 @@
      * and we are on battery with screen off, we give more of the cpu time to those apps holding
      * wakelocks. If the screen is on, we just assign the actual cpu time an app used.
      */
-    public void updateCpuTimeLocked() {
+    public void updateCpuTimeLocked(boolean updateCpuFreqData) {
         if (mPowerProfile == null) {
             return;
         }
@@ -10029,7 +10117,9 @@
                     }
                 });
 
-        readKernelUidCpuFreqTimesLocked();
+        if (updateCpuFreqData) {
+            readKernelUidCpuFreqTimesLocked();
+        }
 
         final long elapse = (mClocks.elapsedRealtime() - startTimeMs);
         if (DEBUG_ENERGY_CPU || (elapse >= 100)) {
@@ -11243,6 +11333,7 @@
             mUidStats.put(uid, u);
 
             u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in);
+            u.mOnBatteryScreenOffBackgroundTimeBase.readSummaryFromParcel(in);
 
             u.mWifiRunning = false;
             if (in.readInt() != 0) {
@@ -11283,6 +11374,9 @@
                 u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
             }
             if (in.readInt() != 0) {
+                u.createAggregatedPartialWakelockTimerLocked().readSummaryFromParcelLocked(in);
+            }
+            if (in.readInt() != 0) {
                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
             }
             if (in.readInt() != 0) {
@@ -11355,19 +11449,10 @@
                 u.mCpuClusterSpeed = null;
             }
 
-            if (in.readInt() != 0) {
-                u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
-                u.mCpuFreqTimeMs.readSummaryFromParcelLocked(in);
-            } else {
-                u.mCpuFreqTimeMs = null;
-            }
-            if (in.readInt() != 0) {
-                u.mScreenOffCpuFreqTimeMs = new LongSamplingCounterArray(
-                        mOnBatteryScreenOffTimeBase);
-                u.mScreenOffCpuFreqTimeMs.readSummaryFromParcelLocked(in);
-            } else {
-                u.mScreenOffCpuFreqTimeMs = null;
-            }
+            u.mCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
+                    in, mOnBatteryTimeBase);
+            u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
+                    in, mOnBatteryScreenOffTimeBase);
 
             if (in.readInt() != 0) {
                 u.mMobileRadioApWakeupCount = new LongSamplingCounter(mOnBatteryTimeBase);
@@ -11628,6 +11713,7 @@
             Uid u = mUidStats.valueAt(iu);
 
             u.mOnBatteryBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
+            u.mOnBatteryScreenOffBackgroundTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
 
             if (u.mWifiRunningTimer != null) {
                 out.writeInt(1);
@@ -11691,6 +11777,12 @@
             } else {
                 out.writeInt(0);
             }
+            if (u.mAggregatedPartialWakelockTimer != null) {
+                out.writeInt(1);
+                u.mAggregatedPartialWakelockTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+            } else {
+                out.writeInt(0);
+            }
             if (u.mBluetoothScanTimer != null) {
                 out.writeInt(1);
                 u.mBluetoothScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -11765,18 +11857,8 @@
                 out.writeInt(0);
             }
 
-            if (u.mCpuFreqTimeMs != null) {
-                out.writeInt(1);
-                u.mCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
-            } else {
-                out.writeInt(0);
-            }
-            if (u.mScreenOffCpuFreqTimeMs != null) {
-                out.writeInt(1);
-                u.mScreenOffCpuFreqTimeMs.writeSummaryFromParcelLocked(out);
-            } else {
-                out.writeInt(0);
-            }
+            LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
+            LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
 
             if (u.mMobileRadioApWakeupCount != null) {
                 out.writeInt(1);
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index a9bec41..2013ac0 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -762,14 +762,6 @@
     public static void applyInvokeWithSystemProperty(Arguments args) {
         if (args.invokeWith == null && args.niceName != null) {
             String property = "wrap." + args.niceName;
-            if (property.length() > 31) {
-                // Properties with a trailing "." are illegal.
-                if (property.charAt(30) != '.') {
-                    property = property.substring(0, 31);
-                } else {
-                    property = property.substring(0, 30);
-                }
-            }
             args.invokeWith = SystemProperties.get(property);
             if (args.invokeWith != null && args.invokeWith.length() == 0) {
                 args.invokeWith = null;
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 1b83708..ba3aa36 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -296,7 +296,11 @@
     @Override
     public void onDraw(Canvas c) {
         super.onDraw(c);
-        mBackgroundFallback.draw(mContentRoot, c, mWindow.mContentParent);
+
+        // When we are resizing, we need the fallback background to cover the area where we have our
+        // system bar background views as the navigation bar will be hidden during resizing.
+        mBackgroundFallback.draw(isResizing() ? this : mContentRoot, mContentRoot, c,
+                mWindow.mContentParent);
     }
 
     @Override
@@ -1755,8 +1759,9 @@
             mFloatingActionMode.finish();
         }
         cleanupFloatingActionModeViews();
+        mFloatingToolbar = new FloatingToolbar(mContext, mWindow);
         final FloatingActionMode mode =
-                new FloatingActionMode(mContext, callback, originatingView);
+                new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar);
         mFloatingActionModeOriginatingView = originatingView;
         mFloatingToolbarPreDrawListener =
             new ViewTreeObserver.OnPreDrawListener() {
@@ -1771,8 +1776,6 @@
 
     private void setHandledFloatingActionMode(ActionMode mode) {
         mFloatingActionMode = mode;
-        mFloatingToolbar = new FloatingToolbar(mContext, mWindow);
-        ((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
         mFloatingActionMode.invalidate();  // Will show the floating toolbar if necessary.
         mFloatingActionModeOriginatingView.getViewTreeObserver()
             .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index effe219..ff211b6 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.view;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -36,26 +37,26 @@
 
 import java.util.Arrays;
 
-public class FloatingActionMode extends ActionMode {
+public final class FloatingActionMode extends ActionMode {
 
     private static final int MAX_HIDE_DURATION = 3000;
     private static final int MOVING_HIDE_DELAY = 50;
 
-    private final Context mContext;
-    private final ActionMode.Callback2 mCallback;
-    private final MenuBuilder mMenu;
-    private final Rect mContentRect;
-    private final Rect mContentRectOnScreen;
-    private final Rect mPreviousContentRectOnScreen;
-    private final int[] mViewPositionOnScreen;
-    private final int[] mPreviousViewPositionOnScreen;
-    private final int[] mRootViewPositionOnScreen;
-    private final Rect mViewRectOnScreen;
-    private final Rect mPreviousViewRectOnScreen;
-    private final Rect mScreenRect;
-    private final View mOriginatingView;
+    @NonNull private final Context mContext;
+    @NonNull private final ActionMode.Callback2 mCallback;
+    @NonNull private final MenuBuilder mMenu;
+    @NonNull private final Rect mContentRect;
+    @NonNull private final Rect mContentRectOnScreen;
+    @NonNull private final Rect mPreviousContentRectOnScreen;
+    @NonNull private final int[] mViewPositionOnScreen;
+    @NonNull private final int[] mPreviousViewPositionOnScreen;
+    @NonNull private final int[] mRootViewPositionOnScreen;
+    @NonNull private final Rect mViewRectOnScreen;
+    @NonNull private final Rect mPreviousViewRectOnScreen;
+    @NonNull private final Rect mScreenRect;
+    @NonNull private final View mOriginatingView;
+    @NonNull private final Point mDisplaySize;
     private final int mBottomAllowance;
-    private final Point mDisplaySize;
 
     private final Runnable mMovingOff = new Runnable() {
         public void run() {
@@ -75,11 +76,12 @@
         }
     };
 
-    private FloatingToolbar mFloatingToolbar;
-    private FloatingToolbarVisibilityHelper mFloatingToolbarVisibilityHelper;
+    @NonNull private FloatingToolbar mFloatingToolbar;
+    @NonNull private FloatingToolbarVisibilityHelper mFloatingToolbarVisibilityHelper;
 
     public FloatingActionMode(
-            Context context, ActionMode.Callback2 callback, View originatingView) {
+            Context context, ActionMode.Callback2 callback,
+            View originatingView, FloatingToolbar floatingToolbar) {
         mContext = Preconditions.checkNotNull(context);
         mCallback = Preconditions.checkNotNull(callback);
         mMenu = new MenuBuilder(context).setDefaultShowAsAction(
@@ -110,17 +112,13 @@
         mBottomAllowance = context.getResources()
                 .getDimensionPixelSize(R.dimen.content_rect_bottom_clip_allowance);
         mDisplaySize = new Point();
+        setFloatingToolbar(Preconditions.checkNotNull(floatingToolbar));
     }
 
-    public void setFloatingToolbar(FloatingToolbar floatingToolbar) {
+    private void setFloatingToolbar(FloatingToolbar floatingToolbar) {
         mFloatingToolbar = floatingToolbar
                 .setMenu(mMenu)
-                .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
-                        @Override
-                    public boolean onMenuItemClick(MenuItem item) {
-                        return mMenu.performItemAction(item, 0);
-                    }
-                });
+                .setOnMenuItemClickListener(item -> mMenu.performItemAction(item, 0));
         mFloatingToolbarVisibilityHelper = new FloatingToolbarVisibilityHelper(mFloatingToolbar);
         mFloatingToolbarVisibilityHelper.activate();
     }
@@ -142,21 +140,17 @@
 
     @Override
     public void invalidate() {
-        checkToolbarInitialized();
         mCallback.onPrepareActionMode(this, mMenu);
         invalidateContentRect();  // Will re-layout and show the toolbar if necessary.
     }
 
     @Override
     public void invalidateContentRect() {
-        checkToolbarInitialized();
         mCallback.onGetContentRect(this, mOriginatingView, mContentRect);
         repositionToolbar();
     }
 
     public void updateViewLocationInWindow() {
-        checkToolbarInitialized();
-
         mOriginatingView.getLocationOnScreen(mViewPositionOnScreen);
         mOriginatingView.getRootView().getLocationOnScreen(mRootViewPositionOnScreen);
         mOriginatingView.getGlobalVisibleRect(mViewRectOnScreen);
@@ -172,8 +166,6 @@
     }
 
     private void repositionToolbar() {
-        checkToolbarInitialized();
-
         mContentRectOnScreen.set(mContentRect);
 
         // Offset the content rect into screen coordinates, taking into account any transformations
@@ -235,8 +227,6 @@
 
     @Override
     public void hide(long duration) {
-        checkToolbarInitialized();
-
         if (duration == ActionMode.DEFAULT_HIDE_DURATION) {
             duration = ViewConfiguration.getDefaultActionModeHideDuration();
         }
@@ -253,14 +243,12 @@
 
     @Override
     public void onWindowFocusChanged(boolean hasWindowFocus) {
-        checkToolbarInitialized();
         mFloatingToolbarVisibilityHelper.setWindowFocused(hasWindowFocus);
         mFloatingToolbarVisibilityHelper.updateToolbarVisibility();
     }
 
     @Override
     public void finish() {
-        checkToolbarInitialized();
         reset();
         mCallback.onDestroyActionMode(this);
     }
@@ -290,14 +278,6 @@
         return new MenuInflater(mContext);
     }
 
-    /**
-     * @throws IllegalStateException
-     */
-    private void checkToolbarInitialized() {
-        Preconditions.checkState(mFloatingToolbar != null);
-        Preconditions.checkState(mFloatingToolbarVisibilityHelper != null);
-    }
-
     private void reset() {
         mFloatingToolbar.dismiss();
         mFloatingToolbarVisibilityHelper.deactivate();
diff --git a/core/java/com/android/internal/widget/BackgroundFallback.java b/core/java/com/android/internal/widget/BackgroundFallback.java
index 4adba4d..309f80c 100644
--- a/core/java/com/android/internal/widget/BackgroundFallback.java
+++ b/core/java/com/android/internal/widget/BackgroundFallback.java
@@ -39,14 +39,22 @@
         return mBackgroundFallback != null;
     }
 
-    public void draw(ViewGroup root, Canvas c, View content) {
+    /**
+     * Draws the fallback background.
+     *
+     * @param boundsView The view determining with which bounds the background should be drawn.
+     * @param root The view group containing the content.
+     * @param c The canvas to draw the background onto.
+     * @param content The view where the actual app content is contained in.
+     */
+    public void draw(ViewGroup boundsView, ViewGroup root, Canvas c, View content) {
         if (!hasFallback()) {
             return;
         }
 
         // Draw the fallback in the padding.
-        final int width = root.getWidth();
-        final int height = root.getHeight();
+        final int width = boundsView.getWidth();
+        final int height = boundsView.getHeight();
         int left = width;
         int top = height;
         int right = 0;
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 8c71cf7..40796e1 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -52,7 +52,6 @@
 import android.view.animation.Transformation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
-import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.ImageButton;
 import android.widget.ImageView;
@@ -67,6 +66,7 @@
 
 import com.android.internal.R;
 import com.android.internal.util.Preconditions;
+import java.util.Objects;
 
 /**
  * A floating toolbar for showing contextual menu items.
@@ -82,12 +82,7 @@
     public static final String FLOATING_TOOLBAR_TAG = "floating_toolbar";
 
     private static final MenuItem.OnMenuItemClickListener NO_OP_MENUITEM_CLICK_LISTENER =
-            new MenuItem.OnMenuItemClickListener() {
-                @Override
-                public boolean onMenuItemClick(MenuItem item) {
-                    return false;
-                }
-            };
+            item -> false;
 
     private final Context mContext;
     private final Window mWindow;
@@ -97,7 +92,7 @@
     private final Rect mPreviousContentRect = new Rect();
 
     private Menu mMenu;
-    private List<Object> mShowingMenuItems = new ArrayList<Object>();
+    private List<MenuItem> mShowingMenuItems = new ArrayList<>();
     private MenuItem.OnMenuItemClickListener mMenuItemClickListener = NO_OP_MENUITEM_CLICK_LISTENER;
 
     private int mSuggestedWidth;
@@ -237,7 +232,7 @@
         if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
             mPopup.dismiss();
             mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
-            mShowingMenuItems = getShowingMenuItemsReferences(menuItems);
+            mShowingMenuItems = menuItems;
         }
         if (!mPopup.isShowing()) {
             mPopup.show(mContentRect);
@@ -252,7 +247,23 @@
      * Returns true if this floating toolbar is currently showing the specified menu items.
      */
     private boolean isCurrentlyShowing(List<MenuItem> menuItems) {
-        return mShowingMenuItems.equals(getShowingMenuItemsReferences(menuItems));
+        if (mShowingMenuItems == null || menuItems.size() != mShowingMenuItems.size()) {
+            return false;
+        }
+
+        final int size = menuItems.size();
+        for (int i = 0; i < size; i++) {
+            final MenuItem menuItem = menuItems.get(i);
+            final MenuItem showingItem = mShowingMenuItems.get(i);
+            if (menuItem.getItemId() != showingItem.getItemId()
+                    || !TextUtils.equals(menuItem.getTitle(), showingItem.getTitle())
+                    || !Objects.equals(menuItem.getIcon(), showingItem.getIcon())
+                    || menuItem.getGroupId() != showingItem.getGroupId()) {
+                return false;
+            }
+        }
+
+        return true;
     }
 
     /**
@@ -260,7 +271,7 @@
      * This method is recursive.
      */
     private List<MenuItem> getVisibleAndEnabledMenuItems(Menu menu) {
-        List<MenuItem> menuItems = new ArrayList<MenuItem>();
+        List<MenuItem> menuItems = new ArrayList<>();
         for (int i = 0; (menu != null) && (i < menu.size()); i++) {
             MenuItem menuItem = menu.getItem(i);
             if (menuItem.isVisible() && menuItem.isEnabled()) {
@@ -305,22 +316,6 @@
         }
     }
 
-    private List<Object> getShowingMenuItemsReferences(List<MenuItem> menuItems) {
-        List<Object> references = new ArrayList<Object>();
-        for (MenuItem menuItem : menuItems) {
-            if (menuItem.getItemId() != Menu.NONE) {
-                references.add(menuItem.getItemId());
-            } else if (!TextUtils.isEmpty(menuItem.getTitle())) {
-                references.add(menuItem.getTitle());
-            } else if (menuItem.getIcon() != null){
-                references.add(menuItem.getIcon());
-            } else {
-                references.add(menuItem);
-            }
-        }
-        return references;
-    }
-
     private void registerOrientationHandler() {
         unregisterOrientationHandler();
         mWindow.getDecorView().addOnLayoutChangeListener(mOrientationChangeHandler);
@@ -383,19 +378,15 @@
         private final Point mCoordsOnWindow = new Point();  // popup window coordinates.
         /* Temporary data holders. Reset values before using. */
         private final int[] mTmpCoords = new int[2];
-        private final Rect mTmpRect = new Rect();
 
         private final Region mTouchableRegion = new Region();
         private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
-                new ViewTreeObserver.OnComputeInternalInsetsListener() {
-                    public void onComputeInternalInsets(
-                            ViewTreeObserver.InternalInsetsInfo info) {
-                        info.contentInsets.setEmpty();
-                        info.visibleInsets.setEmpty();
-                        info.touchableRegion.set(mTouchableRegion);
-                        info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo
-                                .TOUCHABLE_INSETS_REGION);
-                    }
+                info -> {
+                    info.contentInsets.setEmpty();
+                    info.visibleInsets.setEmpty();
+                    info.touchableRegion.set(mTouchableRegion);
+                    info.setTouchableInsets(
+                            ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
                 };
 
         private final int mLineHeight;
@@ -1407,18 +1398,15 @@
             final ImageButton overflowButton = (ImageButton) LayoutInflater.from(mContext)
                     .inflate(R.layout.floating_popup_overflow_button, null);
             overflowButton.setImageDrawable(mOverflow);
-            overflowButton.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    if (mIsOverflowOpen) {
-                        overflowButton.setImageDrawable(mToOverflow);
-                        mToOverflow.start();
-                        closeOverflow();
-                    } else {
-                        overflowButton.setImageDrawable(mToArrow);
-                        mToArrow.start();
-                        openOverflow();
-                    }
+            overflowButton.setOnClickListener(v -> {
+                if (mIsOverflowOpen) {
+                    overflowButton.setImageDrawable(mToOverflow);
+                    mToOverflow.start();
+                    closeOverflow();
+                } else {
+                    overflowButton.setImageDrawable(mToArrow);
+                    mToArrow.start();
+                    openOverflow();
                 }
             });
             return overflowButton;
@@ -1441,13 +1429,10 @@
                     };
             overflowPanel.setAdapter(adapter);
 
-            overflowPanel.setOnItemClickListener(new AdapterView.OnItemClickListener() {
-                @Override
-                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                    MenuItem menuItem = (MenuItem) overflowPanel.getAdapter().getItem(position);
-                    if (mOnMenuItemClickListener != null) {
-                        mOnMenuItemClickListener.onMenuItemClick(menuItem);
-                    }
+            overflowPanel.setOnItemClickListener((parent, view, position, id) -> {
+                MenuItem menuItem = (MenuItem) overflowPanel.getAdapter().getItem(position);
+                if (mOnMenuItemClickListener != null) {
+                    mOnMenuItemClickListener.onMenuItemClick(menuItem);
                 }
             });
 
@@ -1479,12 +1464,9 @@
                 public void onAnimationEnd(Animation animation) {
                     // Posting this because it seems like this is called before the animation
                     // actually ends.
-                    mContentContainer.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            setPanelsStatesAtRestingPosition();
-                            setContentAreaAsTouchableSurface();
-                        }
+                    mContentContainer.post(() -> {
+                        setPanelsStatesAtRestingPosition();
+                        setContentAreaAsTouchableSurface();
                     });
                 }
 
diff --git a/core/java/com/android/internal/widget/ImageFloatingTextView.java b/core/java/com/android/internal/widget/ImageFloatingTextView.java
index e86932c..6b53368 100644
--- a/core/java/com/android/internal/widget/ImageFloatingTextView.java
+++ b/core/java/com/android/internal/widget/ImageFloatingTextView.java
@@ -169,4 +169,8 @@
         }
         return false;
     }
+
+    public int getLayoutHeight() {
+        return getLayout().getHeight();
+    }
 }
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index 1104318..70473a0 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -138,7 +138,7 @@
                 first = false;
                 boolean measuredTooSmall = false;
                 if (textChild != null) {
-                    measuredTooSmall = childHeight < textChild.getLayout().getHeight()
+                    measuredTooSmall = childHeight < textChild.getLayoutHeight()
                             + textChild.getPaddingTop() + textChild.getPaddingBottom();
                 }
 
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index b529e37..5f803da 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -50,27 +50,27 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
-static void Shader_safeUnref(JNIEnv* env, jobject o, jlong shaderHandle) {
-    SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
+static void Shader_safeUnref(SkShader* shader) {
     SkSafeUnref(shader);
 }
 
+static jlong Shader_getNativeFinalizer(JNIEnv*, jobject) {
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&Shader_safeUnref));
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
 static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jobject jbitmap,
         jint tileModeX, jint tileModeY) {
     const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
-    sk_sp<SkImage> image;
+    SkBitmap bitmap;
     if (jbitmap) {
         // Only pass a valid SkBitmap object to the constructor if the Bitmap exists. Otherwise,
         // we'll pass an empty SkBitmap to avoid crashing/excepting for compatibility.
-        image = android::bitmap::toBitmap(env, jbitmap).makeImage(nullptr);
+        android::bitmap::toBitmap(env, jbitmap).getSkBitmapForShaders(&bitmap);
     }
 
-    if (!image.get()) {
-        SkBitmap bitmap;
-        image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
-    }
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
     sk_sp<SkShader> baseShader = image->makeShader(
             (SkShader::TileMode)tileModeX, (SkShader::TileMode)tileModeY);
 
@@ -287,7 +287,7 @@
 };
 
 static const JNINativeMethod gShaderMethods[] = {
-    { "nativeSafeUnref",   "(J)V",    (void*)Shader_safeUnref },
+    { "nativeGetFinalizer",   "()J",    (void*)Shader_getNativeFinalizer },
 };
 
 static const JNINativeMethod gBitmapShaderMethods[] = {
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 56f68d4..d740a76 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -119,11 +119,7 @@
     Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
     if (parcel != NULL) {
         const status_t err = parcel->setDataSize(size);
-        //STOPSHIP: check for BADFLO is for a temporary debug using wtf. Remove once bug resolved.
-        if (err == UNKNOWN_ERROR + 0xBADF10) {
-            jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
-                         "Attempt to resize (size = %d) Parcel would corrupt object memory", size);
-        } else if (err != NO_ERROR) {
+        if (err != NO_ERROR) {
             signalExceptionForError(env, clazz, err);
         }
         return parcel->getOpenAshmemSize();
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index e1c0a21..192e3bb 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -25,6 +25,10 @@
 #include <GraphicsJNI.h>
 #include <ScopedPrimitiveArray.h>
 
+#include <gui/BufferItemConsumer.h>
+#include <gui/BufferQueue.h>
+#include <gui/Surface.h>
+
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <private/EGL/cache.h>
@@ -851,6 +855,75 @@
     return RenderProxy::copySurfaceInto(surface, left, top, right, bottom, &bitmap);
 }
 
+class ContextFactory : public IContextFactory {
+public:
+    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
+        return new AnimationContext(clock);
+    }
+};
+
+static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(JNIEnv* env,
+        jobject clazz, jlong renderNodePtr, jint jwidth, jint jheight) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    if (jwidth <= 0 || jheight <= 0) {
+        ALOGW("Invalid width %d or height %d", jwidth, jheight);
+        return nullptr;
+    }
+
+    uint32_t width = jwidth;
+    uint32_t height = jheight;
+
+    // Create a Surface wired up to a BufferItemConsumer
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> rawConsumer;
+    BufferQueue::createBufferQueue(&producer, &rawConsumer);
+    rawConsumer->setMaxBufferCount(1);
+    sp<BufferItemConsumer> consumer = new BufferItemConsumer(rawConsumer,
+            GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER);
+    consumer->setDefaultBufferSize(width, height);
+    sp<Surface> surface = new Surface(producer);
+
+    // Render into the surface
+    {
+        ContextFactory factory;
+        RenderProxy proxy{false, renderNode, &factory};
+        proxy.loadSystemProperties();
+        proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
+        proxy.initialize(surface);
+        // Shadows can't be used via this interface, so just set the light source
+        // to all 0s.
+        proxy.setup(0, 0, 0);
+        proxy.setLightCenter((Vector3){0, 0, 0});
+        nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
+        UiFrameInfoBuilder(proxy.frameInfo())
+                .setVsync(vsync, vsync)
+                .addFlag(FrameInfoFlags::SurfaceCanvas);
+        proxy.syncAndDrawFrame();
+    }
+
+    // Yank out the GraphicBuffer
+    BufferItem bufferItem;
+    status_t err;
+    if ((err = consumer->acquireBuffer(&bufferItem, 0, true)) != OK) {
+        ALOGW("Failed to acquireBuffer, error %d (%s)", err, strerror(-err));
+        return nullptr;
+    }
+    sp<GraphicBuffer> buffer = bufferItem.mGraphicBuffer;
+    // We don't really care if this fails or not since we're just going to destroy this anyway
+    consumer->releaseBuffer(bufferItem);
+    if (!buffer.get()) {
+        ALOGW("GraphicBuffer is null?");
+        return nullptr;
+    }
+    if (buffer->getWidth() != width || buffer->getHeight() != height) {
+        ALOGW("GraphicBuffer size mismatch, got %dx%d expected %dx%d",
+                buffer->getWidth(), buffer->getHeight(), width, height);
+        // Continue I guess?
+    }
+    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
+    return createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_Mutable);
+}
+
 // ----------------------------------------------------------------------------
 // FrameMetricsObserver
 // ----------------------------------------------------------------------------
@@ -947,6 +1020,8 @@
             (void*)android_view_ThreadedRenderer_removeFrameMetricsObserver },
     { "nCopySurfaceInto", "(Landroid/view/Surface;IIIILandroid/graphics/Bitmap;)I",
                 (void*)android_view_ThreadedRenderer_copySurfaceInto },
+    { "nCreateHardwareBitmap", "(JII)Landroid/graphics/Bitmap;",
+            (void*)android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode },
 };
 
 int register_android_view_ThreadedRenderer(JNIEnv* env) {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 6000fb5..d73e7dd 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -27,6 +27,7 @@
 #include <fcntl.h>
 #include <grp.h>
 #include <inttypes.h>
+#include <malloc.h>
 #include <mntent.h>
 #include <paths.h>
 #include <signal.h>
@@ -519,6 +520,9 @@
     // The child process.
     gMallocLeakZygoteChild = 1;
 
+    // Set the jemalloc decay time to 1.
+    mallopt(M_DECAY_TIME, 1);
+
     // Clean up any descriptors which must be closed immediately
     DetachDescriptors(env, fdsToClose);
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 18cfc99..8ed76de 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3317,12 +3317,16 @@
          confirmation UI for full backup/restore -->
     <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
 
-
-    <!-- Allows the holder to access the instant applications on the device.
+    <!-- Allows the holder to access and manage instant applications on the device.
     @hide -->
     <permission android:name="android.permission.ACCESS_INSTANT_APPS"
             android:protectionLevel="signature|installer|verifier" />
 
+    <!-- Allows the holder to view the instant applications on the device.
+    @hide -->
+    <permission android:name="android.permission.VIEW_INSTANT_APPS"
+            android:protectionLevel="signature|preinstalled" />
+
     <!-- Allows receiving the usage of media resource e.g. video/audio codec and
          graphic memory.
          @hide -->
diff --git a/core/res/res/anim/lock_screen_behind_enter.xml b/core/res/res/anim/lock_screen_behind_enter.xml
index c96e280..c1d26e3 100644
--- a/core/res/res/anim/lock_screen_behind_enter.xml
+++ b/core/res/res/anim/lock_screen_behind_enter.xml
@@ -17,8 +17,7 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:detachWallpaper="true"
-        android:shareInterpolator="false"
-        android:startOffset="100">
+        android:shareInterpolator="false">
 
     <translate android:fromYDelta="110%p" android:toYDelta="0"
             android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
diff --git a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
index 94e40a8..e9475f5 100644
--- a/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
+++ b/core/res/res/anim/lock_screen_behind_enter_fade_in.xml
@@ -22,6 +22,5 @@
     android:interpolator="@interpolator/linear"
     android:fromAlpha="0" android:toAlpha="1"
     android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
-    android:duration="250"
-    android:startOffset="100">
+    android:duration="250">
 </alpha>
\ No newline at end of file
diff --git a/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml b/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
index 660b662..50156fb 100644
--- a/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
+++ b/core/res/res/anim/lock_screen_behind_enter_wallpaper.xml
@@ -16,12 +16,12 @@
   -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:detachWallpaper="true" android:shareInterpolator="false" android:startOffset="100">
+    android:detachWallpaper="true" android:shareInterpolator="false" >
     <alpha
         android:fromAlpha="0.0" android:toAlpha="1.0"
         android:fillEnabled="true" android:fillBefore="true"
         android:interpolator="@interpolator/decelerate_quint"
-        android:duration="400"/>
+        android:duration="300"/>
 
     <translate android:fromYDelta="11%p" android:toYDelta="0"
         android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
diff --git a/core/res/res/anim/lock_screen_wallpaper_exit.xml b/core/res/res/anim/lock_screen_wallpaper_exit.xml
index 49d0327..ba8741a 100644
--- a/core/res/res/anim/lock_screen_wallpaper_exit.xml
+++ b/core/res/res/anim/lock_screen_wallpaper_exit.xml
@@ -16,12 +16,12 @@
   -->
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false" android:startOffset="100">
+        android:shareInterpolator="false">
     <alpha
         android:fromAlpha="1.0" android:toAlpha="0.0"
         android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
         android:interpolator="@interpolator/fast_out_linear_in"
-        android:duration="150"/>
+        android:duration="200"/>
 
     <!-- Empty animation so the animation has same duration as lock_screen_behind_enter animation
          -->
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 8b95f9f..863efef 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -20,11 +20,10 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
-    <LinearLayout
+    <RelativeLayout
         android:id="@+id/time_header"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:orientation="vertical"
         android:gravity="center"
         android:paddingStart="?attr/dialogPreferredPadding"
         android:paddingEnd="?attr/dialogPreferredPadding">
@@ -112,7 +111,7 @@
                 android:includeFontPadding="false"
                 android:button="@null" />
         </RadioGroup>
-    </LinearLayout>
+    </RelativeLayout>
 
     <TextView
         android:visibility="gone"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index bafd40d..d78a980 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vingerafdrukuittelling is bereik. Probeer weer."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Vingerafdrukhandeling is gekanselleer."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Te veel pogings. Probeer later weer."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Te veel pogings. Vingerafdruksensor is gedeaktiveer."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probeer weer."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index d91c185..475167e 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"የጣት አሻራ ስርዓተ ክወና ተትቷል።"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ከልክ በላይ ብዙ ሙከራዎች። በኋላ ላይ እንደገና ይሞክሩ።"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"በጣም ብዙ ሙከራዎች። የጣት አሻራ ዳሳሽ ተሰናክሏል።"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ጣት <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 2646333..3c42334 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -503,8 +503,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"تم بلوغ مهلة إدخال بصمة الإصبع. أعد المحاولة."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"تم إلغاء تشغيل بصمة الإصبع."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"تم إجراء عدد كبير من المحاولات. أعد المحاولة لاحقًا."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"تم إجراء عدد كبير جدًا من المحاولات. لذا تم تعطيل مستشعر بصمات الإصبع."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"أعد المحاولة."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"الإصبع <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index a4a3881..f9c699c 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmaq izinin vaxtı başa çatdı. Yenidən cəhd edin."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Barmaq izi əməliyyatı ləğv edildi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Cəhdlər çox oldu. Sonraya saxlayın."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Həddindən çox cəhd. Barmaq izi sensoru deaktiv edilib."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Yenidən cəhd edin."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Barmaq <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index ebb5cd0..b7bdb69 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -494,8 +494,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Probajte ponovo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Probajte ponovo kasnije."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Previše pokušaja. Senzor za otisak prsta je onemogućen."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probajte ponovo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -1247,7 +1246,7 @@
     <string name="ext_media_nomedia_notification_message" msgid="6471542972147056586">"Uređaj <xliff:g id="NAME">%s</xliff:g> je uklonjen; umetnite novi"</string>
     <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"<xliff:g id="NAME">%s</xliff:g> se još uvek izbacuje…"</string>
     <string name="ext_media_unmounting_notification_message" msgid="4182843895023357756">"Ne uklanjajte"</string>
-    <string name="ext_media_init_action" msgid="7952885510091978278">"Podesi"</string>
+    <string name="ext_media_init_action" msgid="7952885510091978278">"Aktiviraj"</string>
     <string name="ext_media_unmount_action" msgid="1121883233103278199">"Izbaci"</string>
     <string name="ext_media_browse_action" msgid="8322172381028546087">"Istraži"</string>
     <string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> nedostaje"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 32cec88..6515803 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -497,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час чакання адбіткаў пальцаў выйшаў. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Аперацыя з адбіткамі пальцаў скасавана."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Занадта шмат спроб. Паспрабуйце яшчэ раз пазней."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Занадта шмат спроб. Сканер адбіткаў пальцаў адключаны."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Палец <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index e72b2f9..ba640b5 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Актуализации"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Състояние на мрежата"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Сигнали за мрежата"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Налице е мрежа"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Състояние на VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Администриране на устройство"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Сигнали"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Времето за изчакване за отпечатък изтече. Опитайте отново."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцията за отпечатък е анулирана."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Твърде много опити. Пробвайте отново по-късно."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Твърде много опити. Сензорът за отпечатъци е деактивиран."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Опитайте отново."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Пръст <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 954c910..ec7bc7d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"আপডেটগুলি"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"নেটওয়ার্কের স্থিতি"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"নেটওয়ার্ক সক্রান্ত অ্যালার্ট"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"নেটওয়ার্ক পাওয়া যাচ্ছে"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN এর স্থিতি"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"ডিভাইস প্রশাসন"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"সতর্কতাগুলি"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"আঙ্গুলের ছাপ অপারেশন বাতিল করা হয়েছে৷"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"অনেকবার প্রচেষ্টা করা হয়েছে৷ পরে আবার চেষ্টা করুন৷"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"বহুবার চেষ্টা করেছেন। আঙ্গুলের ছাপ নেওয়ার সেন্সর অক্ষম করা হয়েছে।"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"আঙ্গুল <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 101afb7..649cadd 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -447,7 +447,7 @@
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"prikaz mrežnih veza"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Omogućava aplikaciji pregled informacija o mrežnim vezama, npr. koje mreže postoje i koje su povezane."</string>
     <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"ima potpuni pristup mreži"</string>
-    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Omogućava aplikaciji kreiranje spojnih tačaka sa mrežom i korištenje prilagođenih mrežnih protokola. Preglednik i druge aplikacije omogućavaju slanje podataka na internet, tako da ova dozvola nije potrebna za vršenje te radnje."</string>
+    <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Omogućava aplikaciji kreiranje spojnih tačaka sa mrežom i korištenje prilagođenih mrežnih protokola. Preglednik i druge aplikacije omogućavaju slanje podataka na internet, tako da ovo odobrenje nije potrebno za vršenje te radnje."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"izmjene povezivanja na mrežu"</string>
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Dozvoljava aplikaciji izmjenu stanja mrežne povezanosti."</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"izmjene podijeljenog povezivanja"</string>
@@ -494,8 +494,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Vremensko ograničenje za otisak prsta je isteklo. Pokušajte ponovo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja sa otiskom prsta je otkazana."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Previše pokušaja. Senzor za otisak prsta je onemogućen."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -849,7 +848,7 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Dozvoljava aplikaciji postavljanje alarma u instaliranom budilniku. Moguće je da neki budilnici neće primijeniti ovu funkciju."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"dodavanje govorne pošte"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Dozvoljava aplikaciji dodavanje poruka u vašu ulaznu govornu poštu."</string>
-    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"izmjena geolokacijskih dozvola preglednika"</string>
+    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"izmjena geolokacijskih odobrenja preglednika"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Dozvoljava aplikaciji mijenjanje geolokacijskih odobrenja preglednika. Zlonamjerne aplikacije mogu to iskoristiti i dozvoliti slanje informacija o lokaciji proizvoljnim web lokcacijama."</string>
     <string name="save_password_message" msgid="767344687139195790">"Želite li da preglednik zapamti ovu lozinku?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ne sada"</string>
@@ -1205,7 +1204,7 @@
     <string name="date_time_done" msgid="2507683751759308828">"Gotovo"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NOVO: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> omogućava."</string>
-    <string name="no_permissions" msgid="7283357728219338112">"Nisu potrebne dozvole"</string>
+    <string name="no_permissions" msgid="7283357728219338112">"Nisu potrebna odobrenja"</string>
     <string name="perm_costs_money" msgid="4902470324142151116">"ovo se možda dodatno plaća"</string>
     <string name="dlg_ok" msgid="7376953167039865701">"Uredu"</string>
     <string name="usb_charging_notification_title" msgid="6895185153353640787">"Ovaj uređaj se puni preko USB-a"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e928cd9..c644866 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"S\'ha cancel·lat l\'operació d\'empremta digital."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"S\'han produït massa intents. Torna-ho a provar més tard."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"S\'han fet massa intents. S\'ha desactivat el sensor d\'empremtes digitals."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Torna-ho a provar."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dit <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -759,7 +758,7 @@
     <string name="lockscreen_failed_attempts_now_wiping" product="tv" msgid="3195755534096192191">"Has provat de desbloquejar el televisor incorrectament <xliff:g id="NUMBER">%d</xliff:g> vegades. Ara es restabliran els valors de fàbrica de l\'aparell."</string>
     <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Has provat de desbloquejar el telèfon <xliff:g id="NUMBER">%d</xliff:g> vegades incorrectament. Ara el telèfon es restablirà a la configuració predeterminada de fàbrica."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Torneu-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons."</string>
-    <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Heu oblidat el patró?"</string>
+    <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Has oblidat el patró?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Desbloqueig del compte"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Massa intents de patró"</string>
     <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Per desbloquejar el telèfon, inicia la sessió amb el compte de Google."</string>
@@ -1439,7 +1438,7 @@
     <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Superposa #<xliff:g id="ID">%1$d</xliff:g>"</string>
     <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> x <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
     <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", segur"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Patró oblidat"</string>
+    <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"He oblidat el patró"</string>
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Patró incorrecte"</string>
     <string name="kg_wrong_password" msgid="2333281762128113157">"Contrasenya incorrecta"</string>
     <string name="kg_wrong_pin" msgid="1131306510833563801">"PIN incorrecte"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 5b5dbcf..e33b3df 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -497,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operace otisku prstu byla zrušena."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Příliš mnoho pokusů. Zkuste to později."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Příliš mnoho pokusů. Snímač otisků prstů byl deaktivován."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zkuste to znovu."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 441a25b..cdb8a2b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -369,11 +369,11 @@
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Tillader, at appen kan sende klæbende udsendelser, der forbliver tilbage, når udsendelsen er slut. Overdreven brug kan gøre din telefon langsom eller ustabil ved at tvinge den til at bruge for meget hukommelse."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"læse dine kontaktpersoner"</string>
     <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Tillader, at appen kan læse data om de kontaktpersoner, der er gemt på din tablet, f.eks. hvor ofte du har ringet til, sendt e-mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
-    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Giver appen lov til at læse data om dine kontaktpersoner, der er gemt på dit tv, herunder hvor ofte du har ringet, e-mailet eller på andre måder kommunikeret med bestemte personer. Denne tilladelse gør det muligt for apps at gemme dine kontaktoplysninger, og ondsindede apps kan dele kontaktoplysninger uden din viden."</string>
+    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"Giver appen lov til at læse data om dine kontaktpersoner, der er gemt på dit tv, herunder hvor ofte du har ringet, mailet eller på andre måder kommunikeret med bestemte personer. Denne tilladelse gør det muligt for apps at gemme dine kontaktoplysninger, og ondsindede apps kan dele kontaktoplysninger uden din viden."</string>
     <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Tillader, at appen kan læse data om de kontaktpersoner, der er gemt på din telefon, f.eks. hvor ofte du har ringet til, sendt e-mail til eller på anden måde kommunikeret med bestemte personer. Med denne tilladelse kan apps gemme dine kontaktdata, og skadelige apps kan dele kontaktdata uden din viden."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"ændre dine kontaktpersoner"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Tillader, at appen kan ændre data om de kontaktpersoner, der er gemt på din tablet, f.eks. hvor ofte du har ringet til dem, sendt dem en e-mail eller på anden måde kommunikeret med bestemte kontaktpersoner. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
-    <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Giver appen lov til at ændre data om dine kontaktpersoner, der er gemt på dit tv, herunder hvor ofte du har ringet, e-mailet eller på anden måde kommunikeret med bestemte kontaktpersoner. Denne tilladelse gør det muligt for apps at slette kontaktoplysninger."</string>
+    <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"Giver appen lov til at ændre data om dine kontaktpersoner, der er gemt på dit tv, herunder hvor ofte du har ringet, mailet eller på anden måde kommunikeret med bestemte kontaktpersoner. Denne tilladelse gør det muligt for apps at slette kontaktoplysninger."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Tillader, at appen kan ændre data om de kontaktpersoner, der er gemt på din telefon, f.eks. hvor ofte du har ringet til dem, sendt en e-mail til dem eller på anden måde kommunikeret med bestemte kontaktpersoner. Med denne tilladelse kan apps slette kontaktoplysninger."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"læse opkaldsliste"</string>
     <string name="permdesc_readCallLog" msgid="3204122446463552146">"Denne app kan læse din opkaldshistorik."</string>
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Registrering af fingeraftryk fik timeout. Prøv igen."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeraftrykshandlingen blev annulleret."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har prøvet for mange gange. Prøv igen senere."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Du har brugt for mange forsøg. Fingeraftrykslæseren er deaktiveret."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igen."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Fingeraftryk <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index c158ad5..58f3204 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Zeitüberschreitung für Fingerabdruck. Versuche es erneut."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerabdruckvorgang abgebrochen"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zu viele Versuche. Versuche es später erneut."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Zu viele Versuche. Der Fingerabdrucksensor wurde deaktiviert."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Bitte versuche es erneut."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 10db204..780c69d 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Λήξη χρονικού ορίου μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Η λειτουργία μοναδικού χαρακτηριστικού ακυρώθηκε."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Πάρα πολλές προσπάθειες. Ο αισθητήρας δακτυλικών αποτυπωμάτων απενεργοποιήθηκε."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Δοκιμάστε ξανά."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Δάχτυλο <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 8a1b42c..2d823ea 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Too many attempts. Fingerprint sensor disabled."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8a1b42c..2d823ea 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Too many attempts. Fingerprint sensor disabled."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8a1b42c..2d823ea 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Fingerprint timeout reached. Try again."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingerprint operation cancelled."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Too many attempts. Try again later."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Too many attempts. Fingerprint sensor disabled."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Try again."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index ba5af6d..45584b5 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Finalizó el tiempo de espera para la huella digital. Vuelve a intentarlo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Se canceló la operación de huella digital."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Realizaste demasiados intentos. Se inhabilitó el sensor de huellas digitales."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Vuelve a intentarlo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 9369ee5..926ee47 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Se ha cancelado la operación de huella digital."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Vuelve a intentarlo más tarde."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Demasiados intentos. Se ha inhabilitado el sensor de huellas digitales."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Vuelve a intentarlo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index d85a37f..7e690be 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Sõrmejälje toiming tühistati."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Liiga palju katseid. Proovige hiljem uuesti."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Liiga palju katseid. Sõrmejäljeandur on keelatud."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Proovige uuesti."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Sõrm <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 2abdeef..1407479 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Hatz-marka digitalak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hatz-markaren eragiketa bertan behera utzi da."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Saiakera gehiegi egin dituzu. Desgaitu egin da hatz-marken sentsorea."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Saiatu berriro."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> hatza"</string>
   <string-array name="fingerprint_error_vendor">
@@ -865,7 +864,7 @@
     <string name="searchview_description_query" msgid="5911778593125355124">"Bilaketa-kontsulta"</string>
     <string name="searchview_description_clear" msgid="1330281990951833033">"Garbitu kontsulta"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"Bidali kontsulta"</string>
-    <string name="searchview_description_voice" msgid="2453203695674994440">"Ahots bidezko bilaketa"</string>
+    <string name="searchview_description_voice" msgid="2453203695674994440">"Ahozko bilaketa"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"\"Arakatu ukituta\" eginbidea gaitu nahi duzu?"</string>
     <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> zerbitzuak \"Arakatu ukituta\" eginbidea gaitu nahi du. Eginbide hori aktibatuta dagoenean, hatzaren azpian duzunaren azalpena ikus edo entzun dezakezu, edo tabletarekin elkarrekintzan aritzeko keinuak egin ditzakezu."</string>
     <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> zerbitzuak \"Arakatu ukituta\" eginbidea gaitu nahi du. Eginbide hori aktibatuta dagoenean, hatzaren azpian duzunaren azalpena ikus edo entzun dezakezu, edo telefonoarekin elkarrekintzan aritzeko keinuak egin ditzakezu."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 319a5a1..8b894ee 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"به‌روزرسانی‌ها"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"وضعیت شبکه"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"هشدارهای شبکه"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"شبکه دردسترس است"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"‏وضعیت VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"سرپرست دستگاه"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"هشدارها"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"مهلت زمانی ثبت اثر انگشت به پایان رسید. دوباره امتحان کنید."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"عملکرد اثر انگشت لغو شد."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"تلاش‌های زیادی انجام شده است. بعداً دوباره امتحان کنید."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"تلاش‌های بسیاری زیادی انجام شده است. حسگر اثر انگشت غیرفعال شد."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوباره امتحان کنید."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"انگشت <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index f8fd2b3..af1a061 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Sormenjälkitoiminto peruutettiin."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Liian monta yritystä. Yritä myöhemmin uudelleen."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Liian monta yritystä. Sormenjälkitunnistin poistettu käytöstä."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Yritä uudelleen."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Sormi <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 15071e9..ba2c01e 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Mises à jour"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"État du réseau"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertes réseau"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Réseau accessible"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"État du RPV"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administration d\'appareils"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertes"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Le temps attribué pour lire l\'empreinte est écoulé. Veuillez essayer de nouveau."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Trop de tentatives. Capteur d\'empreintes digitales désactivé."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Réessayer."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 6a1b8b7..12c6866 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Délai de détection de l\'empreinte numérique expiré. Veuillez réessayer."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Opération d\'empreinte numérique annulée."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Trop de tentatives. Veuillez réessayer plus tard."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Trop de tentatives. Lecteur d\'empreinte digitale désactivé."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Veuillez réessayer."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Doigt <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index cfbb5c3..68998c3 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Esgotouse o tempo de espera da impresión dixital. Téntao de novo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Cancelouse a operación da impresión dixital."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiados intentos. Téntao de novo máis tarde."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Demasiados intentos. Desactivouse o sensor de impresión dixital."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Téntao de novo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index e78dfa9..7cae6b6 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ફિંગરપ્રિન્ટનો સમય બાહ્ય થયો. ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ફિંગરપ્રિન્ટ ઓપરેશન રદ કર્યું."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ઘણા બધા પ્રયત્નો. પછીથી ફરી પ્રયાસ કરો."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ઘણા વધુ પ્રયત્નો. ફિંગરપ્રિન્ટ સેન્સર અક્ષમ કરવામાં આવ્યું છે."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"આંગળી <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 30be4d5..224710d 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -481,7 +481,7 @@
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"ऐप के प्रमाणीकरण के लिए अंगुली की छाप हार्डवेयर का उपयोग करने देती है"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फ़िंगरप्रिंट की पहचान की गई. कृपया पुनः प्रयास करें."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फ़िंगरप्रिंट संसाधित नहीं हो सका. कृपया पुन: प्रयास करें."</string>
-    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फ़िंगरप्रिंट संवेदक गंदा है. कृपया साफ़ करें और पुनः प्रयास करें."</string>
+    <string name="fingerprint_acquired_imager_dirty" msgid="1087209702421076105">"फ़िंगरप्रिंट सेंसर गंदा है. कृपया साफ़ करें और फिर कोशिश करें."</string>
     <string name="fingerprint_acquired_too_fast" msgid="6470642383109155969">"अंगुली बहुत तेज़ी से चलाई गई है. कृपया पुनः प्रयास करें."</string>
     <string name="fingerprint_acquired_too_slow" msgid="59250885689661653">"अंगुली बहुत धीरे चलाई गई. कृपया पुनः प्रयास करें."</string>
   <string-array name="fingerprint_acquired_vendor">
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फ़िंगरप्रिंट का समय समाप्त हो गया. पुनः प्रयास करें."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फ़िंगरप्रिंट क्रियान्वयन रोक दिया गया."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"बहुत अधिक प्रयास कर लिए गए हैं. बाद में पुन: प्रयास करें."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"बहुत अधिक कोशिशें. फ़िंगरप्रिंट सेंसर अक्षम है."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन: प्रयास करें."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"अंगुली <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 9eaf027..61d1862 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -494,8 +494,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Radnja otiska prsta otkazana je."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Previše pokušaja. Pokušajte ponovo kasnije."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Senzor otiska prsta onemogućen je zbog previše pokušaja."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Pokušajte ponovo."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 1270eb3..e5105b8 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Frissítések"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Hálózati állapot"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Hálózati értesítések"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Van elérhető hálózat"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-állapot"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Eszközfelügyelet"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Értesítések"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ujjlenyomattal kapcsolatos művelet megszakítva"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Túl sok próbálkozás. Próbálja újra később."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Túl sok próbálkozás. Ujjlenyomat-érzékelő letiltva."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Próbálkozzon újra."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. ujj"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 28a01c0..215d83a 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -224,7 +224,7 @@
     <string name="global_actions" product="tablet" msgid="408477140088053665">"Պլանշետի ընտրանքները"</string>
     <string name="global_actions" product="tv" msgid="7240386462508182976">"Հեռուստացույցի ընտրանքներ"</string>
     <string name="global_actions" product="default" msgid="2406416831541615258">"Հեռախոսի ընտրանքներ"</string>
-    <string name="global_action_lock" msgid="2844945191792119712">"Էկրանի փական"</string>
+    <string name="global_action_lock" msgid="2844945191792119712">"Էկրանի կողպում"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Անջատել"</string>
     <string name="global_action_emergency" msgid="7112311161137421166">"Շտապ կանչ"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Վրիպակի զեկույց"</string>
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Իսկորոշումը մատնահետքի միջոցով չեղարկվեց:"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Չափից շատ փորձ եք կատարել: Փորձեք նորից քիչ հետո:"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Չափից շատ փորձ եք կատարել: Մատնահետքերի սկաներն անջատվել է:"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Փորձեք նորից:"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Մատնահետք <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -1302,7 +1301,7 @@
     <string name="submit" msgid="1602335572089911941">"Ուղարկել"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Մեքենայի ռեժիմը միացված է"</string>
     <string name="car_mode_disable_notification_message" msgid="6301524980144350051">"Հպեք` մեքենայի ռեժիմից դուրս գալու համար:"</string>
-    <string name="tethered_notification_title" msgid="3146694234398202601">"Մուտքը կամ թեժ կետը ակտիվ է"</string>
+    <string name="tethered_notification_title" msgid="3146694234398202601">"Մոդեմի ռեժիմը միացված է"</string>
     <string name="tethered_notification_message" msgid="2113628520792055377">"Հպեք՝ կարգավորելու համար:"</string>
     <string name="back_button_label" msgid="2300470004503343439">"Հետ"</string>
     <string name="next_button_label" msgid="1080555104677992408">"Հաջորդը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index e7d160b..c9a8942 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Waktu sidik jari habis. Coba lagi."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operasi sidik jari dibatalkan."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak upaya. Coba lagi nanti."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Terlalu sering dicoba. Sensor sidik jari dinonaktifkan."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Coba lagi."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -533,7 +532,7 @@
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"mengubah penghitungan penggunaan jaringan"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Mengizinkan apl memodifikasi cara penggunaan jaringan diperhitungkan terhadap apl. Tidak untuk digunakan oleh apl normal."</string>
     <string name="permlab_accessNotifications" msgid="7673416487873432268">"mengakses pemberitahuan"</string>
-    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Mengizinkan aplikasi mengambil, memeriksa, dan menghapus pemberitahuan, termasuk pemberitahuan yang diposkan oleh aplikasi lain."</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"Mengizinkan aplikasi mengambil, memeriksa, dan menghapus pemberitahuan, termasuk pemberitahuan yang diposting oleh aplikasi lain."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"mengikat layanan pendengar pemberitahuan"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Memungkinkan pemegang mengikat antarmuka tingkat teratas dari suatu layanan pendengar pemberitahuan. Tidak pernah diperlukan oleh aplikasi normal."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"mengikat ke layanan penyedia ketentuan"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 8313cba12..9e8e022 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Hætt við fingrafarsaðgerð."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Of margar tilraunir. Reyndu aftur síðar."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Of margar tilraunir. Fingrafaralesari gerður óvirkur."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Reyndu aftur."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Fingur <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 53c00b2..975bb57 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timeout impronta digitale. Riprova."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operazione associata all\'impronta digitale annullata."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Troppi tentativi. Riprova più tardi."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Troppi tentativi. Sensore di impronte digitali disattivato."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Riprova."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dito <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 7761209..6eafaaf 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -497,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"חלף הזמן הקצוב לטביעת אצבע. נסה שוב."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"פעולת טביעת האצבע בוטלה."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"יותר מדי ניסיונות. נסה שוב מאוחר יותר."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"יותר מדי ניסיונות. חיישן טביעות האצבע הושבת."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"נסה שוב."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"אצבע <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index b3af109..2a3d9e1 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋の操作をキャンセルしました。"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"所定の回数以上間違えました。しばらくしてからもう一度お試しください。"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"試行回数が上限を超えました。指紋認証センサーを無効にしました。"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"もう一度お試しください。"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"指紋<xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 1301220..1c3f970 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"განახლებები"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"ქსელის სტატუსი"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"ქსელის გაფრთხილებები"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"ქსელი ხელმისაწვდომია"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-ის სტატუსი"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"მოწყობილობის ადმინისტრირება"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"გაფრთხილებები"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"თითის ანაბეჭდის ლოდინის დრო ამოიწურა. სცადეთ ხელახლა."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"თითის ანაბეჭდის აღების ოპერაცია გაუქმდა."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ძალიან ბევრი მცდელობა იყო. სცადეთ მოგვიანებით."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"დაფიქსირდა მეტისმეტად ბევრი მცდელობა. თითის ანაბეჭდის სენსორი გათიშულია."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ხელახლა სცადეთ"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"თითი <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 4c9cd5d..4e11c56 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Саусақ ізін күту уақыты бітті. Әрекетті қайталаңыз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Саусақ ізі операциясынан бас тартылған."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Талпыныстар тым көп. Кейінірек қайталап көріңіз."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Тым көп әрекет жасалды. Саусақ ізін оқу сканері өшірілді."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Әрекетті қайталаңыз."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> саусағы"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 213f305..6994d7f 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ការផ្តិតម្រាមដៃបានអស់ពេល។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ។"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ព្យាយាមចូលច្រើនដងពេកហើយ។ ឧបករណ៍ចាប់ស្នាមម្រាមដៃត្រូវ​បានបិទ។"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ព្យាយាមម្ដងទៀត។"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ម្រាមដៃ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 9a6e89a..b3f42d1 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"ಅಪ್‌ಡೇಟ್‌ಗಳು"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"ನೆಟ್‌ವರ್ಕ್ ಸ್ಥಿತಿ"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"ನೆಟ್‌ವರ್ಕ್ ಎಚ್ಚರಿಕೆಗಳು"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"ನೆಟ್‌ವರ್ಕ್ ಲಭ್ಯವಿದೆ"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN ಸ್ಥಿತಿ"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"ಸಾಧನ ನಿರ್ವಹಣೆ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ಎಚ್ಚರಿಕೆಗಳು"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ಬೆರಳಚ್ಚು ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ಬೆರಳಚ್ಚು ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ಹಲವಾರು ಪ್ರಯತ್ನಗಳು. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಫಿಂಗರ್‌ ಫ್ರಿಂಟ್‌ ಸೆನ್ಸಾರ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ಫಿಂಗರ್ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index cc7aff3..e7f9a7f 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"업데이트"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"네트워크 상태"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"네트워크 알림"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"네트워크 사용 가능"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN 상태"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"기기 관리"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"지문 인식 시간이 초과되었습니다. 다시 시도하세요."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"지문 인식 작업이 취소되었습니다."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"시도 횟수가 너무 많습니다. 나중에 다시 시도하세요."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"시도 횟수가 너무 많습니다. 지문 센서가 사용 중지되었습니다."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"다시 시도해 보세요."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"손가락 <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 0f5f403..d627e61 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Манжа изи иш-аракети жокко чыгарылды."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Аракеттер өтө көп болду. Кийинчерээк кайра аракет кылыңыз."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Өтө көп жолу аракет жасадыңыз. Манжа изинин сенсору өчүрүлдү."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Кайра бир аракеттениңиз."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> манжасы"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index f6eb279..5dc58f6 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ເວ​ລາ​ລາຍ​ນີ້ວ​ມື​ບໍ່​ເຂົ້າ​ເຖິງ​ໄດ້. ລອງ​ໃໝ່​ອີກ."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ຍົກ​ເລີກ​ການ​ດຳ​ເນີນ​ການ​ລາຍ​ນີ້ວ​ມື​ແລ້ວ."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ມີ​ຄວາມ​ພະ​ຍາ​ຍາມ​ຫຼາຍ​ຄັ້ງ​ເກີນ​ໄປ. ລອງ​ໃໝ່​ພາຍ​ຫຼັງ."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ພະຍາຍາມຫຼາຍເທື່ອເກີນໄປ. ລະບົບປິດການເຮັດວຽກຂອງເຊັນເຊີລາຍນິ້ວມືແລ້ວ."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ລອງໃໝ່ອີກຄັ້ງ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ນີ້ວ​ມື <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7838067..14de0a2 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -497,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Baigėsi kontrolinio kodo nustatymo skirtasis laikas. Bandykite dar kartą."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Kontrolinio kodo operacija atšaukta."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Per daug bandymų. Vėliau bandykite dar kartą."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Per daug bandymų. Kontrolinio kodo jutiklis išjungtas."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Bandykite dar kartą."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> pirštas"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index b71a220..b191747 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -494,8 +494,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nospieduma darbība neizdevās."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Pārāk daudz mēģinājumu. Vēlāk mēģiniet vēlreiz."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Pārāk daudz mēģinājumu. Pirksta nospieduma sensors atspējots."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Mēģiniet vēlreiz."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. pirksts"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index febacb2..2e115fc 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операцијата со отпечаток од прст се откажа."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Премногу обиди. Обидете се повторно подоцна."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Премногу обиди. Сензорот за отпечатоци е оневозможен."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Обидете се повторно."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 03e21aa..8bc3ff8 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"അപ്‌ഡേറ്റുകൾ"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"നെറ്റ്‌വർക്ക് നില"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"നെറ്റ്‌വർക്ക് അലേർട്ടുകൾ"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"നെറ്റ്‌വർക്ക് ‌ലഭ്യമല്ല"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN നില"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"ഉപകരണ അഡ്മിനിസ്ട്രേഷൻ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"അലേർട്ടുകൾ"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"വിരലടയാളം നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"നിരവധി തവണ ശ്രമിച്ചതിനാൽ, വിരലടയാള സെൻസർ പ്രവർത്തനരഹിതമായി."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"വീണ്ടും ശ്രമിക്കൂ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"കൈവിരൽ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 7a8e821..8309d77 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Хурууны хээний бүртгэл амжилтгүй боллоо."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Хэтэрхий олон оролдлоо.  Түр хүлээгээд дахин оролдоно уу."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Хэт олон удаа оролдсон тул хурууны хээ мэдрэгчийг идэвхгүй болголоо."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Дахин оролдно уу."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Хурууны хээ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index d44f900..c0bc82c 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"फिंगरप्रिंट कालबाह्य झाले. पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"फिंगरप्रिंट ऑपरेशन रद्द झाले."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"खूप प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"खूप प्रयत्न करून झाले. फिंगरप्रिंट सेंसर बंद आहे."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g> बोट"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 4f0f557..8c4bb4c 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Kemas kini"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Status rangkaian"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Makluman rangkaian"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Rangkaian tersedia"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Status VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Pentadbiran peranti"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Makluman"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tamat masa cap jari dicapai. Cuba lagi."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Pengendalian cap jari dibatalkan."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Terlalu banyak percubaan. Cuba sebentar lagi."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Terlalu banyak percubaan. Penderia cap jadi dilumpuhkan."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Cuba lagi."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Jari <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index f801df5..f5a1429 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"လက်ဗွေရာအချိန်ကုန် သွားပါသည်။ ထပ်မံကြိုးစားပါ။"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"လက်ဗွေရာ လုပ်ငန်း ဖျက်သိမ်းခဲ့၏။"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"အကြိမ်အရေအတွက် အလွန်များနေပါပြီ။ လက်ဗွေဖတ်စနစ်ကို ပိတ်ထားပါသည်။"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ပြန်ကြိုးစားပါ"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"လက်ချောင်း <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index f9b73e0..5972329 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Oppdateringer"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Nettverksstatus"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Nettverksvarsler"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Nettverk er tilgjengelig"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Enhetsadministrasjon"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Varsler"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrykk-operasjonen ble avbrutt."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"For mange forsøk. Prøve på nytt senere."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"For mange forsøk. Fingeravtrykkssensoren er slått av."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Prøv igjen."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 30c6e8c..7283936 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"अद्यावधिकहरू"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"नेटवर्कको स्थिति"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"नेटवर्कका अलर्टहरू"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"नेटवर्क उपलब्ध छ"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN को स्थिति"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"यन्त्रको प्रशासन"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"अलर्टहरू"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"औँठाछापको समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"औँठाछाप सञ्चालन रद्द गरियो।"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"धेरै प्रयासहरू। केहि समय पछि पुन: प्रयास गर्नुहोला"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"अत्यन्त धेरै प्रयासहरू। फिंगरप्रिन्ट सेन्सरलाई असक्षम पारियो।"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"पुन: प्रयास गर्नुहोला।"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"औंला <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index f102451..09cfa70 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Vingerafdrukbewerking geannuleerd."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Te veel pogingen. Probeer het later opnieuw."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Te veel pogingen. Vingerafdruksensor uitgeschakeld."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Probeer het opnieuw."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Vinger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -1318,7 +1317,7 @@
     <string name="progress_erasing" product="default" msgid="6596988875507043042">"SD-kaart wissen..."</string>
     <string name="share" msgid="1778686618230011964">"Delen"</string>
     <string name="find" msgid="4808270900322985960">"Vinden"</string>
-    <string name="websearch" msgid="4337157977400211589">"Online zoeken"</string>
+    <string name="websearch" msgid="4337157977400211589">"Google Zoeken"</string>
     <string name="find_next" msgid="5742124618942193978">"Volgende zoeken"</string>
     <string name="find_previous" msgid="2196723669388360506">"Vorige zoeken"</string>
     <string name="gpsNotifTicker" msgid="5622683912616496172">"Locatieverzoek van <xliff:g id="NAME">%s</xliff:g>"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 4a4bb62..c89224d 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"ਅੱਪਡੇਟ"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"ਨੈੱਟਵਰਕ ਅਵਸਥਾ"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"ਨੈੱਟਵਰਕ ਸੁਚੇਤਨਾਵਾਂ"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਹੈ"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN ਅਵਸਥਾ"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"ਡੀਵਾਈਸ ਪ੍ਰਸ਼ਾਸਨ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"ਸੁਚੇਤਨਾਵਾਂ"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ਫਿੰਗਰ"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ. ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ਹੱਦੋਂ ਵੱਧ ਕੋਸ਼ਿਸ਼ਾਂ। ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ।"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ਉਂਗਲ <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 72cc52a..cac8e583 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -497,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Osiągnięto limit czasu odczytu linii papilarnych. Spróbuj ponownie."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Odczyt odcisku palca został anulowany."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Zbyt wiele prób. Spróbuj ponownie później."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Zbyt wiele prób. Czytnik linii papilarnych został wyłączony."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Spróbuj ponownie."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Odcisk palca <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -774,7 +773,7 @@
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Zaloguj się"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Błędna nazwa użytkownika lub hasło."</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"Nie pamiętasz nazwy użytkownika lub hasła?\nOdwiedź stronę "<b>"google.com/accounts/recovery"</b></string>
-    <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Sprawdzanie…"</string>
+    <string name="lockscreen_glogin_checking_password" msgid="7114627351286933867">"Sprawdzam…"</string>
     <string name="lockscreen_unlock_label" msgid="737440483220667054">"Odblokuj"</string>
     <string name="lockscreen_sound_on_label" msgid="9068877576513425970">"Włącz dźwięk"</string>
     <string name="lockscreen_sound_off_label" msgid="996822825154319026">"Wyłącz dźwięk"</string>
@@ -1811,8 +1810,8 @@
     <string name="app_category_productivity" msgid="3742083261781538852">"Produktywność"</string>
     <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"Pamięć urządzenia"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"Debugowanie USB"</string>
-    <string name="time_picker_hour_label" msgid="2979075098868106450">"godzina"</string>
-    <string name="time_picker_minute_label" msgid="5168864173796598399">"minuta"</string>
+    <string name="time_picker_hour_label" msgid="2979075098868106450">"godz."</string>
+    <string name="time_picker_minute_label" msgid="5168864173796598399">"min"</string>
     <string name="time_picker_header_text" msgid="143536825321922567">"Ustawianie godziny"</string>
     <string name="time_picker_input_error" msgid="7574999942502513765">"Wpisz prawidłowy czas"</string>
     <string name="time_picker_prompt_label" msgid="7588093983899966783">"Podaj czas"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 7157dab..fe6b766 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Atualizações"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Status de rede"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de rede"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Rede disponível"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Status de VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administração do dispositivo"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Excesso de tentativas. Tente novamente mais tarde."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Excesso de tentativas. Sensor de impressão digital desativado."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 026a866..4c04879 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -63,8 +63,8 @@
     <string name="needPuk2" msgid="4526033371987193070">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
     <string name="enablePin" msgid="209412020907207950">"Ação sem êxito. Ative o bloqueio do SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
+      <item quantity="one">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
       <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item>
-      <item quantity="one">Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar bloqueado.</item>
     </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
@@ -179,8 +179,8 @@
     <string name="low_memory" product="tv" msgid="516619861191025923">"O armazenamento da TV está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"O armazenamento do telemóvel está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569">
+      <item quantity="one">Certificate authorities installed</item>
       <item quantity="other">Autoridades de certificação instaladas</item>
-      <item quantity="one">Autoridade de certificação instalada</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por um terceiro desconhecido"</string>
     <string name="ssl_ca_cert_noti_by_administrator" msgid="3541729986326153557">"Pelo administrador do seu perfil de trabalho"</string>
@@ -235,8 +235,8 @@
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"Utilize esta opção para uma interferência mínima do sistema quando o dispositivo não responder ou estiver demasiado lento, ou quando precisar de todas as secções de relatório. Não permite introduzir mais detalhes ou tirar capturas de ecrã adicionais."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
+      <item quantity="one">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="other">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
-      <item quantity="one">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_0">%d</xliff:g> segundo.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Som desativado"</string>
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Demasiadas tentativas. Tente novamente mais tarde."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Demasiadas tentativas. Sensor de impressões digitais desativado."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -872,8 +871,8 @@
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"Há 1 mês"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Há mais de 1 mês"</string>
     <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
+      <item quantity="one">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
-      <item quantity="one">Último <xliff:g id="COUNT_0">%d</xliff:g> dia</item>
     </plurals>
     <string name="last_month" msgid="3959346739979055432">"Último mês"</string>
     <string name="older" msgid="5211975022815554840">"Mais antiga"</string>
@@ -894,68 +893,68 @@
     <string name="years" msgid="6881577717993213522">"anos"</string>
     <string name="now_string_shortest" msgid="8912796667087856402">"agora"</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="3957499975064245495">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>m</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="3552182110578602356">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>h</item>
     </plurals>
     <plurals name="duration_days_shortest" formatted="false" msgid="5213655532597081640">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>d</item>
     </plurals>
     <plurals name="duration_years_shortest" formatted="false" msgid="7848711145196397042">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>a</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>a</item>
     </plurals>
     <plurals name="duration_minutes_shortest_future" formatted="false" msgid="3277614521231489951">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g>m</item>
-      <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g>m</item>
     </plurals>
     <plurals name="duration_hours_shortest_future" formatted="false" msgid="2152452368397489370">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g>h</item>
-      <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g>h</item>
     </plurals>
     <plurals name="duration_days_shortest_future" formatted="false" msgid="8088331502820295701">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g>d</item>
-      <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g>d</item>
     </plurals>
     <plurals name="duration_years_shortest_future" formatted="false" msgid="2317006667145250301">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g>a</item>
-      <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g>a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="3178131706192980192">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
-      <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> minuto</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="676894109982008411">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
-      <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> hora</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="2203515825765397130">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
-      <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> dia</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="4820062134188885734">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
-      <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> ano</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="4655043589817680966">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
-      <item quantity="one">dentro <xliff:g id="COUNT_0">%d</xliff:g> minuto</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8084579714205223891">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
-      <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> hora</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="333215369363433992">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
-      <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> dia</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="8644862986413104011">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
-      <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> ano</item>
     </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"Este vídeo não é válido para transmissão em fluxo contínuo neste aparelho."</string>
@@ -1103,12 +1102,12 @@
     <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sons de notificação"</string>
     <string name="ringtone_unknown" msgid="3914515995813061520">"Desconhecido"</string>
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
+      <item quantity="one">Wi-Fi networks available</item>
       <item quantity="other">Redes Wi-Fi disponíveis</item>
-      <item quantity="one">Rede Wi-Fi disponível</item>
     </plurals>
     <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
+      <item quantity="one">Open Wi-Fi networks available</item>
       <item quantity="other">Redes Wi-Fi abertas disponíveis</item>
-      <item quantity="one">Rede Wi-Fi aberta disponível</item>
     </plurals>
     <string name="wifi_available_sign_in" msgid="9157196203958866662">"Iniciar sessão na rede Wi-Fi"</string>
     <string name="network_available_sign_in" msgid="1848877297365446605">"Início de sessão na rede"</string>
@@ -1310,8 +1309,8 @@
     <string name="no_matches" msgid="8129421908915840737">"Sem correspondências"</string>
     <string name="find_on_page" msgid="1946799233822820384">"Localizar na página"</string>
     <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
+      <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
-      <item quantity="one">1 correspondência</item>
     </plurals>
     <string name="action_mode_done" msgid="7217581640461922289">"Concluído"</string>
     <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"A apagar memória de armazenamento USB..."</string>
@@ -1596,8 +1595,8 @@
     <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Os PINs não correspondem. Tente novamente."</string>
     <string name="restr_pin_error_too_short" msgid="8173982756265777792">"O PIN é demasiado pequeno. Deve ter, no mínimo, 4 dígitos."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
+      <item quantity="one">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
       <item quantity="other">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item>
-      <item quantity="one">Tente novamente dentro de 1 segundo</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Tente novamente mais tarde"</string>
     <string name="immersive_cling_title" msgid="8394201622932303336">"Visualização de ecrã inteiro"</string>
@@ -1629,36 +1628,36 @@
     <string name="data_saver_enable_title" msgid="4674073932722787417">"Ativar a Poupança de dados?"</string>
     <string name="data_saver_enable_button" msgid="7147735965247211818">"Ativar"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
+      <item quantity="one">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Durante %1$d minutos (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="one">Durante um minuto (até às <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="6830154222366042597">
+      <item quantity="one">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Durante %1$d min (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="one">Durante 1 min (até às <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
+      <item quantity="one">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Durante %1$d horas (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="one">Durante uma hora (até às <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="4787552595253082371">
+      <item quantity="one">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Durante %1$d h (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="one">Durante 1 h (até às <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
+      <item quantity="one">For %d minutes</item>
       <item quantity="other">Durante %d minutos</item>
-      <item quantity="one">Durante um minuto</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2199350154433426128">
+      <item quantity="one">For %d min</item>
       <item quantity="other">Durante %d min</item>
-      <item quantity="one">Durante 1 min</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
+      <item quantity="one">For %d hours</item>
       <item quantity="other">Durante %d horas</item>
-      <item quantity="one">Durante uma hora</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="6748277774662434217">
+      <item quantity="one">For %d hr</item>
       <item quantity="other">Durante %d h</item>
-      <item quantity="one">Durante 1 h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_alarm" msgid="9128205721301330797">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string>
@@ -1693,8 +1692,8 @@
     <string name="close_button_text" msgid="3937902162644062866">"Fechar"</string>
     <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
     <plurals name="selected_count" formatted="false" msgid="7187339492915744615">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selecionado</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="5929663562028088222">"Sem categoria"</string>
     <string name="importance_from_user" msgid="7318955817386549931">"Definiu a importância destas notificações."</string>
@@ -1757,8 +1756,8 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher automaticamente o conteúdo"</string>
     <string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"Sem sugestões do preenchimento automático"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="5506565809835815274">
+      <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item>
-      <item quantity="one">Uma sugestão do preenchimento automático</item>
     </plurals>
     <string name="autofill_save_title" msgid="3345527308992082601">"Pretende guardar no &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
     <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Pretende guardar <xliff:g id="TYPE">%1$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 7157dab..fe6b766 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Atualizações"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Status de rede"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Alertas de rede"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Rede disponível"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Status de VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Administração do dispositivo"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Alertas"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operação de impressão digital cancelada."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Excesso de tentativas. Tente novamente mais tarde."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Excesso de tentativas. Sensor de impressão digital desativado."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tente novamente."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Dedo <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 1a3e0c5..835c9ac 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -494,8 +494,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Timpul pentru amprentare a expirat. Încercați din nou."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operațiunea privind amprenta a fost anulată."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Prea multe încercări. Încercați din nou mai târziu."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Prea multe încercări. Senzorul de amprentă este dezactivat."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Încercați din nou."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Degetul <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ab91c0a..69fe42f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -497,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Превышено время ожидания. Повторите попытку."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Операция с отпечатком отменена."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Слишком много попыток. Повторите позже."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Слишком много попыток. Сканер отпечатков пальцев отключен."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Повторите попытку."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Палец <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 71466bc..373fe07 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"ඇඟිලි සලකුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ඇඟිලි සලකුණු මෙහෙයුම අවලංගු කරන ලදී."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"උත්සාහයන් ඉතා වැඩි ගණනකි. කරුණාකර පසුව නැවත උත්සාහ කරන්න."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"උත්සාහයන් ඉතා වැඩි ගණනකි. ඇඟිලි සලකුණු සංවේදකය අබල කරන ලදී."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"ඇඟිලි <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 08efcd9..4352a36 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -266,8 +266,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Aktualizácie"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Stav siete"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Upozornenia týkajúce sa siete"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Sieť je k dispozícii"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"Stav pripojenia VPN"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Správa zariadenia"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Upozornenia"</string>
@@ -498,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Časový limit rozpoznania odtlačku vypršal. Skúste to znova."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Príliš veľa pokusov. Senzor odtlačkov prstov bol deaktivovaný."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Skúste to znova"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst: <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9aa39e9..c6f4404 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -497,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Dejanje s prstnim odtisom je bilo preklicano."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Preveč poskusov. Poskusite znova pozneje."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Preveč poskusov. Tipalo prstnih odtisov je onemogočeno."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Poskusite znova."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Prst <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index b9b8e98..70a3efb 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Koha e veprimit për gjurmën e gishtit skadoi. Provo përsëri."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Operacioni i gjurmës së gishtit u anulua."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Keni bërë shumë tentativa. Provo përsëri më vonë."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Shumë përpjekje. Sensori i gjurmës së gishtit u çaktivizua."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Provo përsëri."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Gishti <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b85df9f..f46505bf 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -494,8 +494,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Временско ограничење за отисак прста је истекло. Пробајте поново."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Радња са отиском прста је отказана."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Превише покушаја. Пробајте поново касније."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Превише покушаја. Сензор за отисак прста је онемогућен."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Пробајте поново."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Прст <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -1247,7 +1246,7 @@
     <string name="ext_media_nomedia_notification_message" msgid="6471542972147056586">"Уређај <xliff:g id="NAME">%s</xliff:g> је уклоњен; уметните нови"</string>
     <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"<xliff:g id="NAME">%s</xliff:g> се још увек избацује…"</string>
     <string name="ext_media_unmounting_notification_message" msgid="4182843895023357756">"Не уклањајте"</string>
-    <string name="ext_media_init_action" msgid="7952885510091978278">"Подеси"</string>
+    <string name="ext_media_init_action" msgid="7952885510091978278">"Активирај"</string>
     <string name="ext_media_unmount_action" msgid="1121883233103278199">"Избаци"</string>
     <string name="ext_media_browse_action" msgid="8322172381028546087">"Истражи"</string>
     <string name="ext_media_missing_title" msgid="620980315821543904">"<xliff:g id="NAME">%s</xliff:g> недостаје"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index c6865a1..a3fb085 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Uppdateringar"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Nätverksstatus"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Nätverksvarningar"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Nätverk tillgängligt"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN-status"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Enhetsadministration"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Varningar"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Fingeravtrycksåtgärden avbröts."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Du har gjort för många försök. Försök igen senare."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Du har försökt för många gånger. Fingeravtryckssensorn har inaktiverats."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Försök igen."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Finger <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 55da8d9..ce4a469 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -81,7 +81,7 @@
     <string name="CnirMmi" msgid="3062102121430548731">"Kupiga nambari kumezuiwa"</string>
     <string name="ThreeWCMmi" msgid="9051047170321190368">"Upigaji simu kwa njia tatu"</string>
     <string name="RuacMmi" msgid="7827887459138308886">"Ukataaji wa simu zinazokera zisizohitajika"</string>
-    <string name="CndMmi" msgid="3116446237081575808">"Uwasilishaji nambari ya kupiga simu"</string>
+    <string name="CndMmi" msgid="3116446237081575808">"Kuonyeshwa kwa nambari inayopiga"</string>
     <string name="DndMmi" msgid="1265478932418334331">"Usisumbue"</string>
     <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"Chaguo-msingi za ID ya mpigaji simu za kutozuia. Simu ifuatayo: Imezuiliwa"</string>
     <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"Chaguo-msingi za kitambulisho cha mpigaji simu huwa kuzuiwa. Simu ifuatayo: Haijazuiliwa"</string>
@@ -489,8 +489,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Muda wa kitambulisho umekwisha. Jaribu tena."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Utendaji wa kitambulisho imeghairiwa."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Majaribio mengi mno. Jaribu tena baadaye."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Majaribio mengi mno. Kitambua alama ya kidole kimezimwa."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Jaribu tena."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Kitambulisho <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 6cbfba5..f45789b 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"கைரேகை செயல்பாடு ரத்துசெய்யப்பட்டது."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"அதிகமான முயற்சிகள். பிறகு முயற்சிக்கவும்."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"பலமுறை முயன்றுவிட்டீர்கள். கைரேகை உணர்வி முடக்கப்பட்டது."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"மீண்டும் முயற்சிக்கவும்."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"கைரேகை <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index b3e5e4a..68065b9 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"నవీకరణలు"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"నెట్‌వర్క్ స్థితి"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"నెట్‌వర్క్ హెచ్చరికలు"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"నెట్‌వర్క్ అందుబాటులో ఉంది"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN స్థితి"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"పరికర నిర్వాహణ"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"హెచ్చరికలు"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"వేలిముద్ర కార్యాచరణ రద్దయింది."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"చాలా ఎక్కువ ప్రయత్నాలు చేసారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"అనేకసార్లు ప్రయత్నించారు. వేలిముద్ర సెన్సార్ నిలిపివేయబడింది."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"వేలు <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index c2ae15e..51d932d 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"หมดเวลาใช้ลายนิ้วมือแล้ว โปรดลองอีกครั้ง"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"ยกเลิกการทำงานของลายนิ้วมือ"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"ดำเนินการหลายครั้งเกินไป ลองอีกครั้งในภายหลัง"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"ลองหลายครั้งเกินไป ปิดใช้เซ็นเซอร์ลายนิ้วมือแล้ว"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"ลองอีกครั้ง"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"นิ้ว <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 2ef0c7a..ee01ff2 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Nag-time out ang fingerprint. Subukang muli."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Nakansela ang operasyong ginagamitan ng fingerprint."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Masyadong maraming beses sumubok. Subukang muli sa ibang pagkakataon."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Masyadong maraming beses sumubok. Na-disable ang sensor para sa fingerprint."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Subukang muli."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Daliri <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index c3b2001..bbae91a 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"Güncellemeler"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"Ağ durumu"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"Ağ uyarıları"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"Ağ mevcut"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN durumu"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"Cihaz yönetimi"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"Uyarılar"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Parmak izi işlemi iptal edildi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Çok fazla deneme yapıldı. Parmak izi sensörü devre dışı bıraıldı."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Tekrar deneyin."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"<xliff:g id="FINGERID">%d</xliff:g>. parmak"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index a5a289c..f187c03 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -497,8 +497,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Час очікування відбитка минув. Повторіть спробу."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Дію з відбитком скасовано."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Забагато спроб. Спробуйте пізніше."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Забагато спроб. Сканер відбитків пальців вимкнено."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Повторіть спробу."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Відбиток пальця <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index c16c0c6..310bddd 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"اپ ڈیٹس"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"نیٹ ورک اسٹیٹس"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"نیٹ ورک الرٹس"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"نیٹ ورک دستیاب ہے"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"‏VPN اسٹیٹس"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"آلہ کا نظم و نسق"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"الرٹس"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"فنگر پرنٹ کی کارروائی منسوخ ہوگئی۔"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"کافی زیادہ کوششیں کی گئیں۔ بعد میں دوبارہ کوشش کریں۔"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"کافی زیادہ کوششیں۔ فنگر پرنٹ سینسر غیر فعال ہو گیا۔"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"انگلی <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index b2ea945..bd53da5 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Barmoq izi tekshiruvi bekor qilindi."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Urinishlar soni ko‘payib ketdi. Keyinroq qayta urinib ko‘ring."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Urinishlar soni ko‘payib ketdi. Barmoq izi skaneri bloklandi."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Qayta urinib ko‘ring."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Barmoq izi <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 504ef5f..655bdc7 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Thao tác dùng dấu vân tay bị hủy."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Quá nhiều lần thử. Hãy thử lại sau."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Quá nhiều lần thử. Cảm biến vân tay đã bị tắt."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Thử lại."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Ngón tay <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index 98dc4cf..f26d6ed 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -63,11 +63,8 @@
          Set to true for watch devices. -->
     <bool name="config_focusScrollContainersInTouchMode">true</bool>
 
-    <!-- The small screens of watch devices makes multi-window support undesireable. -->
-    <bool name="config_supportsMultiWindow">false</bool>
+    <!-- Enable generic multi-window in order to support Activity in virtual display. -->
+    <bool name="config_supportsMultiWindow">true</bool>
+    <bool name="config_supportsMultiDisplay">true</bool>
     <bool name="config_supportsSplitScreenMultiWindow">false</bool>
-
-    <!-- Disable Multi-Display because of small screen space and lack of external display connection
-         options. -->
-    <bool name="config_supportsMultiDisplay">false</bool>
 </resources>
diff --git a/core/res/res/values-watch/styles_material.xml b/core/res/res/values-watch/styles_material.xml
index 0053c12..fd88102 100644
--- a/core/res/res/values-watch/styles_material.xml
+++ b/core/res/res/values-watch/styles_material.xml
@@ -95,7 +95,7 @@
     </style>
 
     <style name="DialogWindowTitle.Material">
-        <item name="maxLines">@empty</item>
+        <item name="maxLines">@null</item>
         <item name="scrollHorizontally">false</item>
         <item name="textAppearance">@style/TextAppearance.Material.DialogWindowTitle</item>
         <item name="gravity">center_horizontal|top</item>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d195de8..c19e3d2 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"更新"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"网络状态"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"网络提醒"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"有可用的网络"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN 状态"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"设备管理"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"提醒"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指纹录入操作超时,请重试。"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"指纹操作已取消。"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"尝试次数过多,请稍后重试。"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"尝试次数过多。指纹传感器已停用。"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"请重试。"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
@@ -779,19 +777,19 @@
     <string name="lockscreen_access_pattern_cell_added_verbose" msgid="7264580781744026939">"已添加圆点 <xliff:g id="CELL_INDEX">%1$s</xliff:g>"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"图案绘制完成"</string>
     <string name="lockscreen_access_pattern_area" msgid="400813207572953209">"图案区域。"</string>
-    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s。%3$d的小部件%2$d。"</string>
-    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"添加小部件。"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s。%3$d的微件%2$d。"</string>
+    <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"添加微件。"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"空白"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"已展开解锁区域。"</string>
     <string name="keyguard_accessibility_unlock_area_collapsed" msgid="6366992066936076396">"已收起解锁区域。"</string>
-    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>小部件。"</string>
+    <string name="keyguard_accessibility_widget" msgid="6527131039741808240">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>微件。"</string>
     <string name="keyguard_accessibility_user_selector" msgid="1226798370913698896">"用户选择器"</string>
     <string name="keyguard_accessibility_status" msgid="8008264603935930611">"状态"</string>
     <string name="keyguard_accessibility_camera" msgid="8904231194181114603">"相机"</string>
     <string name="keygaurd_accessibility_media_controls" msgid="262209654292161806">"媒体控制"</string>
-    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"已开始将小部件重新排序。"</string>
-    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"已完成小部件重新排序。"</string>
-    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"已删除小部件<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>。"</string>
+    <string name="keyguard_accessibility_widget_reorder_start" msgid="8736853615588828197">"已开始将微件重新排序。"</string>
+    <string name="keyguard_accessibility_widget_reorder_end" msgid="7170190950870468320">"已完成微件重新排序。"</string>
+    <string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"已删除微件<xliff:g id="WIDGET_INDEX">%1$s</xliff:g>。"</string>
     <string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"展开解锁区域。"</string>
     <string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"滑动解锁。"</string>
     <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"图案解锁。"</string>
@@ -1260,7 +1258,7 @@
     <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"请求忽略电池优化"</string>
     <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"允许应用请求相应的权限,以便忽略针对该应用的电池优化。"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"双击可以进行缩放控制"</string>
-    <string name="gadget_host_error_inflating" msgid="4882004314906466162">"无法添加小部件。"</string>
+    <string name="gadget_host_error_inflating" msgid="4882004314906466162">"无法添加微件。"</string>
     <string name="ime_action_go" msgid="8320845651737369027">"开始"</string>
     <string name="ime_action_search" msgid="658110271822807811">"搜索"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"发送"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 4eed27c..415c1ac 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"更新"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"網絡狀態"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"網絡通知"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"有可用的網絡"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN 狀態"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"裝置管理"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"通知"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋已逾時。請再試一次。"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋操作已取消。"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"嘗試次數過多,請稍後再試。"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"嘗試次數過多,指紋感應器已停用。"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"再試一次。"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 0c4ffad..36f9a9e 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -260,8 +260,7 @@
     <string name="notification_channel_updates" msgid="4794517569035110397">"更新"</string>
     <string name="notification_channel_network_status" msgid="5025648583129035447">"網路狀態"</string>
     <string name="notification_channel_network_alerts" msgid="2895141221414156525">"網路警示"</string>
-    <!-- no translation found for notification_channel_network_available (4531717914138179517) -->
-    <skip />
+    <string name="notification_channel_network_available" msgid="4531717914138179517">"有可用的網路"</string>
     <string name="notification_channel_vpn" msgid="8330103431055860618">"VPN 狀態"</string>
     <string name="notification_channel_device_admin" msgid="1568154104368069249">"裝置管理"</string>
     <string name="notification_channel_alerts" msgid="4496839309318519037">"快訊"</string>
@@ -492,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"指紋處理作業逾時,請再試一次。"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"指紋作業已取消。"</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"嘗試次數過多,請稍後再試。"</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"嘗試次數過多,指紋感應器已停用。"</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"請再試一次。"</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"手指 <xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 2ce9696..ff35931 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -491,8 +491,7 @@
     <string name="fingerprint_error_timeout" msgid="3927186043737732875">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string>
     <string name="fingerprint_error_canceled" msgid="4402024612660774395">"Ukusebenza kwezingxivizo zeminwe kukhanseliwe."</string>
     <string name="fingerprint_error_lockout" msgid="5536934748136933450">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string>
-    <!-- no translation found for fingerprint_error_lockout_permanent (5033251797919508137) -->
-    <skip />
+    <string name="fingerprint_error_lockout_permanent" msgid="5033251797919508137">"Imizamo eminingi kakhulu. Inzwa yezigxivizo zeminwe ikhutshaziwe."</string>
     <string name="fingerprint_error_unable_to_process" msgid="6107816084103552441">"Zama futhi."</string>
     <string name="fingerprint_name_template" msgid="5870957565512716938">"Umunwe ongu-<xliff:g id="FINGERID">%d</xliff:g>"</string>
   <string-array name="fingerprint_error_vendor">
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6640102..8e6c402 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2849,6 +2849,11 @@
     <!-- Default data warning level in mb -->
     <integer name="default_data_warning_level_mb">2048</integer>
 
+    <!-- When true, indicates that the vendor's IMS implementation requires a workaround when
+     sending a request to enable or disable the camera while the video session is also
+     paused. -->
+    <bool name="config_useVideoPauseWorkaround">false</bool>
+
     <!-- Whether to send a custom package name with the PSD.-->
     <bool name="config_sendPackageName">false</bool>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fcabe31..f747d3d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3225,7 +3225,7 @@
     <skip />
     <!-- Name of notification channel the system post notification to inform the use about apps
          that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
-    <string name="alert_windows_notification_channel_name">App activity</string>
+    <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
     <!-- Notification title when an application is displaying ui on-top of other apps
          [CHAR LIMIT=30] -->
     <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 51d5b1e..8d2666e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3005,7 +3005,7 @@
   <java-symbol type="bool" name="enable_pbap_pce_profile" />
 
   <java-symbol type="integer" name="default_data_warning_level_mb" />
-
+  <java-symbol type="bool" name="config_useVideoPauseWorkaround" />
   <java-symbol type="bool" name="config_sendPackageName" />
   <java-symbol type="string" name="config_helpPackageNameKey" />
   <java-symbol type="string" name="config_helpPackageNameValue" />
diff --git a/core/tests/coretests/res/layout/messaging_linear_layout_test.xml b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
index 8ba3e07..9e70ca3 100644
--- a/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
+++ b/core/tests/coretests/res/layout/messaging_linear_layout_test.xml
@@ -19,7 +19,6 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:maxHeight="300px"
     android:spacing="5px">
 
 </com.android.internal.widget.MessagingLinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
index 1850d57..c83e798 100644
--- a/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
+++ b/core/tests/coretests/src/android/app/LoaderLifecycleTest.java
@@ -17,6 +17,13 @@
 
 package android.app;
 
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertNotSame;
+import static junit.framework.TestCase.assertSame;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 import android.content.Context;
 import android.os.Handler;
 import android.os.Parcelable;
@@ -24,14 +31,11 @@
 import android.support.test.rule.ActivityTestRule;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.ArrayMap;
+
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import static junit.framework.TestCase.assertNotNull;
-import static junit.framework.TestCase.assertNotSame;
-import static junit.framework.TestCase.assertSame;
-
 @RunWith(AndroidJUnit4.class)
 public class LoaderLifecycleTest {
     @Rule
@@ -203,6 +207,16 @@
 
             // Test that the fragments are in the configuration we expect
             final Fragment restoredOne = fm2.findFragmentByTag("one");
+            try {
+                restoredOne.getLoaderManager();
+                fail("A restored fragment on the back stack doesn't have a host, so it should "
+                        + "throw an exception");
+            } catch (IllegalStateException e) {
+                // expected
+            }
+            fm2.popBackStackImmediate();
+            // Now restoredOne should be added and should be in a good state.
+            assertTrue(restoredOne.isAdded());
             final LoaderManager lm2 = restoredOne.getLoaderManager();
 
             assertSame("didn't get same LoaderManager instance back", lm2, lm1);
diff --git a/core/tests/coretests/src/android/transition/FadeTransitionTest.java b/core/tests/coretests/src/android/transition/FadeTransitionTest.java
index 7e7e815..0140a04 100644
--- a/core/tests/coretests/src/android/transition/FadeTransitionTest.java
+++ b/core/tests/coretests/src/android/transition/FadeTransitionTest.java
@@ -50,7 +50,7 @@
         TransitionLatch latch = setVisibilityInTransition(fadeOut, R.id.square1, View.INVISIBLE);
         assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS));
         assertEquals(View.VISIBLE, square1.getVisibility());
-        Thread.sleep(100);
+        waitForAnimation();
         assertFalse(square1.getTransitionAlpha() == 0 || square1.getTransitionAlpha() == 1);
         assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS));
         assertEquals(1.0f, square1.getTransitionAlpha());
@@ -60,7 +60,7 @@
         latch = setVisibilityInTransition(fadeIn, R.id.square1, View.VISIBLE);
         assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS));
         assertEquals(View.VISIBLE, square1.getVisibility());
-        Thread.sleep(100);
+        waitForAnimation();
         final float transitionAlpha = square1.getTransitionAlpha();
         assertTrue("expecting transitionAlpha to be between 0 and 1. Was " + transitionAlpha,
                 transitionAlpha > 0 && transitionAlpha < 1);
@@ -77,7 +77,7 @@
         fadeOut.addListener(fadeOutValueCheck);
         TransitionLatch outLatch = setVisibilityInTransition(fadeOut, R.id.square1, View.INVISIBLE);
         assertTrue(outLatch.startLatch.await(200, TimeUnit.MILLISECONDS));
-        Thread.sleep(100);
+        waitForAnimation();
 
         Fade fadeIn = new Fade(Fade.MODE_IN);
         FadeValueCheck fadeInValueCheck = new FadeValueCheck(square1);
@@ -110,7 +110,7 @@
         fadeIn.addListener(fadeInValueCheck);
         TransitionLatch inLatch = setVisibilityInTransition(fadeIn, R.id.square1, View.VISIBLE);
         assertTrue(inLatch.startLatch.await(200, TimeUnit.MILLISECONDS));
-        Thread.sleep(100);
+        waitForAnimation();
 
         Fade fadeOut = new Fade(Fade.MODE_OUT);
         FadeValueCheck fadeOutValueCheck = new FadeValueCheck(square1);
@@ -145,6 +145,23 @@
         return latch;
     }
 
+    /**
+     * Waits for two animation frames to ensure animation values change.
+     */
+    private void waitForAnimation() throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(2);
+        mActivity.getWindow().getDecorView().postOnAnimation(new Runnable() {
+            @Override
+            public void run() {
+                latch.countDown();
+                if (latch.getCount() > 0) {
+                    mActivity.getWindow().getDecorView().postOnAnimation(this);
+                }
+            }
+        });
+        assertTrue(latch.await(1, TimeUnit.SECONDS));
+    }
+
     public static class TransitionLatch implements TransitionListener {
         public CountDownLatch startLatch = new CountDownLatch(1);
         public CountDownLatch endLatch = new CountDownLatch(1);
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index ebab129..5a7bca4 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -50,14 +50,11 @@
 
 import android.content.ClipData;
 import android.content.ClipboardManager;
-import android.text.TextUtils;
-import android.text.Spanned;
 import android.support.test.espresso.NoMatchingViewException;
 import android.support.test.espresso.ViewAssertion;
 import android.view.ActionMode;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
 import android.view.textclassifier.TextClassificationManager;
 import android.view.textclassifier.TextClassifier;
 import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider;
@@ -72,8 +69,6 @@
 
 import com.android.frameworks.coretests.R;
 
-import junit.framework.AssertionFailedError;
-
 /**
  * Tests the TextView widget from an Activity
  */
@@ -694,6 +689,51 @@
         assertFalse(textView.hasTransientState());
     }
 
+    public void testResetMenuItemTitle() throws Exception {
+        getActivity().getSystemService(TextClassificationManager.class).setTextClassifier(null);
+        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
+        final int itemId = 1;
+        final String title1 = " AFIGBO";
+        final int index = title1.indexOf('I');
+        final String title2 = title1.substring(index);
+        final String[] title = new String[]{title1};
+        textView.post(() -> textView.setCustomSelectionActionModeCallback(
+                new ActionMode.Callback() {
+                    @Override
+                    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
+                        return true;
+                    }
+
+                    @Override
+                    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
+                        menu.removeItem(itemId);
+                        menu.add(Menu.NONE /* group */, itemId, 0 /* order */, title[0]);
+                        return true;
+                    }
+
+                    @Override
+                    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
+                        return false;
+                    }
+
+                    @Override
+                    public void onDestroyActionMode(ActionMode actionMode) {
+                    }
+                }));
+        onView(withId(R.id.textview)).perform(replaceText(title1));
+        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(index));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarContainsItem(title1);
+
+        // Change the menu item title.
+        title[0] = title2;
+        // Change the selection to invalidate the action mode without restarting it.
+        onHandleView(com.android.internal.R.id.selection_start_handle)
+                .perform(dragHandle(textView, Handle.SELECTION_START, index));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarContainsItem(title2);
+    }
+
     public void testAssistItemIsAtIndexZero() throws Exception {
         getActivity().getSystemService(TextClassificationManager.class).setTextClassifier(null);
         final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
index d8de70c..9aabdbb 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
@@ -100,6 +100,55 @@
         assertEquals(227_000, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
     }
 
+    /** Test that BatteryStatsImpl.Uid.mOnBatteryScreenOffBackgroundTimeBase works correctly. */
+    @SmallTest
+    public void testScreenOffBgTimeBase() throws Exception {
+        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+        long cur = 0; // realtime in us
+
+        BatteryStatsImpl.TimeBase bgtb = bi.getOnBatteryScreenOffBackgroundTimeBase(UID);
+
+        // battery=off, screen=off, background=off
+        cur = (clocks.realtime = clocks.uptime = 100) * 1000;
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+        bi.updateTimeBasesLocked(false, false, cur, cur);
+        assertFalse(bgtb.isRunning());
+
+        // battery=on, screen=off, background=off
+        cur = (clocks.realtime = clocks.uptime = 200) * 1000;
+        bi.updateTimeBasesLocked(true, false, cur, cur);
+        assertFalse(bgtb.isRunning());
+
+        // battery=on, screen=on, background=off
+        cur = (clocks.realtime = clocks.uptime = 300) * 1000;
+        bi.updateTimeBasesLocked(true, true, cur, cur);
+        assertFalse(bgtb.isRunning());
+
+        // battery=on, screen=on, background=on
+        // Only during this period should the timebase progress
+        cur = (clocks.realtime = clocks.uptime = 400) * 1000;
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+        assertTrue(bgtb.isRunning());
+
+        // battery=on, screen=off, background=on
+        cur = (clocks.realtime = clocks.uptime = 550) * 1000;
+        bi.updateTimeBasesLocked(true, false, cur, cur);
+        assertFalse(bgtb.isRunning());
+
+        // battery=off, screen=off, background=on
+        cur = (clocks.realtime = clocks.uptime = 660) * 1000;
+        bi.updateTimeBasesLocked(false, false, cur, cur);
+        assertFalse(bgtb.isRunning());
+
+        // battery=off, screen=off, background=off
+        cur = (clocks.realtime = clocks.uptime = 770) * 1000;
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+        assertFalse(bgtb.isRunning());
+
+        assertEquals(150_000, bgtb.computeRealtime(cur, STATS_SINCE_CHARGED));
+    }
+
     @SmallTest
     public void testWifiScan() throws Exception {
         final MockClocks clocks = new MockClocks();
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index e374e11..06ca18d 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -16,7 +16,10 @@
 package com.android.internal.os;
 
 import static android.os.BatteryStats.STATS_SINCE_CHARGED;
+import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
 
+import android.app.ActivityManager;
+import android.os.BatteryStats;
 import android.os.WorkSource;
 import android.support.test.filters.SmallTest;
 
@@ -29,7 +32,7 @@
     private static final int UID = 10500;
     private static final WorkSource WS = new WorkSource(UID);
 
-    /** Test that BatteryStatsImpl.Uid.noteBluetoothScanResultsLocked. */
+    /** Test BatteryStatsImpl.Uid.noteBluetoothScanResultLocked. */
     @SmallTest
     public void testNoteBluetoothScanResultLocked() throws Exception {
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(new MockClocks());
@@ -41,4 +44,30 @@
                 bi.getUidStats().get(UID).getBluetoothScanResultCounter()
                         .getCountLocked(STATS_SINCE_CHARGED));
     }
+
+    /** Test BatteryStatsImpl.Uid.noteStartWakeLocked. */
+    @SmallTest
+    public void testNoteStartWakeLocked() throws Exception {
+        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+
+        int pid = 10;
+        String name = "name";
+
+        bi.updateTimeBasesLocked(true, true, 0, 0);
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
+        bi.getUidStatsLocked(UID).noteStartWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);
+
+        clocks.realtime = clocks.uptime = 100;
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+
+        clocks.realtime = clocks.uptime = 220;
+        bi.getUidStatsLocked(UID).noteStopWakeLocked(pid, name, WAKE_TYPE_PARTIAL, clocks.realtime);
+
+        BatteryStats.Timer aggregTimer = bi.getUidStats().get(UID).getAggregatedPartialWakelockTimer();
+        long actualTime = aggregTimer.getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
+        long bgTime = aggregTimer.getSubTimer().getTotalTimeLocked(300_000, STATS_SINCE_CHARGED);
+        assertEquals(220_000, actualTime);
+        assertEquals(120_000, bgTime);
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
index ad8221b..620acae 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.support.test.filters.SmallTest;
@@ -27,6 +28,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import java.io.BufferedReader;
@@ -70,18 +72,70 @@
                 times[i][j] = uids[i] * freqs[j] * 10;
             }
         }
-        final String[] uidsTimesLines = getUidTimesLines(uids, times);
-        final String[] lines = new String[uidsTimesLines.length + 1];
-        System.arraycopy(uidsTimesLines, 0, lines, 0, uidsTimesLines.length);
-        lines[uidsTimesLines.length] = null;
         when(mBufferedReader.readLine())
-                .thenReturn(getFreqsLine(freqs), lines);
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, times));
         mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
         verify(mCallback).onCpuFreqs(freqs);
         for (int i = 0; i < uids.length; ++i) {
             verify(mCallback).onUidCpuFreqTime(uids[i], times[i]);
         }
         verifyNoMoreInteractions(mCallback);
+
+        // Verify that a second call will only return deltas.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] newTimes1 = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                newTimes1[i][j] = (times[i][j] + uids[i] + freqs[j]) * 10;
+            }
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        for (int i = 0; i < uids.length; ++i) {
+            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes1[i], times[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that calling with a null callback doesn't result in any crashes
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] newTimes2 = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                newTimes2[i][j] = (newTimes1[i][j] + uids[i] * freqs[j]) * 10;
+            }
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, null);
+        verifyZeroInteractions(mCallback);
+
+        // Verify that the readDelta call will only return deltas when
+        // the previous call had null callback.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] newTimes3 = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                newTimes3[i][j] = (newTimes2[i][j] * (uids[i] + freqs[j])) * 10;
+            }
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes3));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        for (int i = 0; i < uids.length; ++i) {
+            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes3[i], newTimes2[i]));
+        }
+        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 getFreqsLine(long[] freqs) {
@@ -94,7 +148,7 @@
     }
 
     private String[] getUidTimesLines(int[] uids, long[][] times) {
-        final String[] lines = new String[uids.length];
+        final String[] lines = new String[uids.length + 1];
         final StringBuilder sb = new StringBuilder();
         for (int i = 0; i < uids.length; ++i) {
             sb.setLength(0);
@@ -104,6 +158,7 @@
             }
             lines[i] = sb.toString();
         }
+        lines[uids.length] = null;
         return lines;
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
new file mode 100644
index 0000000..4a23f40
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/LongSamplingCounterArrayTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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 android.os.BatteryStats.STATS_SINCE_CHARGED;
+
+import static com.android.internal.os.BatteryStatsImpl.LongSamplingCounterArray;
+import static com.android.internal.os.BatteryStatsImpl.TimeBase;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+
+/**
+ * Test class for {@link BatteryStatsImpl.LongSamplingCounterArray}.
+ *
+ * To run the tests, use
+ *
+ * runtest -c com.android.internal.os.LongSamplingCounterArrayTest frameworks-core
+ *
+ * or the following steps:
+ *
+ * Build: m FrameworksCoreTests
+ * Install: adb install -r \
+ *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+ * Run: adb shell am instrument -e class com.android.internal.os.LongSamplingCounterArrayTest -w \
+ *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LongSamplingCounterArrayTest {
+
+    private static final long[] COUNTS = {1111, 2222, 3333, 4444};
+    private static final long[] LOADED_COUNTS = {5555, 6666, 7777, 8888};
+    private static final long[] PLUGGED_COUNTS = {9999, 11111, 22222, 33333};
+    private static final long[] UNPLUGGED_COUNTS = {44444, 55555, 66666, 77777};
+    private static final long[] ZEROES = {0, 0, 0, 0};
+
+    @Mock private TimeBase mTimeBase;
+    private LongSamplingCounterArray mCounterArray;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mCounterArray = new LongSamplingCounterArray(mTimeBase);
+        Mockito.reset(mTimeBase);
+    }
+
+    @Test
+    public void testReadWriteParcel() {
+        final Parcel parcel = Parcel.obtain();
+        initializeCounterArrayWithDefaultValues();
+        LongSamplingCounterArray.writeToParcel(parcel, mCounterArray);
+        parcel.setDataPosition(0);
+
+        // Now clear counterArray and verify values are read from parcel correctly.
+        updateCounts(null, null, null, null);
+        mCounterArray = LongSamplingCounterArray.readFromParcel(parcel, mTimeBase);
+        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+                "Unexpected unpluggedCounts");
+        parcel.recycle();
+    }
+
+    @Test
+    public void testReadWriteSummaryParcel() {
+        final Parcel parcel = Parcel.obtain();
+        initializeCounterArrayWithDefaultValues();
+        LongSamplingCounterArray.writeSummaryToParcelLocked(parcel, mCounterArray);
+        parcel.setDataPosition(0);
+
+        // Now clear counterArray and verify values are read from parcel correctly.
+        updateCounts(null, null, null, null);
+        mCounterArray = LongSamplingCounterArray.readSummaryFromParcelLocked(parcel, mTimeBase);
+        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        parcel.recycle();
+    }
+
+    @Test
+    public void testOnTimeStarted() {
+        initializeCounterArrayWithDefaultValues();
+        mCounterArray.onTimeStarted(0, 0, 0);
+        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+                "Unexpected unpluggedCounts");
+    }
+
+    @Test
+    public void testOnTimeStopped() {
+        initializeCounterArrayWithDefaultValues();
+        mCounterArray.onTimeStopped(0, 0, 0);
+        assertArrayEquals(COUNTS, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+                "Unexpected unpluggedCounts");
+    }
+
+    @Test
+    public void testGetCountsLocked() {
+        initializeCounterArrayWithDefaultValues();
+
+        when(mTimeBase.isRunning()).thenReturn(false);
+        long[] actualVal = mCounterArray.getCountsLocked(STATS_SINCE_CHARGED);
+        long[] expectedVal = PLUGGED_COUNTS;
+        assertArrayEquals(expectedVal, actualVal, "Unexpected values");
+
+        when(mTimeBase.isRunning()).thenReturn(true);
+        actualVal = mCounterArray.getCountsLocked(STATS_SINCE_CHARGED);
+        expectedVal = COUNTS;
+        assertArrayEquals(expectedVal, actualVal, "Unexpected values");
+    }
+
+    @Test
+    public void testAddCountLocked() {
+        final long[] deltas = {123, 234, 345, 456};
+        mCounterArray.addCountLocked(deltas);
+        assertArrayEquals(deltas, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(null, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(null, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(null, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+
+        initializeCounterArrayWithDefaultValues();
+        final long[] newCounts = new long[deltas.length];
+        for (int i = 0; i < deltas.length; ++i) {
+            newCounts[i] = COUNTS[i] + deltas[i];
+        }
+        mCounterArray.addCountLocked(deltas);
+        assertArrayEquals(newCounts, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(LOADED_COUNTS, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(PLUGGED_COUNTS, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(UNPLUGGED_COUNTS, mCounterArray.mUnpluggedCounts,
+                "Unexpected unpluggedCounts");
+    }
+
+    @Test
+    public void testReset() {
+        initializeCounterArrayWithDefaultValues();
+        // Test with detachIfReset=false
+        mCounterArray.reset(false /* detachIfReset */);
+        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        verifyZeroInteractions(mTimeBase);
+
+        initializeCounterArrayWithDefaultValues();
+        // Test with detachIfReset=true
+        mCounterArray.reset(true /* detachIfReset */);
+        assertArrayEquals(ZEROES, mCounterArray.mCounts, "Unexpected counts");
+        assertArrayEquals(ZEROES, mCounterArray.mLoadedCounts, "Unexpected loadedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mPluggedCounts, "Unexpected pluggedCounts");
+        assertArrayEquals(ZEROES, mCounterArray.mUnpluggedCounts, "Unexpected unpluggedCounts");
+        verify(mTimeBase).remove(mCounterArray);
+        verifyNoMoreInteractions(mTimeBase);
+    }
+
+    @Test
+    public void testDetach() {
+        mCounterArray.detach();
+        verify(mTimeBase).remove(mCounterArray);
+        verifyNoMoreInteractions(mTimeBase);
+    }
+
+    private void initializeCounterArrayWithDefaultValues() {
+        updateCounts(COUNTS, LOADED_COUNTS, PLUGGED_COUNTS, UNPLUGGED_COUNTS);
+    }
+
+    private void assertArrayEquals(long[] expected, long[] actual, String msg) {
+        assertTrue(msg + ", expected: " + Arrays.toString(expected)
+                + ", actual: " + Arrays.toString(actual), Arrays.equals(expected, actual));
+    }
+
+    private void updateCounts(long[] counts, long[] loadedCounts,
+            long[] pluggedCounts, long[] unpluggedCounts) {
+        mCounterArray.mCounts = counts;
+        mCounterArray.mLoadedCounts = loadedCounts;
+        mCounterArray.mPluggedCounts = pluggedCounts;
+        mCounterArray.mUnpluggedCounts = unpluggedCounts;
+    }
+}
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 65f898c..a123fce 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -44,5 +44,9 @@
     public TimeBase getOnBatteryBackgroundTimeBase(int uid) {
         return getUidStatsLocked(uid).mOnBatteryBackgroundTimeBase;
     }
+
+    public TimeBase getOnBatteryScreenOffBackgroundTimeBase(int uid) {
+        return getUidStatsLocked(uid).mOnBatteryScreenOffBackgroundTimeBase;
+    }
 }
 
diff --git a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
index 5dc07c2..906d7e9 100644
--- a/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/ImageFloatingTextViewTest.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.widget;
 
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
@@ -111,6 +111,9 @@
         mTextView.measure(widthMeasureSpec, heightMeasureSpec);
         mView.measure(widthMeasureSpec, heightMeasureSpec);
 
-        assertEquals(mTextView.getMeasuredHeight(), mView.getMeasuredHeight());
+        // We're at most allowed to be the same height as the regular textview and maybe a bit
+        // smaller since our layout snaps to full textlines.
+        assertTrue("The measured view should never be taller then the normal textview!",
+                mView.getMeasuredHeight() <= mTextView.getMeasuredHeight());
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
index 75b2c1d..20fd4d3 100644
--- a/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/MessagingLinearLayoutTest.java
@@ -21,7 +21,6 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.os.Debug;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.core.deps.guava.base.Function;
 import android.support.test.filters.SmallTest;
@@ -46,8 +45,7 @@
     @Before
     public void setup() {
         mContext = InstrumentationRegistry.getTargetContext();
-        // maxHeight: 300px
-        // spacing: 50px
+        // spacing: 5px
         mView = (MessagingLinearLayout) LayoutInflater.from(mContext).inflate(
                 R.layout.messaging_linear_layout_test, null);
     }
@@ -81,8 +79,8 @@
 
         assertEquals(3, child1.getNumIndentLines());
         assertEquals(0, child2.getNumIndentLines());
-        assertFalse(child1.isHidden());
-        assertFalse(child2.isHidden());
+        assertFalse("child1 should not be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
         assertEquals(205, mView.getMeasuredHeight());
     }
 
@@ -100,8 +98,8 @@
 
         assertEquals(2, child1.getNumIndentLines());
         assertEquals(1, child2.getNumIndentLines());
-        assertFalse(child1.isHidden());
-        assertFalse(child2.isHidden());
+        assertFalse("child1 should not be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
         assertEquals(105, mView.getMeasuredHeight());
     }
 
@@ -118,14 +116,14 @@
         mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
 
         assertEquals(3, child2.getNumIndentLines());
-        assertTrue(child1.isHidden());
-        assertFalse(child2.isHidden());
-        assertEquals(300, mView.getMeasuredHeight());
+        assertTrue("child1 should be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
+        assertEquals(350, mView.getMeasuredHeight());
     }
 
     @Test
-    public void testLargeSmall_largeWrapsWith3indentbutnot3_andHitsMax() {
-        FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 5 : 4);
+    public void testLargeSmall_largeWrapsWith3indentbutNotFullHeight_andHitsMax() {
+        FakeImageFloatingTextView child1 = fakeChild((i) -> i > 2 ? 7 : 6);
         FakeImageFloatingTextView child2 = fakeChild((i) -> 1);
 
         mView.setNumIndentLines(2);
@@ -135,10 +133,11 @@
         mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
         mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
 
-        assertTrue(child1.isHidden());
-        assertFalse(child2.isHidden());
-        assertEquals(50, mView.getMeasuredHeight());
-        assertEquals(2, child2.getNumIndentLines());
+        assertFalse("child1 should not be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
+        assertEquals(355, mView.getMeasuredHeight());
+        assertEquals(3, child1.getNumIndentLines());
+        assertEquals(0, child2.getNumIndentLines());
     }
 
     @Test
@@ -153,8 +152,8 @@
         mView.measure(WIDTH_SPEC, HEIGHT_SPEC);
         mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight());
 
-        assertFalse(child1.isHidden());
-        assertFalse(child2.isHidden());
+        assertFalse("child1 should not be hidden", child1.isHidden());
+        assertFalse("child2 should not be hidden", child2.isHidden());
         assertEquals(255, mView.getMeasuredHeight());
         assertEquals(3, child1.getNumIndentLines());
         assertEquals(0, child2.getNumIndentLines());
@@ -184,10 +183,23 @@
         }
 
         @Override
+        public int getLayoutHeight() {
+            return Math.max(LINE_HEIGHT, getMeasuredHeight());
+        }
+
+        @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
             setMeasuredDimension(
                     getDefaultSize(500, widthMeasureSpec),
-                    resolveSize(getDesiredHeight(), heightMeasureSpec));
+                    clampToMultiplesOfLineHeight(resolveSize(getDesiredHeight(),
+                            heightMeasureSpec)));
+        }
+
+        private int clampToMultiplesOfLineHeight(int size) {
+            if (size <= LINE_HEIGHT) {
+                return size;
+            }
+            return (size / LINE_HEIGHT) * LINE_HEIGHT;
         }
 
         @Override
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index 0b1141a..70a5f53 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -76,8 +76,9 @@
                 mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
     }
 
+    /** @hide */
     @Override
-    void verifyNativeInstance() {
+    protected void verifyNativeInstance() {
         if (mShaderA.getNativeInstance() != mNativeInstanceShaderA
                 || mShaderB.getNativeInstance() != mNativeInstanceShaderB) {
             // Child shader native instance has been updated,
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 8410ab2..0209cea 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -19,6 +19,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
+import libcore.util.NativeAllocationRegistry;
+
 /**
  * Shader is the based class for objects that return horizontal spans of colors
  * during drawing. A subclass of Shader is installed in a Paint calling
@@ -26,6 +28,12 @@
  * drawn with that paint will get its color(s) from the shader.
  */
 public class Shader {
+
+    private static class NoImagePreloadHolder {
+        public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                Shader.class.getClassLoader(), nativeGetFinalizer(), 50);
+    }
+
     /**
      * @deprecated Use subclass constructors directly instead.
      */
@@ -37,6 +45,8 @@
      * is called - otherwise may be out of date with java setters/properties.
      */
     private long mNativeInstance;
+    // Runnable to do immediate destruction
+    private Runnable mCleaner;
 
     /**
      * Current matrix - always set to null if local matrix is identity.
@@ -80,7 +90,8 @@
 
     /**
      * Set the shader's local matrix. Passing null will reset the shader's
-     * matrix to identity.
+     * matrix to identity. If the matrix has scale value as 0, the drawing
+     * result is undefined.
      *
      * @param localM The shader's new local matrix, or null to specify identity
      */
@@ -105,9 +116,11 @@
         return 0;
     }
 
-    void discardNativeInstance() {
+    /** @hide */
+    protected final void discardNativeInstance() {
         if (mNativeInstance != 0) {
-            nativeSafeUnref(mNativeInstance);
+            mCleaner.run();
+            mCleaner = null;
             mNativeInstance = 0;
         }
     }
@@ -115,20 +128,9 @@
     /**
      * Callback for subclasses to call {@link #discardNativeInstance()} if the most recently
      * constructed native instance is no longer valid.
+     * @hide
      */
-    void verifyNativeInstance() {
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            if (mNativeInstance != 0) {
-                nativeSafeUnref(mNativeInstance);
-            }
-            mNativeInstance = -1;
-        } finally {
-            super.finalize();
-        }
+    protected void verifyNativeInstance() {
     }
 
     /**
@@ -150,20 +152,20 @@
     /**
      * @hide
      */
-    public long getNativeInstance() {
-        if (mNativeInstance == -1) {
-            throw new IllegalStateException("attempting to use a finalized Shader");
-        }
-
+    public final long getNativeInstance() {
         // verify mNativeInstance is valid
         verifyNativeInstance();
 
         if (mNativeInstance == 0) {
             mNativeInstance = createNativeInstance(mLocalMatrix == null
                     ? 0 : mLocalMatrix.native_instance);
+            mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
+                    this, mNativeInstance);
         }
         return mNativeInstance;
     }
 
-    private static native void nativeSafeUnref(long nativeInstance);
+    private static native long nativeGetFinalizer();
+
 }
+
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index bfd0604..8f314c9 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -58,11 +58,11 @@
  * mask using {@code setId(..., android.R.id.mask)} or an existing mask layer
  * may be replaced using {@code setDrawableByLayerId(android.R.id.mask, ...)}.
  * <pre>
- * <code>&lt!-- A red ripple masked against an opaque rectangle. --/>
- * &ltripple android:color="#ffff0000">
- *   &ltitem android:id="@android:id/mask"
+ * <code>&lt;!-- A red ripple masked against an opaque rectangle. --/>
+ * &lt;ripple android:color="#ffff0000">
+ *   &lt;item android:id="@android:id/mask"
  *         android:drawable="@android:color/white" />
- * &lt/ripple></code>
+ * &lt;/ripple></code>
  * </pre>
  * <p>
  * If a mask layer is set, the ripple effect will be masked against that layer
@@ -71,15 +71,15 @@
  * If no mask layer is set, the ripple effect is masked against the composite
  * of the child layers.
  * <pre>
- * <code>&lt!-- A green ripple drawn atop a black rectangle. --/>
- * &ltripple android:color="#ff00ff00">
- *   &ltitem android:drawable="@android:color/black" />
- * &lt/ripple>
+ * <code>&lt;!-- A green ripple drawn atop a black rectangle. --/>
+ * &lt;ripple android:color="#ff00ff00">
+ *   &lt;item android:drawable="@android:color/black" />
+ * &lt;/ripple>
  *
- * &lt!-- A blue ripple drawn atop a drawable resource. --/>
- * &ltripple android:color="#ff0000ff">
- *   &ltitem android:drawable="@drawable/my_drawable" />
- * &lt/ripple></code>
+ * &lt;!-- A blue ripple drawn atop a drawable resource. --/>
+ * &lt;ripple android:color="#ff0000ff">
+ *   &lt;item android:drawable="@drawable/my_drawable" />
+ * &lt;/ripple></code>
  * </pre>
  * <p>
  * If no child layers or mask is specified and the ripple is set as a View
@@ -87,8 +87,8 @@
  * background within the View's hierarchy. In this case, the drawing region
  * may extend outside of the Drawable bounds.
  * <pre>
- * <code>&lt!-- An unbounded red ripple. --/>
- * &ltripple android:color="#ffff0000" /></code>
+ * <code>&lt;!-- An unbounded red ripple. --/>
+ * &lt;ripple android:color="#ffff0000" /></code>
  * </pre>
  *
  * @attr ref android.R.styleable#RippleDrawable_color
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index a0366de..2fdfcd4 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -223,7 +223,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void Caches::clearGarbage() {
-    textureCache.clearGarbage();
     pathCache.clearGarbage();
     patchCache.clearGarbage();
 }
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 63a6a2c..710cdd9 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -191,25 +191,14 @@
     return texture;
 }
 
-void TextureCache::releaseTexture(uint32_t pixelRefStableID) {
-    Mutex::Autolock _l(mLock);
-    mGarbage.push_back(pixelRefStableID);
-}
-
-void TextureCache::clearGarbage() {
-    Mutex::Autolock _l(mLock);
-    size_t count = mGarbage.size();
-    for (size_t i = 0; i < count; i++) {
-        uint32_t pixelRefId = mGarbage[i];
-        auto hardwareIter = mHardwareTextures.find(pixelRefId);
-        if (hardwareIter == mHardwareTextures.end()) {
-            mCache.remove(pixelRefId);
-        } else {
-            hardwareIter->second->deleteTexture();
-            mHardwareTextures.erase(hardwareIter);
-        }
+bool TextureCache::destroyTexture(uint32_t pixelRefStableID) {
+    auto hardwareIter = mHardwareTextures.find(pixelRefStableID);
+    if (hardwareIter != mHardwareTextures.end()) {
+        hardwareIter->second->deleteTexture();
+        mHardwareTextures.erase(hardwareIter);
+        return true;
     }
-    mGarbage.clear();
+    return mCache.remove(pixelRefStableID);
 }
 
 void TextureCache::clear() {
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index db4ff39..776ff8a 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -94,14 +94,10 @@
     Texture* get(Bitmap* bitmap);
 
     /**
-     * Removes the texture associated with the specified pixelRef. This is meant
-     * to be called from threads that are not the EGL context thread.
+     * Removes the texture associated with the specified pixelRef. Must be called from RenderThread
+     * Returns true if a texture was destroyed, false if no texture with that id was found
      */
-    ANDROID_API void releaseTexture(uint32_t pixelRefStableID);
-    /**
-     * Process deferred removals.
-     */
-    void clearGarbage();
+    bool destroyTexture(uint32_t pixelRefStableID);
 
     /**
      * Clears the cache. This causes all textures to be deleted.
@@ -139,9 +135,7 @@
 
     bool mDebugEnabled;
 
-    std::vector<uint32_t> mGarbage;
     std::unordered_map<uint32_t, std::unique_ptr<Texture>> mHardwareTextures;
-    mutable Mutex mLock;
 }; // class TextureCache
 
 }; // namespace uirenderer
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index b0e486d..bb1e674 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -16,7 +16,6 @@
 #include "Bitmap.h"
 
 #include "Caches.h"
-#include "pipeline/skia/SkiaOpenGLPipeline.h"
 #include "renderthread/EglManager.h"
 #include "renderthread/RenderThread.h"
 #include "renderthread/RenderProxy.h"
@@ -35,15 +34,11 @@
 #include <private/gui/ComposerService.h>
 #include <binder/IServiceManager.h>
 #include <ui/PixelFormat.h>
-#include <GrTexture.h>
 
 #include <SkCanvas.h>
-#include <SkImagePriv.h>
 
 namespace android {
 
-Mutex Bitmap::gLock;
-
 static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
     int32_t rowBytes32 = SkToS32(rowBytes);
     int64_t bigSize = (int64_t) height * rowBytes32;
@@ -322,7 +317,8 @@
         return nullptr;
     }
     SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
-            kRGBA_8888_SkColorType, kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
+            kRGBA_8888_SkColorType, kPremul_SkAlphaType,
+            SkColorSpace::MakeSRGB());
     return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info));
 }
 
@@ -397,7 +393,6 @@
     mPixelStorage.hardware.buffer = buffer;
     buffer->incStrong(buffer);
     mRowBytes = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride();
-    setImmutable(); // HW bitmaps are always immutable
 }
 
 Bitmap::~Bitmap() {
@@ -421,9 +416,7 @@
 
     }
 
-    if (android::uirenderer::Caches::hasInstance()) {
-        android::uirenderer::Caches::getInstance().textureCache.releaseTexture(getStableID());
-    }
+    android::uirenderer::renderthread::RenderProxy::onBitmapDestroyed(getStableID());
 }
 
 bool Bitmap::hasHardwareMipMap() const {
@@ -506,9 +499,13 @@
 }
 
 void Bitmap::getSkBitmapForShaders(SkBitmap* outBitmap) {
-    outBitmap->setInfo(info(), rowBytes());
-    outBitmap->setPixelRef(this);
-    outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
+    if (isHardware() && uirenderer::Properties::isSkiaEnabled()) {
+        getSkBitmap(outBitmap);
+    } else {
+        outBitmap->setInfo(info(), rowBytes());
+        outBitmap->setPixelRef(this);
+        outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
+    }
 }
 
 void Bitmap::getBounds(SkRect* bounds) const {
@@ -523,28 +520,4 @@
     return nullptr;
 }
 
-sk_sp<SkImage> Bitmap::makeImage(const uirenderer::renderthread::RenderThread* renderThread) {
-    AutoMutex _lock(gLock); //TODO: implement lock free solution
-    auto image = mImage;
-    //TODO: use new API SkImage::isValid() instead of SkImage::getTexture()->getContext()
-    if (!image.get() || (image->getTexture() && nullptr == image->getTexture()->getContext())) {
-        if (isHardware() && uirenderer::RenderPipelineType::SkiaGL
-                == uirenderer::Properties::getRenderPipelineType()) {
-            //TODO: add Vulkan support
-            if (renderThread) {
-                image = uirenderer::skiapipeline::SkiaOpenGLPipeline::makeTextureImage(
-                        *renderThread, this);
-            } else {
-                image = uirenderer::renderthread::RenderProxy::makeTextureImage(this);
-            }
-        } else {
-            SkBitmap skiaBitmap;
-            getSkBitmapForShaders(&skiaBitmap);
-            image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
-        }
-        mImage = image;
-    }
-    return image;
-}
-
 } // namespace android
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 621e439..da45f76 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -22,8 +22,6 @@
 #include <SkPixelRef.h>
 #include <cutils/compiler.h>
 #include <ui/GraphicBuffer.h>
-#include <utils/Mutex.h>
-#include <SkImage.h>
 
 namespace android {
 
@@ -113,13 +111,6 @@
     }
 
     GraphicBuffer* graphicBuffer();
-
-    // makeImage creates or returns a cached SkImage. Can be invoked from UI or render thread.
-    // If invoked on the render thread, then RenderThread* argument is required.
-    // If not invoked on the render thread, then RenderThread* must be nullptr.
-    // makeImage is wrapping a gralloc buffer with an EGLImage and is passing a texture to Skia.
-    // This is a temporary implementation until Skia can wrap the gralloc buffer in a SkImage.
-    sk_sp<SkImage> makeImage(const uirenderer::renderthread::RenderThread*);
 protected:
     virtual bool onNewLockPixels(LockRec* rec) override;
     virtual void onUnlockPixels() override { };
@@ -154,9 +145,6 @@
             GraphicBuffer* buffer;
         } hardware;
     } mPixelStorage;
-
-    sk_sp<SkImage> mImage;
-    static Mutex gLock;
 };
 
 } //namespace android
\ No newline at end of file
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 4885873..ae13131 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -28,8 +28,6 @@
 
 #include <cutils/properties.h>
 #include <strings.h>
-#include <SkImagePriv.h>
-#include <gl/GrGLTypes.h>
 
 using namespace android::uirenderer::renderthread;
 
@@ -199,87 +197,6 @@
     }
 }
 
-static void deleteImageTexture(void* context) {
-     EGLImageKHR EGLimage = reinterpret_cast<EGLImageKHR>(context);
-     if (EGLimage != EGL_NO_IMAGE_KHR) {
-        EGLDisplay display = eglGetCurrentDisplay();
-        if (EGL_NO_DISPLAY == display) {
-            display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        }
-        eglDestroyImageKHR(display, EGLimage);
-     }
-}
-
-sk_sp<SkImage> SkiaOpenGLPipeline::makeTextureImage(
-        const uirenderer::renderthread::RenderThread& renderThread, Bitmap* bitmap) {
-    renderThread.eglManager().initialize();
-
-    GraphicBuffer* buffer = bitmap->graphicBuffer();
-    EGLDisplay display = eglGetCurrentDisplay();
-    if (EGL_NO_DISPLAY == display) {
-        display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    }
-    LOG_ALWAYS_FATAL_IF(!bitmap->isHardware(),
-                "Texture image requires a HW bitmap.");
-    // We use an EGLImage to access the content of the GraphicBuffer
-    // The EGL image is later bound to a 2D texture
-    EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer->getNativeBuffer();
-    EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
-    EGLImageKHR EGLimage = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
-            clientBuffer, imageAttrs);
-    if (EGLimage == EGL_NO_IMAGE_KHR) {
-        ALOGW("Could not create EGL image, err =%s",
-                uirenderer::renderthread::EglManager::eglErrorString());
-        return nullptr;
-    }
-
-    GLuint textureId = 0;
-    glGenTextures(1, &textureId);
-    glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, EGLimage);
-
-    GLenum status = GL_NO_ERROR;
-    while ((status = glGetError()) != GL_NO_ERROR) {
-        ALOGW("glEGLImageTargetTexture2DOES failed (%#x)", status);
-        eglDestroyImageKHR(display, EGLimage);
-        return nullptr;
-    }
-
-    sk_sp<GrContext> grContext = sk_ref_sp(renderThread.getGrContext());
-    grContext->resetContext();
-
-    GrGLTextureInfo textureInfo;
-    textureInfo.fTarget = GL_TEXTURE_EXTERNAL_OES;
-    textureInfo.fID = textureId;
-
-    GrBackendTextureDesc textureDescription;
-    textureDescription.fWidth = bitmap->info().width();
-    textureDescription.fHeight = bitmap->info().height();
-    textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin;
-    textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&textureInfo);
-    PixelFormat format = buffer->getPixelFormat();
-    switch (format) {
-    case PIXEL_FORMAT_RGBA_8888:
-        textureDescription.fConfig = kRGBA_8888_GrPixelConfig;
-        break;
-    case PIXEL_FORMAT_RGBA_FP16:
-        textureDescription.fConfig = kRGBA_half_GrPixelConfig;
-        break;
-    default:
-        eglDestroyImageKHR(display, EGLimage);
-        return nullptr;
-    }
-
-    // TODO: add color correctness - pass null color space for now
-    sk_sp<SkImage> image = SkImage::MakeFromTexture(grContext.get(), textureDescription,
-                bitmap->info().alphaType(), nullptr, deleteImageTexture, EGLimage);
-    if (!image.get()) {
-        eglDestroyImageKHR(display, EGLimage);
-        return nullptr;
-    }
-    return image;
-}
-
 } /* namespace skiapipeline */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index f3ce189..36685dd 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -46,8 +46,6 @@
     bool isContextReady() override;
 
     static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
-    static sk_sp<SkImage> makeTextureImage(
-            const uirenderer::renderthread::RenderThread& renderThread, Bitmap* bitmap);
 
 private:
     renderthread::EglManager& mEglManager;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index 1a6e709..a18d264 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -61,7 +61,6 @@
     textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture);
 
     CopyResult copyResult = CopyResult::UnknownError;
-    // TODO: add color correctness - pass null color space for now
     sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), textureDescription));
     if (image) {
         SkAutoLockPixels alp(*bitmap);
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 349d4cc..10c1865 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -155,11 +155,11 @@
     GrContext* context = thread.getGrContext();
     if (context) {
         ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
-        auto image = bitmap->makeImage(&thread);
-        if (image.get() && !bitmap->isHardware()) {
-            SkImage_pinAsTexture(image.get(), context);
-            SkImage_unpinAsTexture(image.get(), context);
-        }
+        SkBitmap skiaBitmap;
+        bitmap->getSkBitmap(&skiaBitmap);
+        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
+        SkImage_pinAsTexture(image.get(), context);
+        SkImage_unpinAsTexture(image.get(), context);
     }
 }
 
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 5d7bbfa..559d268 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -168,8 +168,11 @@
 }
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
-    sk_sp<SkImage> image = bitmap.makeImage(nullptr);
-    if (!bitmap.isImmutable()) {
+    SkBitmap skBitmap;
+    bitmap.getSkBitmap(&skBitmap);
+
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skBitmap, kNever_SkCopyPixelsMode);
+    if (!skBitmap.isImmutable()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
     SkPaint tmpPaint;
@@ -178,10 +181,12 @@
 
 void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix,
         const SkPaint* paint) {
+    SkBitmap bitmap;
+    hwuiBitmap.getSkBitmap(&bitmap);
     SkAutoCanvasRestore acr(&mRecorder, true);
     concat(matrix);
-    sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
-    if (!hwuiBitmap.isImmutable()) {
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    if (!bitmap.isImmutable()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
     SkPaint tmpPaint;
@@ -191,10 +196,12 @@
 void SkiaRecordingCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop,
         float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
         float dstBottom, const SkPaint* paint) {
+    SkBitmap bitmap;
+    hwuiBitmap.getSkBitmap(&bitmap);
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
-    sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
-    if (!hwuiBitmap.isImmutable()) {
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    if (!bitmap.isImmutable()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
     SkPaint tmpPaint;
@@ -203,8 +210,11 @@
 
 void SkiaRecordingCanvas::drawNinePatch(Bitmap& hwuiBitmap, const Res_png_9patch& chunk,
         float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) {
+    SkBitmap bitmap;
+    hwuiBitmap.getSkBitmap(&bitmap);
+
     SkCanvas::Lattice lattice;
-    NinePatchUtils::SetLatticeDivs(&lattice, chunk, hwuiBitmap.width(), hwuiBitmap.height());
+    NinePatchUtils::SetLatticeDivs(&lattice, chunk, bitmap.width(), bitmap.height());
 
     lattice.fFlags = nullptr;
     int numFlags = 0;
@@ -221,8 +231,8 @@
 
     lattice.fBounds = nullptr;
     SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
-    sk_sp<SkImage> image = hwuiBitmap.makeImage(nullptr);
-    if (!hwuiBitmap.isImmutable()) {
+    sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
+    if (!bitmap.isImmutable()) {
         mDisplayList->mMutableImages.push_back(image.get());
     }
 
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index c8833d2..ed96d49 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -122,6 +122,13 @@
     mCaches->flush(mode);
 }
 
+void RenderState::onBitmapDestroyed(uint32_t pixelRefId) {
+    if (mCaches && mCaches->textureCache.destroyTexture(pixelRefId)) {
+        glFlush();
+        GL_CHECKPOINT(MODERATE);
+    }
+}
+
 void RenderState::setViewport(GLsizei width, GLsizei height) {
     mViewportWidth = width;
     mViewportHeight = height;
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index f78bf7a..787946f 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -63,6 +63,7 @@
     void onVkContextDestroyed();
 
     void flush(Caches::FlushMode flushMode);
+    void onBitmapDestroyed(uint32_t pixelRefId);
 
     void setViewport(GLsizei width, GLsizei height);
     void getViewport(GLsizei* outWidth, GLsizei* outHeight);
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 5c2ec0e..eed5238 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -24,6 +24,7 @@
 #include "renderthread/EglManager.h"
 #include "renderthread/RenderTask.h"
 #include "renderthread/RenderThread.h"
+#include "renderstate/RenderState.h"
 #include "utils/Macros.h"
 #include "utils/TimeUtils.h"
 
@@ -693,16 +694,18 @@
     }
 }
 
-CREATE_BRIDGE2(makeTextureImage, RenderThread* thread, Bitmap* bitmap) {
-    return args->thread->makeTextureImage(args->bitmap).release();
+CREATE_BRIDGE2(onBitmapDestroyed, RenderThread* thread, uint32_t pixelRefId) {
+    args->thread->renderState().onBitmapDestroyed(args->pixelRefId);
+    return nullptr;
 }
 
-sk_sp<SkImage> RenderProxy::makeTextureImage(Bitmap* bitmap) {
-    SETUP_TASK(makeTextureImage);
-    args->bitmap = bitmap;
-    args->thread = &RenderThread::getInstance();
-    sk_sp<SkImage> hardwareImage(reinterpret_cast<SkImage*>(staticPostAndWait(task)));
-    return hardwareImage;
+void RenderProxy::onBitmapDestroyed(uint32_t pixelRefId) {
+    if (!RenderThread::hasInstance()) return;
+    SETUP_TASK(onBitmapDestroyed);
+    RenderThread& thread = RenderThread::getInstance();
+    args->thread = &thread;
+    args->pixelRefId = pixelRefId;
+    thread.queue(task);
 }
 
 void RenderProxy::post(RenderTask* task) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 97ad796..b21772c 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -136,7 +136,7 @@
 
     static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap);
 
-    static sk_sp<SkImage> makeTextureImage(Bitmap* bitmap);
+    static void onBitmapDestroyed(uint32_t pixelRefId);
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index d62b556..1450ec9 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -17,7 +17,6 @@
 #include "RenderThread.h"
 
 #include "../renderstate/RenderState.h"
-#include "../pipeline/skia/SkiaOpenGLPipeline.h"
 #include "../pipeline/skia/SkiaOpenGLReadback.h"
 #include "CanvasContext.h"
 #include "EglManager.h"
@@ -434,24 +433,6 @@
     return next;
 }
 
-sk_sp<SkImage> RenderThread::makeTextureImage(Bitmap* bitmap) {
-    auto renderType = Properties::getRenderPipelineType();
-    sk_sp<SkImage> hardwareImage;
-    switch (renderType) {
-        case RenderPipelineType::SkiaGL:
-            hardwareImage = skiapipeline::SkiaOpenGLPipeline::makeTextureImage(*this, bitmap);
-            break;
-        case RenderPipelineType::SkiaVulkan:
-            //TODO: add Vulkan support
-            break;
-        default:
-            LOG_ALWAYS_FATAL("makeTextureImage: canvas context type %d not supported",
-                    (int32_t) renderType);
-            break;
-    }
-    return hardwareImage;
-}
-
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 34542c6..9bc5985 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -33,7 +33,6 @@
 
 namespace android {
 
-class Bitmap;
 class DisplayEventReceiver;
 
 namespace uirenderer {
@@ -105,8 +104,6 @@
 
     VulkanManager& vulkanManager() { return *mVkManager; }
 
-    sk_sp<SkImage> makeTextureImage(Bitmap* bitmap);
-
 protected:
     virtual bool threadLoop() override;
 
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index b1dc3ad..9841815 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -40,7 +40,7 @@
  * <p>When an application requests audio focus, it expresses its intention to “own” audio focus to
  * play audio. Let’s review the different types of focus requests, the return value after a request,
  * and the responses to a loss.
- * <br><b>Note:<b> applications should not play anything until granted focus.
+ * <p class="note">Note: applications should not play anything until granted focus.</p>
  *
  * <h3>The different types of focus requests</h3>
  * <p>There are four focus request types. A successful focus request with each will yield different
@@ -77,9 +77,10 @@
  *
  * <p>An {@code AudioFocusRequest} instance always contains one of the four types of requests
  * explained above. It is passed when building an {@code AudioFocusRequest} instance with its
- * builder in the {@link Builder} constructor {@link Builder#Builder(int)}, or with
- * {@link Builder#setFocusGain(int)} after copying an existing instance with
- * {@link Builder#Builder(AudioFocusRequest)}.
+ * builder in the {@link Builder} constructor
+ * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(int)}, or
+ * with {@link AudioFocusRequest.Builder#setFocusGain(int)} after copying an existing instance with
+ * {@link AudioFocusRequest.Builder#AudioFocusRequest.Builder(AudioFocusRequest)}.
  *
  * <h3>Qualifying your focus request</h3>
  * <h4>Use case requiring a focus request</h4>
@@ -105,10 +106,11 @@
  * <h4>Pausing vs ducking</h4>
  * <p>When an application requested audio focus with
  * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, the system will duck the current focus
- * owner. Note that this behavior is <b>new for Android O<b>, whereas applications targeting SDK
- * up to API 25, applications had to implement the ducking themselves when they received a focus
+ * owner.
+ * <p class="note">Note: this behavior is <b>new for Android O</b>, whereas applications targeting
+ * SDK level up to API 25 had to implement the ducking themselves when they received a focus
  * loss of {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
- * <br>But ducking is not always the behavior expected by the user. A typical example is when the
+ * <p>But ducking is not always the behavior expected by the user. A typical example is when the
  * device plays driving directions while the user is listening to an audio book or podcast, and
  * expects the audio playback to pause, instead of duck, as it is hard to understand a navigation
  * prompt and spoken content at the same time. Therefore the system will not automatically duck
@@ -126,7 +128,92 @@
  * speech, you can also declare so with {@link Builder#setWillPauseWhenDucked(boolean)}, which will
  * cause the system to call your focus listener instead of automatically ducking.
  *
+ * <h4>Example</h4>
+ * <p>The example below covers the following steps to be found in any application that would play
+ * audio, and use audio focus. Here we play an audio book, and our application is intended to pause
+ * rather than duck when it loses focus. These steps consist in:
+ * <ul>
+ * <li>Creating {@code AudioAttributes} to be used for the playback and the focus request.</li>
+ * <li>Configuring and creating the {@code AudioFocusRequest} instance that defines the intended
+ *     focus behaviors.</li>
+ * <li>Requesting audio focus and checking the return code to see if playback can happen right
+ *     away, or is delayed.</li>
+ * <li>Implementing a focus change listener to respond to focus gains and losses.</li>
+ * </ul>
+ * <p>
+ * <pre class="prettyprint">
+ * // initialization of the audio attributes and focus request
+ * mAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
+ * mPlaybackAttributes = new AudioAttributes.Builder()
+ *         .setUsage(AudioAttributes.USAGE_MEDIA)
+ *         .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
+ *         .build();
+ * mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
+ *         .setAudioAttributes(mPlaybackAttributes)
+ *         .setAcceptsDelayedFocusGain(true)
+ *         .setWillPauseWhenDucked(true)
+ *         .setOnAudioFocusChangeListener(this, mMyHandler)
+ *         .build();
+ * mMediaPlayer = new MediaPlayer();
+ * mMediaPlayer.setAudioAttributes(mPlaybackAttributes);
+ * final Object mFocusLock = new Object();
+ *
+ * boolean mPlaybackDelayed = false;
+ *
+ * // requesting audio focus
+ * int res = mAudioManager.requestAudioFocus(mFocusRequest);
+ * synchronized (mFocusLock) {
+ *     if (res == AUDIOFOCUS_REQUEST_FAILED) {
+ *         mPlaybackDelayed = false;
+ *     } else if (res == AUDIOFOCUS_REQUEST_GRANTED) {
+ *         mPlaybackDelayed = false;
+ *         playbackNow();
+ *     } else if (res == AUDIOFOCUS_REQUEST_DELAYED) {
+ *        mPlaybackDelayed = true;
+ *     }
+ * }
+ *
+ * // implementation of the OnAudioFocusChangeListener
+ * &#64;Override
+ * public void onAudioFocusChange(int focusChange) {
+ *     switch (focusChange) {
+ *         case AudioManager.AUDIOFOCUS_GAIN:
+ *             if (mPlaybackDelayed || mResumeOnFocusGain) {
+ *                 synchronized (mFocusLock) {
+ *                     mPlaybackDelayed = false;
+ *                     mResumeOnFocusGain = false;
+ *                 }
+ *                 playbackNow();
+ *             }
+ *             break;
+ *         case AudioManager.AUDIOFOCUS_LOSS:
+ *             synchronized (mFocusLock) {
+ *                 // this is not a transient loss, we shouldn't automatically resume for now
+ *                 mResumeOnFocusGain = false;
+ *                 mPlaybackDelayed = false;
+ *             }
+ *             pausePlayback();
+ *             break;
+ *         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+ *         case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
+ *             // we handle all transient losses the same way because we never duck audio books
+ *             synchronized (mFocusLock) {
+ *                 // we should only resume if playback was interrupted
+ *                 mResumeOnFocusGain = mMediaPlayer.isPlaying();
+ *                 mPlaybackDelayed = false;
+ *             }
+ *             pausePlayback();
+ *             break;
+ *     }
+ * }
+ *
+ * // Important:
+ * // Also set "mResumeOnFocusGain" to false when the user pauses or stops playback: this way your
+ * // application doesn't automatically restart when it gains focus, even though the user had
+ * // stopped it.
+ * </pre>
  */
+
 public final class AudioFocusRequest {
 
     // default attributes for the request when not specified
@@ -244,36 +331,15 @@
 
     /**
      * Builder class for {@link AudioFocusRequest} objects.
-     * <p> Here is an example where {@code Builder} is used to define the
-     * {@link AudioFocusRequest} for requesting audio focus:
-     *
-     * <pre class="prettyprint">
-     * mAudioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
-     * mPlaybackAttributes = new AudioAttributes.Builder()
-     *         .setUsage(AudioAttributes.USAGE_GAME)
-     *         .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
-     *         .build();
-     * mFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
-     *         .setAudioAttributes(mPlaybackAttributes)
-     *         .setAcceptsDelayedFocusGain(true)
-     *         .setOnAudioFocusChangeListener(mMyFocusListener, mMyHandler)
-     *         .build();
-     * mMediaPlayer = new MediaPlayer();
-     *  ...
-     * mMediaPlayer.setAudioAttributes(mPlaybackAttributes);
-     *  ...
-     * boolean mPlaybackAuthorized = true;;
-     * int res = mAudioManager.requestAudioFocus(mFocusRequest);
-     * if (res == AUDIOFOCUS_REQUEST_FAILED) {
-     *     mPlaybackAuthorized = false;
-     *     cancelPlayback();
-     * } else if (res == AUDIOFOCUS_REQUEST_DELAYED) {
-     *     playbackDelayed();
-     * } else { // res == AUDIOFOCUS_REQUEST_GRANTED
-     *     playbackNow();
-     * }
-     * </pre>
-     *
+     * <p>See {@link AudioFocusRequest} for an example of building an instance with this builder.
+     * <br>The default values for the instance to be built are:
+     * <table>
+     * <tr><td>focus listener and handler</td><td>none</td></tr>
+     * <tr><td>{@code AudioAttributes}</td><td>attributes with usage set to
+     *     {@link AudioAttributes#USAGE_MEDIA}</td></tr>
+     * <tr><td>pauses on duck</td><td>false</td></tr>
+     * <tr><td>supports delayed focus grant</td><td>false</td></tr>
+     * </table>
      */
     public static final class Builder {
         private OnAudioFocusChangeListener mFocusListener;
diff --git a/media/java/android/media/VolumeAutomation.java b/media/java/android/media/VolumeAutomation.java
index dff8801..ff2e645 100644
--- a/media/java/android/media/VolumeAutomation.java
+++ b/media/java/android/media/VolumeAutomation.java
@@ -31,9 +31,9 @@
      * @param configuration the {@link VolumeShaper.Configuration configuration}
      *        that specifies the curve and duration to use.
      * @return a {@code VolumeShaper} object
-     * @throws IllegalArgumentException if the configuration is not allowed by the player.
-     * @throws IllegalStateException if too many VolumeShapers are requested or the state of
-     * the player does not permit its creation (e.g. player is released).
+     * @throws IllegalArgumentException if the {@code configuration} is not allowed by the player.
+     * @throws IllegalStateException if too many {@code VolumeShaper}s are requested
+     *         or the state of the player does not permit its creation (e.g. player is released).
      */
     public @NonNull VolumeShaper createVolumeShaper(
             @NonNull VolumeShaper.Configuration configuration);
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 8f4721f..3068706 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -31,8 +31,16 @@
 /**
  * The {@code VolumeShaper} class is used to automatically control audio volume during media
  * playback, allowing simple implementation of transition effects and ducking.
+ * It is created from implementations of {@code VolumeAutomation},
+ * such as {@code MediaPlayer} and {@code AudioTrack} (referred to as "players" below),
+ * by {@link MediaPlayer#createVolumeShaper} or {@link AudioTrack#createVolumeShaper}.
  *
- * The {@link VolumeShaper} appears as an additional scaling on the audio output,
+ * A {@code VolumeShaper} is intended for short volume changes.
+ * If the audio output sink changes during
+ * a {@code VolumeShaper} transition, the precise curve position may be lost, and the
+ * {@code VolumeShaper} may advance to the end of the curve for the new audio output sink.
+ *
+ * The {@code VolumeShaper} appears as an additional scaling on the audio output,
  * and adjusts independently of track or stream volume controls.
  */
 public final class VolumeShaper implements AutoCloseable {
@@ -52,7 +60,19 @@
 
     /**
      * Applies the {@link VolumeShaper.Operation} to the {@code VolumeShaper}.
+     *
+     * Applying {@link VolumeShaper.Operation#PLAY} after {@code PLAY}
+     * or {@link VolumeShaper.Operation#REVERSE} after
+     * {@code REVERSE} has no effect.
+     *
+     * Applying {@link VolumeShaper.Operation#PLAY} when the player
+     * hasn't started will synchronously start the {@code VolumeShaper} when
+     * playback begins.
+     *
      * @param operation the {@code operation} to apply.
+     * @throws IllegalStateException if the player is uninitialized or if there
+     *         is a critical failure. In that case, the {@code VolumeShaper} should be
+     *         recreated.
      */
     public void apply(@NonNull Operation operation) {
         /* void */ applyPlayer(new VolumeShaper.Configuration(mId), operation);
@@ -65,11 +85,24 @@
      * This allows the user to change the volume shape
      * while the existing {@code VolumeShaper} is in effect.
      *
+     * The effect of {@code replace()} is similar to an atomic close of
+     * the existing {@code VolumeShaper} and creation of a new {@code VolumeShaper}.
+     *
+     * If the {@code operation} is {@link VolumeShaper.Operation#PLAY} then the
+     * new curve starts immediately.
+     *
+     * If the {@code operation} is
+     * {@link VolumeShaper.Operation#REVERSE}, then the new curve will
+     * be delayed until {@code PLAY} is applied.
+     *
      * @param configuration the new {@code configuration} to use.
-     * @param operation the operation to apply to the {@code VolumeShaper}
+     * @param operation the {@code operation} to apply to the {@code VolumeShaper}
      * @param join if true, match the start volume of the
      *             new {@code configuration} to the current volume of the existing
      *             {@code VolumeShaper}, to avoid discontinuity.
+     * @throws IllegalStateException if the player is uninitialized or if there
+     *         is a critical failure. In that case, the {@code VolumeShaper} should be
+     *         recreated.
      */
     public void replace(
             @NonNull Configuration configuration, @NonNull Operation operation, boolean join) {
@@ -81,7 +114,14 @@
     /**
      * Returns the current volume scale attributable to the {@code VolumeShaper}.
      *
+     * This is the last volume from the {@code VolumeShaper} used for the player,
+     * or the initial volume if the {@code VolumeShaper} hasn't been started with
+     * {@link VolumeShaper.Operation#PLAY}.
+     *
      * @return the volume, linearly represented as a value between 0.f and 1.f.
+     * @throws IllegalStateException if the player is uninitialized or if there
+     *         is a critical failure.  In that case, the {@code VolumeShaper} should be
+     *         recreated.
      */
     public float getVolume() {
         return getStatePlayer(mId).getVolume();
@@ -89,7 +129,14 @@
 
     /**
      * Releases the {@code VolumeShaper} object; any volume scale due to the
-     * {@code VolumeShaper} is removed.
+     * {@code VolumeShaper} is removed after closing.
+     *
+     * If the volume does not reach 1.f when the {@code VolumeShaper} is closed
+     * (or finalized), there may be an abrupt change of volume.
+     *
+     * {@code close()} may be safely called after a prior {@code close()}.
+     * This class implements the Java {@code AutoClosable} interface and
+     * may be used with try-with-resources.
      */
     @Override
     public void close() {
@@ -107,11 +154,11 @@
 
     @Override
     protected void finalize() {
-        close(); // ensure we remove the native volume shaper
+        close(); // ensure we remove the native VolumeShaper
     }
 
     /**
-     * Internal call to apply the configuration and operation to the Player.
+     * Internal call to apply the {@code configuration} and {@code operation} to the player.
      * Returns a valid shaper id or throws the appropriate exception.
      * @param configuration
      * @param operation
@@ -137,7 +184,7 @@
             // Due to RPC handling, we translate integer codes to exceptions right before
             // delivering to the user.
             if (id == VOLUME_SHAPER_INVALID_OPERATION) {
-                throw new IllegalStateException("player or volume shaper deallocated");
+                throw new IllegalStateException("player or VolumeShaper deallocated");
             } else {
                 throw new IllegalArgumentException("invalid configuration or operation: " + id);
             }
@@ -146,9 +193,9 @@
     }
 
     /**
-     * Internal call to retrieve the current VolumeShaper state.
+     * Internal call to retrieve the current {@code VolumeShaper} state.
      * @param id
-     * @return the current {@vode VolumeShaper.State}
+     * @return the current {@code VolumeShaper.State}
      * @throws IllegalStateException if the player has been deallocated or is uninitialized.
      */
     private @NonNull VolumeShaper.State getStatePlayer(int id) {
@@ -180,6 +227,9 @@
      * by {@link VolumeShaper#replace(Configuration, Operation, boolean)
      * VolumeShaper.replace(Configuration, Operation, boolean)}
      * to replace an existing {@code configuration}.
+     * <p>
+     * The {@link AudioTrack} and {@link MediaPlayer} classes implement
+     * the {@link VolumeAutomation} interface.
      */
     public static final class Configuration implements Parcelable {
         private static final int MAXIMUM_CURVE_POINTS = 16;
@@ -485,7 +535,7 @@
 
         /**
          * @hide
-         * Constructs a volume shaper from an id.
+         * Constructs a {@code VolumeShaper} from an id.
          *
          * This is an opaque handle for controlling a {@code VolumeShaper} that has
          * already been sent to a player.  The {@code id} is returned from the
@@ -756,7 +806,7 @@
             /**
              * Sets the interpolator type.
              *
-             * If omitted the interplator type is {@link #INTERPOLATOR_TYPE_CUBIC}.
+             * If omitted the default interpolator type is {@link #INTERPOLATOR_TYPE_CUBIC}.
              *
              * @param interpolatorType method of interpolation used for the volume curve.
              *        One of {@link #INTERPOLATOR_TYPE_STEP},
@@ -802,7 +852,7 @@
             }
 
             /**
-             * Sets the volume shaper duration in milliseconds.
+             * Sets the {@code VolumeShaper} duration in milliseconds.
              *
              * If omitted, the default duration is 1 second.
              *
@@ -1059,13 +1109,13 @@
 
         /**
          * Defer playback until next operation is sent. This is used
-         * when starting a VolumeShaper effect.
+         * when starting a {@code VolumeShaper} effect.
          */
         private static final int FLAG_DEFER = 1 << 3;
 
         /**
          * Use the id specified in the configuration, creating
-         * VolumeShaper as needed; the configuration should be
+         * {@code VolumeShaper} as needed; the configuration should be
          * TYPE_SCALE.
          */
         private static final int FLAG_CREATE_IF_NEEDED = 1 << 4;
@@ -1074,18 +1124,20 @@
 
         private final int mFlags;
         private final int mReplaceId;
+        private final float mXOffset;
 
         @Override
         public String toString() {
             return "VolumeShaper.Operation{"
                     + "mFlags = 0x" + Integer.toHexString(mFlags).toUpperCase()
                     + ", mReplaceId = " + mReplaceId
+                    + ", mXOffset = " + mXOffset
                     + "}";
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(mFlags, mReplaceId);
+            return Objects.hash(mFlags, mReplaceId, mXOffset);
         }
 
         @Override
@@ -1093,10 +1145,10 @@
             if (!(o instanceof Operation)) return false;
             if (o == this) return true;
             final Operation other = (Operation) o;
-            // if xOffset (native field only) is brought into Java
-            // we need to do proper NaN comparison as that is allowed.
+
             return mFlags == other.mFlags
-                    && mReplaceId == other.mReplaceId;
+                    && mReplaceId == other.mReplaceId
+                    && Float.compare(mXOffset, other.mXOffset) == 0;
         }
 
         @Override
@@ -1109,7 +1161,7 @@
             // this needs to match the native VolumeShaper.Operation parceling
             dest.writeInt(mFlags);
             dest.writeInt(mReplaceId);
-            dest.writeFloat(Float.NaN); // xOffset (ignored at Java level)
+            dest.writeFloat(mXOffset);
         }
 
         public static final Parcelable.Creator<VolumeShaper.Operation> CREATOR
@@ -1119,11 +1171,12 @@
                 // this needs to match the native VolumeShaper.Operation parceling
                 final int flags = p.readInt();
                 final int replaceId = p.readInt();
-                final float xOffset = p.readFloat(); // ignored at Java level
+                final float xOffset = p.readFloat();
 
                 return new VolumeShaper.Operation(
                         flags
-                        , replaceId);
+                        , replaceId
+                        , xOffset);
             }
 
             @Override
@@ -1132,9 +1185,10 @@
             }
         };
 
-        private Operation(@Flag int flags, int replaceId) {
+        private Operation(@Flag int flags, int replaceId, float xOffset) {
             mFlags = flags;
             mReplaceId = replaceId;
+            mXOffset = xOffset;
         }
 
         /**
@@ -1146,6 +1200,7 @@
         public static final class Builder {
             int mFlags;
             int mReplaceId;
+            float mXOffset;
 
             /**
              * Constructs a new {@code Builder} with the defaults.
@@ -1153,23 +1208,27 @@
             public Builder() {
                 mFlags = 0;
                 mReplaceId = -1;
+                mXOffset = Float.NaN;
             }
 
             /**
-             * Constructs a new Builder from a given {@code VolumeShaper.Operation}
+             * Constructs a new {@code Builder} from a given {@code VolumeShaper.Operation}
              * @param operation the {@code VolumeShaper.operation} whose data will be
-             *        reused in the new Builder.
+             *        reused in the new {@code Builder}.
              */
             public Builder(@NonNull VolumeShaper.Operation operation) {
                 mReplaceId = operation.mReplaceId;
                 mFlags = operation.mFlags;
+                mXOffset = operation.mXOffset;
             }
 
             /**
-             * Replaces the previous {@code VolumeShaper} specified by id.
-             * It has no other effect if the {@code VolumeShaper} is
-             * already expired.
-             * @param id the id of the previous {@code VolumeShaper}.
+             * Replaces the previous {@code VolumeShaper} specified by {@code id}.
+             *
+             * The {@code VolumeShaper} specified by the {@code id} is removed
+             * if it exists. The configuration should be TYPE_SCALE.
+             *
+             * @param id the {@code id} of the previous {@code VolumeShaper}.
              * @param join if true, match the volume of the previous
              * shaper to the start volume of the new {@code VolumeShaper}.
              * @return the same {@code Builder} instance.
@@ -1194,8 +1253,9 @@
             }
 
             /**
-             * Terminates the VolumeShaper.
-             * Do not call directly, use {@link VolumeShaper#release()}.
+             * Terminates the {@code VolumeShaper}.
+             *
+             * Do not call directly, use {@link VolumeShaper#close()}.
              * @return the same {@code Builder} instance.
              */
             public @NonNull Builder terminate() {
@@ -1214,8 +1274,12 @@
 
             /**
              * Use the id specified in the configuration, creating
-             * VolumeShaper as needed; the configuration should be
+             * {@code VolumeShaper} only as needed; the configuration should be
              * TYPE_SCALE.
+             *
+             * If the {@code VolumeShaper} with the same id already exists
+             * then the operation has no effect.
+             *
              * @return the same {@code Builder} instance.
              */
             public @NonNull Builder createIfNeeded() {
@@ -1224,6 +1288,28 @@
             }
 
             /**
+             * Sets the {@code xOffset} to use for the {@code VolumeShaper}.
+             *
+             * The {@code xOffset} is the position on the volume curve,
+             * and setting takes effect when the {@code VolumeShaper} is used next.
+             *
+             * @param xOffset a value between (or equal to) 0.f and 1.f, or Float.NaN to ignore.
+             * @return the same {@code Builder} instance.
+             * @throws IllegalArgumentException if {@code xOffset} is not between 0.f and 1.f,
+             *         or a Float.NaN.
+             */
+            public @NonNull Builder setXOffset(float xOffset) {
+                if (xOffset < -0.f) {
+                    throw new IllegalArgumentException("Negative xOffset not allowed");
+                } else if (xOffset > 1.f) {
+                    throw new IllegalArgumentException("xOffset > 1.f not allowed");
+                }
+                // Float.NaN passes through
+                mXOffset = xOffset;
+                return this;
+            }
+
+            /**
              * Sets the operation flag.  Do not call this directly but one of the
              * other builder methods.
              *
@@ -1245,7 +1331,7 @@
              * @return a new {@code VolumeShaper.Operation} object
              */
             public @NonNull Operation build() {
-                return new Operation(mFlags, mReplaceId);
+                return new Operation(mFlags, mReplaceId, mXOffset);
             }
         } // Operation.Builder
     } // Operation
@@ -1316,15 +1402,18 @@
 
         /**
          * Gets the volume of the {@link VolumeShaper.State}.
+         * @return linear volume between 0.f and 1.f.
          */
         public float getVolume() {
             return mVolume;
         }
 
         /**
-         * Gets the elapsed ms of the {@link VolumeShaper.State}
+         * Gets the {@code xOffset} position on the normalized curve
+         * of the {@link VolumeShaper.State}.
+         * @return the curve x position between 0.f and 1.f.
          */
-        public double getXOffset() {
+        public float getXOffset() {
             return mXOffset;
         }
     } // State
diff --git a/media/jni/android_media_VolumeShaper.h b/media/jni/android_media_VolumeShaper.h
index 73498a2..1a13ffa 100644
--- a/media/jni/android_media_VolumeShaper.h
+++ b/media/jni/android_media_VolumeShaper.h
@@ -40,6 +40,7 @@
         jmethodID opConstructId;
         jfieldID  opFlagsId;
         jfieldID  opReplaceIdId;
+        jfieldID  opXOffsetId;
 
         // VolumeShaper.State
         jclass    stClazz;
@@ -74,9 +75,10 @@
             if (opClazz == nullptr) {
                 return;
             }
-            opConstructId = env->GetMethodID(opClazz, "<init>", "(II)V");
+            opConstructId = env->GetMethodID(opClazz, "<init>", "(IIF)V");
             opFlagsId = env->GetFieldID(opClazz, "mFlags", "I");
             opReplaceIdId = env->GetFieldID(opClazz, "mReplaceId", "I");
+            opXOffsetId = env->GetFieldID(opClazz, "mXOffset", "F");
             env->DeleteLocalRef(lclazz);
 
             lclazz = env->FindClass("android/media/VolumeShaper$State");
@@ -179,17 +181,20 @@
         VolumeShaper::Operation::Flag flags =
             (VolumeShaper::Operation::Flag)env->GetIntField(joperation, fields.opFlagsId);
         int replaceId = env->GetIntField(joperation, fields.opReplaceIdId);
+        float xOffset = env->GetFloatField(joperation, fields.opXOffsetId);
 
-        sp<VolumeShaper::Operation> operation = new VolumeShaper::Operation(flags, replaceId);
+        sp<VolumeShaper::Operation> operation =
+                new VolumeShaper::Operation(flags, replaceId, xOffset);
         return operation;
     }
 
     static jobject convertOperationToJobject(
             JNIEnv *env, const fields_t &fields, const sp<VolumeShaper::Operation> &operation) {
         // prepare constructor args
-        jvalue args[2];
+        jvalue args[3];
         args[0].i = (jint)operation->getFlags();
         args[1].i = (jint)operation->getReplaceId();
+        args[2].f = (jfloat)operation->getXOffset();
 
         jobject joperation = env->NewObjectA(fields.opClazz, fields.opConstructId, args);
         return joperation;
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 401012f..d4cc3fb 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -86,6 +86,7 @@
     case NO_MEMORY:
         return AUDIOEFFECT_ERROR_NO_MEMORY;
     case DEAD_OBJECT:
+    case FAILED_TRANSACTION: // Hidl crash shows as FAILED_TRANSACTION: -2147483646
         return AUDIOEFFECT_ERROR_DEAD_OBJECT;
     default:
         return AUDIOEFFECT_ERROR;
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index b145290..0cf21d2 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -93,9 +93,9 @@
     }
 
     @Override
-    protected void onPause() {
-        super.onPause();
-        if (!isFinishing()) {
+    protected void onStop() {
+        super.onStop();
+        if (!isFinishing() && !isChangingConfigurations()) {
             cancel();
         }
     }
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml
index 843b313..8d79f62 100644
--- a/packages/MtpDocumentsProvider/AndroidManifest.xml
+++ b/packages/MtpDocumentsProvider/AndroidManifest.xml
@@ -22,7 +22,6 @@
                   android:label="@string/downloads_app_label"
                   android:icon="@mipmap/ic_launcher_download"
                   android:theme="@android:style/Theme.NoDisplay"
-                  android:screenOrientation="locked"
                   android:excludeFromRecents="true">
             <intent-filter>
                 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
index c5292b8..fe79266 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/ServiceIntentSender.java
@@ -18,6 +18,8 @@
 
 import android.annotation.NonNull;
 import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -27,10 +29,21 @@
  * Sends intent to MtpDocumentsService.
  */
 class ServiceIntentSender {
+    private final static String CHANNEL_ID = "device_notification_channel";
     private Context mContext;
 
     ServiceIntentSender(Context context) {
         mContext = context;
+
+        // Create notification channel.
+        final NotificationChannel mChannel = new NotificationChannel(
+                CHANNEL_ID,
+                context.getResources().getString(
+                        com.android.internal.R.string.default_notification_channel_label),
+                NotificationManager.IMPORTANCE_LOW);
+        final NotificationManager notificationManager =
+                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.createNotificationChannel(mChannel);
     }
 
     /**
@@ -60,12 +73,11 @@
         final String title = context.getResources().getString(
                 R.string.accessing_notification_title,
                 device.name);
-        return new Notification.Builder(context)
+        return new Notification.Builder(context, CHANNEL_ID)
                 .setLocalOnly(true)
                 .setContentTitle(title)
                 .setSmallIcon(com.android.internal.R.drawable.stat_sys_data_usb)
                 .setCategory(Notification.CATEGORY_SYSTEM)
-                .setPriority(Notification.PRIORITY_LOW)
                 .setFlag(Notification.FLAG_NO_CLEAR, true)
                 .build();
     }
diff --git a/packages/SettingsLib/res/color/batterymeter_frame_color.xml b/packages/SettingsLib/res/color/meter_background_color.xml
similarity index 100%
rename from packages/SettingsLib/res/color/batterymeter_frame_color.xml
rename to packages/SettingsLib/res/color/meter_background_color.xml
diff --git a/packages/SettingsLib/res/color/batterymeter_charge_color.xml b/packages/SettingsLib/res/color/meter_consumed_color.xml
similarity index 100%
rename from packages/SettingsLib/res/color/batterymeter_charge_color.xml
rename to packages/SettingsLib/res/color/meter_consumed_color.xml
diff --git a/packages/SettingsLib/res/layout/restricted_switch_preference.xml b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
index 0e4ef6b..64b47b6 100644
--- a/packages/SettingsLib/res/layout/restricted_switch_preference.xml
+++ b/packages/SettingsLib/res/layout/restricted_switch_preference.xml
@@ -27,7 +27,7 @@
         android:id="@+id/icon_container"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:minWidth="60dp"
+        android:minWidth="56dp"
         android:gravity="start|center_vertical"
         android:orientation="horizontal"
         android:paddingEnd="12dp"
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index e89b21a..4f52812 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Agtergrondproses-limiet"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Wys alle ANRe"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Wys Program reageer nie-dialoog vir agtergrond programme"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Programme verplig ekstern toegelaat"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Maak dat enige program in eksterne berging geskryf kan word, ongeag manifeswaardes"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Verplig verstelbare groottes vir aktiwiteite"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index d8150d1..465e253 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"የዳራ አሂድ ወሰን"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ሁሉንም ANRs አሳይ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ለዳራ መተግበሪያዎች ምላሽ የማይሰጥ መገናኛ ትግበራ አሳይ"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"በውጫዊ ላይ ሃይል ይፈቀዳል"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"የዝርዝር ሰነዶች እሴቶች ግምት ውስጥ ሳያስገባ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻው ለመጻፍ ብቁ ያደርጋል"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"እንቅስቃሴዎች ዳግመኛ እንዲመጣጠኑ አስገድድ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 034653f..a4ee8fd 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"حد العمليات بالخلفية"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"‏عرض جميع رسائل ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"عرض مربع الحوار \"التطبيق لا يستجيب\" مع تطبيقات الخلفية"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"فرض السماح للتطبيقات على الخارجي"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"تأهيل أي تطبيق بحيث تتم كتابته على وحدة تخزين خارجية، بغض النظر عن قيم البيان"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"فرض إمكانية تغيير على الأنشطة"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 603f6918..690e589 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Fon prosesi limiti"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Bütün ANRları göstər"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Arxa tətbiqlər dialoquna cavab verməyən tətbiqi göstər"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tətbiqlərə xaricdən məcburi icazə"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Ölçü dəyişdirmək üçün məcburi fəaliyyətlər"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 70c6e47..e59dac6 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje pozadinskih procesa"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaži dijalog Aplikacija ne reaguje za aplikacije u pozadini"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Prinudno dozvoli aplikacije u spoljnoj"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Prinudno omogući promenu veličine aktivnosti"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index f8eec7f..b1ec8678 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ліміт фонавага працэсу"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Паказаць усе ANRS"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Паказаць дыялогавае акно \"Праграма не адказвае\" для фонавых прыкладанняў"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Прымусова дазволіць праграмы на вонкавым сховішчы"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Робіць любую праграму даступнай для запісу на вонкавае сховішча, незалежна ад значэнняў маніфеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Зрабіць вокны дзеянняў даступнымі для змены памеру"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 53c50b9..a8039eb 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Лимит за фонови процеси"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Всички нереагиращи прил."</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Диалог. прозорец „НП“ за приложения на заден план"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Външно хран.: Принуд. разрешаване на приложенията"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Прави всички приложения да отговарят на условията да бъдат записвани във външното хранилище независимо от стойностите в манифеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Възможност за преоразмеряване на активностите"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 841c96e..3f0de25 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"পশ্চাদপট প্রক্রিয়ার সীমা"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"সব ANR দেখান"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"পশ্চাদপটের অ্যাপ্লিকেশানগুলির জন্য অ্যাপ্লিকেশান কোনো প্রতিক্রিয়া দিচ্ছে না এমন কথোপকথন দেখান"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"বহিরাগততে বলপূর্বক মঞ্জুরি"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 451a1ff..f91a8a8 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje procesa u pozadini"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prik. dijalog Aplikacija ne reagira za apl. u poz."</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Nametni aplikacije na vanjskoj pohrani"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava da svaka aplikacija bude pogodna za upisivanje na vanjsku pohranu, bez obzira na prikazane vrijednosti"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni aktivnostima mijenjanje veličina"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 2a4db1d..99c5d37 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Límita processos en segon pla"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Tots els errors sense resposta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informa que una aplicació en segon pla no respon"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Força permís d\'aplicacions a l\'emmagatzem. extern"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permet que qualsevol aplicació es pugui escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Força l\'ajust de la mida de les activitats"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 673d51b..7b3fb86 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Omezení procesů na pozadí"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Zobrazit všechny ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Zobrazovat dialog „Aplikace neodpovídá“ pro aplikace na pozadí"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vynutit povolení aplikací na externím úložišti"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vynutit možnost změny velikosti aktivit"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index aa0becf..6ccf45b 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Grænse for baggrundsprocesser"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Vis alle \"Appen svarer ikke\""</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Vis \"Appen svarer ikke\" for baggrundsapps"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Gennemtving tilladelse til eksternt lager"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til at kunne tilpasses"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 0a2cf33..db58ab2 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Hintergrundprozesslimit"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Alle ANRS anzeigen"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Dialogfeld \"App antwortet nicht\" für Hintergrund-Apps anzeigen"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Externe Speichernutzung von Apps erlauben"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Anpassen der Größe von Aktivitäten erzwingen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 24d3bf4..cde2066 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Όριο διεργασ. παρασκηνίου"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Εμφάνιση όλων των ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Εμφ.του παραθ. \"Η εφαρμ.δεν αποκρ.\" για εφ.παρασκ."</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Να επιτρέπονται υποχρεωτικά εφαρμογές σε εξωτ.συσ."</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό αποθηκευτικό χώρο, ανεξάρτητα από τις τιμές του μανιφέστου"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Αναγκαστική δυνατότητα αλλαγής μεγέθους δραστηριοτήτων"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 6b9daf7..b252545 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Background process limit"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 6b9daf7..b252545 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Background process limit"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 6b9daf7..b252545 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Background process limit"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 1464d44..03d8cea9 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Límite de procesos en segundo plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Errores sin respuesta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostrar diálogo cuando las aplic. en 2do plano no responden"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permisos en almacenamiento externo"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Cualquier app puede escribirse en un almacenamiento externo, sin importar los valores del manifiesto"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar actividades para que cambien de tamaño"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 39d4a76..00dbf9c 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Límitar procesos en segundo plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Errores sin respuesta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informar de que una aplicación en segundo plano no responde"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicaciones de forma externa"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hace que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar el ajuste de tamaño de las actividades"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 36d19ef..4d0f5f6 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Taustaprotsesside piir"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Näita kõiki ANR-e"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Kuva taustarakendustele dial. Rakendus ei reageeri"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Luba rakendused välises salvestusruumis"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Lubab mis tahes rakendusi kirjutada välisesse salvestusruumi manifesti väärtustest olenemata"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Muuda tegevuste suurused muudetavaks"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index fd20d47..6ed2d75 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Atzeko planoko prozesuen muga"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Erakutsi ANR guztiak"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"\"Erantzunik ez\" mezua atz. planoko aplikazioetarako"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Behartu aplikazioak onartzea kanpoko biltegian"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Behartu jardueren tamaina doitu ahal izatea"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 65fe22c..bb10b38 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"محدودیت پردازش در پس‌زمینه"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"‏نمایش تمام ANRها"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"نمایش گفتگوی \"برنامه پاسخ نمی‌دهد\" برای برنامه‌های پس‌زمینه"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"اجازه اجباری به برنامه‌های دستگاه ذخیره خارجی"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"بدون توجه به مقادیر مانیفست، هر برنامه‌ای را برای نوشتن در حافظه خارجی واجد شرایط می‌کند"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"اجبار فعالیت‌ها به قابل تغییر اندازه بودن"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index d306e23..7dd2e58 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Taustaprosessi"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Näytä kaikki ANR:t"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Näytä Sovellus ei vastaa -ikkuna taustasovell."</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Salli aina ulkoinen tallennus"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Mahdollistaa sovelluksen tietojen tallentamisen ulkoiseen tallennustilaan luetteloarvoista riippumatta."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Pakota kaikki toiminnot hyväksymään koon muutos"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index f851581..5641d7c 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite processus arr.-plan"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Afficher tous les messages «L\'application ne répond pas»"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Afficher « L\'application ne répond plus » pour applis en arrière-plan"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer l\'autor. d\'applis sur stockage externe"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Rend possible l\'enregistrement de toute application sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer les activités à être redimensionnables"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index c69f324..b0b532f 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite processus arr.-plan"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Afficher tous les messages ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Afficher \"L\'application ne répond plus\" pour applis en arrière-plan"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer disponibilité stockage externe pour applis"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Rend possible l\'enregistrement de toute application sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer possibilité de redimensionner les activités"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 3250d03..81a1ca9 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -109,7 +109,7 @@
     <string name="tts_default_pitch_title" msgid="6135942113172488671">"Ton"</string>
     <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta ao ton da voz sintetizada"</string>
     <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string>
-    <string name="tts_lang_use_system" msgid="2679252467416513208">"Utilizar idioma do sistema"</string>
+    <string name="tts_lang_use_system" msgid="2679252467416513208">"Utiliza o idioma do sistema"</string>
     <string name="tts_lang_not_selected" msgid="7395787019276734765">"Idioma non seleccionado"</string>
     <string name="tts_default_lang_summary" msgid="5219362163902707785">"Define a voz específica do idioma para o texto falado"</string>
     <string name="tts_play_example_title" msgid="7094780383253097230">"Escoitar un exemplo"</string>
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Límite proceso 2º plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informa que aplicación segundo plano non responde"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicacións de forma externa"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permite que calquera aplicación apta se poida escribir nun almacenamento externo, independentemente dos valores expresados"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar o axuste do tamaño das actividades"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index df9eda9..e4e1507 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"પૃષ્ઠભૂમિ પ્રક્રિયા સીમા"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"બધા ANR બતાવો"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"પૃષ્ઠભૂમિ ઍપ્લિકેશનો માટે ઍપ્લિકેશન પ્રતિસાદ આપતી નથી સંવાદ બતાવો"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"બાહ્ય પર એપ્લિકેશનોને મંજૂરી આપવાની ફરજ પાડો"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ ઍપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index c729027..936e775 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"पृष्ठभूमि प्रक्रिया सीमा"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"सभी ANR दिखाएं"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि ऐप्स के लिए ऐप्स प्रतिसाद नहीं दे रहा डॉयलॉग दिखाएं"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"ऐप्स को बाहरी मेमोरी पर बाध्‍य करें"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"इससे कोई भी ऐप्लिकेशन, मेनिफेस्ट मानों को अनदेखा करके, बाहरी मेमोरी पर लिखने योग्य बन जाता है"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"आकार बदले जाने के लिए गतिविधियों को बाध्य करें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index e94b6df..be4ac19 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje pozadinskog procesa"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaz dijaloga o pozad. aplik. koja ne odgovara"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Prisilno dopusti aplikacije u vanjskoj pohrani"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o vrijednostima manifesta"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni mogućnost promjene veličine za aktivnosti"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index d06417f..b791178 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Háttérfolyamat-korlátozás"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Összes ANR mutatása"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Az Alkalmazás nem válaszol ablak megjelenítése"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Külső tárhely alkalmazásainak engedélyezése"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Lehetővé teszi bármely alkalmazás külső tárhelyre való írását a jegyzékértékektől függetlenül"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tevékenységek átméretezésének kényszerítése"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 8dd85c3..da34ccc 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -91,11 +91,11 @@
     <string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
     <string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Հեռացված ծրագրեր"</string>
     <string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Հեռացված հավելվածներն ու օգտատերերը"</string>
-    <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB միացում"</string>
+    <string name="tether_settings_title_usb" msgid="6688416425801386511">"USB մոդեմ"</string>
     <string name="tether_settings_title_wifi" msgid="3277144155960302049">"Դյուրակիր թեժ կետ"</string>
-    <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-ը կապվում է"</string>
-    <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Միացում"</string>
-    <string name="tether_settings_title_all" msgid="8356136101061143841">"Միացում և շարժական թեժ կետ"</string>
+    <string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth մոդեմ"</string>
+    <string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Մոդեմի ռեժիմ"</string>
+    <string name="tether_settings_title_all" msgid="8356136101061143841">"Մոդեմի ռեժիմ"</string>
     <string name="managed_user_title" msgid="8109605045406748842">"Բոլոր աշխատանքային հավելվածները"</string>
     <string name="user_guest" msgid="8475274842845401871">"Հյուր"</string>
     <string name="unknown" msgid="1592123443519355854">"Անհայտ"</string>
@@ -149,7 +149,7 @@
     <string name="development_settings_summary" msgid="1815795401632854041">"Կարգավորել ընտրանքները ծրագրի ծրագրավորման համար"</string>
     <string name="development_settings_not_available" msgid="4308569041701535607">"Ծրագրավորման ընտրանքներն այլևս հասանելի չեն այս օգտատիրոջ"</string>
     <string name="vpn_settings_not_available" msgid="956841430176985598">"VPN-ի կարգավորումները հասանելի չեն այս օգտատիրոջը"</string>
-    <string name="tethering_settings_not_available" msgid="6765770438438291012">"Միակցման կարգավորումները հասանելի չեն այս օգտատիրոջը"</string>
+    <string name="tethering_settings_not_available" msgid="6765770438438291012">"Այս օգտատերը չի կարող փոխել մոդեմի ռեժիմի կարգավորումները"</string>
     <string name="apn_settings_not_available" msgid="7873729032165324000">"Մատչման կետի անվան կարգավորումները հասանելի չեն այս օգտատիրոջը"</string>
     <string name="enable_adb" msgid="7982306934419797485">"USB վրիպազերծում"</string>
     <string name="enable_adb_summary" msgid="4881186971746056635">"Կարգաբերել ռեժիմը, երբ USB-ն միացված է"</string>
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Հետնաշերտի գործընթացի սահմանաչափ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Ցույց տալ բոլոր ANR-երը"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Ցուցադրել այն ծրագիրը, որը չի արձագանքում երկխոսությունը հետնաշերտի ծրագրերի համար"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Միշտ թույլատրել ծրագրեր արտաքին պահեստում"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Թույլ է տալիս ցանկացած հավելված պահել արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Ստիպել, որ ակտիվությունների չափերը լինեն փոփոխելի"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 9e7355b..13407fe 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Batas proses latar blkg"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Tampilkan semua ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Tmplkn dialog Apl Tidak Merespons utk apl ltr blkg"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Paksa izinkan aplikasi di eksternal"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktivitas agar ukurannya dapat diubah"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index d4fde8a..6457e71 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Takmörkun á bakgrunnsvinnslum"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Öll forrit sem svara ekki"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Sýna „Forrit svarar ekki“ fyrir bakgrunnsforrit"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Þvinga fram leyfi forrita í ytri geymslu"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Gerir öll forrit skrifanleg í ytra geymslurými, óháð gildum í upplýsingaskrá"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Þvinga breytanlega stærð virkni"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 0ebe77e5..5182730 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite processi background"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostra tutti errori ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostra finestra ANR per applicazioni in background"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forza autorizzazione app su memoria esterna"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Consente l\'installazione di qualsiasi app su memoria esterna, indipendentemente dai valori manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Imponi formato modificabile alle attività"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 182d819..249fac4 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"מגבלה של תהליכים ברקע"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"‏הצג את כל פריטי ה-ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"הצג תיבת דו-שיח של \'אפליקציה לא מגיבה\' עבור אפליקציות שפועלות ברקע"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאת אפליקציות באחסון חיצוני"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"אלץ יכולת קביעת גודל של הפעילויות"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 440b04d..8837e97 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"バックグラウンドプロセスの上限"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"すべてのANRを表示"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"バックグラウンドアプリが応答しない場合に通知する"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"外部ストレージへのアプリの書き込みを許可"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"アクティビティをサイズ変更可能にする"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 08e6449..81416a0 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"ფონური პროცესების ლიმიტი"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ყველა ANR-ის ჩვენება"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"შეტყობინების ჩვენება, როცა ფონური აპლიკაცია არ პასუხობს"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"აპების დაშვება გარე მეხსიერებაში"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"აპები ჩაიწერება გარე მეხსიერებაზე აღწერის ფაილების მნიშვნელობების მიუხედავად"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ზომაცვლადი აქტივობების იძულება"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index cc8b662..66b4a0e 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Фондық үрдіс шектеуі"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Барлық ANR (қолданба жауап бермеді) хабарларын көрсетіңіз"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Фондық қолданбалардың жауап бермегенін көрсету"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Сыртқыда қолданбаларға мәжбүрлеп рұқсат ету"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Әрекеттерді өлшемін өзгертуге болатын етуге мәжбүрлеу"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 917415c..1adc432 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"ដែន​កំណត់​ដំណើរការ​ក្នុង​ផ្ទៃ​ខាង​ក្រោយ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"បង្ហាញ ANRs ទាំងអស់"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"បង្ហាញ​ប្រអប់​កម្មវិធី​មិន​ឆ្លើយតប​សម្រាប់​កម្មវិធី​ផ្ទៃ​ខាង​ក្រោយ"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"បង្ខំឲ្យអនុញ្ញាតកម្មវិធីលើឧបករណ៍ផ្ទុកខាងក្រៅ"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃជាក់លាក់"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 0120658..c545da7 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"ಹಿನ್ನೆಲೆ ಪ್ರಕ್ರಿಯೆ ಮಿತಿ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ಎಲ್ಲ ANR ಗಳನ್ನು ತೋರಿಸು"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ಹಿನ್ನೆಲೆ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ ಎಂಬ ಸಂಭಾಷಣೆ ತೋರಿಸು"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"ಬಾಹ್ಯವಾಗಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಒತ್ತಾಯವಾಗಿ ಅನುಮತಿಸಿ"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳು ಯಾವುದೇ ಆಗಿದ್ದರೂ, ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಒತ್ತಾಯ ಮಾಡಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index c5f842e..bbaeed7 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"백그라운드 프로세스 수 제한"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"모든 ANR 보기"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"백그라운드 앱에 대해 앱 응답 없음 대화상자 표시"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"외부에서 앱 강제 허용"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"매니페스트 값과 관계없이 모든 앱이 외부 저장소에 작성되도록 허용"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"활동의 크기가 조정 가능하도록 설정"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 492f71d..66f3769 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Фондогу процесстер чеги"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Бардык ANR\'лерди көрсөтүү"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Фондогу колдонмолорго Колдонмо Жооп Бербейт деп көрсөтүү"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Тышкы сактагычка сактоого уруксат берүү"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Аракеттердин өлчөмүн өзгөртүүнү мажбурлоо"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 5abd2a6..c909cbb 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"ການຈຳກັດໂປຣເຊສໃນພື້ນຫຼັງ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ສະ​ແດງ ANRs ທັງ​ຫມົດ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ສະແດງໜ້າຈໍແອັບຯທີ່ບໍ່ຕອບສະໜອງສຳລັບແອັບຯພື້ນຫຼັງ"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"ບັງຄັບອະນຸຍາດແອັບ​ຢູ່​ພາຍນອກ"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ພື້ນທີ່ຈັດເກັບຂໍ້ມູນພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ບັງ​ຄັງ​ໃຫ້​ກິດ​ຈະ​ກຳ​ປ່ຽນ​ຂະ​ໜາດ​ໄດ້"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 830abf0..274ce9a 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Fono procesų apribojimas"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Rodyti visus ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Fon. programose rodyti dialogo langą „Neatsako“"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Priverstinai leisti programas išorinėje atmintin."</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Nustatoma, kad visas programas būtų galima įrašyti į išorinę saugyklą, nepaisant aprašo verčių"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 5749954..e760d78 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Fona procesu ierobežojums"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Rādīt visus ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Rādīt fona lietotņu dialoglodz. Lietotne nereaģē"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Lietotņu piespiedu atļaušana ārējā krātuvē"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Pielāgot darbības"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 88b3675..1979451 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Граница на процес во зад."</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Прикажи ги сите ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Прикажи „Апл. не реагира“ за. апл. во заднина"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Принуд. дозволете апликации на надворешна меморија"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Прави секоја апликација да биде подобна за запишување на надворешна меморија, независно од вредностите на манифестот"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Принуди ги активностите да ја менуваат големината"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 3ed642d..06a9dc1 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"പശ്ചാത്തല പ്രോസ‌സ്സ് പരിധി"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"എല്ലാ ANR-കളും ദൃശ്യമാക്കുക"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"പ‌ശ്ചാത്തല അപ്ലിക്കേഷനുകൾക്ക് അപ്ലിക്കേഷൻ പ്രതികരിക്കുന്നില്ല എന്ന ഡയലോഗ് കാണിക്കുക"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"ബാഹ്യമായതിൽ നിർബന്ധിച്ച് അനുവദിക്കുക"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"വലിപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 12c52812..f400f5a 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Далд процессын хязгаар"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Бүх ANRs харуулах"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Далд апп-уудад Апп Хариу Өгөхгүй байна гэснийг харуулах"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Аппыг гадаад санах ойд хадгалахыг зөвшөөрөх"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест утгыг нь үл хамааран дурын апп-г гадаад санах ойд бичих боломжтой болгодог"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index a45648e..10632e0 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"पार्श्वभूमी प्रक्रिया मर्यादा"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"सर्व ANR दर्शवा"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पार्श्वभूमी अॅप्ससाठी अॅप प्रतिसाद देत नाही संवाद दर्शवा"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यवर अॅप्सना अनुमती देण्याची सक्ती करा"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, कोणत्याही अॅपला बाह्य संचयनावर लेखन केले जाण्यासाठी पात्र बनविते"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"क्र‍ियाकलापाचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 6ca514b..cc6a935 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Had proses latar belakang"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Tunjukkan semua ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Tunjukkan dialog Aplikasi Tidak Memberi Maklum Balas untuk aplikasi latar belakang"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Benarkan apl secara paksa pada storan luaran"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Menjadikan sebarang apl layak ditulis ke storan luaran, tanpa mengambil kira nilai manifes"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktiviti supaya boleh diubah saiz"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index c2e8a94..3e718006 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"နောက်ခံလုပ်ငန်းစဉ်ကန့်သတ်ခြင်း"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ANRsအားလုံးအား ပြသရန်"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"နောက်ခံအပ်ပလီကေးရှင်းအတွက်တုံ့ပြန်မှုမရှိပြရန်"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"အပြင်မှာ အတင်း ခွင့်ပြုရန်"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"တိကျစွာ သတ်မှတ်ထားသည့်တန်ဖိုးများရှိသော်လည်း၊ ပြင်ပသိုလှောင်ခန်းများသို့ မည်သည့်အက်ပ်ကိုမဆို ဝင်ရောက်ခွင့်ပြုပါ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"လုပ်ဆောင်ချက်များ ဆိုက်ညှိရနိုင်ရန် လုပ်ခိုင်းပါ"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 409ccab..61ce9cb 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Bakgrunnsprosessgrense"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Vis alle ANR-er"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Vis Appen svarer ikke-dialog for bakgrunnsapper"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tving frem tillatelse for ekstern lagring av apper"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Dette gjør at alle apper kan lagres på eksterne lagringsmedier – uavhengig av manifestverdier"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til å kunne endre størrelse"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 2f61e8c..e87cf2f 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"पृष्ठभूमि प्रक्रिया सीमा"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"सबै ANRs देखाउनुहोस्"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि अनुप्रयोगका लागि जवाफ नदिइरहेका अनुप्रयोगहरू देखाउनुहोस्"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यमा बल प्रयोगको अनुमति प्राप्त अनुप्रयोगहरू"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"म्यानिफेेस्टका मानहरूको ख्याल नगरी कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न सकिने खाले बनाउँछ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"गतिविधिहरू रिसाइज गर्नको लागि बाध्य गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 77e311e..b98ea2b 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Achtergrondproceslimiet"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Alle ANR\'s weergeven"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"\'App reageert niet\' weerg. voor apps op achtergr."</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Toestaan van apps op externe opslag afdwingen"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hiermee komt elke app in aanmerking voor schrijven naar externe opslag, ongeacht de manifestwaarden"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Formaat activiteiten geforceerd aanpasbaar maken"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 8534e856..08dd09d 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"ਪਿਛੋਕੜ ਪ੍ਰਕਿਰਿਆ ਸੀਮਾ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ਸਾਰੇ ANR ਦਿਖਾਓ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ਪਿਛੋਕੜ ਐਪਸ ਲਈ ਐਪਸ ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਹੇ ਡਾਇਲੌਗ ਦਿਖਾਓ"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"ਐਪਸ ਨੂੰ ਬਾਹਰਲੇ ਤੇ ਜ਼ਬਰਦਸਤੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਕਿਸੇ ਵੀ ਐਪ ਨੂੰ ਬਾਹਰੀ ਸਟੋਰੇਜ \'ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ਮੁੜ-ਆਕਾਰ ਬਦਲਣ ਲਈ ਸਰਗਰਮੀਆਂ \'ਤੇ ਜ਼ੋਰ ਦਿਓ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7624042..e559c69 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limit procesów w tle"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Pokaż wszystkie ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Pokaż okno Aplikacja Nie Reaguje dla aplikacji w tle"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Wymuś zezwalanie na aplikacje w pamięci zewn."</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Pozwala na zapis aplikacji w pamięci zewnętrznej niezależnie od wartości w pliku manifestu"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Wymuś zmianę rozmiaru okien aktywności"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 80b8990..cce80ed 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do proc. 2º plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANRS"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Exibir \"App não responde\" para app em 2º plano"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualifica apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 0059cdd..8124c4b 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite proc. em 2º plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostrar erro \"Aplic. não Resp.\" p/ aplic. 2º plano"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar perm. de aplicações no armazenamento ext."</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Torna qualquer aplicação elegível para ser gravada no armazenamento externo, independentemente dos valores do manifesto"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar as atividades a serem redimensionáveis"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 80b8990..cce80ed 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do proc. 2º plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANRS"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Exibir \"App não responde\" para app em 2º plano"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualifica apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 0ae7049..3a174de 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limită procese fundal"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Afișați toate elem. ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Aplicații din fundal: afișați Aplicația nu răspunde"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forțați accesul aplicațiilor la stocarea externă"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forțați redimensionarea activităților"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index cc82236..cd8d956 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Лимит фоновых процессов"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Все ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Уведомлять о том, что приложение не отвечает"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Разрешить сохранение на внешние накопители"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Разрешить сохранение приложений на внешних накопителях (независимо от значений в манифесте)"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Изменение размера в многооконном режиме"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 1623308..592c2f9 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"පසුබිම් ක්‍රියාවලි සීමාව"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"සියලුම ANR පෙන්වන්න"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"පසුබිම් යෙදුම් වලට යෙදුම ප්‍රතිචාර නොදක්වයි කවුළුව පෙන්වන්න"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"බාහිර මත යෙදුම් ඉඩ දීම බල කරන්න"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් බාහිර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ක්‍රියාකාරකම් ප්‍රතිප්‍රමාණ කළ හැකි බවට බල කරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 028d561..d5c4061 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limit procesov na pozadí"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Zobrazovať všetky ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Zobrazovať dialóg „Aplikácia neodpovedá“ aj pre aplikácie na pozadí"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vynútiť povolenie aplikácií na externom úložisku"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vynútiť možnosť zmeny veľkosti aktivít"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 085621a..4e0085c 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Omejitev postopkov v ozadju"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Pokaži okna neodzivanj"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaz pogovornega okna za neodzivanje aplikacije v ozadju"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vsili omogočanje aplikacij v zunanji shrambi"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vsili povečanje velikosti za aktivnosti"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index c9398a5..e8340bf 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Kufizimi i proceseve në sfond"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Shfaq raportet ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Shfaq raportet ANR (Aplikacioni nuk përgjigjet) për aplikacionet në sfond"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Detyro lejimin në hapësirën e jashtme"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Detyro madhësinë e ndryshueshme për aktivitetet"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 15ba747..63ceb73 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ограничење позадинских процеса"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Прикажи све ANR-ове"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Прикажи дијалог Апликација не реагује за апликације у позадини"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Принудно дозволи апликације у спољној"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Принудно омогући промену величине активности"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index cfae5ae..1f2ca23 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Begränsa bakgrundsprocess"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Visa alla som inte svarar"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Visa dialogrutan om att appen inte svarar för bakgrundsappar"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tillåt appar i externt lagringsutrymme"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Allar appar kan skrivas till extern lagring, oavsett manifestvärden"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Framtvinga storleksanpassning för aktiviteter"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index ef43134..4d75fbc 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -234,7 +234,7 @@
     <string name="debug_monitoring_category" msgid="7640508148375798343">"Ufuatiliaji"</string>
     <string name="strict_mode" msgid="1938795874357830695">"Modi makinifu imewezeshwa"</string>
     <string name="strict_mode_summary" msgid="142834318897332338">"Mulika skrini wakati programu zinafanya uendeshaji mrefu kwenye mnyororo mkuu"</string>
-    <string name="pointer_location" msgid="6084434787496938001">"Mahali pa pointa"</string>
+    <string name="pointer_location" msgid="6084434787496938001">"Mahali pa kiashiria"</string>
     <string name="pointer_location_summary" msgid="840819275172753713">"Kuegeshwa kwa skrini ikionyesha data ya mguso ya sasa"</string>
     <string name="show_touches" msgid="2642976305235070316">"Onyesha unapogonga"</string>
     <string name="show_touches_summary" msgid="6101183132903926324">"Onyesha maoni ya picha unapogonga"</string>
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Kiwango cha mchakato wa mandari nyuma"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Onyesha ANR zote"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Onyesha kisanduku kidadisi cha Programu Haiitikii kwa programu za usuli"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Lazima uruhusu programu kwenye hifadhi ya nje"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Huruhusu programu yoyote iwekwe kwenye hifadhi ya nje, bila kujali thamani za faili ya maelezo"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index e09db51..47f7586 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"பின்புலச் செயல்முறை வரம்பு"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"எல்லா ANRகளையும் காட்டு"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"பின்புலப் பயன்பாடுகளுக்குப் பயன்பாடு பதிலளிக்கவில்லை என்ற உரையாடலைக் காட்டு"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"பயன்பாடுகளை வெளிப்புறச் சேமிப்பிடத்தில் அனுமதி"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், எல்லா பயன்பாட்டையும் வெளிப்புறச் சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index dabf7ed..1a7ad4d 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"నేపథ్య ప్రాసెస్ పరిమితి"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"అన్ని ANRలను చూపు"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"నేపథ్య అనువర్తనాల కోసం అనువర్తనం ప్రతిస్పందించడం లేదు డైలాగ్‌ను చూపు"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"అనువర్తనాలను బాహ్య నిల్వలో నిర్బంధంగా అనుమతించు"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయడానికి అనుమతిస్తుంది"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"కార్యాచరణలను పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 9a265f5..aa0296c 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"ขีดจำกัดกระบวนการพื้นหลัง"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"แสดง ANR ทั้งหมด"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"แสดงหน้าต่างแอปไม่ตอบสนอง สำหรับแอปพื้นหลัง"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"บังคับให้แอปสามารถใช้ที่เก็บภายนอก"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ทำให้สามารถเขียนแอปใดๆ ก็ตามไปยังพื้นที่เก็บข้อมูลภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"บังคับให้กิจกรรมปรับขนาดได้"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index c46ac78..988a88b 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limitasyon ng proseso sa background"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Ipakita ang lahat ng ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"App Not Responding dialog para sa background apps"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Pwersahang payagan ang mga app sa external"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ginagawang kwalipikado ang anumang app na mailagay sa external na storage, anuman ang mga value ng manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Sapilitang gawing resizable ang mga aktibidad"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 696b209..5eff6c3a 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Arka plan işlem sınırı"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Tüm ANR\'leri göster"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Arka plan uygulamalar için Uygulama Yanıt Vermiyor mesajını göster"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Harici birimdeki uygulamalara izin vermeye zorla"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Manifest değerlerinden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index d3f137f..419a8c0 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Обмеження фон. процесів"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Показувати всі ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Сповіщати, коли додаток не відповідає"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Примусово записувати додатки в зовнішню пам’ять"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Можна записувати додатки в зовнішню пам’ять, незалежно від значень у маніфесті"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Примусово масштабувати активність"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 3fceb98..55f7132 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"پس منظر پروسیس کی حد"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"‏سبھی ANRs کو دکھائیں"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"پس منظر کی ایپس کیلئے ایپ جواب نہیں دے رہی ہے ڈائلاگ دکھائیں"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"بیرونی پر ایپس کو زبردستی اجازت دیں"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"‏manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"سرگرمیوں کو ری سائز ایبل بنائیں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index ad9dc3a..4b53da5 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Fondagi jarayonlarni cheklash"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Hamma ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Ilova javob bermayotgani haqida xabar qilish"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tashqi xotira qurilmasidagi ilova dasturlariga majburiy ruxsat berish"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 910e66c..a6a54d0 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Giới hạn quá trình nền"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Hiển thị tất cả ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Hiện hộp thoại Ứng dụng ko đáp ứng cho ứng dụng nền"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Buộc cho phép các ứng dụng trên bộ nhớ ngoài"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Giúp mọi ứng dụng đủ điều kiện để được ghi vào bộ nhớ ngoài, bất kể giá trị tệp kê khai là gì"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Buộc các hoạt động có thể thay đổi kích thước"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index b224c23..41c5f60 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"后台进程限制"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"显示所有“应用无响应”(ANR)"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"为后台应用显示“应用无响应”对话框"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"强制允许将应用写入外部存储设备"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"强制将活动设为可调整大小"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 03081af..00748b0 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"背景處理程序限制"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"顯示所有 ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"顯示背景應用程式的「應用程式無回應」對話框"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許應用程式寫入到外部儲存空間"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"在任何資訊清單值下,允許將所有符合資格的應用程式寫入到外部儲存完間"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"強制可變更活動尺寸"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 050c556..3988edd 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"背景處理程序限制"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"顯示所有無回應程式"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"為背景應用程式顯示「應用程式無回應」對話方塊"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index d2a5743..11dfdcc 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -272,6 +272,10 @@
     <string name="app_process_limit_title" msgid="4280600650253107163">"Isilinganiso senqubo yesithombe sanemuva"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Bonisa wonke ama-ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Boniso idayalogi Yohlelo Lokusebenza Olungasabeli kwizinhlelo zokusebenza zasemuva"</string>
+    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
+    <skip />
+    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
+    <skip />
     <string name="force_allow_on_external" msgid="3215759785081916381">"Phoqelela ukuvumela izinhlelo zokusebenza ngaphandle"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Imisebenzi yamandla izonikezwa usayizi omusha"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 044392c..4921be1 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -684,6 +684,12 @@
     <string name="show_all_anrs_summary">Show App Not Responding dialog
         for background apps</string>
 
+    <!-- UI debug setting: show all ANRs? [CHAR LIMIT=25] -->
+    <string name="show_notification_channel_warnings">Show notification channel warnings</string>
+    <!-- UI debug setting: show all ANRs summary [CHAR LIMIT=50] -->
+    <string name="show_notification_channel_warnings_summary">Displays on-screen warning when an app posts a notification without a valid channel</string>
+
+
     <!-- UI debug setting: force allow apps on external storage [CHAR LIMIT=50] -->
     <string name="force_allow_on_external">Force allow apps on external</string>
     <!-- UI debug setting: force allow on external summary [CHAR LIMIT=150] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 24ede16..7268d00 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -19,6 +19,8 @@
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothUuid;
@@ -26,16 +28,22 @@
 import android.os.ParcelUuid;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settingslib.R;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
-public final class A2dpProfile implements LocalBluetoothProfile {
+public class A2dpProfile implements LocalBluetoothProfile {
     private static final String TAG = "A2dpProfile";
     private static boolean V = false;
 
+    private Context mContext;
+
     private BluetoothA2dp mService;
+    BluetoothA2dpWrapper.Factory mWrapperFactory;
+    private BluetoothA2dpWrapper mServiceWrapper;
     private boolean mIsProfileReady;
 
     private final LocalBluetoothAdapter mLocalAdapter;
@@ -59,6 +67,7 @@
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
             if (V) Log.d(TAG,"Bluetooth service connected");
             mService = (BluetoothA2dp) proxy;
+            mServiceWrapper = mWrapperFactory.getInstance(mService);
             // We just bound to the service, so refresh the UI for any connected A2DP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
             while (!deviceList.isEmpty()) {
@@ -88,13 +97,20 @@
     A2dpProfile(Context context, LocalBluetoothAdapter adapter,
             CachedBluetoothDeviceManager deviceManager,
             LocalBluetoothProfileManager profileManager) {
+        mContext = context;
         mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mProfileManager = profileManager;
+        mWrapperFactory = new BluetoothA2dpWrapperImpl.Factory();
         mLocalAdapter.getProfileProxy(context, new A2dpServiceListener(),
                 BluetoothProfile.A2DP);
     }
 
+    @VisibleForTesting
+    void setWrapperFactory(BluetoothA2dpWrapper.Factory factory) {
+        mWrapperFactory = factory;
+    }
+
     public boolean isConnectable() {
         return true;
     }
@@ -173,6 +189,72 @@
         return false;
     }
 
+    public boolean supportsHighQualityAudio(BluetoothDevice device) {
+        int support = mServiceWrapper.supportsOptionalCodecs(device);
+        return support == BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED;
+    }
+
+    public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
+        int enabled = mServiceWrapper.getOptionalCodecsEnabled(device);
+        if (enabled != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN) {
+            return enabled == BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED;
+        } else if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED &&
+                supportsHighQualityAudio(device)) {
+            // Since we don't have a stored preference and the device isn't connected, just return
+            // true since the default behavior when the device gets connected in the future would be
+            // to have optional codecs enabled.
+            return true;
+        }
+        BluetoothCodecConfig codecConfig = null;
+        if (mServiceWrapper.getCodecStatus() != null) {
+            codecConfig = mServiceWrapper.getCodecStatus().getCodecConfig();
+        }
+        if (codecConfig != null)  {
+            return !codecConfig.isMandatoryCodec();
+        } else {
+            return false;
+        }
+    }
+
+    public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) {
+        int prefValue = enabled
+                ? BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED
+                : BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED;
+        mServiceWrapper.setOptionalCodecsEnabled(device, prefValue);
+        if (getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
+            return;
+        }
+        if (enabled) {
+            mService.enableOptionalCodecs();
+        } else {
+            mService.disableOptionalCodecs();
+        }
+    }
+
+    public String getHighQualityAudioOptionLabel(BluetoothDevice device) {
+        int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec;
+        if (!supportsHighQualityAudio(device) ||
+                getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
+            return mContext.getString(unknownCodecId);
+        }
+        // We want to get the highest priority codec, since that's the one that will be used with
+        // this device, and see if it is high-quality (ie non-mandatory).
+        BluetoothCodecConfig[] selectable = null;
+        if (mServiceWrapper.getCodecStatus() != null) {
+            selectable = mServiceWrapper.getCodecStatus().getCodecsSelectableCapabilities();
+            // To get the highest priority, we sort in reverse.
+            Arrays.sort(selectable,
+                    (a, b) -> {
+                        return b.getCodecPriority() - a.getCodecPriority();
+                    });
+        }
+        if (selectable == null || selectable.length < 1 || selectable[0].isMandatoryCodec()) {
+            return mContext.getString(unknownCodecId);
+        }
+        return mContext.getString(R.string.bluetooth_profile_a2dp_high_quality,
+                selectable[0].getCodecName());
+    }
+
     public String toString() {
         return NAME;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.java
new file mode 100644
index 0000000..aa3e835
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapper.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.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * This interface replicates some methods of android.bluetooth.BluetoothA2dp that are new and not
+ * yet available in our current version of  Robolectric. It provides a thin wrapper to call the real
+ * methods in production and a mock in tests.
+ */
+public interface BluetoothA2dpWrapper {
+
+    static interface Factory {
+        BluetoothA2dpWrapper getInstance(BluetoothA2dp service);
+    }
+
+    /**
+     * @return the real {@code BluetoothA2dp} object
+     */
+    BluetoothA2dp getService();
+
+    /**
+     * Wraps {@code BluetoothA2dp.getCodecStatus}
+     */
+    public BluetoothCodecStatus getCodecStatus();
+
+    /**
+     * Wraps {@code BluetoothA2dp.supportsOptionalCodecs}
+     */
+    int supportsOptionalCodecs(BluetoothDevice device);
+
+    /**
+     * Wraps {@code BluetoothA2dp.getOptionalCodecsEnabled}
+     */
+    int getOptionalCodecsEnabled(BluetoothDevice device);
+
+    /**
+     * Wraps {@code BluetoothA2dp.setOptionalCodecsEnabled}
+     */
+    void setOptionalCodecsEnabled(BluetoothDevice device, int value);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java
new file mode 100644
index 0000000..14fa796
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothA2dpWrapperImpl.java
@@ -0,0 +1,62 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+
+public class BluetoothA2dpWrapperImpl implements BluetoothA2dpWrapper {
+
+    public static class Factory implements BluetoothA2dpWrapper.Factory {
+        @Override
+        public BluetoothA2dpWrapper getInstance(BluetoothA2dp service) {
+            return new BluetoothA2dpWrapperImpl(service);
+        }
+    }
+
+    private BluetoothA2dp mService;
+
+    public BluetoothA2dpWrapperImpl(BluetoothA2dp service) {
+        mService = service;
+    }
+
+    @Override
+    public BluetoothA2dp getService() {
+        return mService;
+    }
+
+    @Override
+    public BluetoothCodecStatus getCodecStatus() {
+        return mService.getCodecStatus();
+    }
+
+    @Override
+    public int supportsOptionalCodecs(BluetoothDevice device) {
+        return mService.supportsOptionalCodecs(device);
+    }
+
+    @Override
+    public int getOptionalCodecsEnabled(BluetoothDevice device) {
+        return mService.getOptionalCodecsEnabled(device);
+    }
+
+    @Override
+    public void setOptionalCodecsEnabled(BluetoothDevice device, int value) {
+        mService.setOptionalCodecsEnabled(device, value);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 5a9a749..0750dc7 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -42,7 +42,7 @@
  * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
  * objects for the available Bluetooth profiles.
  */
-public final class LocalBluetoothProfileManager {
+public class LocalBluetoothProfileManager {
     private static final String TAG = "LocalBluetoothProfileManager";
     private static final boolean DEBUG = Utils.D;
     /** Singleton instance. */
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
index 3a2397f..3d50f23 100755
--- a/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/BatteryMeterDrawableBase.java
@@ -141,7 +141,7 @@
             mWarningTextPaint.setColor(mColors[1]);
         }
 
-        mChargeColor = Utils.getDefaultColor(mContext, R.color.batterymeter_charge_color);
+        mChargeColor = Utils.getDefaultColor(mContext, R.color.meter_consumed_color);
 
         mBoltPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mBoltPaint.setColor(Utils.getDefaultColor(mContext, R.color.batterymeter_bolt_color));
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index eb513e1..b3565ea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -521,7 +521,8 @@
     public boolean isMetered() {
         return mIsScoredNetworkMetered
                 || (mConfig != null && mConfig.meteredHint)
-                || (mInfo != null && mInfo.getMeteredHint());
+                || (mInfo != null && mInfo.getMeteredHint()
+                || (mNetworkInfo != null && mNetworkInfo.isMetered()));
     }
 
     public NetworkInfo getNetworkInfo() {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 56cb0a3..801844b 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -18,7 +18,6 @@
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
 
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.when;
 
@@ -237,7 +236,7 @@
         homeSp.setFriendlyName("Test Provider");
         config.setHomeSp(homeSp);
         AccessPoint ap = new AccessPoint(mContext, config);
-        assertTrue(ap.isPasspointConfig());
+        assertThat(ap.isPasspointConfig()).isTrue();
     }
 
     @Test
@@ -254,8 +253,8 @@
         wifiInfo.setNetworkId(configuration.networkId);
         accessPoint.update(configuration, wifiInfo, networkInfo);
 
-        assertTrue(accessPoint.isMetered());
-    };
+        assertThat(accessPoint.isMetered()).isTrue();
+    }
 
     @Test
     public void testIsMetered_returnTrueWhenWifiInfoIsMetered() {
@@ -271,8 +270,25 @@
         wifiInfo.setMeteredHint(true);
         accessPoint.update(configuration, wifiInfo, networkInfo);
 
-        assertTrue(accessPoint.isMetered());
-    };
+        assertThat(accessPoint.isMetered()).isTrue();
+    }
+
+    @Test
+    public void testIsMetered_returnTrueWhenNetworkInfoIsMetered() {
+        WifiConfiguration configuration = createWifiConfiguration();
+
+        NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
+        networkInfo.setMetered(true);
+        AccessPoint accessPoint = new AccessPoint(mContext, configuration);
+        WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
+        wifiInfo.setBSSID(configuration.BSSID);
+        wifiInfo.setNetworkId(configuration.networkId);
+        accessPoint.update(configuration, wifiInfo, networkInfo);
+
+        assertThat(accessPoint.isMetered()).isTrue();
+    }
 
     @Test
     public void testIsMetered_returnTrueWhenScoredNetworkIsMetered() {
@@ -286,8 +302,24 @@
                                 true /* metered */));
         ap.update(mWifiNetworkScoreCache, false /* scoringUiEnabled */);
 
-        assertTrue(ap.isMetered());
-    };
+        assertThat(ap.isMetered()).isTrue();
+    }
+
+    @Test
+    public void testIsMetered_returnFalseByDefault() {
+        WifiConfiguration configuration = createWifiConfiguration();
+
+        NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 2, "WIFI", "WIFI_SUBTYPE");
+        AccessPoint accessPoint = new AccessPoint(mContext, configuration);
+        WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setSSID(WifiSsid.createFromAsciiEncoded(configuration.SSID));
+        wifiInfo.setBSSID(configuration.BSSID);
+        wifiInfo.setNetworkId(configuration.networkId);
+        accessPoint.update(configuration, wifiInfo, networkInfo);
+
+        assertThat(accessPoint.isMetered()).isFalse();
+    }
 
     private AccessPoint createAccessPointWithScanResultCache() {
         Bundle bundle = new Bundle();
@@ -400,7 +432,7 @@
         String providerFriendlyName = "Test Provider";
         AccessPoint ap = new TestAccessPointBuilder(mContext).setFqdn(fqdn)
                 .setProviderFriendlyName(providerFriendlyName).build();
-        assertTrue(ap.isPasspointConfig());
+        assertThat(ap.isPasspointConfig()).isTrue();
         assertThat(ap.getPasspointFqdn()).isEqualTo(fqdn);
         assertThat(ap.getConfigName()).isEqualTo(providerFriendlyName);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
copy to packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
index ee0df87..656ab86 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
+++ b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
+package android.bluetooth;
 
 /**
- * This is sent when the in-app animations into Recents completes.
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
  */
-public class EnterRecentsTaskStackAnimationCompletedEvent extends EventBus.AnimatedEvent {
-    // Simple event
+public class BluetoothCodecConfig {
+    public boolean isMandatoryCodec() { return true; }
+    public String getCodecName() { return null;}
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
similarity index 61%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
copy to packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
index ee0df87..919ec3f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
+++ b/packages/SettingsLib/tests/robotests/src/android/bluetooth/BluetoothCodecStatus.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
+package android.bluetooth;
 
 /**
- * This is sent when the in-app animations into Recents completes.
+ * A placeholder class to prevent ClassNotFound exceptions caused by lack of visibility.
  */
-public class EnterRecentsTaskStackAnimationCompletedEvent extends EventBus.AnimatedEvent {
-    // Simple event
+public class BluetoothCodecStatus {
+    public BluetoothCodecConfig getCodecConfig() { return null; }
+    public BluetoothCodecConfig[] getCodecsSelectableCapabilities() { return null; }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
new file mode 100644
index 0000000..07a0e11
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -0,0 +1,203 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.R;
+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.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class A2dpProfileTest {
+
+    @Mock Context mContext;
+    @Mock LocalBluetoothAdapter mAdapter;
+    @Mock CachedBluetoothDeviceManager mDeviceManager;
+    @Mock LocalBluetoothProfileManager mProfileManager;
+    @Mock BluetoothDevice mDevice;
+    @Mock BluetoothA2dp mBluetoothA2dp;
+    @Mock BluetoothA2dpWrapper mBluetoothA2dpWrapper;
+    BluetoothProfile.ServiceListener mServiceListener;
+
+    A2dpProfile mProfile;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        // Capture the A2dpServiceListener our A2dpProfile will pass during its constructor, so that
+        // we can call its onServiceConnected method and get it to use our mock BluetoothA2dp
+        // object.
+        doAnswer((invocation) -> {
+            mServiceListener = (BluetoothProfile.ServiceListener) invocation.getArguments()[1];
+            return null;
+        }).when(mAdapter).getProfileProxy(any(Context.class), any(), eq(BluetoothProfile.A2DP));
+
+        mProfile = new A2dpProfile(mContext, mAdapter, mDeviceManager, mProfileManager);
+        mProfile.setWrapperFactory((service) -> { return mBluetoothA2dpWrapper; });
+        mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
+    }
+
+    @Test
+    public void supportsHighQualityAudio() {
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+        assertThat(mProfile.supportsHighQualityAudio(mDevice)).isTrue();
+
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+        assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
+
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN);
+        assertThat(mProfile.supportsHighQualityAudio(mDevice)).isFalse();
+    }
+
+    @Test
+    public void isHighQualityAudioEnabled() {
+        when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+
+        when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+
+        // If we don't have a stored pref for whether optional codecs should be enabled or not,
+        // then isHighQualityAudioEnabled() should return true or false based on whether optional
+        // codecs are supported. If the device is connected then we should ask it directly, but if
+        // the device isn't connected then rely on the stored pref about such support.
+        when(mBluetoothA2dpWrapper.getOptionalCodecsEnabled(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN);
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_DISCONNECTED);
+
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_CONNECTED);
+        BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+        when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+        BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+        when(status.getCodecConfig()).thenReturn(config);
+        when(config.isMandatoryCodec()).thenReturn(false);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isTrue();
+        when(config.isMandatoryCodec()).thenReturn(true);
+        assertThat(mProfile.isHighQualityAudioEnabled(mDevice)).isFalse();
+    }
+
+    // Strings to use in fake resource lookups.
+    private static String KNOWN_CODEC_LABEL = "Use high quality audio: %1$s";
+    private static String UNKNOWN_CODEC_LABEL = "Use high quality audio";
+
+    /**
+     * Helper for setting up several tests of getHighQualityAudioOptionLabel
+     */
+    private void setupLabelTest() {
+        // SettingsLib doesn't have string resource lookup working for robotests, so fake our own
+        // string loading.
+        when(mContext.getString(eq(R.string.bluetooth_profile_a2dp_high_quality),
+                any(String.class))).thenAnswer((invocation) -> {
+            return String.format(KNOWN_CODEC_LABEL, invocation.getArguments()[1]);
+        });
+        when(mContext.getString(eq(R.string.bluetooth_profile_a2dp_high_quality_unknown_codec)))
+                .thenReturn(UNKNOWN_CODEC_LABEL);
+
+        // Most tests want to simulate optional codecs being supported by the device, so do that
+        // by default here.
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED);
+    }
+
+    @Test
+    public void getLableCodecsNotSupported() {
+        setupLabelTest();
+        when(mBluetoothA2dpWrapper.supportsOptionalCodecs(any())).thenReturn(
+                BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED);
+        assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+    }
+
+    @Test
+    public void getLabelDeviceDisconnected() {
+        setupLabelTest();
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_DISCONNECTED);
+        assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+    }
+
+    @Test
+    public void getLabelDeviceConnectedButNotHighQualityCodec() {
+        setupLabelTest();
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_CONNECTED);
+        BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+        BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+        BluetoothCodecConfig[] configs = {config};
+        when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+        when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
+
+        when(config.isMandatoryCodec()).thenReturn(true);
+        assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(UNKNOWN_CODEC_LABEL);
+    }
+
+    @Test
+    public void getLabelDeviceConnectedWithHighQualityCodec() {
+        setupLabelTest();
+        when(mBluetoothA2dp.getConnectionState(any())).thenReturn(
+                BluetoothProfile.STATE_CONNECTED);
+        BluetoothCodecStatus status = mock(BluetoothCodecStatus.class);
+        BluetoothCodecConfig config = mock(BluetoothCodecConfig.class);
+        BluetoothCodecConfig[] configs = {config};
+        when(mBluetoothA2dpWrapper.getCodecStatus()).thenReturn(status);
+        when(status.getCodecsSelectableCapabilities()).thenReturn(configs);
+
+        when(config.isMandatoryCodec()).thenReturn(false);
+        when(config.getCodecName()).thenReturn("PiedPiper");
+        assertThat(mProfile.getHighQualityAudioOptionLabel(mDevice)).isEqualTo(
+                String.format(KNOWN_CODEC_LABEL, config.getCodecName()));
+    }
+}
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 415bf9a..1ddbcad 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -52,6 +52,7 @@
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
+import android.annotation.MainThread;
 import android.annotation.SuppressLint;
 import android.app.AlertDialog;
 import android.app.Notification;
@@ -126,6 +127,8 @@
  * <li>Stops itself if it doesn't have any process left to monitor.
  * </ol>
  * </ol>
+ *
+ * TODO: There are multiple threads involved.  Add synchronization accordingly.
  */
 public class BugreportProgressService extends Service {
     private static final String TAG = "BugreportProgressService";
@@ -201,11 +204,15 @@
 
     private static final String NOTIFICATION_CHANNEL_ID = "bugreports";
 
+    private final Object mLock = new Object();
+
     /** Managed dumpstate processes (keyed by id) */
     private final SparseArray<DumpstateListener> mProcesses = new SparseArray<>();
 
     private Context mContext;
-    private ServiceHandler mMainHandler;
+
+    private Handler mMainThreadHandler;
+    private ServiceHandler mServiceHandler;
     private ScreenshotHandler mScreenshotHandler;
 
     private final BugreportInfoDialog mInfoDialog = new BugreportInfoDialog();
@@ -234,7 +241,8 @@
     @Override
     public void onCreate() {
         mContext = getApplicationContext();
-        mMainHandler = new ServiceHandler("BugreportProgressServiceMainThread");
+        mMainThreadHandler = new Handler(Looper.getMainLooper());
+        mServiceHandler = new ServiceHandler("BugreportProgressServiceMainThread");
         mScreenshotHandler = new ScreenshotHandler("BugreportProgressServiceScreenshotThread");
 
         mScreenshotsDir = new File(getFilesDir(), SCREENSHOT_DIR);
@@ -260,10 +268,10 @@
         Log.v(TAG, "onStartCommand(): " + dumpIntent(intent));
         if (intent != null) {
             // Handle it in a separate thread.
-            final Message msg = mMainHandler.obtainMessage();
+            final Message msg = mServiceHandler.obtainMessage();
             msg.what = MSG_SERVICE_COMMAND;
             msg.obj = intent;
-            mMainHandler.sendMessage(msg);
+            mServiceHandler.sendMessage(msg);
         }
 
         // If service is killed it cannot be recreated because it would not know which
@@ -278,7 +286,7 @@
 
     @Override
     public void onDestroy() {
-        mMainHandler.getLooper().quit();
+        mServiceHandler.getLooper().quit();
         mScreenshotHandler.getLooper().quit();
         super.onDestroy();
     }
@@ -613,7 +621,7 @@
             // ignore it
         }
 
-        mInfoDialog.initialize(mContext, info);
+        mMainThreadHandler.post(() -> mInfoDialog.initialize(mContext, info));
     }
 
     /**
@@ -652,11 +660,11 @@
     private void takeScreenshot(int id, int delay) {
         if (delay > 0) {
             Log.d(TAG, "Taking screenshot for " + id + " in " + delay + " seconds");
-            final Message msg = mMainHandler.obtainMessage();
+            final Message msg = mServiceHandler.obtainMessage();
             msg.what = MSG_DELAYED_SCREENSHOT;
             msg.arg1 = id;
             msg.arg2 = delay - 1;
-            mMainHandler.sendMessageDelayed(msg, DateUtils.SECOND_IN_MILLIS);
+            mServiceHandler.sendMessageDelayed(msg, DateUtils.SECOND_IN_MILLIS);
             return;
         }
 
@@ -696,7 +704,7 @@
         boolean taken = takeScreenshot(mContext, screenshotFile);
         setTakingScreenshot(false);
 
-        Message.obtain(mMainHandler, MSG_SCREENSHOT_RESPONSE, requestMsg.arg1, taken ? 1 : 0,
+        Message.obtain(mServiceHandler, MSG_SCREENSHOT_RESPONSE, requestMsg.arg1, taken ? 1 : 0,
                 screenshotFile).sendToTarget();
     }
 
@@ -981,6 +989,8 @@
         // Since we may be launched behind lockscreen, make sure that ChooserActivity doesn't finish
         // itself in onStop.
         chooserIntent.putExtra(ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP, true);
+        // Starting the activity from a service.
+        chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         context.startActivity(chooserIntent);
     }
 
@@ -1109,6 +1119,12 @@
      * description will be saved on {@code description.txt}.
      */
     private void addDetailsToZipFile(BugreportInfo info) {
+        synchronized (mLock) {
+            addDetailsToZipFileLocked(info);
+        }
+    }
+
+    private void addDetailsToZipFileLocked(BugreportInfo info) {
         if (info.bugreportFile == null) {
             // One possible reason is a bug in the Parcelization code.
             Log.wtf(TAG, "addDetailsToZipFile(): no bugreportFile on " + info);
@@ -1430,6 +1446,7 @@
         /**
          * Sets its internal state and displays the dialog.
          */
+        @MainThread
         void initialize(final Context context, BugreportInfo info) {
             final String dialogTitle =
                     context.getString(R.string.bugreport_info_dialog_title, info.id);
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 823b9b1..8bfcc74 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -355,7 +355,7 @@
         assertProgressNotification(NEW_NAME, 00.00f);
 
         Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath,
-                mScreenshotPath);
+                mScreenshotPath, TITLE);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
                 NEW_NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);
 
@@ -410,7 +410,7 @@
         assertProgressNotification(NEW_NAME, 00.00f);
 
         Bundle extras = sendBugreportFinishedAndGetSharedIntent(ID,
-                plainText? mPlainTextPath : mZipPath, mScreenshotPath);
+                plainText? mPlainTextPath : mZipPath, mScreenshotPath, TITLE);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, SCREENSHOT_CONTENT, ID, PID, TITLE,
                 NEW_NAME, TITLE, mDescription, 0, RENAMED_SCREENSHOTS);
 
@@ -465,7 +465,7 @@
         sendBugreportStarted(ID2, PID2, NAME2, 1000);
 
         sendBugreportFinished(ID, mZipPath, mScreenshotPath);
-        Bundle extras = acceptBugreportAndGetSharedIntent(ID);
+        Bundle extras = acceptBugreportAndGetSharedIntent(TITLE);
 
         detailsUi = new DetailsUi(mUiBot, ID2, NAME2);
         detailsUi.assertName(NAME2);
@@ -479,7 +479,7 @@
 
         // Must use a different zip file otherwise it will fail because zip already contains
         // title.txt and description.txt entries.
-        extras = sendBugreportFinishedAndGetSharedIntent(ID2, mZipPath2, NO_SCREENSHOT);
+        extras = sendBugreportFinishedAndGetSharedIntent(ID2, mZipPath2, NO_SCREENSHOT, TITLE2);
         assertActionSendMultiple(extras, BUGREPORT_CONTENT, NO_SCREENSHOT, ID2, PID2, TITLE2,
                 NEW_NAME2, TITLE2, DESCRIPTION2, 0, RENAMED_SCREENSHOTS);
 
@@ -568,7 +568,7 @@
 
         // Send notification and click on share.
         sendBugreportFinished(NO_ID, mPlainTextPath, null);
-        acceptBugreport(NO_ID);
+        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, NO_ID));
 
         // Handle the warning
         mUiBot.getVisibleObject(mContext.getString(R.string.bugreport_confirm));
@@ -725,13 +725,26 @@
         return acceptBugreportAndGetSharedIntent(id);
     }
 
+    // TODO: document / merge these 3 sendBugreportFinishedAndGetSharedIntent methods
+    private Bundle sendBugreportFinishedAndGetSharedIntent(int id, String bugreportPath,
+            String screenshotPath, String notificationTitle) {
+        sendBugreportFinished(id, bugreportPath, screenshotPath);
+        return acceptBugreportAndGetSharedIntent(notificationTitle);
+    }
+
     /**
      * Accepts the notification to share the finished bugreport and waits for the result.
      *
      * @return extras sent in the shared intent.
      */
     private Bundle acceptBugreportAndGetSharedIntent(int id) {
-        acceptBugreport(id);
+        final String notificationTitle = mContext.getString(R.string.bugreport_finished_title, id);
+        return acceptBugreportAndGetSharedIntent(notificationTitle);
+    }
+
+    // TODO: document and/or merge these 2 acceptBugreportAndGetSharedIntent methods
+    private Bundle acceptBugreportAndGetSharedIntent(String notificationTitle) {
+        mUiBot.clickOnNotification(notificationTitle);
         mUiBot.chooseActivity(UI_NAME);
         return mListener.getExtras();
     }
@@ -744,13 +757,6 @@
     }
 
     /**
-     * Accepts the notification to share the finished bugreport.
-     */
-    private void acceptBugreport(int id) {
-        mUiBot.clickOnNotification(mContext.getString(R.string.bugreport_finished_title, id));
-    }
-
-    /**
      * Sends a "bugreport finished" intent.
      */
     private void sendBugreportFinished(int id, String bugreportPath, String screenshotPath) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 5460304..79b02a5 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -187,6 +187,9 @@
     <!-- to access ResolverRankerServices -->
     <uses-permission android:name="android.permission.BIND_RESOLVER_RANKER_SERVICE" />
 
+    <!-- to access instant apps -->
+    <uses-permission android:name="android.permission.ACCESS_INSTANT_APPS" />
+
     <application
         android:name=".SystemUIApplication"
         android:persistent="true"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index 8fe2835..ed415b8 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -30,7 +30,6 @@
         android:layout_height="wrap_content"
         android:textColor="@color/clock_white"
         style="@style/widget_label"
-        android:textAllCaps="true"
         android:letterSpacing="0.15"
         android:gravity="center"
         />
@@ -41,7 +40,6 @@
         android:drawableStart="@drawable/ic_access_alarms_big"
         android:textColor="@color/clock_gray"
         android:letterSpacing="0.15"
-        android:textAllCaps="true"
         style="@style/widget_label"
         android:layout_marginStart="6dp"
         android:gravity="center"
diff --git a/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml b/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
index 469ce52..3fb86d0 100644
--- a/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
@@ -16,5 +16,5 @@
   -->
 
 <resources>
-    <dimen name="widget_big_font_size">84dp</dimen>
+    <dimen name="widget_big_font_size">64dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml b/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
index cb89cb4..3fb86d0 100644
--- a/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
@@ -16,5 +16,5 @@
   -->
 
 <resources>
-    <dimen name="widget_big_font_size">88dp</dimen>
+    <dimen name="widget_big_font_size">64dp</dimen>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 83ba8bf..7e208c2 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -91,13 +91,13 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="8364140853305528449">"Desenhou a sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Após mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem êxito, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="3389829202093674267">"Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="4314341367727055967">
+      <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
       <item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
-      <item quantity="one">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de precisar de contactar o seu operador para desbloquear o dispositivo.</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3329017604125179374">"Cartão SIM inutilizável. Contacte o seu operador."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="2287504898931957513">
+      <item quantity="one">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item>
       <item quantity="other">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável.</item>
-      <item quantity="one">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="8769990811451236223">"Falha ao introduzir o PIN do cartão SIM!"</string>
     <string name="kg_password_puk_failed" msgid="1331621440873439974">"Falha ao introduzir o PUK do cartão SIM!"</string>
@@ -117,16 +117,16 @@
     <string name="kg_prompt_reason_device_admin" msgid="3452168247888906179">"Dispositivo bloqueado pelo administrador"</string>
     <string name="kg_prompt_reason_user_request" msgid="8236951765212462286">"O dispositivo foi bloqueado manualmente"</string>
     <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="71299470072448533">
+      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm pattern.</item>
       <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o padrão.</item>
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme o padrão.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="34586942088144385">
+      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm PIN.</item>
       <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o PIN.</item>
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme o PIN.</item>
     </plurals>
     <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="257297696215346527">
+      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm password.</item>
       <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme a palavra-passe.</item>
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme a palavra-passe.</item>
     </plurals>
     <string name="fingerprint_not_recognized" msgid="348813995267914625">"Não reconhecido"</string>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
index a3b01b6..9e788be 100644
--- a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml
@@ -26,7 +26,7 @@
     <dimen name="keyguard_security_view_margin">12dp</dimen>
 
     <!-- Overload default clock widget parameters -->
-    <dimen name="widget_big_font_size">110dp</dimen>
+    <dimen name="widget_big_font_size">100dp</dimen>
     <dimen name="widget_label_font_size">16sp</dimen>
     <dimen name="bottom_text_spacing_digital">-1dp</dimen>
 
diff --git a/packages/SystemUI/res-keyguard/values-sw720dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw720dp/dimens.xml
index 210c7eb..7eb63d7 100644
--- a/packages/SystemUI/res-keyguard/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-sw720dp/dimens.xml
@@ -24,5 +24,5 @@
     <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) -->
     <dimen name="keyguard_security_height">420dp</dimen>
 
-    <dimen name="widget_big_font_size">122dp</dimen>
+    <dimen name="widget_big_font_size">100dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 7b952be2..3ca6e69 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -41,7 +41,7 @@
     <!-- Default clock parameters -->
     <dimen name="bottom_text_spacing_digital">-1dp</dimen>
     <dimen name="widget_label_font_size">14sp</dimen>
-    <dimen name="widget_big_font_size">78dp</dimen>
+    <dimen name="widget_big_font_size">64dp</dimen>
 
     <!-- The y translation to apply at the start in appear animations. -->
     <dimen name="appear_y_translation_start">32dp</dimen>
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index fb47bbc..fb4ac04 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -35,6 +35,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:elevation="4dp"
+        android:background="#00000000"
         android:layout_marginBottom="48dp" />
 
     <include layout="@layout/quick_status_bar_expanded_header" />
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 65344b7..2502d41 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -24,6 +24,7 @@
     android:layout_height="@dimen/status_bar_header_height"
     android:layout_gravity="@integer/notification_panel_layout_gravity"
     android:baselineAligned="false"
+    android:background="#00000000"
     android:elevation="4dp"
     android:clickable="false"
     android:clipChildren="false"
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 1cde012..29a5e19 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -473,7 +473,7 @@
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Brže dobijajte obaveštenja"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"Pregledajte ih pre otključavanja"</string>
     <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Ne, hvala"</string>
-    <string name="hidden_notifications_setup" msgid="41079514801976810">"Podesi"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Aktiviraj"</string>
     <string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="volume_zen_end_now" msgid="6930243045593601084">"Isključi odmah"</string>
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Proširi"</string>
@@ -739,7 +739,7 @@
     <string name="lockscreen_unlock_left" msgid="2043092136246951985">"I leva prečica otključava"</string>
     <string name="lockscreen_unlock_right" msgid="1529992940510318775">"I desna prečica otključava"</string>
     <string name="lockscreen_none" msgid="4783896034844841821">"Ništa"</string>
-    <string name="tuner_launch_app" msgid="1527264114781925348">"Pokretanje <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Pokreni <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="tuner_other_apps" msgid="4726596850501162493">"Druge aplikacije"</string>
     <string name="tuner_circle" msgid="2340998864056901350">"Krug"</string>
     <string name="tuner_plus" msgid="6792960658533229675">"Plus"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 18b9357..811b16c 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -719,8 +719,8 @@
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Réduire"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Fermer"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Faire glisser vers le bas pour ignorer"</string>
-    <string name="pip_menu_title" msgid="3328510504196964712">"Menu PIP"</string>
-    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> est en mode PIP"</string>
+    <string name="pip_menu_title" msgid="3328510504196964712">"Menu Picture-in-picture"</string>
+    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> est en mode Picture-in-picture"</string>
     <string name="pip_notification_message" msgid="4171698133469539591">"Si vous ne voulez pas que l\'application <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, appuyez ici pour ouvrir les paramètres et la désactiver."</string>
     <string name="pip_play" msgid="1417176722760265888">"Lecture"</string>
     <string name="pip_pause" msgid="8881063404466476571">"Suspendre"</string>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
index 3c0ad7a..43579af 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture"</string>
+    <string name="notification_channel_tv_pip" msgid="134047986446577723">"Picture-in-Picture (PIP)"</string>
     <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Programme sans titre)"</string>
     <string name="pip_close" msgid="3480680679023423574">"Fermer mode PIP"</string>
     <string name="pip_fullscreen" msgid="8604643018538487816">"Plein écran"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index ff3dba4..7481d1a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -719,8 +719,8 @@
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Pechar"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra cara abaixo para ignorar"</string>
-    <string name="pip_menu_title" msgid="3328510504196964712">"Menú de imaxe superposta"</string>
-    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está na imaxe superposta"</string>
+    <string name="pip_menu_title" msgid="3328510504196964712">"Menú de pantalla superposta"</string>
+    <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está na pantalla superposta"</string>
     <string name="pip_notification_message" msgid="4171698133469539591">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca para abrir a configuración e desactivala."</string>
     <string name="pip_play" msgid="1417176722760265888">"Reproducir"</string>
     <string name="pip_pause" msgid="8881063404466476571">"Pausar"</string>
diff --git a/packages/SystemUI/res/values-gl/strings_tv.xml b/packages/SystemUI/res/values-gl/strings_tv.xml
index c7f0ce1..87a636c 100644
--- a/packages/SystemUI/res/values-gl/strings_tv.xml
+++ b/packages/SystemUI/res/values-gl/strings_tv.xml
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="notification_channel_tv_pip" msgid="134047986446577723">"Imaxe superposta"</string>
+    <string name="notification_channel_tv_pip" msgid="134047986446577723">"Pantalla superposta"</string>
     <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Programa sen título)"</string>
     <string name="pip_close" msgid="3480680679023423574">"Pechar PIP"</string>
     <string name="pip_fullscreen" msgid="8604643018538487816">"Pantalla completa"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 9567c91..92bc82e 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -470,7 +470,7 @@
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"जब तक कि आप मैन्‍युअल रूप से अनलॉक नहीं करते तब तक डिवाइस लॉक रहेगा"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"सूचनाएं अधिक तेज़ी से प्राप्त करें"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"आपके द्वारा उन्हें अनलॉक किए जाने से पहले देखें"</string>
-    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"नहीं धन्यवाद"</string>
+    <string name="hidden_notifications_cancel" msgid="3690709735122344913">"रहने दें"</string>
     <string name="hidden_notifications_setup" msgid="41079514801976810">"सेट करें"</string>
     <string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="volume_zen_end_now" msgid="6930243045593601084">"अभी बंद करें"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 4d1fc9f..1189b05 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -155,7 +155,7 @@
     <string name="accessibility_cell_data" msgid="5326139158682385073">"Բջջային ինտերնետ"</string>
     <string name="accessibility_cell_data_on" msgid="5927098403452994422">"Բջջային տվյալները միացված են"</string>
     <string name="accessibility_cell_data_off" msgid="443267573897409704">"Բջջային տվյալներն անջատված են"</string>
-    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-ը կապվում է:"</string>
+    <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth մոդեմ"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Ինքնաթիռի ռեժիմ"</string>
     <string name="accessibility_vpn_on" msgid="5993385083262856059">"Միացնել VPN-ը։"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM քարտ չկա:"</string>
@@ -311,7 +311,7 @@
     <string name="quick_settings_done" msgid="3402999958839153376">"Պատրաստ է"</string>
     <string name="quick_settings_connected" msgid="1722253542984847487">"Կապակցված է"</string>
     <string name="quick_settings_connecting" msgid="47623027419264404">"Միանում է..."</string>
-    <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Միացում"</string>
+    <string name="quick_settings_tethering_label" msgid="7153452060448575549">"Մոդեմի ռեժիմ"</string>
     <string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Թեժ կետ"</string>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ծանուցումներ"</string>
     <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"Լապտեր"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c4f8e7b..273b390 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -750,8 +750,8 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"스크린샷"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"일반 메시지"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"저장소"</string>
-    <string name="instant_apps" msgid="6647570248119804907">"빠른 실행 앱"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"빠른 실행 앱은 설치가 필요하지 않습니다."</string>
+    <string name="instant_apps" msgid="6647570248119804907">"인스턴트 앱"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"인스턴트 앱은 설치가 필요하지 않습니다."</string>
     <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
     <string name="go_to_web" msgid="1106022723459948514">"웹으로 이동"</string>
     <string name="mobile_data" msgid="7094582042819250762">"모바일 데이터"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index c5089a4..74089b2 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -26,8 +26,8 @@
     <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Os ecrãs recentes aparecem aqui"</string>
     <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ignorar aplicações recentes"</string>
     <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
+      <item quantity="one">%d screens in Overview</item>
       <item quantity="other">%d ecrãs na Vista geral</item>
-      <item quantity="one">1 ecrã na Vista geral</item>
     </plurals>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string>
@@ -252,8 +252,8 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
+      <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
-      <item quantity="one">Mais <xliff:g id="NUMBER_0">%s</xliff:g> notificação no grupo.</item>
     </plurals>
     <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Definições de notificação"</string>
     <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Definições do <xliff:g id="APP_NAME">%s</xliff:g>"</string>
@@ -552,13 +552,13 @@
     <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorias de notificação"</string>
     <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicação não tem categorias de notificação"</string>
     <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
+      <item quantity="one">1 out of <xliff:g id="NUMBER_1">%d</xliff:g> notification categories from this app</item>
       <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorias de notificação desta aplicação</item>
-      <item quantity="one">1 de <xliff:g id="NUMBER_0">%d</xliff:g> categoria de notificação desta aplicação</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> e mais <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> e mais <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
     </plurals>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Controlos de notificações da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Controlos de notificações da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> fechados"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 46e6b5f..b0e770f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -758,8 +758,8 @@
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"Posnetki zaslona"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"Splošna sporočila"</string>
     <string name="notification_channel_storage" msgid="3077205683020695313">"Shramba"</string>
-    <string name="instant_apps" msgid="6647570248119804907">"Aplikacije brez nameščanja"</string>
-    <string name="instant_apps_message" msgid="8116608994995104836">"Aplikacij brez nameščanja ni treba namestiti."</string>
+    <string name="instant_apps" msgid="6647570248119804907">"Nenamestljive aplikacije"</string>
+    <string name="instant_apps_message" msgid="8116608994995104836">"Nenamestljivih aplikacij ni treba namestiti."</string>
     <string name="app_info" msgid="6856026610594615344">"Podatki o aplikaciji"</string>
     <string name="go_to_web" msgid="1106022723459948514">"Pojdi v splet"</string>
     <string name="mobile_data" msgid="7094582042819250762">"Mobilni podatki"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 596ef38..f4b488422 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -473,7 +473,7 @@
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Брже добијајте обавештења"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"Прегледајте их пре откључавања"</string>
     <string name="hidden_notifications_cancel" msgid="3690709735122344913">"Не, хвала"</string>
-    <string name="hidden_notifications_setup" msgid="41079514801976810">"Подеси"</string>
+    <string name="hidden_notifications_setup" msgid="41079514801976810">"Активирај"</string>
     <string name="zen_mode_and_condition" msgid="4462471036429759903">"<xliff:g id="ZEN_MODE">%1$s</xliff:g>. <xliff:g id="EXIT_CONDITION">%2$s</xliff:g>"</string>
     <string name="volume_zen_end_now" msgid="6930243045593601084">"Искључи одмах"</string>
     <string name="accessibility_volume_expand" msgid="5946812790999244205">"Прошири"</string>
@@ -739,7 +739,7 @@
     <string name="lockscreen_unlock_left" msgid="2043092136246951985">"И лева пречица откључава"</string>
     <string name="lockscreen_unlock_right" msgid="1529992940510318775">"И десна пречица откључава"</string>
     <string name="lockscreen_none" msgid="4783896034844841821">"Ништа"</string>
-    <string name="tuner_launch_app" msgid="1527264114781925348">"Покретање <xliff:g id="APP">%1$s</xliff:g>"</string>
+    <string name="tuner_launch_app" msgid="1527264114781925348">"Покрени <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="tuner_other_apps" msgid="4726596850501162493">"Друге апликације"</string>
     <string name="tuner_circle" msgid="2340998864056901350">"Круг"</string>
     <string name="tuner_plus" msgid="6792960658533229675">"Плус"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 9dd39d4..cf8747e 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -89,7 +89,7 @@
         TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView,
                 defStyle, 0);
         final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
-                context.getColor(R.color.batterymeter_frame_color));
+                context.getColor(R.color.meter_background_color));
         mDrawable = new BatteryMeterDrawableBase(context, frameColor);
         atts.recycle();
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index f4d4a9f..0cf8ff0 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -264,6 +264,8 @@
         mProviders.put(AccessibilityManagerWrapper.class,
                 () -> new AccessibilityManagerWrapper(mContext));
 
+        mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index cdad8ae..44a044b 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -22,9 +22,6 @@
 
 public interface RecentsComponent {
     void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
-    void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
-    void toggleRecents();
-    void preloadRecents();
     void showNextAffiliatedTask();
     void showPrevAffiliatedTask();
 
diff --git a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
new file mode 100644
index 0000000..82fd9b3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+/**
+ * Thread that offloads work from the UI thread but that is still perceptible to the user, so the
+ * priority is the same as the main thread.
+ */
+public class UiOffloadThread {
+
+    private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
+
+    public Future<?> submit(Runnable runnable) {
+        return mExecutorService.submit(runnable);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index 1abea37..a129ace 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -30,7 +30,10 @@
 import android.view.MotionEvent;
 import android.view.accessibility.AccessibilityManager;
 
+import com.android.systemui.Dependency;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.analytics.DataCollector;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.StatusBarState;
 
 import java.io.PrintWriter;
@@ -63,6 +66,7 @@
     private final DataCollector mDataCollector;
     private final HumanInteractionClassifier mHumanInteractionClassifier;
     private final AccessibilityManager mAccessibilityManager;
+    private final UiOffloadThread mUiOffloadThread;
 
     private static FalsingManager sInstance = null;
 
@@ -86,6 +90,7 @@
         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
         mDataCollector = DataCollector.getInstance(mContext);
         mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
+        mUiOffloadThread = Dependency.get(UiOffloadThread.class);
         mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
 
         mContext.getContentResolver().registerContentObserver(
@@ -130,7 +135,11 @@
     private void sessionExitpoint(boolean force) {
         if (mSessionActive && (force || !shouldSessionBeActive())) {
             mSessionActive = false;
-            mSensorManager.unregisterListener(this);
+
+            // This can be expensive, and doesn't need to happen on the main thread.
+            mUiOffloadThread.submit(() -> {
+                mSensorManager.unregisterListener(this);
+            });
         }
     }
 
@@ -154,7 +163,11 @@
         for (int sensorType : sensors) {
             Sensor s = mSensorManager.getDefaultSensor(sensorType);
             if (s != null) {
-                mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
+
+                // This can be expensive, and doesn't need to happen on the main thread.
+                mUiOffloadThread.submit(() -> {
+                    mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
+                });
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
index 262d29d..745f312 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -17,6 +17,10 @@
 package com.android.systemui.keyguard;
 
 import com.android.internal.policy.IKeyguardDismissCallback;
+import com.android.systemui.Dependency;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 
 import java.util.ArrayList;
 
@@ -26,6 +30,7 @@
 public class DismissCallbackRegistry {
 
     private final ArrayList<DismissCallbackWrapper> mDismissCallbacks = new ArrayList<>();
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     public void addCallback(IKeyguardDismissCallback callback) {
         mDismissCallbacks.add(new DismissCallbackWrapper(callback));
@@ -33,14 +38,16 @@
 
     public void notifyDismissCancelled() {
         for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
-            mDismissCallbacks.get(i).notifyDismissCancelled();
+            DismissCallbackWrapper callback = mDismissCallbacks.get(i);
+            mUiOffloadThread.submit(callback::notifyDismissCancelled);
         }
         mDismissCallbacks.clear();
     }
 
     public void notifyDismissSucceeded() {
         for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
-            mDismissCallbacks.get(i).notifyDismissSucceeded();
+            DismissCallbackWrapper callback = mDismissCallbacks.get(i);
+            mUiOffloadThread.submit(callback::notifyDismissSucceeded);
         }
         mDismissCallbacks.clear();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f618a2c..b977dd4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -51,6 +51,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.provider.Settings.System;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.EventLog;
@@ -76,9 +77,13 @@
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.LatencyTracker;
 import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.Dependency;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.phone.FingerprintUnlockController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.ScrimController;
@@ -195,6 +200,7 @@
     private AlarmManager mAlarmManager;
     private AudioManager mAudioManager;
     private StatusBarManager mStatusBarManager;
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     private boolean mSystemReady;
     private boolean mBootCompleted;
@@ -1199,18 +1205,20 @@
             updateInputRestrictedLocked();
         }
     }
+
     private void updateInputRestrictedLocked() {
         boolean inputRestricted = isInputRestricted();
         if (mInputRestricted != inputRestricted) {
             mInputRestricted = inputRestricted;
             int size = mKeyguardStateCallbacks.size();
             for (int i = size - 1; i >= 0; i--) {
+                final IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i);
                 try {
-                    mKeyguardStateCallbacks.get(i).onInputRestrictedStateChanged(inputRestricted);
+                    callback.onInputRestrictedStateChanged(inputRestricted);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to call onDeviceProvisioned", e);
                     if (e instanceof DeadObjectException) {
-                        mKeyguardStateCallbacks.remove(i);
+                        mKeyguardStateCallbacks.remove(callback);
                     }
                 }
             }
@@ -1569,9 +1577,11 @@
     private void handleKeyguardDone() {
         Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");
         final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
-        if (mLockPatternUtils.isSecure(currentUser)) {
-            mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
-        }
+        mUiOffloadThread.submit(() -> {
+            if (mLockPatternUtils.isSecure(currentUser)) {
+                mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
+            }
+        });
         if (DEBUG) Log.d(TAG, "handleKeyguardDone");
         synchronized (this) {
             resetKeyguardDonePendingLocked();
@@ -1611,10 +1621,12 @@
                 final UserHandle currentUser = new UserHandle(currentUserId);
                 final UserManager um = (UserManager) mContext.getSystemService(
                         Context.USER_SERVICE);
-                for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
-                    mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
-                }
-                getLockPatternUtils().userPresent(currentUserId);
+                mUiOffloadThread.submit(() -> {
+                    for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
+                        mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
+                    }
+                    getLockPatternUtils().userPresent(currentUserId);
+                });
             } else {
                 mBootSendUserPresent = true;
             }
@@ -1659,11 +1671,18 @@
                 if (mAudioManager == null) return;
                 mUiSoundsStreamType = mAudioManager.getUiSoundsStreamType();
             }
-            // If the stream is muted, don't play the sound
-            if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
 
-            mLockSoundStreamId = mLockSounds.play(soundId,
-                    mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
+            mUiOffloadThread.submit(() -> {
+                // If the stream is muted, don't play the sound
+                if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
+
+                int id = mLockSounds.play(soundId,
+                        mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
+                synchronized (this) {
+                    mLockSoundStreamId = id;
+                }
+            });
+
         }
     }
 
@@ -1671,13 +1690,13 @@
         playSound(mTrustedSoundId);
     }
 
-    private void updateActivityLockScreenState() {
-        Trace.beginSection("KeyguardViewMediator#updateActivityLockScreenState");
-        try {
-            ActivityManager.getService().setLockScreenShown(mShowing);
-        } catch (RemoteException e) {
-        }
-        Trace.endSection();
+    private void updateActivityLockScreenState(boolean showing) {
+        mUiOffloadThread.submit(() -> {
+            try {
+                ActivityManager.getService().setLockScreenShown(showing);
+            } catch (RemoteException e) {
+            }
+        });
     }
 
     /**
@@ -1808,11 +1827,11 @@
 
             mWakeAndUnlocking = false;
             setShowingLocked(false);
+            mDismissCallbackRegistry.notifyDismissSucceeded();
             mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
             adjustStatusBarLocked();
-            mDismissCallbackRegistry.notifyDismissSucceeded();
             sendUserPresentBroadcast();
             mUpdateMonitor.setKeyguardGoingAway(false /* goingAway */);
         }
@@ -1846,7 +1865,10 @@
             }
 
             if (!(mContext instanceof Activity)) {
-                mStatusBarManager.disable(flags);
+                final int finalFlags = flags;
+                mUiOffloadThread.submit(() -> {
+                    mStatusBarManager.disable(finalFlags);
+                });
             }
         }
     }
@@ -2044,18 +2066,21 @@
             mShowing = showing;
             int size = mKeyguardStateCallbacks.size();
             for (int i = size - 1; i >= 0; i--) {
+                IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i);
                 try {
-                    mKeyguardStateCallbacks.get(i).onShowingStateChanged(showing);
+                    callback.onShowingStateChanged(showing);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to call onShowingStateChanged", e);
                     if (e instanceof DeadObjectException) {
-                        mKeyguardStateCallbacks.remove(i);
+                        mKeyguardStateCallbacks.remove(callback);
                     }
                 }
             }
             updateInputRestrictedLocked();
-            mTrustManager.reportKeyguardShowingChanged();
-            updateActivityLockScreenState();
+            mUiOffloadThread.submit(() -> {
+                mTrustManager.reportKeyguardShowingChanged();
+            });
+            updateActivityLockScreenState(showing);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
index 68c8007..36dbb0f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
@@ -17,12 +17,13 @@
 package com.android.systemui.pip;
 
 import android.content.Context;
+import android.content.res.Configuration;
 
 import java.io.PrintWriter;
 
 public interface  BasePipManager {
     void initialize(Context context);
     void showPictureInPictureMenu();
-    void onConfigurationChanged();
+    void onConfigurationChanged(Configuration newConfig);
     void dump(PrintWriter pw);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index a1f6553..b7164cb 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -72,7 +72,7 @@
             return;
         }
 
-        mPipManager.onConfigurationChanged();
+        mPipManager.onConfigurationChanged(newConfig);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index da2d38f..0373d77 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -16,13 +16,16 @@
 
 package com.android.systemui.pip.phone;
 
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import android.app.ActivityManager;
+import android.app.ActivityManager.StackInfo;
 import android.app.IActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -33,6 +36,8 @@
 import android.view.WindowManagerGlobal;
 
 import com.android.systemui.pip.BasePipManager;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
 import com.android.systemui.statusbar.CommandQueue;
@@ -65,8 +70,8 @@
      */
     TaskStackListener mTaskStackListener = new TaskStackListener() {
         @Override
-        public void onActivityPinned(String packageName) {
-            if (!checkCurrentUserId(false /* debug */)) {
+        public void onActivityPinned(String packageName, int taskId) {
+            if (!checkCurrentUserId(mContext, false /* debug */)) {
                 return;
             }
 
@@ -81,7 +86,7 @@
 
         @Override
         public void onActivityUnpinned() {
-            if (!checkCurrentUserId(false /* debug */)) {
+            if (!checkCurrentUserId(mContext, false /* debug */)) {
                 return;
             }
 
@@ -110,7 +115,7 @@
 
         @Override
         public void onPinnedActivityRestartAttempt(boolean clearedTask) {
-            if (!checkCurrentUserId(false /* debug */)) {
+            if (!checkCurrentUserId(mContext, false /* debug */)) {
                 return;
             }
 
@@ -186,16 +191,37 @@
                 mInputConsumerController);
         mNotificationController = new PipNotificationController(context, mActivityManager,
                 mTouchHandler.getMotionHelper());
+        EventBus.getDefault().register(this);
     }
 
     /**
      * Updates the PIP per configuration changed.
      */
-    public void onConfigurationChanged() {
+    public void onConfigurationChanged(Configuration newConfig) {
         mTouchHandler.onConfigurationChanged();
     }
 
     /**
+     * Expands the PIP.
+     */
+    public final void onBusEvent(ExpandPipEvent event) {
+        if (event.clearThumbnailWindows) {
+            try {
+                StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+                if (stackInfo != null && stackInfo.taskIds != null) {
+                    SystemServicesProxy ssp = SystemServicesProxy.getInstance(mContext);
+                    for (int taskId : stackInfo.taskIds) {
+                        ssp.cancelThumbnailTransition(taskId);
+                    }
+                }
+            } catch (RemoteException e) {
+                // Do nothing
+            }
+        }
+        mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
+    }
+
+    /**
      * Sent from KEYCODE_WINDOW handler in PhoneWindowManager, to request the menu to be shown.
      */
     public void showPictureInPictureMenu() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 766914c..013b9ac 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -63,6 +63,8 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -221,9 +223,9 @@
     protected void onUserLeaveHint() {
         super.onUserLeaveHint();
 
-        // If another task is starting on top of the menu, then finish it so that it can be
+        // If another task is starting on top of the menu, then hide and finish it so that it can be
         // recreated on the top next time it starts
-        finish();
+        hideMenu();
     }
 
     @Override
@@ -231,6 +233,7 @@
         super.onStop();
 
         cancelDelayedFinish();
+        EventBus.getDefault().unregister(this);
     }
 
     @Override
@@ -290,6 +293,19 @@
         // Do nothing
     }
 
+    public final void onBusEvent(HidePipMenuEvent event) {
+        if (mMenuState != MENU_STATE_NONE) {
+            // If the menu is visible in either the closed or full state, then hide the menu and
+            // trigger the animation trigger afterwards
+            event.getAnimationTrigger().increment();
+            hideMenu(() -> {
+                mHandler.post(() -> {
+                    event.getAnimationTrigger().decrement();
+                });
+            }, true /* notifyMenuVisibility */);
+        }
+    }
+
     private void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
             boolean allowMenuTimeout) {
         mAllowMenuTimeout = allowMenuTimeout;
@@ -373,11 +389,16 @@
     private void updateFromIntent(Intent intent) {
         mToControllerMessenger = intent.getParcelableExtra(EXTRA_CONTROLLER_MESSENGER);
         notifyActivityCallback(mMessenger);
+
+        // Register for HidePipMenuEvents once we notify the controller of this activity
+        EventBus.getDefault().register(this);
+
         ParceledListSlice actions = intent.getParcelableExtra(EXTRA_ACTIONS);
         if (actions != null) {
             mActions.clear();
             mActions.addAll(actions.getList());
         }
+
         final int menuState = intent.getIntExtra(EXTRA_MENU_STATE, MENU_STATE_NONE);
         if (menuState != MENU_STATE_NONE) {
             Rect stackBounds = intent.getParcelableExtra(EXTRA_STACK_BOUNDS);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 5afa53f..e310847 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -27,6 +27,7 @@
 import android.content.pm.ParceledListSlice;
 import android.graphics.Rect;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Messenger;
@@ -36,6 +37,9 @@
 import android.view.IWindowManager;
 
 import com.android.systemui.pip.phone.PipMediaController.ActionListener;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -119,6 +123,7 @@
     // The dismiss fraction update is sent frequently, so use a temporary bundle for the message
     private Bundle mTmpDismissFractionData = new Bundle();
 
+    private ReferenceCountedTrigger mOnAttachDecrementTrigger;
     private boolean mStartActivityRequested;
     private Messenger mToActivityMessenger;
     private Messenger mMessenger = new Messenger(new Handler() {
@@ -157,6 +162,10 @@
                 case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                     mToActivityMessenger = msg.replyTo;
                     mStartActivityRequested = false;
+                    if (mOnAttachDecrementTrigger != null) {
+                        mOnAttachDecrementTrigger.decrement();
+                        mOnAttachDecrementTrigger = null;
+                    }
                     // Mark the menu as invisible once the activity finishes as well
                     if (mToActivityMessenger == null) {
                         onMenuStateChanged(MENU_STATE_NONE, true /* resize */);
@@ -181,6 +190,8 @@
         mActivityManager = activityManager;
         mMediaController = mediaController;
         mInputConsumerController = inputConsumerController;
+
+        EventBus.getDefault().register(this);
     }
 
     public void onActivityPinned() {
@@ -244,7 +255,9 @@
     public void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
             boolean allowMenuTimeout) {
         if (DEBUG) {
-            Log.d(TAG, "showMenu() hasActivity=" + (mToActivityMessenger != null));
+            Log.d(TAG, "showMenu() state=" + menuState
+                    + " hasActivity=" + (mToActivityMessenger != null)
+                    + " callers=\n" + Debug.getCallers(5, "    "));
         }
         if (mToActivityMessenger != null) {
             Bundle data = new Bundle();
@@ -288,7 +301,9 @@
      */
     public void hideMenu() {
         if (DEBUG) {
-            Log.d(TAG, "hideMenu() hasActivity=" + (mToActivityMessenger != null));
+            Log.d(TAG, "hideMenu() state=" + mMenuState
+                    + " hasActivity=" + (mToActivityMessenger != null)
+                    + " callers=\n" + Debug.getCallers(5, "    "));
         }
         if (mToActivityMessenger != null) {
             Message m = Message.obtain();
@@ -311,13 +326,6 @@
     }
 
     /**
-     * @return the current menu state.
-     */
-    public int getMenuState() {
-        return mMenuState;
-    }
-
-    /**
      * Sets the menu actions to the actions provided by the current PiP activity.
      */
     public void setAppActions(ParceledListSlice appActions) {
@@ -435,6 +443,15 @@
         mMenuState = menuState;
     }
 
+    public final void onBusEvent(HidePipMenuEvent event) {
+        if (mStartActivityRequested) {
+            // If the menu has been start-requested, but not actually started, then we defer the
+            // trigger callback until the menu has started and called back to the controller
+            mOnAttachDecrementTrigger = event.getAnimationTrigger();
+            mOnAttachDecrementTrigger.increment();
+        }
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 590e3c6..9fa7ff6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -34,6 +34,7 @@
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Log;
@@ -54,6 +55,7 @@
 public class PipMotionHelper {
 
     private static final String TAG = "PipMotionHelper";
+    private static final boolean DEBUG = false;
 
     private static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect());
 
@@ -150,6 +152,10 @@
      * Resizes the pinned stack back to fullscreen.
      */
     void expandPip(boolean skipAnimation) {
+        if (DEBUG) {
+            Log.d(TAG, "expandPip: skipAnimation=" + skipAnimation
+                    + " callers=\n" + Debug.getCallers(5, "    "));
+        }
         cancelAnimations();
         mMenuController.hideMenuWithoutResize();
         mHandler.post(() -> {
@@ -171,6 +177,9 @@
      * Dismisses the pinned stack.
      */
     void dismissPip() {
+        if (DEBUG) {
+            Log.d(TAG, "dismissPip: callers=\n" + Debug.getCallers(5, "    "));
+        }
         cancelAnimations();
         mMenuController.hideMenuWithoutResize();
         mHandler.post(() -> {
@@ -419,6 +428,10 @@
      * Directly resizes the PiP to the given {@param bounds}.
      */
     private void resizePipUnchecked(Rect toBounds) {
+        if (DEBUG) {
+            Log.d(TAG, "resizePipUnchecked: toBounds=" + toBounds
+                    + " callers=\n" + Debug.getCallers(5, "    "));
+        }
         if (!toBounds.equals(mBounds)) {
             mVsyncChoreographer.scheduleAtSfVsync(() -> {
                 try {
@@ -435,6 +448,10 @@
      * Directly resizes the PiP to the given {@param bounds}.
      */
     private void resizeAndAnimatePipUnchecked(Rect toBounds, int duration) {
+        if (DEBUG) {
+            Log.d(TAG, "resizeAndAnimatePipUnchecked: toBounds=" + toBounds
+                    + " duration=" + duration + " callers=\n" + Debug.getCallers(5, "    "));
+        }
         if (!toBounds.equals(mBounds)) {
             mHandler.post(() -> {
                 try {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 199b027..c35fdd5 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -484,14 +484,15 @@
             // Try and restore the PiP to the closest edge, using the saved snap fraction
             // if possible
             if (resize) {
-                // This is a very special case: when the menu is expanded and visible, navigating to
-                // another activity can trigger auto-enter PiP, and if the revealed activity has a
-                // forced rotation set, then the controller will get updated with the new rotation
-                // of the display. However, at the same time, SystemUI will try to hide the menu by
-                // creating an animation to the normal bounds which are now stale.  In such a case
-                // we defer the animation to the normal bounds until after the next
-                // onMovementBoundsChanged() call to get the bounds in the new orientation
                 if (mDeferResizeToNormalBoundsUntilRotation == -1) {
+                    // This is a very special case: when the menu is expanded and visible,
+                    // navigating to another activity can trigger auto-enter PiP, and if the
+                    // revealed activity has a forced rotation set, then the controller will get
+                    // updated with the new rotation of the display. However, at the same time,
+                    // SystemUI will try to hide the menu by creating an animation to the normal
+                    // bounds which are now stale.  In such a case we defer the animation to the
+                    // normal bounds until after the next onMovementBoundsChanged() call to get the
+                    // bounds in the new orientation
                     try {
                         int displayRotation = mPinnedStackController.getDisplayRotation();
                         if (mDisplayRotation != displayRotation) {
@@ -510,6 +511,9 @@
                     mSavedSnapFraction = -1f;
                 }
             } else {
+                // If resizing is not allowed, then the PiP should be frozen until the transition
+                // ends as well
+                setTouchEnabled(false);
                 mSavedSnapFraction = -1f;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 198bbe5..5414aad 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -26,6 +26,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ParceledListSlice;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.media.session.MediaController;
@@ -116,6 +117,7 @@
     private Rect mDefaultPipBounds = new Rect();
     private Rect mSettingsPipBounds;
     private Rect mMenuModePipBounds;
+    private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
     private boolean mInitialized;
     private int mPipTaskId = TASK_ID_NO_PIP;
     private ComponentName mPipComponentName;
@@ -237,7 +239,7 @@
             }
         }
 
-        loadConfigurationsAndApply();
+        loadConfigurationsAndApply(mContext.getResources().getConfiguration());
         mMediaSessionManager =
                 (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
 
@@ -250,7 +252,14 @@
         mPipNotification = new PipNotification(context);
     }
 
-    private void loadConfigurationsAndApply() {
+    private void loadConfigurationsAndApply(Configuration newConfig) {
+        if (mLastOrientation != newConfig.orientation) {
+            // Don't resize the pinned stack on orientation change. TV does not care about this case
+            // and this could clobber the existing animation to the new bounds calculated by WM.
+            mLastOrientation = newConfig.orientation;
+            return;
+        }
+
         Resources res = mContext.getResources();
         mSettingsPipBounds = Rect.unflattenFromString(res.getString(
                 R.string.pip_settings_bounds));
@@ -267,8 +276,8 @@
     /**
      * Updates the PIP per configuration changed.
      */
-    public void onConfigurationChanged() {
-        loadConfigurationsAndApply();
+    public void onConfigurationChanged(Configuration newConfig) {
+        loadConfigurationsAndApply(newConfig);
         mPipNotification.onConfigurationChanged(mContext);
     }
 
@@ -577,7 +586,7 @@
         @Override
         public void onTaskStackChanged() {
             if (DEBUG) Log.d(TAG, "onTaskStackChanged()");
-            if (!checkCurrentUserId(DEBUG)) {
+            if (!checkCurrentUserId(mContext, DEBUG)) {
                 return;
             }
             if (getState() != STATE_NO_PIP) {
@@ -612,9 +621,9 @@
         }
 
         @Override
-        public void onActivityPinned(String packageName) {
+        public void onActivityPinned(String packageName, int taskId) {
             if (DEBUG) Log.d(TAG, "onActivityPinned()");
-            if (!checkCurrentUserId(DEBUG)) {
+            if (!checkCurrentUserId(mContext, DEBUG)) {
                 return;
             }
             StackInfo stackInfo = getPinnedStackInfo();
@@ -641,7 +650,7 @@
         @Override
         public void onPinnedActivityRestartAttempt(boolean clearedTask) {
             if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
-            if (!checkCurrentUserId(DEBUG)) {
+            if (!checkCurrentUserId(mContext, DEBUG)) {
                 return;
             }
             // If PIPed activity is launched again by Launcher or intent, make it fullscreen.
@@ -651,7 +660,7 @@
         @Override
         public void onPinnedStackAnimationEnded() {
             if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()");
-            if (!checkCurrentUserId(DEBUG)) {
+            if (!checkCurrentUserId(mContext, DEBUG)) {
                 return;
             }
             switch (getState()) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index 30240c3..c8f4185 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -194,7 +194,7 @@
 
     private void dismissPipNotification() {
         mNotified = false;
-        mNotificationManager.cancel(SystemMessage.NOTE_TV_PIP);
+        mNotificationManager.cancel(NOTIFICATION_TAG, SystemMessage.NOTE_TV_PIP);
     }
 
     private boolean updateMediaControllerMetadata() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index ecc275d..74cc0ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -141,7 +141,7 @@
         private final BatteryMeterDrawableBase mDrawable
                 = new BatteryMeterDrawableBase(
                         mHost.getContext(),
-                        mHost.getContext().getColor(R.color.batterymeter_frame_color));
+                        mHost.getContext().getColor(R.color.meter_background_color));
         private View mCurrentView;
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 6f28838..f0d7d6c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -16,33 +16,33 @@
 
 package com.android.systemui.qs.tiles;
 
+import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
+
 import android.app.Dialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnDismissListener;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.media.MediaRouter;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.quicksettings.Tile;
-import android.support.v7.app.MediaRouteChooserDialog;
-import android.support.v7.app.MediaRouteControllerDialog;
-import android.support.v7.media.MediaControlIntent;
-import android.support.v7.media.MediaRouteSelector;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.widget.Button;
 
+import com.android.internal.app.MediaRouteChooserDialog;
+import com.android.internal.app.MediaRouteControllerDialog;
+import com.android.internal.app.MediaRouteDialogPresenter;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.R.style;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
@@ -133,19 +133,12 @@
     @Override
     public void showDetail(boolean show) {
         mUiHandler.post(() -> {
-            Context context = new ContextThemeWrapper(mContext,
-                    R.style.Theme_AppCompat_Light_Dialog_Alert);
-            if (mState.value) {
-                mDialog = new MediaRouteControllerDialog(context);
-            } else {
-                // Instead of showing detail, show standard media routing UI.
-                MediaRouteChooserDialog dialog = new MediaRouteChooserDialog(context);
-                MediaRouteSelector selector = new MediaRouteSelector.Builder()
-                        .addControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO)
-                        .build();
-                dialog.setRouteSelector(selector);
-                mDialog = dialog;
-            }
+            mDialog = MediaRouteDialogPresenter.createDialog(mContext, ROUTE_TYPE_REMOTE_DISPLAY,
+                    v -> {
+                        mDialog.dismiss();
+                        Dependency.get(ActivityStarter.class)
+                                .postStartActivityDismissingKeyguard(getLongClickIntent(), 0);
+                    });
             mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
             mUiHandler.post(() -> mDialog.show());
             registerReceiver();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 72dd2da..9ba32b3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -19,7 +19,6 @@
 import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
 
 import android.app.ActivityManager;
-import android.app.UiModeManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -33,7 +32,6 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -41,7 +39,6 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.view.Display;
-import android.view.WindowManager;
 import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
@@ -60,11 +57,12 @@
 import com.android.systemui.recents.events.component.ShowUserToastEvent;
 import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.model.HighResThumbnailLoader;
 import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Set;
@@ -322,16 +320,11 @@
         }
     }
 
-    @Override
-    public void toggleRecentApps() {
-        toggleRecents();
-    }
-
     /**
      * Toggles the Recents activity.
      */
     @Override
-    public void toggleRecents() {
+    public void toggleRecentApps() {
         // Ensure the device has been provisioned before allowing the user to interact with
         // recents
         if (!isUserSetup()) {
@@ -368,7 +361,7 @@
      * Preloads info for the Recents activity.
      */
     @Override
-    public void preloadRecents() {
+    public void preloadRecentApps() {
         // Ensure the device has been provisioned before allowing the user to interact with
         // recents
         if (!isUserSetup()) {
@@ -792,4 +785,10 @@
         }
         return false;
     }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("Recents");
+        pw.println("  currentUserId=" + SystemServicesProxy.getInstance(mContext).getCurrentUser());
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index c0e4b99..7697061 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -62,6 +62,7 @@
 import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
+import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
@@ -113,7 +114,6 @@
     private boolean mFinishedOnStartup;
     private boolean mIgnoreAltTabRelease;
     private boolean mIsVisible;
-    private boolean mReceivedNewIntent;
 
     // Top level views
     private RecentsView mRecentsView;
@@ -127,9 +127,6 @@
     private int mFocusTimerDuration;
     private DozeTrigger mIterateTrigger;
     private final UserInteractionEvent mUserInteractionEvent = new UserInteractionEvent();
-    private final Runnable mSendEnterWindowAnimationCompleteRunnable = () -> {
-        EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
-    };
 
     /**
      * A common Runnable to finish Recents by launching Home with an animation depending on the
@@ -203,8 +200,12 @@
                                 Recents.getSystemServices().removeTask(task.persistentId);
                             }
                         }
-                        Settings.Secure.putLongForUser(RecentsActivity.this.getContentResolver(),
-                                Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, currentTime, currentUser);
+                        Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+                                currentTime, currentUser);
+
+                        // Clear the last PiP task time, it's an edge case and we'd rather it
+                        // not relaunch the PiP task if the user double taps
+                        RecentsImpl.clearLastPipTime();
                     }
                 }
             }
@@ -385,7 +386,6 @@
     @Override
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
-        mReceivedNewIntent = true;
 
         // Reload the stack view
         reloadStackView();
@@ -395,6 +395,7 @@
      * Reloads the stack views upon launching Recents.
      */
     private void reloadStackView() {
+
         // If the Recents component has preloaded a load plan, then use that to prevent
         // reconstructing the task stack
         RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -463,16 +464,7 @@
     @Override
     public void onEnterAnimationComplete() {
         super.onEnterAnimationComplete();
-
-        // Workaround for b/28705801, on first docking, we may receive the enter animation callback
-        // before the first layout, so in such cases, send the event on the next frame after all
-        // the views are laid out and attached (and registered to the EventBus).
-        mHandler.removeCallbacks(mSendEnterWindowAnimationCompleteRunnable);
-        if (!mReceivedNewIntent) {
-            mHandler.post(mSendEnterWindowAnimationCompleteRunnable);
-        } else {
-            mSendEnterWindowAnimationCompleteRunnable.run();
-        }
+        EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
     }
 
     @Override
@@ -501,28 +493,7 @@
     public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
         super.onMultiWindowModeChanged(isInMultiWindowMode);
 
-        // Reload the task stack completely
-        RecentsConfiguration config = Recents.getConfiguration();
-        RecentsActivityLaunchState launchState = config.getLaunchState();
-        RecentsTaskLoader loader = Recents.getTaskLoader();
-        RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
-        loader.preloadTasks(loadPlan, -1 /* runningTaskId */,
-                false /* includeFrontMostExcludedTask */);
-
-        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
-        loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
-        loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
-        loader.loadTasks(this, loadPlan, loadOpts);
-
-        TaskStack stack = loadPlan.getTaskStack();
-        int numStackTasks = stack.getStackTaskCount();
-        boolean showDeferredAnimation = numStackTasks > 0;
-
-        EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
-                false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
-                numStackTasks > 0));
-        EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
-                showDeferredAnimation, stack));
+        reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */);
     }
 
     @Override
@@ -531,7 +502,6 @@
 
         // Notify that recents is now hidden
         mIsVisible = false;
-        mReceivedNewIntent = false;
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
         MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
         Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(false);
@@ -821,6 +791,41 @@
         mRecentsView.invalidate();
     }
 
+    public final void onBusEvent(final ActivityUnpinnedEvent event) {
+        if (mIsVisible) {
+            // Skip the configuration change event as the PiP activity does not actually affect the
+            // config of recents
+            reloadTaskStack(isInMultiWindowMode(), false /* sendConfigChangedEvent */);
+        }
+    }
+
+    private void reloadTaskStack(boolean isInMultiWindowMode, boolean sendConfigChangedEvent) {
+        // Reload the task stack completely
+        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsActivityLaunchState launchState = config.getLaunchState();
+        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoadPlan loadPlan = loader.createLoadPlan(this);
+        loader.preloadTasks(loadPlan, -1 /* runningTaskId */,
+                false /* includeFrontMostExcludedTask */);
+
+        RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
+        loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
+        loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
+        loader.loadTasks(this, loadPlan, loadOpts);
+
+        TaskStack stack = loadPlan.getTaskStack();
+        int numStackTasks = stack.getStackTaskCount();
+        boolean showDeferredAnimation = numStackTasks > 0;
+
+        if (sendConfigChangedEvent) {
+            EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
+                    false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
+                    numStackTasks > 0));
+        }
+        EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
+                showDeferredAnimation, stack));
+    }
+
     @Override
     public boolean onPreDraw() {
         mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index a7f6b70..5b8ed94 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -29,6 +29,10 @@
 
     public boolean launchedWithAltTab;
     public boolean launchedFromApp;
+    // Set if the activity that we launched from entered PiP during the transition into Recents
+    public boolean launchedFromPipApp;
+    // Set if the next activity that quick-switch will launch is the PiP activity
+    public boolean launchedWithNextPipApp;
     public boolean launchedFromBlacklistedApp;
     public boolean launchedFromHome;
     public boolean launchedViaDragGesture;
@@ -41,6 +45,8 @@
         launchedFromHome = false;
         launchedFromApp = false;
         launchedFromBlacklistedApp = false;
+        launchedFromPipApp = false;
+        launchedWithNextPipApp = false;
         launchedToTaskId = -1;
         launchedWithAltTab = false;
         launchedViaDragGesture = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 2522d0f..e2e9b1b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -35,15 +35,18 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.util.Log;
 import android.util.MutableBoolean;
+import android.util.Pair;
 import android.view.AppTransitionAnimationSpec;
 import android.view.LayoutInflater;
 import android.view.ViewConfiguration;
 import android.view.WindowManager;
 
 import android.widget.Toast;
+
+import com.google.android.collect.Lists;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.policy.DockedDividerUtils;
 import com.android.systemui.R;
@@ -57,6 +60,9 @@
 import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
 import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
 import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
+import com.android.systemui.recents.events.component.ActivityPinnedEvent;
+import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
@@ -71,6 +77,8 @@
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskGrouping;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.RecentsTransitionHelper;
+import com.android.systemui.recents.views.RecentsTransitionHelper.AppTransitionAnimationSpecsFuture;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport;
 import com.android.systemui.recents.views.TaskStackView;
@@ -111,6 +119,11 @@
 
         @Override
         public void onTaskStackChangedBackground() {
+            // Check this is for the right user
+            if (!checkCurrentUserId(mContext, false /* debug */)) {
+                return;
+            }
+
             // Preloads the next task
             RecentsConfiguration config = Recents.getConfiguration();
             if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) {
@@ -127,6 +140,7 @@
                 // previous one.
                 VisibilityReport visibilityReport;
                 synchronized (mDummyStackView) {
+                    mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */);
                     mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */);
                     updateDummyStackViewLayout(plan.getTaskStack(),
                             getWindowRect(null /* windowRectOverride */));
@@ -151,12 +165,46 @@
         }
 
         @Override
+        public void onActivityPinned(String packageName, int taskId) {
+            // Check this is for the right user
+            if (!checkCurrentUserId(mContext, false /* debug */)) {
+                return;
+            }
+
+            // This time needs to be fetched the same way the last active time is fetched in
+            // {@link TaskRecord#touchActiveTime}
+            Recents.getConfiguration().getLaunchState().launchedFromPipApp = true;
+            Recents.getConfiguration().getLaunchState().launchedWithNextPipApp = false;
+            EventBus.getDefault().send(new ActivityPinnedEvent(taskId));
+            consumeInstanceLoadPlan();
+            sLastPipTime = System.currentTimeMillis();
+        }
+
+        @Override
+        public void onActivityUnpinned() {
+            // Check this is for the right user
+            if (!checkCurrentUserId(mContext, false /* debug */)) {
+                return;
+            }
+
+            EventBus.getDefault().send(new ActivityUnpinnedEvent());
+            sLastPipTime = -1;
+        }
+
+        @Override
         public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
+            // Check this is for the right user
+            if (!checkCurrentUserId(mContext, false /* debug */)) {
+                return;
+            }
+
             EventBus.getDefault().send(new TaskSnapshotChangedEvent(taskId, snapshot));
         }
     }
 
     protected static RecentsTaskLoadPlan sInstanceLoadPlan;
+    // Stores the last pinned task time
+    protected static long sLastPipTime = -1;
 
     protected Context mContext;
     protected Handler mHandler;
@@ -385,30 +433,34 @@
 
     public void preloadRecents() {
         // Preload only the raw task list into a new load plan (which will be consumed by the
-        // RecentsActivity) only if there is a task to animate to.
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        MutableBoolean isHomeStackVisible = new MutableBoolean(true);
-        if (!ssp.isRecentsActivityVisible(isHomeStackVisible)) {
-            ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
-            if (runningTask == null) {
-                return;
-            }
+        // RecentsActivity) only if there is a task to animate to.  Post this to ensure that we
+        // don't block the touch feedback on the nav bar button which triggers this.
+        mHandler.post(() -> {
+            SystemServicesProxy ssp = Recents.getSystemServices();
+            MutableBoolean isHomeStackVisible = new MutableBoolean(true);
+            if (!ssp.isRecentsActivityVisible(isHomeStackVisible)) {
+                ActivityManager.RunningTaskInfo runningTask = ssp.getRunningTask();
+                if (runningTask == null) {
+                    return;
+                }
 
-            RecentsTaskLoader loader = Recents.getTaskLoader();
-            sInstanceLoadPlan = loader.createLoadPlan(mContext);
-            loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible.value);
-            TaskStack stack = sInstanceLoadPlan.getTaskStack();
-            if (stack.getTaskCount() > 0) {
-                // Only preload the icon (but not the thumbnail since it may not have been taken for
-                // the pausing activity)
-                preloadIcon(runningTask.id);
+                RecentsTaskLoader loader = Recents.getTaskLoader();
+                sInstanceLoadPlan = loader.createLoadPlan(mContext);
+                loader.preloadTasks(sInstanceLoadPlan, runningTask.id, !isHomeStackVisible.value);
+                TaskStack stack = sInstanceLoadPlan.getTaskStack();
+                if (stack.getTaskCount() > 0) {
+                    // Only preload the icon (but not the thumbnail since it may not have been taken
+                    // for the pausing activity)
+                    preloadIcon(runningTask.id);
 
-                // At this point, we don't know anything about the stack state.  So only calculate
-                // the dimensions of the thumbnail that we need for the transition into Recents, but
-                // do not draw it until we construct the activity options when we start Recents
-                updateHeaderBarLayout(stack, null /* window rect override*/);
+                    // At this point, we don't know anything about the stack state.  So only
+                    // calculate the dimensions of the thumbnail that we need for the transition
+                    // into Recents, but do not draw it until we construct the activity options when
+                    // we start Recents
+                    updateHeaderBarLayout(stack, null /* window rect override*/);
+                }
             }
-        }
+        });
     }
 
     public void cancelPreloadingRecents() {
@@ -595,6 +647,20 @@
     }
 
     /**
+     * @return the time at which a task last entered picture-in-picture.
+     */
+    public static long getLastPipTime() {
+        return sLastPipTime;
+    }
+
+    /**
+     * Clears the time at which a task last entered picture-in-picture.
+     */
+    public static void clearLastPipTime() {
+        sLastPipTime = -1;
+    }
+
+    /**
      * Reloads all the resources for the current configuration.
      */
     private void reloadResources() {
@@ -634,7 +700,7 @@
             windowRect.bottom -= systemInsets.bottom;
             systemInsets.bottom = 0;
         }
-        calculateWindowStableInsets(systemInsets, windowRect);
+        calculateWindowStableInsets(systemInsets, windowRect, displayRect);
         windowRect.offsetTo(0, 0);
 
         synchronized (mDummyStackView) {
@@ -676,6 +742,7 @@
             updateDummyStackViewLayout(stack, windowRect);
             if (stack != null) {
                 TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
+                mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */);
                 mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
                 // Get the width of a task view so that we know how wide to draw the header bar.
                 if (useGridLayout) {
@@ -723,8 +790,7 @@
      * Given the stable insets and the rect for our window, calculates the insets that affect our
      * window.
      */
-    private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect) {
-        Rect displayRect = Recents.getSystemServices().getDisplayRect();
+    private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect, Rect displayRect) {
 
         // Display rect without insets - available app space
         Rect appRect = new Rect(displayRect);
@@ -774,8 +840,9 @@
     /**
      * Creates the activity options for an app->recents transition.
      */
-    private ActivityOptions getThumbnailTransitionActivityOptions(
-            ActivityManager.RunningTaskInfo runningTask, Rect windowOverrideRect) {
+    private Pair<ActivityOptions, AppTransitionAnimationSpecsFuture>
+            getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask,
+                    Rect windowOverrideRect) {
         if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) {
             ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>();
             ArrayList<Task> tasks;
@@ -806,23 +873,27 @@
             }
             AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()];
             specs.toArray(specsArray);
-            return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
-                    specsArray, mHandler, null, this);
+            return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
+                    specsArray, mHandler, null, this), null);
         } else {
             // Update the destination rect
             Task toTask = new Task();
             TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask,
                     windowOverrideRect);
-            Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
-                            mThumbTransitionBitmapCache);
-            if (thumbnail != null) {
-                RectF toTaskRect = toTransform.rect;
-                return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
-                        thumbnail, (int) toTaskRect.left, (int) toTaskRect.top,
-                        (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null);
-            }
-            // If both the screenshot and thumbnail fails, then just fall back to the default transition
-            return getUnknownTransitionActivityOptions();
+
+            RectF toTaskRect = toTransform.rect;
+            AppTransitionAnimationSpecsFuture future =
+                    new RecentsTransitionHelper(mContext).getAppTransitionFuture(
+                            () -> {
+                        Rect rect = new Rect();
+                        toTaskRect.round(rect);
+                        Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
+                                mThumbTransitionBitmapCache);
+                        return Lists.newArrayList(new AppTransitionAnimationSpec(
+                                toTask.key.id, thumbnail, rect));
+                    });
+            return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
+                    mHandler, future.getFuture(), null, false /* scaleUp */), future);
         }
     }
 
@@ -921,6 +992,9 @@
         launchState.launchedFromHome = !useThumbnailTransition && !mLaunchedWhileDocking;
         launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking;
         launchState.launchedFromBlacklistedApp = launchState.launchedFromApp && isBlacklisted;
+        launchState.launchedFromPipApp = false;
+        launchState.launchedWithNextPipApp =
+                stack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime());
         launchState.launchedViaDockGesture = mLaunchedWhileDocking;
         launchState.launchedViaDragGesture = mDraggingInRecents;
         launchState.launchedToTaskId = runningTaskId;
@@ -945,30 +1019,31 @@
         launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails;
 
         if (!animate) {
-            startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1));
+            startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1),
+                    null /* future */);
             return;
         }
 
-        ActivityOptions opts;
+        Pair<ActivityOptions, AppTransitionAnimationSpecsFuture> pair;
         if (isBlacklisted) {
-            opts = getUnknownTransitionActivityOptions();
+            pair = new Pair<>(getUnknownTransitionActivityOptions(), null);
         } else if (useThumbnailTransition) {
             // Try starting with a thumbnail transition
-            opts = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect);
+            pair = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect);
         } else {
             // If there is no thumbnail transition, but is launching from home into recents, then
             // use a quick home transition
-            opts = hasRecentTasks
-                ? getHomeTransitionActivityOptions()
-                : getUnknownTransitionActivityOptions();
+            pair = new Pair<>(hasRecentTasks
+                    ? getHomeTransitionActivityOptions()
+                    : getUnknownTransitionActivityOptions(), null);
         }
-        startRecentsActivity(opts);
+        startRecentsActivity(pair.first, pair.second);
         mLastToggleTime = SystemClock.elapsedRealtime();
     }
 
     private Rect getWindowRectOverride(int growTarget) {
         if (growTarget == DividerView.INVALID_RECENTS_GROW_TARGET) {
-            return null;
+            return SystemServicesProxy.getInstance(mContext).getWindowRect();
         }
         Rect result = new Rect();
         Rect displayRect = Recents.getSystemServices().getDisplayRect();
@@ -981,19 +1056,22 @@
     /**
      * Starts the recents activity.
      */
-    private void startRecentsActivity(ActivityOptions opts) {
+    private void startRecentsActivity(ActivityOptions opts,
+            final AppTransitionAnimationSpecsFuture future) {
         Intent intent = new Intent();
         intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
                 | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
-
-        if (opts != null) {
-            mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
-        } else {
-            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
-        }
-        EventBus.getDefault().send(new RecentsActivityStartingEvent());
+        HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
+        hideMenuEvent.addPostAnimationCallback(() -> {
+            Recents.getSystemServices().startActivityAsUserAsync(intent, opts);
+            EventBus.getDefault().send(new RecentsActivityStartingEvent());
+            if (future != null) {
+                future.precacheSpecs();
+            }
+        });
+        EventBus.getDefault().send(hideMenuEvent);
     }
 
     /**** OnAnimationFinishedListener Implementation ****/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
index a737505..d7abb38 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
@@ -810,6 +810,11 @@
     private void queueEvent(final Event event) {
         ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(event.getClass());
         if (eventHandlers == null) {
+            // This is just an optimization to return early if there are no handlers. However, we
+            // should still ensure that we call pre/post dispatch callbacks so that AnimatedEvents
+            // are still cleaned up correctly if a listener has not been registered to handle them
+            event.onPreDispatch();
+            event.onPostDispatch();
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java
index 918875a..b31f320 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java
@@ -23,6 +23,6 @@
  * we can start in-app animations so that they don't conflict with the window transition into
  * Recents.
  */
-public class EnterRecentsWindowAnimationCompletedEvent extends EventBus.AnimatedEvent {
+public class EnterRecentsWindowAnimationCompletedEvent extends EventBus.Event {
     // Simple event
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
similarity index 70%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
rename to packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
index ee0df87..75bfd7b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -11,7 +11,7 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License.
+ * limitations under the License
  */
 
 package com.android.systemui.recents.events.activity;
@@ -19,8 +19,7 @@
 import com.android.systemui.recents.events.EventBus;
 
 /**
- * This is sent when the in-app animations into Recents completes.
+ * Sent when the stack should be hidden and the empty view shown.
  */
-public class EnterRecentsTaskStackAnimationCompletedEvent extends EventBus.AnimatedEvent {
-    // Simple event
+public class ShowEmptyViewEvent extends EventBus.Event {
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
similarity index 65%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
copy to packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
index ee0df87..f4d2fcf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents.events.activity;
+package com.android.systemui.recents.events.component;
 
 import com.android.systemui.recents.events.EventBus;
 
 /**
- * This is sent when the in-app animations into Recents completes.
+ * This is sent when an activity is pinned.
  */
-public class EnterRecentsTaskStackAnimationCompletedEvent extends EventBus.AnimatedEvent {
-    // Simple event
+public class ActivityPinnedEvent extends EventBus.Event {
+
+    public final int taskId;
+
+    public ActivityPinnedEvent(int taskId) {
+        this.taskId = taskId;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
similarity index 68%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
copy to packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
index ee0df87..48c5f0b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents.events.activity;
+package com.android.systemui.recents.events.component;
 
 import com.android.systemui.recents.events.EventBus;
 
 /**
- * This is sent when the in-app animations into Recents completes.
+ * This is sent when an activity is unpinned.
  */
-public class EnterRecentsTaskStackAnimationCompletedEvent extends EventBus.AnimatedEvent {
-    // Simple event
+public class ActivityUnpinnedEvent extends EventBus.Event {
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
similarity index 68%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
copy to packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
index ee0df87..8fe4975 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents.events.activity;
+package com.android.systemui.recents.events.component;
 
 import com.android.systemui.recents.events.EventBus;
 
 /**
- * This is sent when the in-app animations into Recents completes.
+ * This is sent when the PiP should be expanded due to being relaunched.
  */
-public class EnterRecentsTaskStackAnimationCompletedEvent extends EventBus.AnimatedEvent {
-    // Simple event
+public class ExpandPipEvent extends EventBus.Event {
+    public final boolean clearThumbnailWindows = true;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
similarity index 70%
copy from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
copy to packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
index ee0df87..ce4f207 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsTaskStackAnimationCompletedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.systemui.recents.events.activity;
+package com.android.systemui.recents.events.component;
 
 import com.android.systemui.recents.events.EventBus;
 
 /**
- * This is sent when the in-app animations into Recents completes.
+ * This is sent when the PiP menu should be hidden.
  */
-public class EnterRecentsTaskStackAnimationCompletedEvent extends EventBus.AnimatedEvent {
+public class HidePipMenuEvent extends EventBus.AnimatedEvent {
     // Simple event
 }
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 1dc3c82..cbfa0e5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -58,20 +58,22 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.IRemoteCallback;
-import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
 import android.util.ArraySet;
 import android.util.IconDrawableFactory;
 import android.util.Log;
 import android.util.MutableBoolean;
-import android.view.AppTransitionAnimationSpec;
 import android.view.Display;
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.IDockedStackListener;
@@ -83,15 +85,17 @@
 
 import com.android.internal.app.AssistUtils;
 import com.android.internal.os.BackgroundThread;
-import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.pip.tv.PipMenuActivity;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.RecentsImpl;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.ThumbnailData;
-import com.android.systemui.recents.views.RecentsTransitionHelper.AnimationSpecComposer;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -99,8 +103,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 
 /**
  * Acts as a shim around the real system services that we need to access data from, and provides
@@ -130,6 +132,8 @@
     PackageManager mPm;
     IconDrawableFactory mDrawableFactory;
     IPackageManager mIpm;
+    private final IDreamManager mDreamManager;
+    private final Context mContext;
     AssistUtils mAssistUtils;
     WindowManager mWm;
     IWindowManager mIwm;
@@ -138,6 +142,7 @@
     Display mDisplay;
     String mRecentsPackage;
     ComponentName mAssistComponent;
+    private int mCurrentUserId;
 
     boolean mIsSafeMode;
     boolean mHasFreeformWorkspaceSupport;
@@ -149,7 +154,8 @@
     Canvas mBgProtectionCanvas;
 
     private final Handler mHandler = new H();
-    private final ExecutorService mOnewayExecutor = Executors.newSingleThreadExecutor();
+
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     /**
      * An abstract class to track task stack changes.
@@ -163,7 +169,7 @@
         public void onTaskStackChangedBackground() { }
         public void onTaskStackChanged() { }
         public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
-        public void onActivityPinned(String packageName) { }
+        public void onActivityPinned(String packageName, int taskId) { }
         public void onActivityUnpinned() { }
         public void onPinnedActivityRestartAttempt(boolean clearedTask) { }
         public void onPinnedStackAnimationStarted() { }
@@ -179,9 +185,9 @@
          * TaskStackListener should make this call to verify that we don't act on events from other
          * user's processes.
          */
-        protected final boolean checkCurrentUserId(boolean debug) {
+        protected final boolean checkCurrentUserId(Context context, boolean debug) {
             int processUserId = UserHandle.myUserId();
-            int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+            int currentUserId = SystemServicesProxy.getInstance(context).getCurrentUser();
             if (processUserId != currentUserId) {
                 if (debug) {
                     Log.d(TAG, "UID mismatch. SystemUI is running uid=" + processUserId
@@ -218,9 +224,9 @@
         }
 
         @Override
-        public void onActivityPinned(String packageName) throws RemoteException {
+        public void onActivityPinned(String packageName, int taskId) throws RemoteException {
             mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
-            mHandler.obtainMessage(H.ON_ACTIVITY_PINNED, packageName).sendToTarget();
+            mHandler.obtainMessage(H.ON_ACTIVITY_PINNED, taskId, 0, packageName).sendToTarget();
         }
 
         @Override
@@ -278,6 +284,10 @@
         }
     };
 
+    private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
+            (String name, Drawable picture, String userAccount) ->
+                    mCurrentUserId = mAm.getCurrentUser();
+
     /**
      * List of {@link TaskStackListener} registered from {@link #registerTaskStackListener}.
      */
@@ -285,6 +295,7 @@
 
     /** Private constructor */
     private SystemServicesProxy(Context context) {
+        mContext = context.getApplicationContext();
         mAccm = AccessibilityManager.getInstance(context);
         mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         mIam = ActivityManager.getService();
@@ -296,6 +307,8 @@
         mIwm = WindowManagerGlobal.getWindowManagerService();
         mKgm = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
         mUm = UserManager.get(context);
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.checkService(DreamService.DREAM_SERVICE));
         mDisplay = mWm.getDefaultDisplay();
         mRecentsPackage = context.getPackageName();
         mHasFreeformWorkspaceSupport =
@@ -303,6 +316,7 @@
                         Settings.Global.getInt(context.getContentResolver(),
                                 DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
         mIsSafeMode = mPm.isSafeMode();
+        mCurrentUserId = mAm.getCurrentUser();
 
         // Get the dummy thumbnail width/heights
         Resources res = context.getResources();
@@ -320,6 +334,12 @@
         // Resolve the assist intent
         mAssistComponent = mAssistUtils.getAssistComponentForUser(UserHandle.myUserId());
 
+        // Since SystemServicesProxy can be accessed from a per-SysUI process component, create a
+        // per-process listener to keep track of the current user id to reduce the number of binder
+        // calls to fetch it.
+        UserInfoController userInfoController = Dependency.get(UserInfoController.class);
+        userInfoController.addCallback(mOnUserInfoChangedListener);
+
         if (RecentsDebugFlags.Static.EnableMockTasks) {
             // Create a dummy icon
             mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
@@ -449,9 +469,18 @@
      * Returns the top running task.
      */
     public ActivityManager.RunningTaskInfo getRunningTask() {
-        List<ActivityManager.RunningTaskInfo> tasks = mAm.getRunningTasks(1);
+        // Note: The set of running tasks from the system is ordered by recency
+        List<ActivityManager.RunningTaskInfo> tasks = mAm.getRunningTasks(10);
         if (tasks != null && !tasks.isEmpty()) {
-            return tasks.get(0);
+            // Find the first task in a valid stack, we ignore everything from the Recents and PiP
+            // stacks
+            for (int i = 0; i < tasks.size(); i++) {
+                ActivityManager.RunningTaskInfo task = tasks.get(i);
+                int stackId = task.stackId;
+                if (stackId != RECENTS_STACK_ID && stackId != PINNED_STACK_ID) {
+                    return task;
+                }
+            }
         }
         return null;
     }
@@ -769,7 +798,7 @@
      * Sends a message to close other system windows.
      */
     public void sendCloseSystemWindows(String reason) {
-        mOnewayExecutor.submit(() -> {
+        mUiOffloadThread.submit(() -> {
             try {
                 mIam.closeSystemDialogs(reason);
             } catch (RemoteException e) {
@@ -1011,10 +1040,11 @@
     }
 
     /**
-     * Returns the current user id.
+     * Returns the current user id.  Used instead of KeyguardUpdateMonitor in SystemUI components
+     * that run in the non-primary SystemUI process.
      */
     public int getCurrentUser() {
-        return KeyguardUpdateMonitor.getCurrentUser();
+        return mCurrentUserId;
     }
 
     /**
@@ -1118,6 +1148,11 @@
         }
     }
 
+    public void startActivityAsUserAsync(Intent intent, ActivityOptions opts) {
+        mUiOffloadThread.submit(() -> mContext.startActivityAsUser(intent,
+                opts != null ? opts.toBundle() : null, UserHandle.CURRENT));
+    }
+
     /** Starts an activity from recents. */
     public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName,
             ActivityOptions options, int stackId,
@@ -1142,7 +1177,7 @@
 
         // Execute this from another thread such that we can do other things (like caching the
         // bitmap for the thumbnail) while AM is busy starting our activity.
-        mOnewayExecutor.submit(() -> {
+        mUiOffloadThread.submit(() -> {
             try {
                 mIam.startActivityFromRecents(
                         taskKey.id, finalOptions == null ? null : finalOptions.toBundle());
@@ -1274,6 +1309,33 @@
         }
     }
 
+    public boolean isDreaming() {
+        try {
+            return mDreamManager.isDreaming();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to query dream manager.", e);
+        }
+        return false;
+    }
+
+    public void awakenDreamsAsync() {
+        mUiOffloadThread.submit(() -> {
+            try {
+                mDreamManager.awaken();
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        });
+    }
+
+    public void updateOverviewLastStackActiveTimeAsync(long newLastStackActiveTime,
+            int currentUserId) {
+        mUiOffloadThread.submit(() -> {
+            Settings.Secure.putLongForUser(mContext.getContentResolver(),
+                    Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId);
+        });
+    }
+
     public interface StartActivityFromRecentsResultListener {
         void onStartActivityResult(boolean succeeded);
     }
@@ -1314,7 +1376,7 @@
                     }
                     case ON_ACTIVITY_PINNED: {
                         for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
-                            mTaskStackListeners.get(i).onActivityPinned((String) msg.obj);
+                            mTaskStackListeners.get(i).onActivityPinned((String) msg.obj, msg.arg1);
                         }
                         break;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 7ee0906..93033ea 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -22,7 +22,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -33,15 +32,13 @@
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
-import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-
 import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -87,7 +84,7 @@
         mCurrentQuietProfiles.clear();
 
         if (currentUserId == UserHandle.USER_CURRENT) {
-            currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+            currentUserId = SystemServicesProxy.getInstance(mContext).getCurrentUser();
         }
         UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         List<UserInfo> profiles = userManager.getProfiles(currentUserId);
@@ -218,8 +215,8 @@
             affiliatedTasks.put(taskKey.id, taskKey);
         }
         if (newLastStackActiveTime != -1) {
-            Settings.Secure.putLongForUser(mContext.getContentResolver(),
-                    Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId);
+            Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+                    newLastStackActiveTime, currentUserId);
         }
 
         // Initialize the stacks
@@ -316,9 +313,8 @@
             for (int i = 0; i < users.size(); i++) {
                 int userId = users.get(i).id;
                 if (userId != currentUserId) {
-                    Settings.Secure.putLongForUser(mContext.getContentResolver(),
-                            Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, legacyLastStackActiveTime,
-                            userId);
+                    Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync(
+                            legacyLastStackActiveTime, userId);
                 }
             }
             return legacyLastStackActiveTime;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 97a9659..15e1739 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -28,6 +28,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.Trace;
 import android.util.Log;
 import android.util.LruCache;
 
@@ -102,6 +103,7 @@
     Bitmap mDefaultThumbnail;
     BitmapDrawable mDefaultIcon;
 
+    boolean mStarted;
     boolean mCancelled;
     boolean mWaitingOnLoadQueue;
 
@@ -121,16 +123,21 @@
                 android.os.Process.THREAD_PRIORITY_BACKGROUND);
         mLoadThread.start();
         mLoadThreadHandler = new Handler(mLoadThread.getLooper());
-        mLoadThreadHandler.post(this);
     }
 
     /** Restarts the loader thread */
     void start(Context context) {
         mContext = context;
         mCancelled = false;
-        // Notify the load thread to start loading
-        synchronized(mLoadThread) {
-            mLoadThread.notifyAll();
+        if (!mStarted) {
+            // Start loading on the load thread
+            mStarted = true;
+            mLoadThreadHandler.post(this);
+        } else {
+            // Notify the load thread to start loading again
+            synchronized (mLoadThread) {
+                mLoadThread.notifyAll();
+            }
         }
     }
 
@@ -351,7 +358,12 @@
     /** Preloads recents tasks using the specified plan to store the output. */
     public synchronized void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId,
             boolean includeFrontMostExcludedTask) {
-        plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
+        try {
+            Trace.beginSection("preloadPlan");
+            plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask);
+        } finally {
+            Trace.endSection();
+        }
     }
 
     /** Begins loading the heavy task data according to the specified options. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 9b25ef8..6e3be09 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -229,7 +229,8 @@
          * Notifies when a task has been removed from the stack.
          */
         void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
-                AnimationProps animation, boolean fromDockGesture);
+                AnimationProps animation, boolean fromDockGesture,
+                boolean dismissRecentsIfAllRemoved);
 
         /**
          * Notifies when all tasks have been removed from the stack.
@@ -631,13 +632,22 @@
      * how they should update themselves.
      */
     public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture) {
+        removeTask(t, animation, fromDockGesture, true /* dismissRecentsIfAllRemoved */);
+    }
+
+    /**
+     * Removes a task from the stack, with an additional {@param animation} hint to the callbacks on
+     * how they should update themselves.
+     */
+    public void removeTask(Task t, AnimationProps animation, boolean fromDockGesture,
+            boolean dismissRecentsIfAllRemoved) {
         if (mStackTaskList.contains(t)) {
             removeTaskImpl(mStackTaskList, t);
             Task newFrontMostTask = getStackFrontMostTask(false  /* includeFreeform */);
             if (mCb != null) {
                 // Notify that a task has been removed
                 mCb.onStackTaskRemoved(this, t, newFrontMostTask, animation,
-                        fromDockGesture);
+                        fromDockGesture, dismissRecentsIfAllRemoved);
             }
         }
         mRawTaskList.remove(t);
@@ -646,19 +656,27 @@
     /**
      * Removes all tasks from the stack.
      */
-    public void removeAllTasks() {
+    public void removeAllTasks(boolean notifyStackChanges) {
         ArrayList<Task> tasks = mStackTaskList.getTasks();
         for (int i = tasks.size() - 1; i >= 0; i--) {
             Task t = tasks.get(i);
             removeTaskImpl(mStackTaskList, t);
             mRawTaskList.remove(t);
         }
-        if (mCb != null) {
+        if (mCb != null && notifyStackChanges) {
             // Notify that all tasks have been removed
             mCb.onStackTasksRemoved(this);
         }
     }
 
+
+    /**
+     * @see #setTasks(Context, List, boolean, boolean)
+     */
+    public void setTasks(Context context, TaskStack stack, boolean notifyStackChanges) {
+        setTasks(context, stack.mRawTaskList, notifyStackChanges);
+    }
+
     /**
      * Sets a few tasks in one go, without calling any callbacks.
      *
@@ -723,7 +741,8 @@
         Task newFrontMostTask = getStackFrontMostTask(false);
         for (int i = 0; i < removedTaskCount; i++) {
             mCb.onStackTaskRemoved(this, removedTasks.get(i), newFrontMostTask,
-                    AnimationProps.IMMEDIATE, false /* fromDockGesture */);
+                    AnimationProps.IMMEDIATE, false /* fromDockGesture */,
+                    true /* dismissRecentsIfAllRemoved */);
         }
 
         // Only callback for the newly added tasks after this stack has been updated
@@ -854,21 +873,46 @@
     }
 
     /**
+     * Returns whether the next launch target should actually be the PiP task.
+     */
+    public boolean isNextLaunchTargetPip(long lastPipTime) {
+        Task launchTarget = getLaunchTarget();
+        Task nextLaunchTarget = getNextLaunchTargetRaw();
+        if (nextLaunchTarget != null && lastPipTime > 0) {
+            // If the PiP time is more recent than the next launch target, then launch the PiP task
+            return lastPipTime > nextLaunchTarget.key.lastActiveTime;
+        } else if (launchTarget != null && lastPipTime > 0 && getTaskCount() == 1) {
+            // Otherwise, if there is no next launch target, but there is a PiP, then launch
+            // the PiP task
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Returns the task in stack tasks which should be launched next if Recents are toggled
-     * again, or null if there is no task to be launched.
+     * again, or null if there is no task to be launched. Callers should check
+     * {@link #isNextLaunchTargetPip(long)} before fetching the next raw launch target from the
+     * stack.
      */
     public Task getNextLaunchTarget() {
+        Task nextLaunchTarget = getNextLaunchTargetRaw();
+        if (nextLaunchTarget != null) {
+            return nextLaunchTarget;
+        }
+        return getStackTasks().get(getTaskCount() - 1);
+    }
+
+    private Task getNextLaunchTargetRaw() {
         int taskCount = getTaskCount();
         if (taskCount == 0) {
             return null;
         }
         int launchTaskIndex = indexOfStackTask(getLaunchTarget());
-        if (launchTaskIndex != -1) {
-            launchTaskIndex = Math.max(0, launchTaskIndex - 1);
-        } else {
-            launchTaskIndex = getTaskCount() - 1;
+        if (launchTaskIndex != -1 && launchTaskIndex > 0) {
+            return getStackTasks().get(launchTaskIndex - 1);
         }
-        return getStackTasks().get(launchTaskIndex);
+        return null;
     }
 
     /** Returns the index of this task in this current task stack */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index e06c40c..a0ad782 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -55,7 +55,9 @@
 import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
+import com.android.systemui.recents.events.activity.ShowEmptyViewEvent;
 import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
 import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
@@ -250,6 +252,12 @@
 
     /** Launches the task that recents was launched from if possible */
     public boolean launchPreviousTask() {
+        if (Recents.getConfiguration().getLaunchState().launchedFromPipApp) {
+            // If the app auto-entered PiP on the way to Recents, then just re-expand it
+            EventBus.getDefault().send(new ExpandPipEvent());
+            return true;
+        }
+
         if (mTaskStackView != null) {
             Task task = getStack().getLaunchTarget();
             if (task != null) {
@@ -635,6 +643,10 @@
         updateStack(event.stack, false /* setStackViewTasks */);
     }
 
+    public final void onBusEvent(ShowEmptyViewEvent event) {
+        showEmptyView(R.string.recents_empty_message);
+    }
+
     /**
      * Shows the stack action button.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 7ba705e..8135034 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -562,7 +562,8 @@
             mMinScrollP = 0;
             mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
                     Math.max(0, mFocusedRange.getAbsoluteX(maxBottomNormX)));
-            if (launchState.launchedFromHome) {
+            if (launchState.launchedFromHome || launchState.launchedFromPipApp
+                    || launchState.launchedWithNextPipApp) {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
             } else {
                 mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
@@ -581,8 +582,8 @@
             mMinScrollP = 0;
             mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
                     Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
-            boolean scrollToFront = launchState.launchedFromHome ||
-                    launchState.launchedViaDockGesture;
+            boolean scrollToFront = launchState.launchedFromHome || launchState.launchedFromPipApp
+                    || launchState.launchedWithNextPipApp || launchState.launchedViaDockGesture;
             if (launchState.launchedFromBlacklistedApp) {
                 mInitialScrollP = mMaxScrollP;
             } else if (launchState.launchedWithAltTab) {
@@ -608,6 +609,8 @@
         mTaskIndexOverrideMap.clear();
 
         boolean scrollToFront = launchState.launchedFromHome ||
+                launchState.launchedFromPipApp ||
+                launchState.launchedWithNextPipApp ||
                 launchState.launchedFromBlacklistedApp ||
                 launchState.launchedViaDockGesture;
         if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
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 18a9bab..6ad6a15 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -57,11 +57,11 @@
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsDebugFlags;
+import com.android.systemui.recents.RecentsImpl;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
 import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
@@ -72,7 +72,11 @@
 import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
 import com.android.systemui.recents.events.activity.PackagesChangedEvent;
+import com.android.systemui.recents.events.activity.ShowEmptyViewEvent;
 import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
+import com.android.systemui.recents.events.component.ActivityPinnedEvent;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
 import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
 import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
@@ -92,6 +96,7 @@
 import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
 import com.android.systemui.recents.misc.DozeTrigger;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
@@ -170,7 +175,11 @@
     @ViewDebug.ExportedProperty(category="recents")
     private boolean mTaskViewsClipDirty = true;
     @ViewDebug.ExportedProperty(category="recents")
-    private boolean mAwaitingFirstLayout = true;
+    private boolean mEnterAnimationComplete = false;
+    @ViewDebug.ExportedProperty(category="recents")
+    private boolean mStackReloaded = false;
+    @ViewDebug.ExportedProperty(category="recents")
+    private boolean mFinishedLayoutAfterStackReload = false;
     @ViewDebug.ExportedProperty(category="recents")
     private boolean mLaunchNextAfterFirstMeasure = false;
     @ViewDebug.ExportedProperty(category="recents")
@@ -179,8 +188,6 @@
     @ViewDebug.ExportedProperty(category="recents")
     private boolean mInMeasureLayout = false;
     @ViewDebug.ExportedProperty(category="recents")
-    private boolean mEnterAnimationComplete = false;
-    @ViewDebug.ExportedProperty(category="recents")
     boolean mTouchExplorationEnabled;
     @ViewDebug.ExportedProperty(category="recents")
     boolean mScreenPinningEnabled;
@@ -350,7 +357,6 @@
         // Reset the stack state
         readSystemFlags();
         mTaskViewsClipDirty = true;
-        mEnterAnimationComplete = false;
         mUIDozeTrigger.stopDozing();
         if (isResumingFromVisible) {
             // Animate in the freeform workspace
@@ -365,7 +371,8 @@
 
         // Since we always animate to the same place in (the initial state), always reset the stack
         // to the initial state when resuming
-        mAwaitingFirstLayout = true;
+        mStackReloaded = true;
+        mFinishedLayoutAfterStackReload = false;
         mLaunchNextAfterFirstMeasure = false;
         mInitialState = INITIAL_STATE_UPDATE_ALL;
         requestLayout();
@@ -379,8 +386,7 @@
 
         // Only notify if we are already initialized, otherwise, everything will pick up all the
         // new and old tasks when we next layout
-        mStack.setTasks(getContext(), stack.computeAllTasksList(),
-                allowNotifyStackChanges && isInitialized);
+        mStack.setTasks(getContext(), stack, allowNotifyStackChanges && isInitialized);
     }
 
     /** Returns the task stack. */
@@ -1278,13 +1284,13 @@
         // TaskViews with the stack so that we can lay them out
         boolean resetToInitialState = (width != mLastWidth || height != mLastHeight)
                 && mResetToInitialStateWhenResized;
-        if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE
+        if (!mFinishedLayoutAfterStackReload || mInitialState != INITIAL_STATE_UPDATE_NONE
                 || resetToInitialState) {
             if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY || resetToInitialState) {
                 updateToInitialState();
                 mResetToInitialStateWhenResized = false;
             }
-            if (!mAwaitingFirstLayout) {
+            if (mFinishedLayoutAfterStackReload) {
                 mInitialState = INITIAL_STATE_UPDATE_NONE;
             }
         }
@@ -1357,10 +1363,15 @@
         relayoutTaskViews(AnimationProps.IMMEDIATE);
         clipTaskViews();
 
-        if (mAwaitingFirstLayout || !mEnterAnimationComplete) {
-            mAwaitingFirstLayout = false;
+        if (!mFinishedLayoutAfterStackReload) {
+            // Prepare the task enter animations (this can be called numerous times)
             mInitialState = INITIAL_STATE_UPDATE_NONE;
             onFirstLayout();
+
+            if (mStackReloaded) {
+                mFinishedLayoutAfterStackReload = true;
+                tryStartEnterAnimation();
+            }
         }
     }
 
@@ -1486,7 +1497,7 @@
         updateLayoutAlgorithm(true /* boundScroll */);
 
         // Animate all the tasks into place
-        relayoutTaskViews(mAwaitingFirstLayout
+        relayoutTaskViews(!mFinishedLayoutAfterStackReload
                 ? AnimationProps.IMMEDIATE
                 : new AnimationProps(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN));
     }
@@ -1496,7 +1507,7 @@
      */
     @Override
     public void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
-            AnimationProps animation, boolean fromDockGesture) {
+            AnimationProps animation, boolean fromDockGesture, boolean dismissRecentsIfAllRemoved) {
         if (mFocusedTask == removedTask) {
             resetFocusedTask(removedTask);
         }
@@ -1527,9 +1538,13 @@
 
         // If there are no remaining tasks, then just close recents
         if (mStack.getTaskCount() == 0) {
-            EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
-                    ? R.string.recents_empty_message
-                    : R.string.recents_empty_message_dismissed_all));
+            if (dismissRecentsIfAllRemoved) {
+                EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
+                        ? R.string.recents_empty_message
+                        : R.string.recents_empty_message_dismissed_all));
+            } else {
+                EventBus.getDefault().send(new ShowEmptyViewEvent());
+            }
         }
     }
 
@@ -1555,7 +1570,7 @@
 
     @Override
     public void onStackTasksUpdated(TaskStack stack) {
-        if (mAwaitingFirstLayout) {
+        if (!mFinishedLayoutAfterStackReload) {
             return;
         }
 
@@ -1797,19 +1812,41 @@
     }
 
     public final void onBusEvent(LaunchNextTaskRequestEvent event) {
-        if (mAwaitingFirstLayout) {
+        if (!mFinishedLayoutAfterStackReload) {
             mLaunchNextAfterFirstMeasure = true;
             return;
         }
 
-        final Task launchTask = mStack.getNextLaunchTarget();
-        if (launchTask != null) {
-            launchTask(launchTask);
-            MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
-                    launchTask.key.getComponent().toString());
-        } else if (mStack.getTaskCount() == 0) {
-            // If there are no tasks, then just hide recents back to home.
-            EventBus.getDefault().send(new HideRecentsEvent(false, true));
+        if (mStack.getTaskCount() == 0) {
+            if (RecentsImpl.getLastPipTime() != -1) {
+                EventBus.getDefault().send(new ExpandPipEvent());
+                MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
+                        "pip");
+            } else {
+                // If there are no tasks, then just hide recents back to home.
+                EventBus.getDefault().send(new HideRecentsEvent(false, true));
+            }
+            return;
+        }
+
+        if (!Recents.getConfiguration().getLaunchState().launchedFromPipApp
+                && mStack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime())) {
+            // If the launch task is in the pinned stack, then expand the PiP now
+            EventBus.getDefault().send(new ExpandPipEvent());
+            MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK, "pip");
+        } else {
+            final Task launchTask = mStack.getNextLaunchTarget();
+            if (launchTask != null) {
+                // Defer launching the task until the PiP menu has been dismissed (if it is
+                // showing at all)
+                HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
+                hideMenuEvent.addPostAnimationCallback(() -> {
+                    launchTask(launchTask);
+                });
+                EventBus.getDefault().send(hideMenuEvent);
+                MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
+                        launchTask.key.getComponent().toString());
+            }
         }
     }
 
@@ -1871,7 +1908,7 @@
                         R.string.accessibility_recents_all_items_dismissed));
 
                 // Remove all tasks and delete the task data for all tasks
-                mStack.removeAllTasks();
+                mStack.removeAllTasks(true /* notifyStackChanges */);
                 for (int i = tasks.size() - 1; i >= 0; i--) {
                     EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));
                 }
@@ -2095,39 +2132,45 @@
 
     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
         mEnterAnimationComplete = true;
+        tryStartEnterAnimation();
+    }
+
+    private void tryStartEnterAnimation() {
+        if (!mStackReloaded || !mFinishedLayoutAfterStackReload || !mEnterAnimationComplete) {
+            return;
+        }
 
         if (mStack.getTaskCount() > 0) {
             // Start the task enter animations
-            mAnimationHelper.startEnterAnimation(event.getAnimationTrigger());
+            ReferenceCountedTrigger trigger = new ReferenceCountedTrigger();
+            mAnimationHelper.startEnterAnimation(trigger);
 
             // Add a runnable to the post animation ref counter to clear all the views
-            event.addPostAnimationCallback(new Runnable() {
-                @Override
-                public void run() {
-                    // Start the dozer to trigger to trigger any UI that shows after a timeout
-                    if (!Recents.getSystemServices().hasFreeformWorkspaceSupport()) {
-                        mUIDozeTrigger.startDozing();
-                    }
+            trigger.addLastDecrementRunnable(() -> {
+                // Start the dozer to trigger to trigger any UI that shows after a timeout
+                if (!Recents.getSystemServices().hasFreeformWorkspaceSupport()) {
+                    mUIDozeTrigger.startDozing();
+                }
 
-                    // Update the focused state here -- since we only set the focused task without
-                    // requesting view focus in onFirstLayout(), actually request view focus and
-                    // animate the focused state if we are alt-tabbing now, after the window enter
-                    // animation is completed
-                    if (mFocusedTask != null) {
-                        RecentsConfiguration config = Recents.getConfiguration();
-                        RecentsActivityLaunchState launchState = config.getLaunchState();
-                        setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
-                                false /* scrollToTask */, launchState.launchedWithAltTab);
-                        TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
-                        if (mTouchExplorationEnabled && focusedTaskView != null) {
-                            focusedTaskView.requestAccessibilityFocus();
-                        }
+                // Update the focused state here -- since we only set the focused task without
+                // requesting view focus in onFirstLayout(), actually request view focus and
+                // animate the focused state if we are alt-tabbing now, after the window enter
+                // animation is completed
+                if (mFocusedTask != null) {
+                    RecentsConfiguration config = Recents.getConfiguration();
+                    RecentsActivityLaunchState launchState = config.getLaunchState();
+                    setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
+                            false /* scrollToTask */, launchState.launchedWithAltTab);
+                    TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
+                    if (mTouchExplorationEnabled && focusedTaskView != null) {
+                        focusedTaskView.requestAccessibilityFocus();
                     }
-
-                    EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent());
                 }
             });
         }
+
+        // This flag is only used to choreograph the enter animation, so we can reset it here
+        mStackReloaded = false;
     }
 
     public final void onBusEvent(UpdateFreeformTaskViewVisibilityEvent event) {
@@ -2205,23 +2248,41 @@
     }
 
     public final void onBusEvent(RecentsVisibilityChangedEvent event) {
-        if (!event.visible && mTaskViewFocusFrame != null) {
-            mTaskViewFocusFrame.moveGridTaskViewFocus(null);
-        }
         if (!event.visible) {
+            if (mTaskViewFocusFrame != null) {
+                mTaskViewFocusFrame.moveGridTaskViewFocus(null);
+            }
+
             List<TaskView> taskViews = new ArrayList<>(getTaskViews());
             for (int i = 0; i < taskViews.size(); i++) {
                 mViewPool.returnViewToPool(taskViews.get(i));
             }
             clearPrefetchingTask();
+
+            // We can not reset mEnterAnimationComplete in onReload() because when docking the top
+            // task, we can receive the enter animation callback before onReload(), so reset it
+            // here onces Recents is not visible
+            mEnterAnimationComplete = false;
         }
     }
 
+    public final void onBusEvent(ActivityPinnedEvent event) {
+        // If an activity enters PiP while Recents is open, remove the stack task associated with
+        // the new PiP task
+        Task removeTask = mStack.findTaskWithId(event.taskId);
+        if (removeTask != null) {
+            // In this case, we remove the task, but if the last task is removed, don't dismiss
+            // Recents to home
+            mStack.removeTask(removeTask, AnimationProps.IMMEDIATE, false /* fromDockGesture */,
+                    false /* dismissRecentsIfAllRemoved */);
+        }
+        updateLayoutAlgorithm(false /* boundScroll */);
+        updateToInitialState();
+    }
+
     public void reloadOnConfigurationChange() {
         mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
         mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
-
-        boolean hasDockedTask = Recents.getSystemServices().hasDockedTask();
     }
 
     /**
@@ -2335,7 +2396,7 @@
         writer.print(" hasDefRelayout=");
         writer.print(mDeferredTaskViewLayoutAnimation != null ? "Y" : "N");
         writer.print(" clipDirty="); writer.print(mTaskViewsClipDirty ? "Y" : "N");
-        writer.print(" awaitingFirstLayout="); writer.print(mAwaitingFirstLayout ? "Y" : "N");
+        writer.print(" awaitingStackReload="); writer.print(mFinishedLayoutAfterStackReload ? "Y" : "N");
         writer.print(" initialState="); writer.print(mInitialState);
         writer.print(" inMeasureLayout="); writer.print(mInMeasureLayout ? "Y" : "N");
         writer.print(" enterAnimCompleted="); writer.print(mEnterAnimationComplete ? "Y" : "N");
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 24a2927..012accd 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -725,14 +725,21 @@
             mMinimizedSnapAlgorithm = null;
             mDockedStackMinimized = minimized;
             initializeSnapAlgorithm();
-            if (!mIsInMinimizeInteraction && minimized) {
-                mIsInMinimizeInteraction = true;
-                mDividerPositionBeforeMinimized = DockedDividerUtils.calculateMiddlePosition(
-                        isHorizontalDivision(), mStableInsets, mDisplayWidth, mDisplayHeight,
-                        mDividerSize);
+            if (mIsInMinimizeInteraction != minimized) {
+                if (minimized) {
+                    mIsInMinimizeInteraction = true;
+                    mDividerPositionBeforeMinimized = DockedDividerUtils.calculateMiddlePosition(
+                            isHorizontalDivision(), mStableInsets, mDisplayWidth, mDisplayHeight,
+                            mDividerSize);
 
-                int position = mMinimizedSnapAlgorithm.getMiddleTarget().position;
-                resizeStack(position, position, mMinimizedSnapAlgorithm.getMiddleTarget());
+                    int position = mMinimizedSnapAlgorithm.getMiddleTarget().position;
+                    resizeStack(position, position, mMinimizedSnapAlgorithm.getMiddleTarget());
+                } else {
+                    resizeStack(mDividerPositionBeforeMinimized, mDividerPositionBeforeMinimized,
+                            mSnapAlgorithm.calculateNonDismissingSnapTarget(
+                                    mDividerPositionBeforeMinimized));
+                    mIsInMinimizeInteraction = false;
+                }
             }
         }
     }
@@ -1169,7 +1176,7 @@
     }
 
     public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) {
-        if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP
+        if (mGrowRecents && mDockSide == WindowManager.DOCKED_TOP
                 && getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget()
                 && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) {
             mState.growAfterRecentsDrawn = true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index be221bb..bf89b01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -279,7 +279,9 @@
     public void toggleRecentApps() {
         synchronized (mLock) {
             mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
-            mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null).sendToTarget();
+            Message msg = mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null);
+            msg.setAsynchronous(true);
+            msg.sendToTarget();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 3a39e91..3542500 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -813,10 +813,10 @@
 
     public void onDensityOrFontScaleChanged() {
         initDimens();
-        if (mIsSummaryWithChildren) {
-            if (mChildrenContainer != null) {
-                mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
-            }
+        // Let's update our childrencontainer. This is intentionally not guarded with
+        // mIsSummaryWithChildren since we might have had children but not anymore.
+        if (mChildrenContainer != null) {
+            mChildrenContainer.reInflateViews(mExpandClickListener, mEntry.notification);
         }
         if (mGuts != null) {
             View oldGuts = mGuts;
@@ -1458,9 +1458,11 @@
     public void setUserLocked(boolean userLocked) {
         mUserLocked = userLocked;
         mPrivateLayout.setUserExpanding(userLocked);
-        if (mIsSummaryWithChildren) {
+        // This is intentionally not guarded with mIsSummaryWithChildren since we might have had
+        // children but not anymore.
+        if (mChildrenContainer != null) {
             mChildrenContainer.setUserLocked(userLocked);
-            if (userLocked || !isGroupExpanded()) {
+            if (mIsSummaryWithChildren && (userLocked || !isGroupExpanded())) {
                 updateBackgroundForGroupState();
             }
         }
@@ -2189,4 +2191,9 @@
             }
         }
     }
+
+    @VisibleForTesting
+    protected void setChildrenContainer(NotificationChildrenContainer childrenContainer) {
+        mChildrenContainer = childrenContainer;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 0924089..1691e135 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -270,7 +270,7 @@
                 return;
             }
 
-            if (!mUserManager.isUserUnlocked(ActivityManager.getCurrentUser())) {
+            if (!mUserManager.isUserUnlocked(KeyguardUpdateMonitor.getCurrentUser())) {
                 mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
                 mTextView.setTextColor(Color.WHITE);
 
@@ -365,6 +365,9 @@
     };
 
     public void setDozing(boolean dozing) {
+        if (mDozing == dozing) {
+            return;
+        }
         mDozing = dozing;
         updateIndication();
         updateDisclosure();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 78a5194..5cb3c1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -227,7 +227,7 @@
             }
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
             float notificationClipEnd;
-            boolean aboveShelf = row.getTranslationZ() > baseZHeight;
+            boolean aboveShelf = ViewState.getFinalTranslationZ(row) > baseZHeight;
             boolean isLastChild = child == lastChild;
             float rowTranslationY = row.getTranslationY();
             if (isLastChild || aboveShelf || backgroundForceHidden) {
@@ -284,10 +284,15 @@
     private void updateNotificationClipHeight(ExpandableNotificationRow row,
             float notificationClipEnd) {
         float viewEnd = row.getTranslationY() + row.getActualHeight();
+        boolean isPinned = row.isPinned() || row.isHeadsUpAnimatingAway();
         if (viewEnd > notificationClipEnd
-                && (mAmbientState.isShadeExpanded()
-                        || (!row.isPinned() && !row.isHeadsUpAnimatingAway()))) {
-            row.setClipBottomAmount((int) (viewEnd - notificationClipEnd));
+                && (mAmbientState.isShadeExpanded() || !isPinned)) {
+            int clipBottomAmount = (int) (viewEnd - notificationClipEnd);
+            if (isPinned) {
+                clipBottomAmount = Math.min(row.getIntrinsicHeight() - row.getCollapsedHeight(),
+                        clipBottomAmount);
+            }
+            row.setClipBottomAmount(clipBottomAmount);
         } else {
             row.setClipBottomAmount(0);
         }
@@ -381,7 +386,8 @@
                 ? fullTransitionAmount
                 : transitionAmount;
         iconState.clampedAppearAmount = clampedAmount;
-        float contentTransformationAmount = isLastChild || iconState.translateContent
+        float contentTransformationAmount = !row.isAboveShelf()
+                    && (isLastChild || iconState.translateContent)
                 ? iconTransitionAmount
                 : 0.0f;
         row.setContentTransformationAmount(contentTransformationAmount, isLastChild);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index 9a3de61..80854ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -24,7 +24,6 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.support.annotation.VisibleForTesting;
-import android.support.v4.graphics.ColorUtils;
 import android.support.v7.graphics.Palette;
 import android.util.LayoutDirection;
 
@@ -41,10 +40,31 @@
     /**
      * The fraction below which we select the vibrant instead of the light/dark vibrant color
      */
-    private static final float POPULATION_FRACTION_FOR_MORE_VIBRANT = 0.75f;
+    private static final float POPULATION_FRACTION_FOR_MORE_VIBRANT = 1.0f;
+
+    /**
+     * Minimum saturation that a muted color must have if there exists if deciding between two
+     * colors
+     */
+    private static final float MIN_SATURATION_WHEN_DECIDING = 0.19f;
+
+    /**
+     * Minimum fraction that any color must have to be picked up as a text color
+     */
+    private static final double MINIMUM_IMAGE_FRACTION = 0.002;
+
+    /**
+     * The population fraction to select the dominant color as the text color over a the colored
+     * ones.
+     */
+    private static final float POPULATION_FRACTION_FOR_DOMINANT = 0.01f;
+
+    /**
+     * The population fraction to select a white or black color as the background over a color.
+     */
     private static final float POPULATION_FRACTION_FOR_WHITE_OR_BLACK = 2.5f;
     private static final float BLACK_MAX_LIGHTNESS = 0.08f;
-    private static final float WHITE_MIN_LIGHTNESS = 0.92f;
+    private static final float WHITE_MIN_LIGHTNESS = 0.90f;
     private static final int RESIZE_BITMAP_AREA = 150 * 150;
     private final ImageGradientColorizer mColorizer;
     private final Context mContext;
@@ -109,8 +129,11 @@
                         .resizeBitmapArea(RESIZE_BITMAP_AREA);
                 Palette palette = paletteBuilder.generate();
                 backgroundColor = findBackgroundColorAndFilter(palette);
-                // we want the full region again
-                paletteBuilder.setRegion(0, 0, bitmap.getWidth(), bitmap.getHeight());
+                // we want most of the full region again, slightly shifted to the right
+                float textColorStartWidthFraction = 0.4f;
+                paletteBuilder.setRegion((int) (bitmap.getWidth() * textColorStartWidthFraction), 0,
+                        bitmap.getWidth(),
+                        bitmap.getHeight());
                 if (mFilteredBackgroundHsl != null) {
                     paletteBuilder.addFilter((rgb, hsl) -> {
                         // at least 10 degrees hue difference
@@ -120,78 +143,7 @@
                 }
                 paletteBuilder.addFilter(mBlackWhiteFilter);
                 palette = paletteBuilder.generate();
-                int foregroundColor;
-                if (NotificationColorUtil.isColorLight(backgroundColor)) {
-                    Palette.Swatch first = palette.getDarkVibrantSwatch();
-                    Palette.Swatch second = palette.getVibrantSwatch();
-                    if (first != null && second != null) {
-                        int firstPopulation = first.getPopulation();
-                        int secondPopulation = second.getPopulation();
-                        if (firstPopulation / secondPopulation
-                                < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
-                            foregroundColor = second.getRgb();
-                        } else {
-                            foregroundColor = first.getRgb();
-                        }
-                    } else if (first != null) {
-                        foregroundColor = first.getRgb();
-                    } else if (second != null) {
-                        foregroundColor = second.getRgb();
-                    } else {
-                        first = palette.getMutedSwatch();
-                        second = palette.getDarkMutedSwatch();
-                        if (first != null && second != null) {
-                            float firstSaturation = first.getHsl()[1];
-                            float secondSaturation = second.getHsl()[1];
-                            if (firstSaturation > secondSaturation) {
-                                foregroundColor = first.getRgb();
-                            } else {
-                                foregroundColor = second.getRgb();
-                            }
-                        } else if (first != null) {
-                            foregroundColor = first.getRgb();
-                        } else if (second != null) {
-                            foregroundColor = second.getRgb();
-                        } else {
-                            foregroundColor = Color.BLACK;
-                        }
-                    }
-                } else {
-                    Palette.Swatch first = palette.getLightVibrantSwatch();
-                    Palette.Swatch second = palette.getVibrantSwatch();
-                    if (first != null && second != null) {
-                        int firstPopulation = first.getPopulation();
-                        int secondPopulation = second.getPopulation();
-                        if (firstPopulation / secondPopulation
-                                < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
-                            foregroundColor = second.getRgb();
-                        } else {
-                            foregroundColor = first.getRgb();
-                        }
-                    } else if (first != null) {
-                        foregroundColor = first.getRgb();
-                    } else if (second != null) {
-                        foregroundColor = second.getRgb();
-                    } else {
-                        first = palette.getMutedSwatch();
-                        second = palette.getLightMutedSwatch();
-                        if (first != null && second != null) {
-                            float firstSaturation = first.getHsl()[1];
-                            float secondSaturation = second.getHsl()[1];
-                            if (firstSaturation > secondSaturation) {
-                                foregroundColor = first.getRgb();
-                            } else {
-                                foregroundColor = second.getRgb();
-                            }
-                        } else if (first != null) {
-                            foregroundColor = first.getRgb();
-                        } else if (second != null) {
-                            foregroundColor = second.getRgb();
-                        } else {
-                            foregroundColor = Color.WHITE;
-                        }
-                    }
-                }
+                int foregroundColor = selectForegroundColor(backgroundColor, palette);
                 builder.setColorPalette(backgroundColor, foregroundColor);
             } else {
                 int id = mIsLowPriority
@@ -206,6 +158,95 @@
         }
     }
 
+    private int selectForegroundColor(int backgroundColor, Palette palette) {
+        if (NotificationColorUtil.isColorLight(backgroundColor)) {
+            return selectForegroundColorForSwatches(palette.getDarkVibrantSwatch(),
+                    palette.getVibrantSwatch(),
+                    palette.getDarkMutedSwatch(),
+                    palette.getMutedSwatch(),
+                    palette.getDominantSwatch(),
+                    Color.BLACK);
+        } else {
+            return selectForegroundColorForSwatches(palette.getLightVibrantSwatch(),
+                    palette.getVibrantSwatch(),
+                    palette.getLightMutedSwatch(),
+                    palette.getMutedSwatch(),
+                    palette.getDominantSwatch(),
+                    Color.WHITE);
+        }
+    }
+
+    private int selectForegroundColorForSwatches(Palette.Swatch moreVibrant,
+            Palette.Swatch vibrant, Palette.Swatch moreMutedSwatch, Palette.Swatch mutedSwatch,
+            Palette.Swatch dominantSwatch, int fallbackColor) {
+        Palette.Swatch coloredCandidate = selectVibrantCandidate(moreVibrant, vibrant);
+        if (coloredCandidate == null) {
+            coloredCandidate = selectMutedCandidate(mutedSwatch, moreMutedSwatch);
+        }
+        if (coloredCandidate != null) {
+            if (dominantSwatch == coloredCandidate) {
+                return coloredCandidate.getRgb();
+            } else if ((float) coloredCandidate.getPopulation() / dominantSwatch.getPopulation()
+                    < POPULATION_FRACTION_FOR_DOMINANT
+                    && dominantSwatch.getHsl()[1] > MIN_SATURATION_WHEN_DECIDING) {
+                return dominantSwatch.getRgb();
+            } else {
+                return coloredCandidate.getRgb();
+            }
+        } else if (hasEnoughPopulation(dominantSwatch)) {
+            return dominantSwatch.getRgb();
+        } else {
+            return fallbackColor;
+        }
+    }
+
+    private Palette.Swatch selectMutedCandidate(Palette.Swatch first,
+            Palette.Swatch second) {
+        boolean firstValid = hasEnoughPopulation(first);
+        boolean secondValid = hasEnoughPopulation(second);
+        if (firstValid && secondValid) {
+            float firstSaturation = first.getHsl()[1];
+            float secondSaturation = second.getHsl()[1];
+            float populationFraction = first.getPopulation() / (float) second.getPopulation();
+            if (firstSaturation * populationFraction > secondSaturation) {
+                return first;
+            } else {
+                return second;
+            }
+        } else if (firstValid) {
+            return first;
+        } else if (secondValid) {
+            return second;
+        }
+        return null;
+    }
+
+    private Palette.Swatch selectVibrantCandidate(Palette.Swatch first, Palette.Swatch second) {
+        boolean firstValid = hasEnoughPopulation(first);
+        boolean secondValid = hasEnoughPopulation(second);
+        if (firstValid && secondValid) {
+            int firstPopulation = first.getPopulation();
+            int secondPopulation = second.getPopulation();
+            if (firstPopulation / (float) secondPopulation
+                    < POPULATION_FRACTION_FOR_MORE_VIBRANT) {
+                return second;
+            } else {
+                return first;
+            }
+        } else if (firstValid) {
+            return first;
+        } else if (secondValid) {
+            return second;
+        }
+        return null;
+    }
+
+    private boolean hasEnoughPopulation(Palette.Swatch swatch) {
+        // We want a fraction that is at least 1% of the image
+        return swatch != null
+                && (swatch.getPopulation() / (float) RESIZE_BITMAP_AREA > MINIMUM_IMAGE_FRACTION);
+    }
+
     private int findBackgroundColorAndFilter(Palette palette) {
         // by default we use the dominant palette
         Palette.Swatch dominantSwatch = palette.getDominantSwatch();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index c5f23c5..6b276f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -53,6 +53,7 @@
     private float mInFrontTarget;
     private float mBehindTarget;
     private boolean mDozingAborted;
+    private boolean mWakeAndUnlocking;
 
     public DozeScrimController(ScrimController scrimController, Context context) {
         mContext = context;
@@ -63,6 +64,7 @@
     public void setDozing(boolean dozing, boolean animate) {
         if (mDozing == dozing) return;
         mDozing = dozing;
+        mWakeAndUnlocking = false;
         if (mDozing) {
             mDozingAborted = false;
             abortAnimations();
@@ -85,6 +87,16 @@
         }
     }
 
+    public void setWakeAndUnlocking() {
+        // Immediately abort the doze scrims in case of wake-and-unlock
+        // for pulsing so the Keyguard fade-out animation scrim can take over.
+        if (!mWakeAndUnlocking) {
+            mWakeAndUnlocking = true;
+            mScrimController.setDozeBehindAlpha(0f);
+            mScrimController.setDozeInFrontAlpha(0f);
+        }
+    }
+
     /** When dozing, fade screen contents in and out using the front scrim. */
     public void pulse(@NonNull DozeHost.PulseCallback callback, int reason) {
         if (callback == null) {
@@ -109,7 +121,7 @@
      */
     public void abortPulsing() {
         cancelPulsing();
-        if (mDozing) {
+        if (mDozing && !mWakeAndUnlocking) {
             mScrimController.setDozeBehindAlpha(1f);
             mScrimController.setDozeInFrontAlpha(
                     mDozeParameters.getAlwaysOn() && !mDozingAborted ? 0f : 1f);
@@ -244,6 +256,9 @@
     }
 
     private void setDozeAlpha(boolean inFront, float alpha) {
+        if (mWakeAndUnlocking) {
+            return;
+        }
         if (inFront) {
             mScrimController.setDozeInFrontAlpha(alpha);
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index f216d6c..6cb722f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -98,7 +98,6 @@
     private StatusBar mStatusBar;
     private final UnlockMethodCache mUnlockMethodCache;
     private final Context mContext;
-    private boolean mGoingToSleep;
     private int mPendingAuthenticatedUserId = -1;
 
     public FingerprintUnlockController(Context context,
@@ -213,17 +212,19 @@
                 Trace.endSection();
                 break;
             case MODE_WAKE_AND_UNLOCK_PULSING:
-                Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
-                mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
-                        true /* allowEnterAnimation */);
-                // Fall through.
-                Trace.endSection();
             case MODE_WAKE_AND_UNLOCK:
-                Trace.beginSection("MODE_WAKE_AND_UNLOCK");
+                if (mMode == MODE_WAKE_AND_UNLOCK_PULSING) {
+                    Trace.beginSection("MODE_WAKE_AND_UNLOCK_PULSING");
+                    mStatusBar.updateMediaMetaData(false /* metaDataChanged */,
+                            true /* allowEnterAnimation */);
+                } else {
+                    Trace.beginSection("MODE_WAKE_AND_UNLOCK");
+                    mDozeScrimController.abortDoze();
+                }
                 mStatusBarWindowManager.setStatusBarFocusable(false);
-                mDozeScrimController.abortDoze();
                 mKeyguardViewMediator.onWakeAndUnlocking();
                 mScrimController.setWakeAndUnlocking();
+                mDozeScrimController.setWakeAndUnlocking();
                 if (mStatusBar.getNavigationBarView() != null) {
                     mStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
                 }
@@ -302,10 +303,7 @@
     }
 
     private void cleanup() {
-        mMode = MODE_NONE;
         releaseFingerprintWakeLock();
-        mStatusBarWindowManager.setForceDozeBrightness(false);
-        mStatusBar.notifyFpAuthModeChanged();
     }
 
     public void startKeyguardFadingAway() {
@@ -321,6 +319,7 @@
 
     public void finishKeyguardFadingAway() {
         mMode = MODE_NONE;
+        mStatusBarWindowManager.setForceDozeBrightness(false);
         if (mStatusBar.getNavigationBarView() != null) {
             mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 2124011..95f32bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 import android.content.Context;
+import android.os.Handler;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Slog;
@@ -55,6 +56,7 @@
     protected final ViewGroup mContainer;
     private final FalsingManager mFalsingManager;
     private final DismissCallbackRegistry mDismissCallbackRegistry;
+    private final Handler mHandler;
     protected KeyguardHostView mKeyguardView;
     protected ViewGroup mRoot;
     private boolean mShowingSoon;
@@ -66,6 +68,7 @@
                     mBouncerPromptReason = mCallback.getBouncerPromptReason();
                 }
             };
+    private final Runnable mRemoveViewRunnable = this::removeView;
 
     public KeyguardBouncer(Context context, ViewMediatorCallback callback,
             LockPatternUtils lockPatternUtils, ViewGroup container,
@@ -77,6 +80,7 @@
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
         mFalsingManager = FalsingManager.getInstance(mContext);
         mDismissCallbackRegistry = dismissCallbackRegistry;
+        mHandler = new Handler();
     }
 
     public void show(boolean resetSecuritySelection) {
@@ -179,10 +183,14 @@
             mKeyguardView.cancelDismissAction();
             mKeyguardView.cleanUp();
         }
-        if (destroyView) {
-            removeView();
-        } else if (mRoot != null) {
+        if (mRoot != null) {
             mRoot.setVisibility(View.INVISIBLE);
+            if (destroyView) {
+
+                // We have a ViewFlipper that unregisters a broadcast when being detached, which may
+                // be slow because of AM lock contention during unlocking. We can delay it a bit.
+                mHandler.postDelayed(mRemoveViewRunnable, 50);
+            }
         }
     }
 
@@ -226,6 +234,7 @@
     }
 
     protected void ensureView() {
+        mHandler.removeCallbacks(mRemoveViewRunnable);
         if (mRoot == null) {
             inflateView();
         }
@@ -233,6 +242,7 @@
 
     protected void inflateView() {
         removeView();
+        mHandler.removeCallbacks(mRemoveViewRunnable);
         mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
         mKeyguardView = (KeyguardHostView) mRoot.findViewById(R.id.keyguard_host_view);
         mKeyguardView.setLockPatternUtils(mLockPatternUtils);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 4581204..52838b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -128,8 +128,7 @@
 
     protected boolean shouldShowNotificationIcon(NotificationData.Entry entry,
             NotificationData notificationData, boolean showAmbient) {
-        if (notificationData.isAmbient(entry.key) && !showAmbient
-                && !NotificationData.showNotificationEvenIfUnprovisioned(entry.notification)) {
+        if (notificationData.isAmbient(entry.key) && !showAmbient) {
             return false;
         }
         if (!StatusBar.isTopLevelChild(entry)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 0fa8afa..af2f7e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2401,17 +2401,26 @@
     @Override
     public void setAlpha(float alpha) {
         super.setAlpha(alpha);
-        updateFullyVisibleState();
+        updateFullyVisibleState(false /* forceNotFullyVisible */);
+    }
+
+    /**
+     * Must be called before starting a ViewPropertyAnimator alpha animation because those
+     * do NOT call setAlpha and therefore don't properly update the fullyVisibleState.
+     */
+    public void notifyStartFading() {
+        updateFullyVisibleState(true /* forceNotFullyVisible */);
     }
 
     @Override
     public void setVisibility(int visibility) {
         super.setVisibility(visibility);
-        updateFullyVisibleState();
+        updateFullyVisibleState(false /* forceNotFullyVisible */);
     }
 
-    private void updateFullyVisibleState() {
-        mNotificationStackScroller.setParentNotFullyVisible(getAlpha() != 1.0f
+    private void updateFullyVisibleState(boolean forceNotFullyVisible) {
+        mNotificationStackScroller.setParentNotFullyVisible(forceNotFullyVisible
+                || getAlpha() != 1.0f
                 || getVisibility() != VISIBLE);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index e378e871..4b1d7d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -34,10 +34,9 @@
 import android.widget.FrameLayout;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.EventLogTags;
-import com.android.systemui.Interpolators;
 import com.android.keyguard.LatencyTracker;
+import com.android.systemui.DejankUtils;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.doze.DozeLog;
@@ -225,6 +224,7 @@
             if (mTracking) {
                 onTrackingStopped(true /* expanded */);
             }
+            notifyExpandingFinished();
         }
     }
 
@@ -833,6 +833,14 @@
             }
         }
 
+        // If we are closing the panel and we are almost there due to a slow decelerating
+        // interpolator, abort the animation.
+        if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) {
+            mExpandedHeight = 0f;
+            if (mHeightAnimator != null) {
+                mHeightAnimator.end();
+            }
+        }
         mExpandedFraction = Math.min(1f,
                 fhWithoutOverExpansion == 0 ? 0 : mExpandedHeight / fhWithoutOverExpansion);
         onHeightUpdated(mExpandedHeight);
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 41fb5f7..f3ba5aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -58,6 +58,7 @@
 import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -128,6 +129,7 @@
     private final KeyguardMonitor mKeyguardMonitor;
     private final LocationController mLocationController;
     private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
@@ -472,30 +474,38 @@
     }
 
     private void updateManagedProfile() {
-        try {
-            final boolean showIcon;
-            final int userId = ActivityManager.getService().getLastResumedActivityUserId();
-            if (mUserManager.isManagedProfile(userId) && !mKeyguardMonitor.isShowing()) {
-                showIcon = true;
-                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;
+        // 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
+        // or in the next one, we call this method from our UI offload thread.
+        mUiOffloadThread.submit(() -> {
+            final int userId;
+            try {
+                userId = ActivityManager.getService().getLastResumedActivityUserId();
+                boolean isManagedProfile = mUserManager.isManagedProfile(userId);
+                mHandler.post(() -> {
+                    final boolean showIcon;
+                    if (isManagedProfile && !mKeyguardMonitor.isShowing()) {
+                        showIcon = true;
+                        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;
+                    }
+                    if (mManagedProfileIconVisible != showIcon) {
+                        mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
+                        mManagedProfileIconVisible = showIcon;
+                    }
+                });
+            } catch (RemoteException e) {
+                Log.w(TAG, "updateManagedProfile: ", e);
             }
-            if (mManagedProfileIconVisible != showIcon) {
-                mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
-                mManagedProfileIconVisible = showIcon;
-            }
-        } catch (RemoteException ex) {
-            Log.w(TAG, "updateManagedProfile: ", ex);
-            // ignore
-        }
+        });
     }
 
     private void updateForegroundInstantApps() {
@@ -503,26 +513,22 @@
         ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
         IPackageManager pm = AppGlobals.getPackageManager();
         mCurrentNotifs.clear();
-        try {
-            ArraySet<Integer> stacksToCheck = new ArraySet<>();
-            int[] STACKS_TO_CHECK = new int[]{
-                    StackId.FULLSCREEN_WORKSPACE_STACK_ID,
-                    StackId.DOCKED_STACK_ID,
-            };
-            int focusedId = ActivityManager.getService().getFocusedStackId();
-            if (focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID
-                    || focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID) {
-                checkStack(StackId.FULLSCREEN_WORKSPACE_STACK_ID, notifs, noMan, pm);
+        mUiOffloadThread.submit(() -> {
+            try {
+                int focusedId = ActivityManager.getService().getFocusedStackId();
+                if (focusedId == StackId.FULLSCREEN_WORKSPACE_STACK_ID) {
+                    checkStack(StackId.FULLSCREEN_WORKSPACE_STACK_ID, notifs, noMan, pm);
+                }
+                if (mDockedStackExists) {
+                    checkStack(StackId.DOCKED_STACK_ID, notifs, noMan, pm);
+                }
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
             }
-            if (mDockedStackExists) {
-                checkStack(StackId.DOCKED_STACK_ID, notifs, noMan, pm);
-            }
-        } catch (RemoteException e) {
-            e.rethrowFromSystemServer();
-        }
-        // Cancel all the leftover notifications that don't have a foreground process anymore.
-        notifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
-                new UserHandle(v.second)));
+            // Cancel all the leftover notifications that don't have a foreground process anymore.
+            notifs.forEach(v -> noMan.cancelAsUser(v.first, SystemMessage.NOTE_INSTANT_APPS,
+                    new UserHandle(v.second)));
+        });
     }
 
     private void checkStack(int stackId, ArraySet<Pair<String, Integer>> notifs,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 916b603..970d1de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -121,12 +121,12 @@
     public void onPanelCollapsed() {
         super.onPanelCollapsed();
         // Close the status bar in the next frame so we can show the end of the animation.
-        DejankUtils.postAfterTraversal(mHideExpandedRunnable);
+        post(mHideExpandedRunnable);
         mIsFullyOpenedPanel = false;
     }
 
     public void removePendingHideExpandedRunnables() {
-        DejankUtils.removeCallbacks(mHideExpandedRunnable);
+        removeCallbacks(mHideExpandedRunnable);
     }
 
     @Override
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 fc73c0f..699d367 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -83,6 +83,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.SystemService;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -131,6 +132,7 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SystemUIFactory;
+import com.android.systemui.UiOffloadThread;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.classifier.FalsingLog;
 import com.android.systemui.classifier.FalsingManager;
@@ -149,6 +151,7 @@
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
 import com.android.systemui.recents.events.activity.UndockingTaskEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.stackdivider.WindowManagerProxy;
 import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -220,8 +223,6 @@
 import android.content.pm.UserInfo;
 import android.os.Build;
 import android.os.Handler;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
 import android.service.notification.NotificationListenerService;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
@@ -538,6 +539,7 @@
     private ViewMediatorCallback mKeyguardViewMediatorCallback;
     protected ScrimController mScrimController;
     protected DozeScrimController mDozeScrimController;
+    private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
 
     private final Runnable mAutohide = new Runnable() {
         @Override
@@ -778,8 +780,6 @@
         mAccessibilityManager = (AccessibilityManager)
                 mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
 
-        mDreamManager = IDreamManager.Stub.asInterface(
-                ServiceManager.checkService(DreamService.DREAM_SERVICE));
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
 
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
@@ -1532,13 +1532,7 @@
     }
 
     void awakenDreams() {
-        if (mDreamManager != null) {
-            try {
-                mDreamManager.awaken();
-            } catch (RemoteException e) {
-                // fine, stay asleep then
-            }
-        }
+        SystemServicesProxy.getInstance(mContext).awakenDreamsAsync();
     }
 
     public UserHandle getCurrentUserHandle() {
@@ -4144,6 +4138,7 @@
      * fading.
      */
     public void fadeKeyguardWhilePulsing() {
+        mNotificationPanel.notifyStartFading();
         mNotificationPanel.animate()
                 .alpha(0f)
                 .setStartDelay(0)
@@ -4348,7 +4343,7 @@
         checkBarModes();
         updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
         mKeyguardMonitor.notifyKeyguardState(mStatusBarKeyguardViewManager.isShowing(),
-                mStatusBarKeyguardViewManager.isSecure(),
+                mUnlockMethodCache.isMethodSecure(),
                 mStatusBarKeyguardViewManager.isOccluded());
         Trace.endSection();
     }
@@ -4362,12 +4357,7 @@
         mKeyguardIndicationController.setDozing(mDozing);
         mNotificationPanel.setDark(mDozing, animate);
         updateQsExpansionEnabled();
-
-        // Immediately abort the dozing from the doze scrim controller in case of wake-and-unlock
-        // for pulsing so the Keyguard fade-out animation scrim can take over.
-        mDozeScrimController.setDozing(mDozing &&
-                mFingerprintUnlockController.getMode()
-                        != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, animate);
+        mDozeScrimController.setDozing(mDozing, animate);
         updateRowStates();
         Trace.endSection();
     }
@@ -5173,7 +5163,6 @@
     protected boolean mDisableNotificationAlerts = false;
 
     protected DevicePolicyManager mDevicePolicyManager;
-    protected IDreamManager mDreamManager;
     protected PowerManager mPowerManager;
     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
@@ -6816,12 +6805,8 @@
             return false;
         }
 
-        boolean inUse = mPowerManager.isScreenOn();
-        try {
-            inUse = inUse && !mDreamManager.isDreaming();
-        } catch (RemoteException e) {
-            Log.d(TAG, "failed to query dream manager", e);
-        }
+        boolean inUse = mPowerManager.isScreenOn()
+                && !SystemServicesProxy.getInstance(mContext).isDreaming();
 
         if (!inUse && !isDozing()) {
             if (DEBUG) {
@@ -6898,11 +6883,13 @@
 
     @Override
     public void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
-        try {
-            mBarService.onNotificationExpansionChanged(key, userAction, expanded);
-        } catch (RemoteException e) {
-            // Ignore.
-        }
+        mUiOffloadThread.submit(() -> {
+            try {
+                mBarService.onNotificationExpansionChanged(key, userAction, expanded);
+            } catch (RemoteException e) {
+                // Ignore.
+            }
+        });
     }
 
     public boolean isKeyguardSecure() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 2a69c1e..bb302bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -29,6 +29,7 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.DejankUtils;
 import com.android.keyguard.LatencyTracker;
@@ -97,12 +98,26 @@
     private boolean mDeviceWillWakeUp;
     private boolean mDeferScrimFadeOut;
 
+    private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
+            new KeyguardUpdateMonitorCallback() {
+        @Override
+        public void onEmergencyCallAction() {
+
+            // Since we won't get a setOccluded call we have to reset the view manually such that
+            // the bouncer goes away.
+            if (mOccluded) {
+                reset(false /* hideBouncerWhenShowing */);
+            }
+        }
+    };
+
     public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
             LockPatternUtils lockPatternUtils) {
         mContext = context;
         mViewMediatorCallback = callback;
         mLockPatternUtils = lockPatternUtils;
         mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+        KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
     }
 
     public void registerStatusBar(StatusBar statusBar,
@@ -381,6 +396,7 @@
                 } else {
                     mScrimController.animateGoingToFullShade(delay, fadeoutDuration);
                     mStatusBar.finishKeyguardFadingAway();
+                    mFingerprintUnlockController.finishKeyguardFadingAway();
                 }
             }
             mStatusBarWindowManager.setKeyguardShowing(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 26e007c..f050be4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -407,8 +407,9 @@
             mFloatingActionMode.finish();
         }
         cleanupFloatingActionModeViews();
+        mFloatingToolbar = new FloatingToolbar(mContext, mFakeWindow);
         final FloatingActionMode mode =
-                new FloatingActionMode(mContext, callback, originatingView);
+                new FloatingActionMode(mContext, callback, originatingView, mFloatingToolbar);
         mFloatingActionModeOriginatingView = originatingView;
         mFloatingToolbarPreDrawListener =
                 new ViewTreeObserver.OnPreDrawListener() {
@@ -423,8 +424,6 @@
 
     private void setHandledFloatingActionMode(ActionMode mode) {
         mFloatingActionMode = mode;
-        mFloatingToolbar = new FloatingToolbar(mContext, mFakeWindow);
-        ((FloatingActionMode) mFloatingActionMode).setFloatingToolbar(mFloatingToolbar);
         mFloatingActionMode.invalidate();  // Will show the floating toolbar if necessary.
         mFloatingActionModeOriginatingView.getViewTreeObserver()
                 .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index d6c080a..7bce33a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -124,13 +124,11 @@
         mKeyguardFadingAway = true;
         mKeyguardFadingAwayDelay = delay;
         mKeyguardFadingAwayDuration = fadeoutDuration;
-        notifyKeyguardChanged();
     }
 
     public void notifyKeyguardDoneFading() {
         mKeyguardFadingAway = false;
         mKeyguardGoingAway = false;
-        notifyKeyguardChanged();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 53671a1..e0f4429 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -18,6 +18,7 @@
 
 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 
+import android.R.attr;
 import android.app.ActivityManager;
 import android.app.Dialog;
 import android.app.Notification;
@@ -31,6 +32,7 @@
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -52,6 +54,7 @@
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.GuestResumeSessionReceiver;
 import com.android.systemui.R;
@@ -739,7 +742,12 @@
             if (item.isAddUser) {
                 return context.getDrawable(R.drawable.ic_add_circle_qs);
             }
-            return UserIcons.getDefaultUserIcon(item.resolveId(), /* light= */ true);
+            Drawable icon = UserIcons.getDefaultUserIcon(item.resolveId(), /* light= */ false);
+            if (item.isGuest) {
+                icon.setColorFilter(Utils.getColorAttr(context, android.R.attr.colorForeground),
+                        Mode.SRC_IN);
+            }
+            return icon;
         }
 
         public void refresh() {
@@ -872,7 +880,14 @@
     private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
         @Override
         public void onKeyguardShowingChanged() {
-            notifyAdapters();
+
+            // When Keyguard is going away, we don't need to update our items immediately which
+            // helps making the transition faster.
+            if (!mKeyguardMonitor.isShowing()) {
+                mHandler.post(UserSwitcherController.this::notifyAdapters);
+            } else {
+                notifyAdapters();
+            }
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index cb1f44e..0dbd1d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -29,6 +29,7 @@
 import android.widget.RemoteViews;
 import android.widget.TextView;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -535,8 +536,8 @@
             firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
         }
 
-        boolean childrenExpanded = !mContainingNotification.isGroupExpansionChanging()
-                && mChildrenExpanded;
+        boolean childrenExpandedAndNotAnimating = mChildrenExpanded
+                && !mContainingNotification.isGroupExpansionChanging();
         for (int i = 0; i < childCount; i++) {
             ExpandableNotificationRow child = mChildren.get(i);
             if (!firstChild) {
@@ -544,7 +545,7 @@
                     yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
                             expandFactor);
                 } else {
-                    yPosition += childrenExpanded ? mDividerHeight : mChildPadding;
+                    yPosition += mChildrenExpanded ? mDividerHeight : mChildPadding;
                 }
             } else {
                 if (expandingToExpandedGroup) {
@@ -553,7 +554,7 @@
                             mNotificatonTopPadding + mDividerHeight,
                             expandFactor);
                 } else {
-                    yPosition += childrenExpanded ? mNotificatonTopPadding + mDividerHeight : 0;
+                    yPosition += mChildrenExpanded ? mNotificatonTopPadding + mDividerHeight : 0;
                 }
                 firstChild = false;
             }
@@ -565,7 +566,7 @@
             childState.hidden = false;
             // When the group is expanded, the children cast the shadows rather than the parent
             // so use the parent's elevation here.
-            childState.zTranslation = childrenExpanded
+            childState.zTranslation = childrenExpandedAndNotAnimating
                     ? mContainingNotification.getTranslationZ()
                     : 0;
             childState.dimmed = parentState.dimmed;
@@ -619,7 +620,7 @@
                 mHeaderViewState = new ViewState();
             }
             mHeaderViewState.initFrom(mNotificationHeader);
-            mHeaderViewState.zTranslation = childrenExpanded
+            mHeaderViewState.zTranslation = childrenExpandedAndNotAnimating
                     ? mContainingNotification.getTranslationZ()
                     : 0;
         }
@@ -1223,4 +1224,9 @@
         }
         return getGroupExpandFraction();
     }
+
+    @VisibleForTesting
+    public boolean isUserLocked() {
+        return mUserLocked;
+    }
 }
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 b5db78d..12a8783 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -410,7 +410,7 @@
             if (mIsExpanded) {
                 // Ensure that the heads up is always visible even when scrolled off
                 clampHunToTop(ambientState, row, childState);
-                if (i == 0) {
+                if (i == 0 && row.isAboveShelf()) {
                     // the first hun can't get off screen.
                     clampHunToMaxTranslation(ambientState, row, childState);
                 }
@@ -447,10 +447,14 @@
     private void clampHunToMaxTranslation(AmbientState ambientState, ExpandableNotificationRow row,
             ExpandableViewState childState) {
         float newTranslation;
-        float bottomPosition = ambientState.getMaxHeadsUpTranslation() - row.getCollapsedHeight();
+        float maxHeadsUpTranslation = ambientState.getMaxHeadsUpTranslation();
+        float maxShelfPosition = ambientState.getInnerHeight() + ambientState.getTopPadding()
+                + ambientState.getStackTranslation();
+        maxHeadsUpTranslation = Math.min(maxHeadsUpTranslation, maxShelfPosition);
+        float bottomPosition = maxHeadsUpTranslation - row.getCollapsedHeight();
         newTranslation = Math.min(childState.yTranslation, bottomPosition);
-        childState.height = (int) Math.max(childState.height
-                - (childState.yTranslation - newTranslation), row.getCollapsedHeight());
+        childState.height = (int) Math.min(childState.height, maxHeadsUpTranslation
+                - newTranslation);
         childState.yTranslation = newTranslation;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
index d664b12..27b730cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ViewState.java
@@ -657,6 +657,22 @@
         }
     }
 
+    /**
+     * Get the end value of the zTranslation animation running on a view or the zTranslation
+     * if no animation is running.
+     */
+    public static float getFinalTranslationZ(View view) {
+        if (view == null) {
+            return 0;
+        }
+        ValueAnimator zAnimator = getChildTag(view, TAG_ANIMATOR_TRANSLATION_Z);
+        if (zAnimator == null) {
+            return view.getTranslationZ();
+        } else {
+            return getChildTag(view, TAG_END_TRANSLATION_Z);
+        }
+    }
+
     public static boolean isAnimatingY(View child) {
         return getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y) != null;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index aadae0f..0aac1c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -21,15 +21,21 @@
 import android.os.MessageQueue;
 import android.support.test.InstrumentationRegistry;
 import android.testing.LeakCheck;
+import android.util.Log;
 
 import org.junit.Before;
 import org.junit.Rule;
 
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
 /**
  * Base class that does System UI specific setup.
  */
 public abstract class SysuiTestCase {
 
+    private static final String TAG = "SysuiTestCase";
+
     private Handler mHandler;
     @Rule
     public SysuiTestableContext mContext = new SysuiTestableContext(
@@ -57,6 +63,15 @@
         waitForIdleSync(mHandler);
     }
 
+    protected void waitForUiOffloadThread() {
+        Future<?> future = Dependency.get(UiOffloadThread.class).submit(() -> {});
+        try {
+            future.get();
+        } catch (InterruptedException | ExecutionException e) {
+            Log.e(TAG, "Failed to wait for ui offload thread.", e);
+        }
+    }
+
     public static void waitForIdleSync(Handler h) {
         validateThread(h.getLooper());
         Idler idler = new Idler(null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
index 131a70b..308670d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
@@ -23,6 +23,8 @@
 import android.support.test.runner.AndroidJUnit4;
 
 import com.android.internal.policy.IKeyguardDismissCallback;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.UiOffloadThread;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -35,7 +37,7 @@
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class DismissCallbackRegistryTest {
+public class DismissCallbackRegistryTest extends SysuiTestCase {
 
     private final DismissCallbackRegistry mDismissCallbackRegistry = new DismissCallbackRegistry();
     private @Mock IKeyguardDismissCallback mMockCallback;
@@ -50,6 +52,7 @@
     public void testCancelled() throws Exception {
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.notifyDismissCancelled();
+        waitForUiOffloadThread();
         verify(mMockCallback).onDismissCancelled();
     }
 
@@ -58,6 +61,7 @@
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.addCallback(mMockCallback2);
         mDismissCallbackRegistry.notifyDismissCancelled();
+        waitForUiOffloadThread();
         verify(mMockCallback).onDismissCancelled();
         verify(mMockCallback2).onDismissCancelled();
     }
@@ -66,6 +70,7 @@
     public void testSucceeded() throws Exception {
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.notifyDismissSucceeded();
+        waitForUiOffloadThread();
         verify(mMockCallback).onDismissSucceeded();
     }
 
@@ -74,6 +79,7 @@
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.addCallback(mMockCallback2);
         mDismissCallbackRegistry.notifyDismissSucceeded();
+        waitForUiOffloadThread();
         verify(mMockCallback).onDismissSucceeded();
         verify(mMockCallback2).onDismissSucceeded();
     }
@@ -83,6 +89,7 @@
         mDismissCallbackRegistry.addCallback(mMockCallback);
         mDismissCallbackRegistry.notifyDismissSucceeded();
         mDismissCallbackRegistry.notifyDismissSucceeded();
+        waitForUiOffloadThread();
         verify(mMockCallback, times(1)).onDismissSucceeded();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
index 8609eeb..0a945ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.support.test.filters.FlakyTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -37,12 +38,14 @@
 import com.android.systemui.plugins.qs.DetailAdapter;
 
 import org.junit.After;
+import org.junit.Ignore;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@FlakyTest
 public class QSDetailTest extends SysuiTestCase {
 
     private MetricsLogger mMetricsLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
index 778ab8e..09c5725 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterTest.java
@@ -20,6 +20,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.support.test.filters.FlakyTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -33,11 +34,13 @@
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@FlakyTest
 public class QSFooterTest extends LeakCheckedTest {
 
     private QSFooter mFooter;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index d81224e..601d4e2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -21,6 +21,7 @@
 import android.app.FragmentController;
 import android.app.FragmentManagerNonConfig;
 import android.os.Looper;
+import android.support.test.filters.FlakyTest;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.keyguard.CarrierText;
@@ -39,6 +40,7 @@
 import android.testing.TestableLooper.RunWithLooper;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -48,6 +50,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
+@FlakyTest
 public class QSFragmentTest extends SysuiBaseFragmentTest {
 
     private MetricsLogger mMockMetricsLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
index 4979684..5f6fc33 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java
@@ -19,6 +19,7 @@
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
 
+import android.support.test.filters.FlakyTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -29,6 +30,7 @@
 import com.android.systemui.qs.customize.QSCustomizer;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -36,6 +38,7 @@
 
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
+@FlakyTest
 public class QSPanelTest extends SysuiTestCase {
 
     private MetricsLogger mMetricsLogger;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
index 5cd092b..a3a0a6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
@@ -16,22 +16,29 @@
 
 package com.android.systemui.statusbar;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.FlakyTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 
+import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
+
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@FlakyTest
 public class ExpandableNotificationRowTest {
 
     private Context mContext;
@@ -62,4 +69,25 @@
                 == View.VISIBLE);
     }
 
+    @Test
+    public void testUserLockedResetEvenWhenNoChildren() {
+        mGroup.setUserLocked(true);
+        mGroup.removeAllChildren();
+        mGroup.setUserLocked(false);
+        Assert.assertFalse("The childrencontainer should not be userlocked but is, the state "
+                + "seems out of sync.", mGroup.getChildrenContainer().isUserLocked());
+    }
+
+    @Test
+    public void testReinflatedOnDensityChange() {
+        mGroup.setUserLocked(true);
+        mGroup.removeAllChildren();
+        mGroup.setUserLocked(false);
+        NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
+        mGroup.setChildrenContainer(mockContainer);
+        mGroup.onDensityOrFontScaleChanged();
+        verify(mockContainer).reInflateViews(any(), any());
+    }
+
+
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
index 77f96b8..fecf901 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationContentViewTest.java
@@ -19,12 +19,14 @@
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.FlakyTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -35,6 +37,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@FlakyTest
 public class NotificationContentViewTest {
 
     NotificationContentView mView;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
index f016aa1..00f2b18 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.FlakyTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.View;
@@ -30,11 +31,13 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@FlakyTest
 public class NotificationCustomViewWrapperTest {
 
     private Context mContext;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
index 0c5bdea..f9f40a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationInflaterTest.java
@@ -27,6 +27,7 @@
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.FlakyTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.widget.RemoteViews;
@@ -38,6 +39,7 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -45,6 +47,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@FlakyTest
 public class NotificationInflaterTest {
 
     private Context mContext;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
index f051f30..4932ba1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.FlakyTest;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.NotificationHeaderView;
@@ -29,11 +30,13 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
+@FlakyTest
 public class NotificationChildrenContainerTest {
 
     private Context mContext;
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index debb157..564d135 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -241,6 +241,20 @@
 
   // List of events
   repeated StaEvent sta_event_list = 52;
+
+  // Total number of times WiFi HAL crashed.
+  optional int32 num_hal_crashes = 53;
+
+  // Total number of times WiFicond crashed.
+  optional int32 num_wificond_crashes = 54;
+
+  // Indicates the number of times an error was encountered in
+  // Wifi HAL when wifi was turned on.
+  optional int32 num_wifi_on_failure_due_to_hal = 55;
+
+  // Indicates the number of times an error was encountered in
+  // Wificond when wifi was turned on.
+  optional int32 num_wifi_on_failure_due_to_wificond = 56;
 }
 
 // Information that gets logged for every WiFi connection.
diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
index 0e30fb2..de8a518 100644
--- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
+++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
@@ -26,6 +26,7 @@
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -96,7 +97,7 @@
                 mNodeFromOriginalWindow = info;
             } else {
                 Slog.e(LOG_TAG, "Callback with unexpected interactionId");
-                throw new RuntimeException("Callback with unexpected interactionId"); // Remove
+                return;
             }
 
             mSingleNodeCallbackHappened = true;
@@ -119,7 +120,7 @@
                 mNodesWithReplacementActions = infos;
             } else {
                 Slog.e(LOG_TAG, "Callback with unexpected interactionId");
-                throw new RuntimeException("Callback with unexpected interactionId"); // Remove
+                return;
             }
             callbackForSingleNode = mSingleNodeCallbackHappened;
             callbackForMultipleNodes = mMultiNodeCallbackHappened;
@@ -147,7 +148,7 @@
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Extra callback");
                 }
-                throw new RuntimeException("Extra callback"); // Replace with return before submit
+                return;
             }
             if (mNodeFromOriginalWindow != null) {
                 replaceActionsOnInfoLocked(mNodeFromOriginalWindow);
@@ -172,7 +173,7 @@
                 if (DEBUG) {
                     Slog.e(LOG_TAG, "Extra callback");
                 }
-                throw new RuntimeException("Extra callback"); // Replace with return before submit
+                return;
             }
             if (mNodesFromOriginalWindow != null) {
                 for (int i = 0; i < mNodesFromOriginalWindow.size(); i++) {
@@ -180,7 +181,8 @@
                 }
             }
             recycleReplaceActionNodesLocked();
-            nodesToReturn = mNodesFromOriginalWindow;
+            nodesToReturn = (mNodesFromOriginalWindow == null)
+                    ? null : new ArrayList<>(mNodesFromOriginalWindow);
             mDone = true;
         }
         try {
@@ -195,6 +197,12 @@
     @GuardedBy("mLock")
     private void replaceActionsOnInfoLocked(AccessibilityNodeInfo info) {
         info.removeAllActions();
+        info.setClickable(false);
+        info.setFocusable(false);
+        info.setContextClickable(false);
+        info.setScrollable(false);
+        info.setLongClickable(false);
+        info.setDismissable(false);
         // We currently only replace actions for the root node
         if ((info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID)
                 && mNodesWithReplacementActions != null) {
@@ -213,6 +221,12 @@
                         info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
                         info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
                     }
+                    info.setClickable(nodeWithReplacementActions.isClickable());
+                    info.setFocusable(nodeWithReplacementActions.isFocusable());
+                    info.setContextClickable(nodeWithReplacementActions.isContextClickable());
+                    info.setScrollable(nodeWithReplacementActions.isScrollable());
+                    info.setLongClickable(nodeWithReplacementActions.isLongClickable());
+                    info.setDismissable(nodeWithReplacementActions.isDismissable());
                 }
             }
         }
@@ -220,6 +234,7 @@
 
     @GuardedBy("mLock")
     private void recycleReplaceActionNodesLocked() {
+        if (mNodesWithReplacementActions == null) return;
         for (int i = mNodesWithReplacementActions.size() - 1; i >= 0; i--) {
             AccessibilityNodeInfo nodeWithReplacementAction = mNodesWithReplacementActions.get(i);
             nodeWithReplacementAction.recycle();
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 6e87f88..e380f2c 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -938,7 +938,12 @@
         if (pointerIdBits == ALL_POINTER_ID_BITS) {
             event = prototype;
         } else {
-            event = prototype.split(pointerIdBits);
+            try {
+                event = prototype.split(pointerIdBits);
+            } catch (IllegalArgumentException e) {
+                Slog.e(LOG_TAG, "sendMotionEvent: Failed to split motion event: " + e);
+                return;
+            }
         }
         if (action == MotionEvent.ACTION_DOWN) {
             event.setDownTime(event.getEventTime());
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index 0281f73..86e32e0 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -16,7 +16,10 @@
 
 package com.android.server.autofill;
 
+import android.annotation.Nullable;
 import android.os.Bundle;
+import android.util.ArraySet;
+import android.view.autofill.AutofillId;
 
 import java.util.Arrays;
 import java.util.Objects;
@@ -68,4 +71,15 @@
         append(builder, bundle);
         return builder.toString();
     }
+
+    @Nullable
+    static AutofillId[] toArray(@Nullable ArraySet<AutofillId> set) {
+        if (set == null) return null;
+
+        final AutofillId[] array = new AutofillId[set.size()];
+        for (int i = 0; i < set.size(); i++) {
+            array[i] = set.valueAt(i);
+        }
+        return array;
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 0122301..bad8dcf 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -28,6 +28,7 @@
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sPartitionMaxCount;
 import static com.android.server.autofill.Helper.sVerbose;
+import static com.android.server.autofill.Helper.toArray;
 import static com.android.server.autofill.ViewState.STATE_AUTOFILLED;
 import static com.android.server.autofill.ViewState.STATE_RESTARTED_SESSION;
 
@@ -57,6 +58,7 @@
 import android.service.autofill.SaveInfo;
 import android.service.autofill.SaveRequest;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.autofill.AutofillId;
@@ -172,13 +174,13 @@
         public void send(int resultCode, Bundle resultData) throws RemoteException {
             final AssistStructure structure = resultData.getParcelable(KEY_STRUCTURE);
             if (structure == null) {
-                Slog.wtf(TAG, "no assist structure");
+                Slog.e(TAG, "No assist structure - app might have crashed providing it");
                 return;
             }
 
             final Bundle receiverExtras = resultData.getBundle(KEY_RECEIVER_EXTRAS);
             if (receiverExtras == null) {
-                Slog.wtf(TAG, "No " + KEY_RECEIVER_EXTRAS + " on receiver");
+                Slog.e(TAG, "No receiver extras - app might have crashed providing it");
                 return;
             }
 
@@ -680,7 +682,6 @@
                 removeSelf();
                 return;
             }
-            resetViewStatesLocked(dataset, ViewState.STATE_WAITING_DATASET_AUTH);
         }
 
         final Parcelable result = data.getParcelable(AutofillManager.EXTRA_AUTHENTICATION_RESULT);
@@ -1139,15 +1140,20 @@
 
         // Only track the views of the last response as only those are reported back to the
         // service, see #showSaveLocked
-        ArrayList<AutofillId> trackedViews = new ArrayList<>();
+        final FillResponse response = mResponses.valueAt(getLastResponseIndex());
+
+        ArraySet<AutofillId> trackedViews = null;
         boolean saveOnAllViewsInvisible = false;
-        SaveInfo saveInfo = mResponses.valueAt(getLastResponseIndex()).getSaveInfo();
+        final SaveInfo saveInfo = response.getSaveInfo();
         if (saveInfo != null) {
             saveOnAllViewsInvisible =
                     (saveInfo.getFlags() & SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE) != 0;
 
             // We only need to track views if we want to save once they become invisible.
             if (saveOnAllViewsInvisible) {
+                if (trackedViews == null) {
+                    trackedViews = new ArraySet<>();
+                }
                 if (saveInfo.getRequiredIds() != null) {
                     Collections.addAll(trackedViews, saveInfo.getRequiredIds());
                 }
@@ -1158,8 +1164,32 @@
             }
         }
 
+        // Must also track that are part of datasets, otherwise the FillUI won't be hidden when
+        // they go away (if they're not savable).
+
+        final ArrayList<Dataset> datasets = response.getDatasets();
+        ArraySet<AutofillId> fillableIds = null;
+        if (datasets != null) {
+            for (int i = 0; i < datasets.size(); i++) {
+                final Dataset dataset = datasets.get(i);
+                final ArrayList<AutofillId> fieldIds = dataset.getFieldIds();
+                if (fieldIds == null) continue;
+
+                for (int j = 0; j < fieldIds.size(); j++) {
+                    final AutofillId id = fieldIds.get(j);
+                    if (trackedViews == null || !trackedViews.contains(id)) {
+                        fillableIds = ArrayUtils.add(fillableIds, id);
+                    }
+                }
+            }
+        }
+
         try {
-            mClient.setTrackedViews(id, trackedViews, saveOnAllViewsInvisible);
+            if (sVerbose) {
+                Slog.v(TAG, "updateTrackedIdsLocked(): " + trackedViews + " => " + fillableIds);
+            }
+            mClient.setTrackedViews(id, toArray(trackedViews), saveOnAllViewsInvisible,
+                    toArray(fillableIds));
         } catch (RemoteException e) {
             Slog.w(TAG, "Cannot set tracked ids", e);
         }
@@ -1331,7 +1361,6 @@
             }
 
             // ...or handle authentication.
-            // TODO(b/37424539): proper implementation
             mService.setDatasetAuthenticationSelected(dataset.getId());
             setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false);
             final Intent fillInIntent = createAuthFillInIntent(
@@ -1424,21 +1453,36 @@
             }
             try {
                 if (sDebug) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
+
                 // Skip null values as a null values means no change
                 final int entryCount = dataset.getFieldIds().size();
                 final List<AutofillId> ids = new ArrayList<>(entryCount);
                 final List<AutofillValue> values = new ArrayList<>(entryCount);
+                boolean waitingDatasetAuth = false;
                 for (int i = 0; i < entryCount; i++) {
                     if (dataset.getFieldValues().get(i) == null) {
                         continue;
                     }
-                    ids.add(dataset.getFieldIds().get(i));
+                    final AutofillId viewId = dataset.getFieldIds().get(i);
+                    ids.add(viewId);
                     values.add(dataset.getFieldValues().get(i));
+                    final ViewState viewState = mViewStates.get(viewId);
+                    if (viewState != null
+                            && (viewState.getState() & ViewState.STATE_WAITING_DATASET_AUTH) != 0) {
+                        if (sVerbose) {
+                            Slog.v(TAG, "autofillApp(): view " + viewId + " waiting auth");
+                        }
+                        waitingDatasetAuth = true;
+                        viewState.resetState(ViewState.STATE_WAITING_DATASET_AUTH);
+                    }
                 }
                 if (!ids.isEmpty()) {
+                    if (waitingDatasetAuth) {
+                        hideFillUiIfOwnedByMe();
+                    }
                     mClient.autofill(id, ids, values);
+                    setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED, false);
                 }
-                setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED, false);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Error autofilling activity: " + e);
             }
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index f87fa19..8a52c96 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -174,7 +174,7 @@
      * fill UI is ready to be displayed (i.e. when response and bounds are set).
      */
     void maybeCallOnFillReady() {
-        if ((mState & (STATE_AUTOFILLED | STATE_WAITING_DATASET_AUTH)) != 0) {
+        if ((mState & STATE_AUTOFILLED) != 0) {
             if (sDebug) Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString());
             return;
         }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index b65f54e..61057dd 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1697,7 +1697,7 @@
                     mHandler.removeMessages(MESSAGE_USER_SWITCHED);
 
                     /* disable and enable BT when detect a user switch */
-                    if (mEnable && mBluetooth != null) {
+                    if (mBluetooth != null && isEnabled()) {
                         try {
                             mBluetoothLock.readLock().lock();
                             if (mBluetooth != null) {
@@ -1766,6 +1766,8 @@
                         mState = BluetoothAdapter.STATE_OFF;
                         // enable
                         addActiveLog(REASON_USER_SWITCH, true);
+                        // mEnable flag could have been reset on disableBLE. Reenable it.
+                        mEnable = true;
                         handleEnable(mQuietEnable);
                     } else if (mBinding || mBluetooth != null) {
                         Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 7ae4138..4b12bc4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -175,6 +175,9 @@
         implements PendingIntent.OnFinished {
     private static final String TAG = ConnectivityService.class.getSimpleName();
 
+    public static final String DIAG_ARG = "--diag";
+    public static final String SHORT_ARG = "--short";
+
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
@@ -1852,7 +1855,7 @@
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
-        if (argsContain(args, "--diag")) {
+        if (argsContain(args, DIAG_ARG)) {
             dumpNetworkDiagnostics(pw);
             return;
         }
@@ -1938,7 +1941,7 @@
             pw.decreaseIndent();
         }
 
-        if (argsContain(args, "--short") == false) {
+        if (argsContain(args, SHORT_ARG) == false) {
             pw.println();
             synchronized (mValidationLogs) {
                 pw.println("mValidationLogs (most recent first):");
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index f7a682a..773a1ee 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -161,7 +161,7 @@
      */
     private static final int[] SYSTEM_CREDENTIAL_UIDS = {
             Process.WIFI_UID, Process.VPN_UID,
-            Process.ROOT_UID };
+            Process.ROOT_UID, Process.SYSTEM_UID };
 
     // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
     // devices. The most basic of these is to show/hide notifications about missing features until
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index a94bf79..45f9025 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -16,12 +16,15 @@
 
 package com.android.server;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
@@ -33,6 +36,7 @@
 import android.system.Os;
 import android.system.OsConstants;
 import android.system.StructStat;
+import android.util.ArraySet;
 import android.util.Slog;
 
 import com.android.internal.app.ResolverActivity;
@@ -68,6 +72,19 @@
 
     private PinnerHandler mPinnerHandler = null;
 
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+          // If this user's camera app has been updated, update pinned files accordingly.
+          if (intent.getAction() == Intent.ACTION_PACKAGE_REPLACED) {
+                Uri packageUri = intent.getData();
+                String packageName = packageUri.getSchemeSpecificPart();
+                ArraySet<String> updatedPackages = new ArraySet<>();
+                updatedPackages.add(packageName);
+                update(updatedPackages);
+            }
+        }
+    };
 
     public PinnerService(Context context) {
         super(context);
@@ -76,6 +93,11 @@
         mShouldPinCamera = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_pinnerCameraApp);
         mPinnerHandler = new PinnerHandler(BackgroundThread.get().getLooper());
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+        filter.addDataScheme("package");
+        mContext.registerReceiver(mBroadcastReceiver, filter);
     }
 
     @Override
@@ -85,6 +107,7 @@
         }
         mBinderService = new BinderService();
         publishBinderService("pinner", mBinderService);
+        publishLocalService(PinnerService.class, this);
 
         mPinnerHandler.obtainMessage(PinnerHandler.PIN_ONSTART_MSG).sendToTarget();
         mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0)
@@ -103,6 +126,20 @@
     }
 
     /**
+     * Update the currently pinned files.
+     * Specifically, this only updates camera pinning.
+     * The other files pinned in onStart will not need to be updated.
+     */
+    public void update(ArraySet<String> updatedPackages) {
+        ApplicationInfo cameraInfo = getCameraInfo(UserHandle.USER_SYSTEM);
+        if (cameraInfo != null && updatedPackages.contains(cameraInfo.packageName)) {
+            Slog.i(TAG, "Updating pinned files.");
+            mPinnerHandler.obtainMessage(PinnerHandler.PIN_CAMERA_MSG, UserHandle.USER_SYSTEM, 0)
+                    .sendToTarget();
+        }
+    }
+
+    /**
      * Handler for on start pinning message
      */
     private void handlePinOnStart() {
@@ -202,13 +239,10 @@
         return cameraResolveInfo.activityInfo.applicationInfo;
     }
 
+    /**
+     * If the camera app is already pinned, unpin and repin it.
+     */
     private boolean pinCamera(int userHandle){
-        //we may have already pinned a camera app.  If we've pinned this
-        //camera app, we're done.  otherwise, unpin and pin the new app
-        if (alreadyPinned(userHandle)){
-            return true;
-        }
-
         ApplicationInfo cameraInfo = getCameraInfo(userHandle);
         if (cameraInfo == null) {
             return false;
@@ -244,20 +278,22 @@
 
         // get the path to the odex or oat file
         String baseCodePath = cameraInfo.getBaseCodePath();
-        String odex = null;
+        String[] files = null;
         try {
-            odex = DexFile.getDexFileOutputPath(baseCodePath, arch);
+            files = DexFile.getDexFileOutputPaths(baseCodePath, arch);
         } catch (IOException ioe) {}
-        if (odex == null) {
+        if (files == null) {
             return true;
         }
 
         //not pinning the oat/odex is not a fatal error
-        pf = pinFile(odex, 0, 0, MAX_CAMERA_PIN_SIZE);
-        if (pf != null) {
-            mPinnedCameraFiles.add(pf);
-            if (DEBUG) {
-                Slog.i(TAG, "Pinned " + pf.mFilename);
+        for (String file : files) {
+            pf = pinFile(file, 0, 0, MAX_CAMERA_PIN_SIZE);
+            if (pf != null) {
+                mPinnedCameraFiles.add(pf);
+                if (DEBUG) {
+                    Slog.i(TAG, "Pinned " + pf.mFilename);
+                }
             }
         }
 
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/services/core/java/com/android/server/SystemServiceManager.java
index 10b2609..72ff606 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/services/core/java/com/android/server/SystemServiceManager.java
@@ -164,6 +164,13 @@
         }
     }
 
+    /**
+     * @return true if system has completed the boot; false otherwise.
+     */
+    public boolean isBootCompleted() {
+        return mCurrentPhase >= SystemService.PHASE_BOOT_COMPLETED;
+    }
+
     public void startUser(final int userHandle) {
         Slog.i(TAG, "Calling onStartUser u" + userHandle);
         final int serviceLen = mServices.size();
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 678ae38..03e9dd2 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -221,12 +221,19 @@
 
         long[] clickEffectTimings = getLongIntArray(context.getResources(),
                 com.android.internal.R.array.config_virtualKeyVibePattern);
-        VibrationEffect clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1);
+        VibrationEffect clickEffect;
+        if (clickEffectTimings.length == 0) {
+            clickEffect = null;
+        } else if (clickEffectTimings.length == 1) {
+            clickEffect = VibrationEffect.createOneShot(
+                    clickEffectTimings[0], VibrationEffect.DEFAULT_AMPLITUDE);
+        } else {
+            clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1);
+        }
         VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
                 new long[] {0, 30, 100, 30} /*timings*/, -1);
 
         mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect };
-
     }
 
     public void systemReady() {
@@ -695,7 +702,7 @@
                 }
             }
             final int id = prebaked.getId();
-            if (id < 0 || id >= mFallbackEffects.length) {
+            if (id < 0 || id >= mFallbackEffects.length || mFallbackEffects[id] == null) {
                 Slog.w(TAG, "Failed to play prebaked effect, no fallback");
                 return 0;
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 5e03508..2680b425 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -780,7 +780,8 @@
                 smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
                 if (nextUpdateTime < Long.MAX_VALUE) {
                     Message msg = smap.obtainMessage();
-                    smap.sendMessageAtTime(msg, nextUpdateTime);
+                    smap.sendMessageAtTime(msg, nextUpdateTime
+                            + SystemClock.uptimeMillis() - SystemClock.elapsedRealtime());
                 }
             }
             if (!smap.mActiveForegroundAppsChanged) {
@@ -811,30 +812,35 @@
             Intent intent;
             String title;
             String msg;
+            String[] pkgs;
             if (active.size() == 1) {
                 intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                 intent.setData(Uri.fromParts("package", active.get(0).mPackageName, null));
                 title = context.getString(
                         R.string.foreground_service_app_in_background, active.get(0).mLabel);
                 msg = context.getString(R.string.foreground_service_tap_for_details);
+                pkgs = new String[] { active.get(0).mPackageName };
             } else {
                 intent = new Intent(Settings.ACTION_FOREGROUND_SERVICES_SETTINGS);
-                String[] pkgs = new String[active.size()];
+                pkgs = new String[active.size()];
                 for (int i = 0; i < active.size(); i++) {
                     pkgs[i] = active.get(i).mPackageName;
                 }
                 intent.putExtra("packages", pkgs);
                 title = context.getString(
                         R.string.foreground_service_apps_in_background, active.size());
-                msg =  active.get(0).mLabel.toString();
+                msg = active.get(0).mLabel.toString();
                 for (int i = 1; i < active.size(); i++) {
                     msg = context.getString(R.string.foreground_service_multiple_separator,
                             msg, active.get(i).mLabel);
                 }
             }
+            Bundle notificationBundle = new Bundle();
+            notificationBundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, pkgs);
             Notification.Builder n =
                     new Notification.Builder(context,
                             SystemNotificationChannels.FOREGROUND_SERVICE)
+                            .addExtras(notificationBundle)
                             .setSmallIcon(R.drawable.ic_check_circle_24px)
                             .setOngoing(true)
                             .setShowWhen(false)
@@ -854,10 +860,11 @@
         }
     }
 
-    private void requestUpdateActiveForegroundAppsLocked(ServiceMap smap, long time) {
+    private void requestUpdateActiveForegroundAppsLocked(ServiceMap smap, long timeElapsed) {
         Message msg = smap.obtainMessage(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
-        if (time != 0) {
-            smap.sendMessageAtTime(msg, time);
+        if (timeElapsed != 0) {
+            smap.sendMessageAtTime(msg,
+                    timeElapsed + SystemClock.uptimeMillis() - SystemClock.elapsedRealtime());
         } else {
             smap.mActiveForegroundAppsChanged = true;
             smap.sendMessage(msg);
@@ -909,6 +916,9 @@
                     if (changed) {
                         requestUpdateActiveForegroundAppsLocked(smap,
                                 nowElapsed + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME);
+                    } else if (smap.mActiveForegroundApps.size() > 0) {
+                        // Just being paranoid.
+                        requestUpdateActiveForegroundAppsLocked(smap, 0);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 54b28d1..bb6637d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4587,9 +4587,9 @@
     }
 
     @Override
-    public int startActivityIntentSender(IApplicationThread caller, IntentSender intent,
-            Intent fillInIntent, String resolvedType, IBinder resultTo, String resultWho,
-            int requestCode, int flagsMask, int flagsValues, Bundle bOptions)
+    public int startActivityIntentSender(IApplicationThread caller, IIntentSender target,
+            IBinder whitelistToken, Intent fillInIntent, String resolvedType, IBinder resultTo,
+            String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle bOptions)
             throws TransactionTooLargeException {
         enforceNotIsolatedCaller("startActivityIntentSender");
         // Refuse possible leaked file descriptors
@@ -4597,12 +4597,11 @@
             throw new IllegalArgumentException("File descriptors passed in Intent");
         }
 
-        IIntentSender sender = intent.getTarget();
-        if (!(sender instanceof PendingIntentRecord)) {
+        if (!(target instanceof PendingIntentRecord)) {
             throw new IllegalArgumentException("Bad PendingIntent object");
         }
 
-        PendingIntentRecord pir = (PendingIntentRecord)sender;
+        PendingIntentRecord pir = (PendingIntentRecord)target;
 
         synchronized (this) {
             // If this is coming from the currently resumed activity, it is
@@ -4613,7 +4612,7 @@
                 mAppSwitchesAllowedTime = 0;
             }
         }
-        int ret = pir.sendInner(0, fillInIntent, resolvedType, null, null, null,
+        int ret = pir.sendInner(0, fillInIntent, resolvedType, whitelistToken, null, null,
                 resultTo, resultWho, requestCode, flagsMask, flagsValues, bOptions, null);
         return ret;
     }
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 55ec3b0..5636e19 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -284,7 +284,6 @@
     boolean visible;        // does this activity's window need to be shown?
     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
                                      // might hide this activity?
-    private boolean mLastSetWindowVisibility; // The last window visibility state that was set.
     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
                                         // process that it is hidden.
     boolean sleeping;       // have we told the activity to sleep?
@@ -1589,10 +1588,6 @@
     }
 
     void setVisibility(boolean visible) {
-        if (mLastSetWindowVisibility == visible) {
-            return;
-        }
-        mLastSetWindowVisibility = visible;
         mWindowContainerController.setVisibility(visible, mDeferHidingClient);
         mStackSupervisor.mActivityMetricsLogger.notifyVisibilityChanged(this, visible);
     }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index c56e4ea..7df9b69 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1152,11 +1152,15 @@
 
     void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
         final String packageName = aInfo.packageName;
+        final int userId = UserHandle.getUserId(aInfo.uid);
+
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
-                if (packageName.equals(activities.get(activityNdx).packageName)) {
-                    activities.get(activityNdx).info.applicationInfo = aInfo;
+                final ActivityRecord ar = activities.get(activityNdx);
+
+                if ((userId == ar.userId) && packageName.equals(ar.packageName)) {
+                    ar.info.applicationInfo = aInfo;
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8210c07..79ea7ba 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2998,7 +2998,8 @@
 
         stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
                 true /* schedulePipModeChangedOnAnimationEnd */);
-        mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName);
+        mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName,
+                r.getTask().taskId);
     }
 
     /** Move activity with its stack to front and make the stack focused. */
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index a2eec5c..7ed07e0 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -533,11 +533,12 @@
                     auxiliaryResponse, originalIntent, resolvedType, callingPackage,
                     verificationBundle, userId);
         }
-        return InstantAppResolver.buildEphemeralInstallerIntent(originalIntent,
-            auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
-            resolvedType, userId, auxiliaryResponse.packageName,
-            auxiliaryResponse.splitName, auxiliaryResponse.versionCode,
-            auxiliaryResponse.token, auxiliaryResponse.needsPhaseTwo);
+        return InstantAppResolver.buildEphemeralInstallerIntent(
+                Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE, originalIntent,
+                auxiliaryResponse.failureIntent, callingPackage, verificationBundle,
+                resolvedType, userId, auxiliaryResponse.packageName, auxiliaryResponse.splitName,
+                auxiliaryResponse.versionCode, auxiliaryResponse.token,
+                auxiliaryResponse.needsPhaseTwo);
     }
 
     void postStartActivityProcessing(
@@ -956,7 +957,7 @@
             // If we are not able to proceed, disassociate the activity from the task. Leaving an
             // activity in an incomplete state can lead to issues, such as performing operations
             // without a window container.
-            if (ActivityManager.isStartResultFatalError(result)
+            if (!ActivityManager.isStartResultSuccessful(result)
                     && mStartActivity.getTask() != null) {
                 mStartActivity.getTask().removeActivity(mStartActivity);
             }
@@ -1050,6 +1051,15 @@
 
             reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
 
+            final ActivityRecord outResult =
+                    outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
+
+            // When there is a reused activity and the current result is a trampoline activity,
+            // set the reused activity as the result.
+            if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
+                outActivity[0] = reusedActivity;
+            }
+
             if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
                 // We don't need to start a new activity, and the client said not to do anything
                 // if that is the case, so this is it!  And for paranoia, make sure we have
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 11fc40b..2439062 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -16,6 +16,8 @@
 
 package com.android.server.am;
 
+import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
+
 import android.annotation.Nullable;
 import android.bluetooth.BluetoothActivityEnergyInfo;
 import android.bluetooth.BluetoothAdapter;
@@ -1549,7 +1551,9 @@
                         BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS,
                         reason, 0);
 
-                mStats.updateCpuTimeLocked();
+                if ((updateFlags & UPDATE_CPU) != 0) {
+                    mStats.updateCpuTimeLocked(true /* updateCpuFreqData */);
+                }
                 mStats.updateKernelWakelocksLocked();
                 mStats.updateKernelMemoryBandwidthLocked();
 
diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
index f5d7b68..ea9ff59 100644
--- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java
@@ -96,7 +96,7 @@
     };
 
     private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> {
-        l.onActivityPinned((String) m.obj);
+        l.onActivityPinned((String) m.obj, m.arg1);
     };
 
     private final TaskStackConsumer mNotifyActivityUnpinned = (l, m) -> {
@@ -279,10 +279,10 @@
     }
 
     /** Notifies all listeners when an Activity is pinned. */
-    void notifyActivityPinned(String packageName) {
+    void notifyActivityPinned(String packageName, int taskId) {
         mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
         final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG,
-                packageName);
+                taskId, 0, packageName);
         forAllLocalListeners(mNotifyActivityPinned, msg);
         msg.sendToTarget();
     }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e9555f7..e5c3106 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3931,7 +3931,7 @@
 
     public int setBluetoothA2dpDeviceConnectionState(BluetoothDevice device, int state, int profile)
     {
-        if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE)) {
+        if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, device)) {
             return 0;
         }
         return setBluetoothA2dpDeviceConnectionStateInt(
@@ -5070,7 +5070,7 @@
 
     private void onSetA2dpSinkConnectionState(BluetoothDevice btDevice, int state)
     {
-        if (DEBUG_VOL) {
+        if (DEBUG_DEVICES) {
             Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice+"state=" + state);
         }
         if (btDevice == null) {
@@ -5173,7 +5173,7 @@
 
         int device = AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
         synchronized (mConnectedDevices) {
-            if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE)) {
+            if (mAudioHandler.hasMessages(MSG_SET_A2DP_SINK_CONNECTION_STATE, btDevice)) {
                 return;
             }
             final String key = makeDeviceListKey(device, address);
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index dcd58e7..702cbbe 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -67,6 +67,10 @@
                     .createIfNeeded()
                     .build();
 
+    // like a PLAY_CREATE_IF_NEEDED operation but with a skip to the end of the ramp
+    private static final VolumeShaper.Operation PLAY_SKIP_RAMP =
+            new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build();
+
     private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>();
     // a public client is one that needs an anonymized version of the playback configurations, we
     // keep track of whether there is at least one to know when we need to create the list of
@@ -487,17 +491,19 @@
     private static final class DuckingManager {
         private final HashMap<Integer, DuckedApp> mDuckers = new HashMap<Integer, DuckedApp>();
 
-        void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) {
+        synchronized void duckUid(int uid, ArrayList<AudioPlaybackConfiguration> apcsToDuck) {
+            if (DEBUG) {  Log.v(TAG, "DuckingManager: duckUid() uid:"+ uid); }
             if (!mDuckers.containsKey(uid)) {
                 mDuckers.put(uid, new DuckedApp(uid));
             }
             final DuckedApp da = mDuckers.get(uid);
             for (AudioPlaybackConfiguration apc : apcsToDuck) {
-                da.addDuck(apc);
+                da.addDuck(apc, false /*skipRamp*/);
             }
         }
 
-        void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) {
+        synchronized void unduckUid(int uid, HashMap<Integer, AudioPlaybackConfiguration> players) {
+            if (DEBUG) {  Log.v(TAG, "DuckingManager: unduckUid() uid:"+ uid); }
             final DuckedApp da = mDuckers.remove(uid);
             if (da == null) {
                 return;
@@ -506,25 +512,27 @@
         }
 
         // pre-condition: apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
-        void checkDuck(@NonNull AudioPlaybackConfiguration apc) {
+        synchronized void checkDuck(@NonNull AudioPlaybackConfiguration apc) {
+            if (DEBUG) {  Log.v(TAG, "DuckingManager: checkDuck() player piid:"
+                    + apc.getPlayerInterfaceId()+ " uid:"+ apc.getClientUid()); }
             final DuckedApp da = mDuckers.get(apc.getClientUid());
             if (da == null) {
                 return;
             }
-            // FIXME here the player needs to be put in a state that is the same as if it
-            //   had been ducked as it starts. At the moment, this works already for linked
-            //   players, as is the case in gapless playback.
-            da.addDuck(apc);
+            da.addDuck(apc, true /*skipRamp*/);
         }
 
-        void dump(PrintWriter pw) {
+        synchronized void dump(PrintWriter pw) {
             for (DuckedApp da : mDuckers.values()) {
                 da.dump(pw);
             }
         }
 
-        void removeReleased(@NonNull AudioPlaybackConfiguration apc) {
-            final DuckedApp da = mDuckers.get(apc.getClientUid());
+        synchronized void removeReleased(@NonNull AudioPlaybackConfiguration apc) {
+            final int uid = apc.getClientUid();
+            if (DEBUG) {  Log.v(TAG, "DuckingManager: removedReleased() player piid: "
+                    + apc.getPlayerInterfaceId() + " uid:" + uid); }
+            final DuckedApp da = mDuckers.get(uid);
             if (da == null) {
                 return;
             }
@@ -550,20 +558,21 @@
             // pre-conditions:
             //  * apc != null
             //  * apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED
-            void addDuck(@NonNull AudioPlaybackConfiguration apc) {
+            void addDuck(@NonNull AudioPlaybackConfiguration apc, boolean skipRamp) {
                 final int piid = new Integer(apc.getPlayerInterfaceId());
                 if (mDuckedPlayers.contains(piid)) {
-                    if (DEBUG) { Log.v(TAG, "player " + piid + " already ducked"); }
+                    if (DEBUG) { Log.v(TAG, "player piid:" + piid + " already ducked"); }
                     return;
                 }
                 try {
-                    Log.v(TAG, "ducking player " + apc.getPlayerInterfaceId() + " uid:" + mUid);
+                    Log.v(TAG, "ducking (skipRamp=" + skipRamp + ") player piid:"
+                            + apc.getPlayerInterfaceId() + " uid:" + mUid);
                     apc.getPlayerProxy().applyVolumeShaper(
                             DUCK_VSHAPE,
-                            PLAY_CREATE_IF_NEEDED);
+                            skipRamp ? PLAY_SKIP_RAMP : PLAY_CREATE_IF_NEEDED);
                     mDuckedPlayers.add(piid);
                 } catch (Exception e) {
-                    Log.e(TAG, "Error ducking player " + piid + " uid:" + mUid, e);
+                    Log.e(TAG, "Error ducking player piid:" + piid + " uid:" + mUid, e);
                 }
             }
 
@@ -577,13 +586,13 @@
                                     DUCK_ID,
                                     VolumeShaper.Operation.REVERSE);
                         } catch (Exception e) {
-                            Log.e(TAG, "Error unducking player " + piid + " uid:" + mUid, e);
+                            Log.e(TAG, "Error unducking player piid:" + piid + " uid:" + mUid, e);
                         }
                     } else {
                         // this piid was in the list of ducked players, but wasn't found
                         if (DEBUG) {
-                            Log.v(TAG, "Error unducking player " + piid + ", player not found for"
-                                    + " uid " + mUid);
+                            Log.v(TAG, "Error unducking player piid:" + piid
+                                    + ", player not found for uid " + mUid);
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 96f6f2d..11296ab 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -960,14 +960,18 @@
                 return result;
             }
         }
-        // Otherwise wait until https probe completes and use its result.
+        // Otherwise wait until http and https probes completes and use their results.
         try {
+            httpProbe.join();
+            if (httpProbe.result().isPortal()) {
+                return httpProbe.result();
+            }
             httpsProbe.join();
+            return httpsProbe.result();
         } catch (InterruptedException e) {
-            validationLog("Error: https probe wait interrupted!");
+            validationLog("Error: http or https probe wait interrupted!");
             return CaptivePortalProbeResult.FAILED;
         }
-        return httpsProbe.result();
     }
 
     private URL makeURL(String url) {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 81a1458..901092e 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -20,6 +20,7 @@
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static com.android.server.ConnectivityService.SHORT_ARG;
 
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -47,6 +48,7 @@
 import android.net.NetworkState;
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
+import android.net.util.SharedLog;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Bundle;
@@ -62,7 +64,6 @@
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
-import android.util.LocalLog;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -147,9 +148,7 @@
         }
     }
 
-    private final static int MAX_LOG_RECORDS = 500;
-
-    private final LocalLog mLocalLog = new LocalLog(MAX_LOG_RECORDS);
+    private final SharedLog mLog = new SharedLog(TAG);
 
     // used to synchronize public access to members
     private final Object mPublicSync;
@@ -180,7 +179,7 @@
     public Tethering(Context context, INetworkManagementService nmService,
             INetworkStatsService statsService, INetworkPolicyManager policyManager,
             Looper looper, MockableSystemProperties systemProperties) {
-        mLocalLog.log("CONSTRUCTED");
+        mLog.mark("constructed");
         mContext = context;
         mNMService = nmService;
         mStatsService = statsService;
@@ -195,9 +194,9 @@
         mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
         mTetherMasterSM.start();
 
-        mOffloadController = new OffloadController(mTetherMasterSM.getHandler());
+        mOffloadController = new OffloadController(mTetherMasterSM.getHandler(), mLog);
         mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
-                mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK);
+                mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK, mLog);
         mForwardedDownstreams = new HashSet<>();
 
         mStateReceiver = new StateReceiver();
@@ -1094,7 +1093,7 @@
             addState(mSetDnsForwardersErrorState);
 
             mNotifyList = new ArrayList<>();
-            mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList);
+            mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList, mLog);
             setInitialState(mInitialState);
         }
 
@@ -1141,7 +1140,7 @@
                 try {
                     mNMService.setIpForwardingEnabled(true);
                 } catch (Exception e) {
-                    mLocalLog.log("ERROR " + e);
+                    mLog.e(e);
                     transitionTo(mSetIpForwardingEnabledErrorState);
                     return false;
                 }
@@ -1154,12 +1153,12 @@
                         mNMService.stopTethering();
                         mNMService.startTethering(cfg.dhcpRanges);
                     } catch (Exception ee) {
-                        mLocalLog.log("ERROR " + ee);
+                        mLog.e(ee);
                         transitionTo(mStartTetheringErrorState);
                         return false;
                     }
                 }
-                mLocalLog.log("SET master tether settings: ON");
+                mLog.log("SET master tether settings: ON");
                 return true;
             }
 
@@ -1167,19 +1166,19 @@
                 try {
                     mNMService.stopTethering();
                 } catch (Exception e) {
-                    mLocalLog.log("ERROR " + e);
+                    mLog.e(e);
                     transitionTo(mStopTetheringErrorState);
                     return false;
                 }
                 try {
                     mNMService.setIpForwardingEnabled(false);
                 } catch (Exception e) {
-                    mLocalLog.log("ERROR " + e);
+                    mLog.e(e);
                     transitionTo(mSetIpForwardingDisabledErrorState);
                     return false;
                 }
                 transitionTo(mInitialState);
-                mLocalLog.log("SET master tether settings: OFF");
+                mLog.log("SET master tether settings: OFF");
                 return true;
             }
 
@@ -1305,13 +1304,13 @@
                 }
                 try {
                     mNMService.setDnsForwarders(network, dnsServers);
-                    mLocalLog.log(String.format(
-                            "SET DNS forwarders: network=%s dnsServers=[%s]",
+                    mLog.log(String.format(
+                            "SET DNS forwarders: network=%s dnsServers=%s",
                             network, Arrays.toString(dnsServers)));
                 } catch (Exception e) {
                     // TODO: Investigate how this can fail and what exactly
                     // happens if/when such failures occur.
-                    mLocalLog.log("ERROR setting DNS forwarders failed, " + e);
+                    mLog.e("setting DNS forwarders failed, " + e);
                     transitionTo(mSetDnsForwardersErrorState);
                 }
             }
@@ -1788,12 +1787,23 @@
 
         pw.println("Log:");
         pw.increaseIndent();
-        mLocalLog.readOnlyLocalLog().dump(fd, pw, args);
+        if (argsContain(args, SHORT_ARG)) {
+            pw.println("<log removed for brevity>");
+        } else {
+            mLog.dump(fd, pw, args);
+        }
         pw.decreaseIndent();
 
         pw.decreaseIndent();
     }
 
+    private static boolean argsContain(String[] args, String target) {
+        for (String arg : args) {
+            if (arg.equals(target)) return true;
+        }
+        return false;
+    }
+
     @Override
     public void notifyInterfaceStateChange(String iface, TetherInterfaceStateMachine who,
                                            int state, int error) {
@@ -1807,8 +1817,7 @@
             }
         }
 
-        mLocalLog.log(String.format("OBSERVED iface=%s state=%s error=%s",
-                iface, state, error));
+        mLog.log(String.format("OBSERVED iface=%s state=%s error=%s", iface, state, error));
 
         try {
             // Notify that we're tethering (or not) this interface.
@@ -1846,8 +1855,8 @@
     private void trackNewTetherableInterface(String iface, int interfaceType) {
         TetherState tetherState;
         tetherState = new TetherState(new TetherInterfaceStateMachine(iface, mLooper,
-                interfaceType, mNMService, mStatsService, this,
-                new IPv6TetheringInterfaceServices(iface, mNMService)));
+                interfaceType, mLog, mNMService, mStatsService, this,
+                new IPv6TetheringInterfaceServices(iface, mNMService, mLog)));
         mTetherStates.put(iface, tetherState);
         tetherState.stateMachine.start();
     }
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
index 2485654..518f6c1 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringCoordinator.java
@@ -25,6 +25,7 @@
 import android.net.NetworkState;
 import android.net.RouteInfo;
 import android.net.util.NetworkConstants;
+import android.net.util.SharedLog;
 import android.util.Log;
 
 import java.net.Inet6Address;
@@ -64,6 +65,7 @@
     }
 
     private final ArrayList<TetherInterfaceStateMachine> mNotifyList;
+    private final SharedLog mLog;
     // NOTE: mActiveDownstreams is a list and not a hash data structure because
     // we keep active downstreams in arrival order.  This is done so /64s can
     // be parceled out on a "first come, first served" basis and a /64 used by
@@ -74,8 +76,10 @@
     private short mNextSubnetId;
     private NetworkState mUpstreamNetworkState;
 
-    public IPv6TetheringCoordinator(ArrayList<TetherInterfaceStateMachine> notifyList) {
+    public IPv6TetheringCoordinator(ArrayList<TetherInterfaceStateMachine> notifyList,
+                                    SharedLog log) {
         mNotifyList = notifyList;
+        mLog = log.forSubComponent(TAG);
         mActiveDownstreams = new LinkedList<>();
         mUniqueLocalPrefix = generateUniqueLocalPrefix();
         mNextSubnetId = 0;
@@ -115,7 +119,7 @@
         if (VDBG) {
             Log.d(TAG, "updateUpstreamNetworkState: " + toDebugString(ns));
         }
-        if (!canTetherIPv6(ns)) {
+        if (!canTetherIPv6(ns, mLog)) {
             stopIPv6TetheringOnAllInterfaces();
             setUpstreamNetworkState(null);
             return;
@@ -150,9 +154,7 @@
                     null);
         }
 
-        if (DBG) {
-            Log.d(TAG, "setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
-        }
+        mLog.log("setUpstreamNetworkState: " + toDebugString(mUpstreamNetworkState));
     }
 
     private void updateIPv6TetheringInterfaces() {
@@ -206,7 +208,7 @@
         return null;
     }
 
-    private static boolean canTetherIPv6(NetworkState ns) {
+    private static boolean canTetherIPv6(NetworkState ns, SharedLog sharedLog) {
         // Broadly speaking:
         //
         //     [1] does the upstream have an IPv6 default route?
@@ -260,13 +262,11 @@
 
         final boolean outcome = canTether && supportedConfiguration;
 
-        if (VDBG) {
-            if (ns == null) {
-                Log.d(TAG, "No available upstream.");
-            } else {
-                Log.d(TAG, String.format("IPv6 tethering is %s for upstream: %s",
-                        (outcome ? "available" : "not available"), toDebugString(ns)));
-            }
+        if (ns == null) {
+            sharedLog.log("No available upstream.");
+        } else {
+            sharedLog.log(String.format("IPv6 tethering is %s for upstream: %s",
+                    (outcome ? "available" : "not available"), toDebugString(ns)));
         }
 
         return outcome;
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
index c6a7925..adf4af8 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
@@ -28,10 +28,10 @@
 import android.net.ip.RouterAdvertisementDaemon;
 import android.net.ip.RouterAdvertisementDaemon.RaParams;
 import android.net.util.NetdService;
+import android.net.util.SharedLog;
 import android.os.INetworkManagementService;
 import android.os.ServiceSpecificException;
 import android.os.RemoteException;
-import android.util.Log;
 import android.util.Slog;
 
 import java.net.Inet6Address;
@@ -54,6 +54,7 @@
 
     private final String mIfName;
     private final INetworkManagementService mNMService;
+    private final SharedLog mLog;
 
     private NetworkInterface mNetworkInterface;
     private byte[] mHwAddr;
@@ -61,9 +62,11 @@
     private RouterAdvertisementDaemon mRaDaemon;
     private RaParams mLastRaParams;
 
-    public IPv6TetheringInterfaceServices(String ifname, INetworkManagementService nms) {
+    public IPv6TetheringInterfaceServices(
+            String ifname, INetworkManagementService nms, SharedLog log) {
         mIfName = ifname;
         mNMService = nms;
+        mLog = log.forSubComponent(mIfName);
     }
 
     public boolean start() {
@@ -72,12 +75,12 @@
         try {
             mNetworkInterface = NetworkInterface.getByName(mIfName);
         } catch (SocketException e) {
-            Log.e(TAG, "Error looking up NetworkInterfaces for " + mIfName, e);
+            mLog.e("Error looking up NetworkInterfaces: " + e);
             stop();
             return false;
         }
         if (mNetworkInterface == null) {
-            Log.e(TAG, "Failed to find NetworkInterface for " + mIfName);
+            mLog.e("Failed to find NetworkInterface");
             stop();
             return false;
         }
@@ -85,7 +88,7 @@
         try {
             mHwAddr = mNetworkInterface.getHardwareAddress();
         } catch (SocketException e) {
-            Log.e(TAG, "Failed to find hardware address for " + mIfName, e);
+            mLog.e("Failed to find hardware address: " + e);
             stop();
             return false;
         }
@@ -161,11 +164,11 @@
             try {
                 final int removalFailures = mNMService.removeRoutesFromLocalNetwork(toBeRemoved);
                 if (removalFailures > 0) {
-                    Log.e(TAG, String.format("Failed to remove %d IPv6 routes from local table.",
+                    mLog.e(String.format("Failed to remove %d IPv6 routes from local table.",
                             removalFailures));
                 }
             } catch (RemoteException e) {
-                Log.e(TAG, "Failed to remove IPv6 routes from local table: ", e);
+                mLog.e("Failed to remove IPv6 routes from local table: " + e);
             }
         }
 
@@ -195,7 +198,7 @@
                     // error (EEXIST is silently ignored).
                     mNMService.addInterfaceToLocalNetwork(mIfName, toBeAdded);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to add IPv6 routes to local table: ", e);
+                    mLog.e("Failed to add IPv6 routes to local table: " + e);
                 }
             }
         }
@@ -206,7 +209,7 @@
         final INetd netd = NetdService.getInstance();
         if (netd == null) {
             if (newDnses != null) newDnses.clear();
-            Log.e(TAG, "No netd service instance available; not setting local IPv6 addresses");
+            mLog.e("No netd service instance available; not setting local IPv6 addresses");
             return;
         }
 
@@ -217,7 +220,7 @@
                 try {
                     netd.interfaceDelAddress(mIfName, dnsString, RFC7421_PREFIX_LENGTH);
                 } catch (ServiceSpecificException | RemoteException e) {
-                    Log.e(TAG, "Failed to remove local dns IP: " + dnsString, e);
+                    mLog.e("Failed to remove local dns IP " + dnsString + ": " + e);
                 }
             }
         }
@@ -234,7 +237,7 @@
                 try {
                     netd.interfaceAddAddress(mIfName, dnsString, RFC7421_PREFIX_LENGTH);
                 } catch (ServiceSpecificException | RemoteException e) {
-                    Log.e(TAG, "Failed to add local dns IP: " + dnsString, e);
+                    mLog.e("Failed to add local dns IP " + dnsString + ": " + e);
                     newDnses.remove(dns);
                 }
             }
@@ -243,7 +246,7 @@
         try {
             netd.tetherApplyDnsInterfaces();
         } catch (ServiceSpecificException | RemoteException e) {
-            Log.e(TAG, "Failed to update local DNS caching server");
+            mLog.e("Failed to update local DNS caching server");
             if (newDnses != null) newDnses.clear();
         }
     }
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index 220e751..8f21d99 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -18,7 +18,7 @@
 
 import android.net.LinkProperties;
 import android.os.Handler;
-import android.util.Log;
+import android.net.util.SharedLog;
 
 /**
  * A wrapper around hardware offload interface.
@@ -29,16 +29,18 @@
     private static final String TAG = OffloadController.class.getSimpleName();
 
     private final Handler mHandler;
+    private final SharedLog mLog;
     private LinkProperties mUpstreamLinkProperties;
 
-    public OffloadController(Handler h) {
+    public OffloadController(Handler h, SharedLog log) {
         mHandler = h;
+        mLog = log.forSubComponent(TAG);
     }
 
     public void start() {
         // TODO: initOffload() and configure callbacks to be handled on our
         // preferred Handler.
-        Log.d(TAG, "tethering offload not supported");
+        mLog.i("tethering offload not supported");
     }
 
     public void stop() {
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
index d3cfd87..4a1d405 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
@@ -22,6 +22,7 @@
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkUtils;
+import android.net.util.SharedLog;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
@@ -82,6 +83,7 @@
     private final State mTetheredState;
     private final State mUnavailableState;
 
+    private final SharedLog mLog;
     private final INetworkManagementService mNMService;
     private final INetworkStatsService mStatsService;
     private final IControlsTethering mTetherController;
@@ -93,10 +95,12 @@
     private int mLastError;
     private String mMyUpstreamIfaceName;  // may change over time
 
-    public TetherInterfaceStateMachine(String ifaceName, Looper looper, int interfaceType,
-                    INetworkManagementService nMService, INetworkStatsService statsService,
-                    IControlsTethering tetherController, IPv6TetheringInterfaceServices ipv6Svc) {
+    public TetherInterfaceStateMachine(
+            String ifaceName, Looper looper, int interfaceType, SharedLog log,
+            INetworkManagementService nMService, INetworkStatsService statsService,
+            IControlsTethering tetherController, IPv6TetheringInterfaceServices ipv6Svc) {
         super(ifaceName, looper);
+        mLog = log.forSubComponent(ifaceName);
         mNMService = nMService;
         mStatsService = statsService;
         mTetherController = tetherController;
@@ -162,7 +166,7 @@
                 mNMService.setInterfaceConfig(mIfaceName, ifcg);
             }
         } catch (Exception e) {
-            Log.e(TAG, "Error configuring interface " + mIfaceName, e);
+            mLog.e("Error configuring interface " + e);
             return false;
         }
 
@@ -203,7 +207,7 @@
                             transitionTo(mTetheredState);
                             break;
                         default:
-                            Log.e(TAG, "Invalid tethering interface serving state specified.");
+                            mLog.e("Invalid tethering interface serving state specified.");
                     }
                     break;
                 case CMD_INTERFACE_DOWN:
@@ -232,13 +236,13 @@
             try {
                 mNMService.tetherInterface(mIfaceName);
             } catch (Exception e) {
-                Log.e(TAG, "Error Tethering: " + e.toString());
+                mLog.e("Error Tethering: " + e);
                 mLastError = ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
                 return;
             }
 
             if (!mIPv6TetherSvc.start()) {
-                Log.e(TAG, "Failed to start IPv6TetheringInterfaceServices");
+                mLog.e("Failed to start IPv6TetheringInterfaceServices");
                 // TODO: Make this a fatal error once Bluetooth IPv6 is sorted.
                 return;
             }
@@ -255,7 +259,7 @@
                 mNMService.untetherInterface(mIfaceName);
             } catch (Exception e) {
                 mLastError = ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
-                Log.e(TAG, "Failed to untether interface: " + e.toString());
+                mLog.e("Failed to untether interface: " + e);
             }
 
             configureIfaceIp(false);
@@ -316,7 +320,7 @@
             maybeLogMessage(this, message.what);
             switch (message.what) {
                 case CMD_TETHER_REQUESTED:
-                    Log.e(TAG, "CMD_TETHER_REQUESTED while in local hotspot mode.");
+                    mLog.e("CMD_TETHER_REQUESTED while in local-only hotspot mode.");
                     break;
                 case CMD_TETHER_CONNECTION_CHANGED:
                     // Ignored in local hotspot state.
@@ -389,7 +393,7 @@
             boolean retValue = true;
             switch (message.what) {
                 case CMD_TETHER_REQUESTED:
-                    Log.e(TAG, "CMD_TETHER_REQUESTED while already tethering.");
+                    mLog.e("CMD_TETHER_REQUESTED while already tethering.");
                     break;
                 case CMD_TETHER_CONNECTION_CHANGED:
                     String newUpstreamIfaceName = (String)(message.obj);
@@ -406,7 +410,7 @@
                             mNMService.startInterfaceForwarding(mIfaceName,
                                     newUpstreamIfaceName);
                         } catch (Exception e) {
-                            Log.e(TAG, "Exception enabling Nat: " + e.toString());
+                            mLog.e("Exception enabling NAT: " + e);
                             cleanupUpstreamInterface(newUpstreamIfaceName);
                             mLastError = ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
                             transitionTo(mInitialState);
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 44c61f0..6941193 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -163,20 +163,31 @@
         }
 
         // Fix up upstream interface types for DUN or mobile. NOTE: independent
-        // of the value of |requiresDun|, cell data of one form or another is
+        // of the value of |dunCheck|, cell data of one form or another is
         // *always* an upstream, regardless of the upstream interface types
         // specified by configuration resources.
         if (dunCheck == DUN_REQUIRED) {
             if (!upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)) {
                 upstreamIfaceTypes.add(TYPE_MOBILE_DUN);
             }
-        } else {
+        } else if (dunCheck == DUN_NOT_REQUIRED) {
             if (!upstreamIfaceTypes.contains(TYPE_MOBILE)) {
                 upstreamIfaceTypes.add(TYPE_MOBILE);
             }
             if (!upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI)) {
                 upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
             }
+        } else {
+            // Fix upstream interface types for case DUN_UNSPECIFIED.
+            // Do not modify if a cellular interface type is already present in the
+            // upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no
+            // cellular interface types are found in the upstream interface types.
+            if (!(upstreamIfaceTypes.contains(TYPE_MOBILE_DUN)
+                    || upstreamIfaceTypes.contains(TYPE_MOBILE)
+                    || upstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI))) {
+                upstreamIfaceTypes.add(TYPE_MOBILE);
+                upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI);
+            }
         }
 
         return upstreamIfaceTypes;
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 97a2d5e..be71490 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -29,6 +29,7 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.NetworkState;
+import android.net.util.SharedLog;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -73,6 +74,7 @@
     private static final int CALLBACK_MOBILE_REQUEST = 3;
 
     private final Context mContext;
+    private final SharedLog mLog;
     private final StateMachine mTarget;
     private final Handler mHandler;
     private final int mWhat;
@@ -84,16 +86,18 @@
     private boolean mDunRequired;
     private Network mCurrentDefault;
 
-    public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what) {
+    public UpstreamNetworkMonitor(Context ctx, StateMachine tgt, int what, SharedLog log) {
         mContext = ctx;
         mTarget = tgt;
         mHandler = mTarget.getHandler();
         mWhat = what;
+        mLog = log.forSubComponent(TAG);
     }
 
     @VisibleForTesting
-    public UpstreamNetworkMonitor(StateMachine tgt, int what, ConnectivityManager cm) {
-        this(null, tgt, what);
+    public UpstreamNetworkMonitor(
+            StateMachine tgt, int what, ConnectivityManager cm, SharedLog log) {
+        this(null, tgt, what, log);
         mCM = cm;
     }
 
@@ -136,7 +140,7 @@
 
     public void registerMobileNetworkRequest() {
         if (mMobileNetworkCallback != null) {
-            Log.e(TAG, "registerMobileNetworkRequest() already registered");
+            mLog.e("registerMobileNetworkRequest() already registered");
             return;
         }
 
@@ -156,7 +160,7 @@
         // TODO: Change the timeout from 0 (no onUnavailable callback) to some
         // moderate callback timeout. This might be useful for updating some UI.
         // Additionally, we log a message to aid in any subsequent debugging.
-        Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
+        mLog.i("requesting mobile upstream network: " + mobileUpstreamRequest);
 
         cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler);
     }
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 069ae73..f804fa1 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -18,6 +18,7 @@
 
 import android.accounts.Account;
 import android.accounts.AccountAndUser;
+import android.accounts.AccountManager;
 import android.app.backup.BackupManager;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -27,6 +28,7 @@
 import android.content.SyncInfo;
 import android.content.SyncRequest;
 import android.content.SyncStatusInfo;
+import android.content.pm.PackageManager;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
@@ -350,6 +352,50 @@
         void onAuthorityRemoved(EndPoint removedAuthority);
     }
 
+    /**
+     * Validator that maintains a lazy cache of accounts and providers to tell if an authority or
+     * account is valid.
+     */
+    private static class AccountAuthorityValidator {
+        final private AccountManager mAccountManager;
+        final private PackageManager mPackageManager;
+        final private SparseArray<Account[]> mAccountsCache;
+        final private SparseArray<ArrayMap<String, Boolean>> mProvidersPerUserCache;
+
+        AccountAuthorityValidator(Context context) {
+            mAccountManager = context.getSystemService(AccountManager.class);
+            mPackageManager = context.getPackageManager();
+            mAccountsCache = new SparseArray<>();
+            mProvidersPerUserCache = new SparseArray<>();
+        }
+
+        // An account is valid if an installed authenticator has previously created that account
+        // on the device
+        boolean isAccountValid(Account account, int userId) {
+            Account[] accountsForUser = mAccountsCache.get(userId);
+            if (accountsForUser == null) {
+                accountsForUser = mAccountManager.getAccountsAsUser(userId);
+                mAccountsCache.put(userId, accountsForUser);
+            }
+            return ArrayUtils.contains(accountsForUser, account);
+        }
+
+        // An authority is only valid if it has a content provider installed on the system
+        boolean isAuthorityValid(String authority, int userId) {
+            ArrayMap<String, Boolean> authorityMap = mProvidersPerUserCache.get(userId);
+            if (authorityMap == null) {
+                authorityMap = new ArrayMap<>();
+                mProvidersPerUserCache.put(userId, authorityMap);
+            }
+            if (!authorityMap.containsKey(authority)) {
+                authorityMap.put(authority, mPackageManager.resolveContentProviderAsUser(authority,
+                        PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId) != null);
+            }
+            return authorityMap.get(authority);
+        }
+    }
+
     // Primary list of all syncable authorities.  Also our global lock.
     private final SparseArray<AuthorityInfo> mAuthorities =
             new SparseArray<AuthorityInfo>();
@@ -1502,12 +1548,13 @@
                 eventType = parser.next();
                 AuthorityInfo authority = null;
                 PeriodicSync periodicSync = null;
+                AccountAuthorityValidator validator = new AccountAuthorityValidator(mContext);
                 do {
                     if (eventType == XmlPullParser.START_TAG) {
                         tagName = parser.getName();
                         if (parser.getDepth() == 2) {
                             if ("authority".equals(tagName)) {
-                                authority = parseAuthority(parser, version);
+                                authority = parseAuthority(parser, version, validator);
                                 periodicSync = null;
                                 if (authority != null) {
                                     if (authority.ident > highestAuthorityId) {
@@ -1636,7 +1683,8 @@
         mMasterSyncAutomatically.put(userId, listen);
     }
 
-    private AuthorityInfo parseAuthority(XmlPullParser parser, int version) {
+    private AuthorityInfo parseAuthority(XmlPullParser parser, int version,
+            AccountAuthorityValidator validator) {
         AuthorityInfo authority = null;
         int id = -1;
         try {
@@ -1676,21 +1724,26 @@
                 if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
                     Slog.v(TAG_FILE, "Creating authority entry");
                 }
-                EndPoint info = null;
                 if (accountName != null && authorityName != null) {
-                    info = new EndPoint(
+                    EndPoint info = new EndPoint(
                             new Account(accountName, accountType),
                             authorityName, userId);
-                }
-                if (info != null) {
-                    authority = getOrCreateAuthorityLocked(info, id, false);
-                    // If the version is 0 then we are upgrading from a file format that did not
-                    // know about periodic syncs. In that case don't clear the list since we
-                    // want the default, which is a daily periodic sync.
-                    // Otherwise clear out this default list since we will populate it later with
-                    // the periodic sync descriptions that are read from the configuration file.
-                    if (version > 0) {
-                        authority.periodicSyncs.clear();
+                    if (validator.isAccountValid(info.account, userId)
+                            && validator.isAuthorityValid(authorityName, userId)) {
+                        authority = getOrCreateAuthorityLocked(info, id, false);
+                        // If the version is 0 then we are upgrading from a file format that did not
+                        // know about periodic syncs. In that case don't clear the list since we
+                        // want the default, which is a daily periodic sync.
+                        // Otherwise clear out this default list since we will populate it later
+                        // with
+                        // the periodic sync descriptions that are read from the configuration file.
+                        if (version > 0) {
+                            authority.periodicSyncs.clear();
+                        }
+                    } else {
+                        EventLog.writeEvent(0x534e4554, "35028827", -1,
+                                "account:" + info.account + " provider:" + authorityName + " user:"
+                                        + userId);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 0ef0561..9dc317a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -71,6 +71,7 @@
 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
     private static final String TAG = "DisplayPowerController";
     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
+    private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
 
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
@@ -90,6 +91,7 @@
     private static final int MSG_UPDATE_POWER_STATE = 1;
     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
     private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
+    private static final int MSG_SCREEN_OFF_UNBLOCKED = 4;
 
     private static final int PROXIMITY_UNKNOWN = -1;
     private static final int PROXIMITY_NEGATIVE = 0;
@@ -105,6 +107,7 @@
     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
+    private static final int REPORTED_TO_POLICY_SCREEN_TURNING_OFF = 3;
 
     private final Object mLock = new Object();
 
@@ -219,6 +222,7 @@
     // The currently active screen on unblocker.  This field is non-null whenever
     // we are waiting for a callback to release it and unblock the screen.
     private ScreenOnUnblocker mPendingScreenOnUnblocker;
+    private ScreenOffUnblocker mPendingScreenOffUnblocker;
 
     // True if we were in the process of turning off the screen.
     // This allows us to recover more gracefully from situations where we abort
@@ -230,6 +234,7 @@
 
     // The elapsed real time when the screen on was blocked.
     private long mScreenOnBlockStartRealTime;
+    private long mScreenOffBlockStartRealTime;
 
     // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
     private int mReportedScreenStateToPolicy;
@@ -810,9 +815,43 @@
         }
     }
 
+    private void blockScreenOff() {
+        if (mPendingScreenOffUnblocker == null) {
+            Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
+            mPendingScreenOffUnblocker = new ScreenOffUnblocker();
+            mScreenOffBlockStartRealTime = SystemClock.elapsedRealtime();
+            Slog.i(TAG, "Blocking screen off");
+        }
+    }
+
+    private void unblockScreenOff() {
+        if (mPendingScreenOffUnblocker != null) {
+            mPendingScreenOffUnblocker = null;
+            long delay = SystemClock.elapsedRealtime() - mScreenOffBlockStartRealTime;
+            Slog.i(TAG, "Unblocked screen off after " + delay + " ms");
+            Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_OFF_BLOCKED_TRACE_NAME, 0);
+        }
+    }
+
     private boolean setScreenState(int state) {
+        final boolean isOff = (state == Display.STATE_OFF);
         if (mPowerState.getScreenState() != state) {
-            final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
+
+            // If we are trying to turn screen off, give policy a chance to do something before we
+            // actually turn the screen off.
+            if (isOff && !mScreenOffBecauseOfProximity) {
+                if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
+                    mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_OFF;
+                    blockScreenOff();
+                    mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
+                    return false;
+                } else if (mPendingScreenOffUnblocker != null) {
+
+                    // Abort doing the state change until screen off is unblocked.
+                    return false;
+                }
+            }
+
             mPowerState.setScreenState(state);
 
             // Tell battery stats about the transition.
@@ -829,13 +868,21 @@
         // This surface is essentially the final state of the color fade animation and
         // it is only removed once the window manager tells us that the activity has
         // finished drawing underneath.
-        final boolean isOff = (state == Display.STATE_OFF);
         if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
                 && !mScreenOffBecauseOfProximity) {
             mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
             unblockScreenOn();
             mWindowManagerPolicy.screenTurnedOff();
-        } else if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
+        } else if (!isOff
+                && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {
+
+            // We told policy already that screen was turning off, but now we changed our minds.
+            // Complete the full state transition on -> turningOff -> off.
+            unblockScreenOff();
+            mWindowManagerPolicy.screenTurnedOff();
+            mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
+        }
+        if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
             mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
             if (mPowerState.getColorFadeLevel() == 0.0f) {
                 blockScreenOn();
@@ -1282,6 +1329,12 @@
                         updatePowerState();
                     }
                     break;
+                case MSG_SCREEN_OFF_UNBLOCKED:
+                    if (mPendingScreenOffUnblocker == msg.obj) {
+                        unblockScreenOff();
+                        updatePowerState();
+                    }
+                    break;
             }
         }
     }
@@ -1311,4 +1364,14 @@
             mHandler.sendMessage(msg);
         }
     }
+
+    private final class ScreenOffUnblocker implements WindowManagerPolicy.ScreenOffListener {
+
+        @Override
+        public void onScreenOff() {
+            Message msg = mHandler.obtainMessage(MSG_SCREEN_OFF_UNBLOCKED, this);
+            msg.setAsynchronous(true);
+            mHandler.sendMessage(msg);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index dbccc07..1b984a4 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -86,6 +86,7 @@
     private boolean mCurrentDreamCanDoze;
     private boolean mCurrentDreamIsDozing;
     private boolean mCurrentDreamIsWaking;
+    private Runnable mStopDreamRunnable;
     private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
     private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
 
@@ -349,6 +350,11 @@
 
     private void startDreamLocked(final ComponentName name,
             final boolean isTest, final boolean canDoze, final int userId) {
+        if (mStopDreamRunnable != null) {
+            mHandler.removeCallbacks(mStopDreamRunnable);
+            mStopDreamRunnable = null;
+        }
+
         if (Objects.equal(mCurrentDreamName, name)
                 && mCurrentDreamIsTest == isTest
                 && mCurrentDreamCanDoze == canDoze
@@ -386,13 +392,15 @@
                 mCurrentDreamIsWaking = true;
             }
 
-            mHandler.post(new Runnable() {
+            mStopDreamRunnable = new Runnable() {
                 @Override
                 public void run() {
                     Slog.i(TAG, "Performing gentle wake from dream.");
                     mController.stopDream(immediate);
+                    mStopDreamRunnable = null;
                 }
-            });
+            };
+            mHandler.post(mStopDreamRunnable);
         }
     }
 
diff --git a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
index 98771df..a91fe77 100644
--- a/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
+++ b/services/core/java/com/android/server/emergency/EmergencyAffordanceService.java
@@ -219,6 +219,7 @@
         List<SubscriptionInfo> activeSubscriptionInfoList =
                 mSubscriptionManager.getActiveSubscriptionInfoList();
         if (activeSubscriptionInfoList == null) {
+            setSimNeedsEmergencyAffordance(neededNow);
             return neededNow;
         }
         for (SubscriptionInfo info : activeSubscriptionInfoList) {
diff --git a/services/core/java/com/android/server/fingerprint/RemovalClient.java b/services/core/java/com/android/server/fingerprint/RemovalClient.java
index 88a6bdd..8646107 100644
--- a/services/core/java/com/android/server/fingerprint/RemovalClient.java
+++ b/services/core/java/com/android/server/fingerprint/RemovalClient.java
@@ -85,7 +85,6 @@
         IFingerprintServiceReceiver receiver = getReceiver();
         try {
             if (receiver != null) {
-                // TODO: plumb remaining
                 receiver.onRemoved(getHalDeviceId(), fingerId, groupId, remaining);
             }
         } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index c08f866..b0d76e8 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -63,6 +63,7 @@
 import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.os.UserManagerInternal;
 import android.provider.Settings;
 import android.util.KeyValueListParser;
 import android.util.Slog;
@@ -751,6 +752,13 @@
         }
     }
 
+    private void cancelJobsForNonExistentUsers() {
+        UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
+        synchronized (mLock) {
+            mJobs.removeJobsOfNonUsers(umi.getUserIds());
+        }
+    }
+
     void cancelJobsForPackageAndUid(String pkgName, int uid) {
         synchronized (mLock) {
             final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
@@ -941,6 +949,8 @@
             } catch (RemoteException e) {
                 // ignored; both services live in system_server
             }
+            // Remove any jobs that are not associated with any of the current users.
+            cancelJobsForNonExistentUsers();
         } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
             synchronized (mLock) {
                 // Let's go!
@@ -1270,6 +1280,17 @@
         }
     }
 
+    private void stopNonReadyActiveJobsLocked() {
+        for (int i=0; i<mActiveServices.size(); i++) {
+            JobServiceContext serviceContext = mActiveServices.get(i);
+            final JobStatus running = serviceContext.getRunningJobLocked();
+            if (running != null && !running.isReady()) {
+                serviceContext.cancelExecutingJobLocked(
+                        JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
+            }
+        }
+    }
+
     /**
      * Run through list of jobs and execute all possible - at least one is expired so we do
      * as many as we can.
@@ -1280,6 +1301,7 @@
         }
         noteJobsNonpending(mPendingJobs);
         mPendingJobs.clear();
+        stopNonReadyActiveJobsLocked();
         mJobs.forEachJob(mReadyQueueFunctor);
         mReadyQueueFunctor.postProcess();
 
@@ -1306,9 +1328,6 @@
                     newReadyJobs = new ArrayList<JobStatus>();
                 }
                 newReadyJobs.add(job);
-            } else if (areJobConstraintsNotSatisfiedLocked(job)) {
-                stopJobOnServiceContextLocked(job,
-                        JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
             }
         }
 
@@ -1387,9 +1406,6 @@
                     runnableJobs = new ArrayList<>();
                 }
                 runnableJobs.add(job);
-            } else if (areJobConstraintsNotSatisfiedLocked(job)) {
-                stopJobOnServiceContextLocked(job,
-                        JobParameters.REASON_CONSTRAINTS_NOT_SATISFIED);
             }
         }
 
@@ -1439,6 +1455,7 @@
 
         noteJobsNonpending(mPendingJobs);
         mPendingJobs.clear();
+        stopNonReadyActiveJobsLocked();
         mJobs.forEachJob(mMaybeQueueFunctor);
         mMaybeQueueFunctor.postProcess();
     }
@@ -1516,15 +1533,6 @@
     }
 
     /**
-     * Criteria for cancelling an active job:
-     *      - It's not ready
-     *      - It's running on a JSC.
-     */
-    private boolean areJobConstraintsNotSatisfiedLocked(JobStatus job) {
-        return !job.isReady() && isCurrentlyActiveLocked(job);
-    }
-
-    /**
      * Reconcile jobs in the pending queue against available execution contexts.
      * A controller can force a job into the pending queue even if it's already running, but
      * here is where we decide whether to actually execute it.
@@ -2088,6 +2096,83 @@
         }
     }
 
+    int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) {
+        try {
+            final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0,
+                    userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM);
+            if (uid < 0) {
+                pw.print("unknown("); pw.print(pkgName); pw.println(")");
+                return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
+            }
+
+            synchronized (mLock) {
+                final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId);
+                if (DEBUG) Slog.d(TAG, "get-job-state " + uid + "/" + jobId + ": " + js);
+                if (js == null) {
+                    pw.print("unknown("); UserHandle.formatUid(pw, uid);
+                    pw.print("/jid"); pw.print(jobId); pw.println(")");
+                    return JobSchedulerShellCommand.CMD_ERR_NO_JOB;
+                }
+
+                boolean printed = false;
+                if (mPendingJobs.contains(js)) {
+                    pw.print("pending");
+                    printed = true;
+                }
+                if (isCurrentlyActiveLocked(js)) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("active");
+                }
+                if (!ArrayUtils.contains(mStartedUsers, js.getUserId())) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("user-stopped");
+                }
+                if (mBackingUpUids.indexOfKey(js.getSourceUid()) >= 0) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("backing-up");
+                }
+                boolean componentPresent = false;
+                try {
+                    componentPresent = (AppGlobals.getPackageManager().getServiceInfo(
+                            js.getServiceComponent(),
+                            PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+                            js.getUserId()) != null);
+                } catch (RemoteException e) {
+                }
+                if (!componentPresent) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("no-component");
+                }
+                if (js.isReady()) {
+                    if (printed) {
+                        pw.print(" ");
+                    }
+                    printed = true;
+                    pw.println("ready");
+                }
+                if (!printed) {
+                    pw.print("waiting");
+                }
+                pw.println();
+            }
+        } catch (RemoteException e) {
+            // can't happen
+        }
+        return 0;
+    }
+
     private String printContextIdToJobMap(JobStatus[] map, String initial) {
         StringBuilder s = new StringBuilder(initial + ": ");
         for (int i=0; i<map.length; i++) {
@@ -2152,7 +2237,8 @@
         }
 
         final int filterUidFinal = UserHandle.getAppId(filterUid);
-        final long now = SystemClock.elapsedRealtime();
+        final long nowElapsed = SystemClock.elapsedRealtime();
+        final long nowUptime = SystemClock.uptimeMillis();
         synchronized (mLock) {
             mConstants.dump(pw);
             pw.println();
@@ -2184,7 +2270,7 @@
                         continue;
                     }
 
-                    job.dump(pw, "    ", true, now);
+                    job.dump(pw, "    ", true, nowElapsed);
                     pw.print("    Ready: ");
                     pw.print(isReadyToBeExecutedLocked(job));
                     pw.print(" (job=");
@@ -2254,14 +2340,14 @@
                 JobStatus job = mPendingJobs.get(i);
                 pw.print("  Pending #"); pw.print(i); pw.print(": ");
                 pw.println(job.toShortString());
-                job.dump(pw, "    ", false, now);
+                job.dump(pw, "    ", false, nowElapsed);
                 int priority = evaluateJobPriorityLocked(job);
                 if (priority != JobInfo.PRIORITY_DEFAULT) {
                     pw.print("    Evaluated priority: "); pw.println(priority);
                 }
                 pw.print("    Tag: "); pw.println(job.getTag());
                 pw.print("    Enq: ");
-                TimeUtils.formatDuration(job.madePending - now, pw);
+                TimeUtils.formatDuration(job.madePending - nowUptime, pw);
                 pw.println();
             }
             pw.println();
@@ -2276,17 +2362,17 @@
                 } else {
                     pw.println(job.toShortString());
                     pw.print("    Running for: ");
-                    TimeUtils.formatDuration(now - jsc.getExecutionStartTimeElapsed(), pw);
+                    TimeUtils.formatDuration(nowElapsed - jsc.getExecutionStartTimeElapsed(), pw);
                     pw.print(", timeout at: ");
-                    TimeUtils.formatDuration(jsc.getTimeoutElapsed() - now, pw);
+                    TimeUtils.formatDuration(jsc.getTimeoutElapsed() - nowElapsed, pw);
                     pw.println();
-                    job.dump(pw, "    ", false, now);
+                    job.dump(pw, "    ", false, nowElapsed);
                     int priority = evaluateJobPriorityLocked(jsc.getRunningJobLocked());
                     if (priority != JobInfo.PRIORITY_DEFAULT) {
                         pw.print("    Evaluated priority: "); pw.println(priority);
                     }
                     pw.print("    Active at ");
-                    TimeUtils.formatDuration(job.madeActive - now, pw);
+                    TimeUtils.formatDuration(job.madeActive - nowUptime, pw);
                     pw.print(", pending for ");
                     TimeUtils.formatDuration(job.madeActive - job.madePending, pw);
                     pw.println();
diff --git a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
index fdfb345..2d2f61f 100644
--- a/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/services/core/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -60,6 +60,8 @@
                     return getStorageSeq(pw);
                 case "get-storage-not-low":
                     return getStorageNotLow(pw);
+                case "get-job-state":
+                    return getJobState(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -83,6 +85,43 @@
         }
     }
 
+    private boolean printError(int errCode, String pkgName, int userId, int jobId) {
+        PrintWriter pw;
+        switch (errCode) {
+            case CMD_ERR_NO_PACKAGE:
+                pw = getErrPrintWriter();
+                pw.print("Package not found: ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.println(userId);
+                return true;
+
+            case CMD_ERR_NO_JOB:
+                pw = getErrPrintWriter();
+                pw.print("Could not find job ");
+                pw.print(jobId);
+                pw.print(" in package ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.println(userId);
+                return true;
+
+            case CMD_ERR_CONSTRAINTS:
+                pw = getErrPrintWriter();
+                pw.print("Job ");
+                pw.print(jobId);
+                pw.print(" in package ");
+                pw.print(pkgName);
+                pw.print(" / user ");
+                pw.print(userId);
+                pw.println(" has functional constraints but --force not specified");
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
     private int runJob(PrintWriter pw) throws Exception {
         checkPermission("force scheduled jobs");
 
@@ -114,42 +153,17 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             int ret = mInternal.executeRunCommand(pkgName, userId, jobId, force);
-            switch (ret) {
-                case CMD_ERR_NO_PACKAGE:
-                    pw.print("Package not found: ");
-                    pw.print(pkgName);
-                    pw.print(" / user ");
-                    pw.println(userId);
-                    break;
-
-                case CMD_ERR_NO_JOB:
-                    pw.print("Could not find job ");
-                    pw.print(jobId);
-                    pw.print(" in package ");
-                    pw.print(pkgName);
-                    pw.print(" / user ");
-                    pw.println(userId);
-                    break;
-
-                case CMD_ERR_CONSTRAINTS:
-                    pw.print("Job ");
-                    pw.print(jobId);
-                    pw.print(" in package ");
-                    pw.print(pkgName);
-                    pw.print(" / user ");
-                    pw.print(userId);
-                    pw.println(" has functional constraints but --force not specified");
-                    break;
-
-                default:
-                    // success!
-                    pw.print("Running job");
-                    if (force) {
-                        pw.print(" [FORCED]");
-                    }
-                    pw.println();
-                    break;
+            if (printError(ret, pkgName, userId, jobId)) {
+                return ret;
             }
+
+            // success!
+            pw.print("Running job");
+            if (force) {
+                pw.print(" [FORCED]");
+            }
+            pw.println();
+
             return ret;
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -244,6 +258,43 @@
         return 0;
     }
 
+    private int getJobState(PrintWriter pw) throws Exception {
+        checkPermission("force timeout jobs");
+
+        int userId = UserHandle.USER_SYSTEM;
+
+        String opt;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case "-u":
+                case "--user":
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+
+                default:
+                    pw.println("Error: unknown option '" + opt + "'");
+                    return -1;
+            }
+        }
+
+        if (userId == UserHandle.USER_CURRENT) {
+            userId = ActivityManager.getCurrentUser();
+        }
+
+        final String pkgName = getNextArgRequired();
+        final String jobIdStr = getNextArgRequired();
+        final int jobId = Integer.parseInt(jobIdStr);
+
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            int ret = mInternal.getJobState(pw, pkgName, userId, jobId);
+            printError(ret, pkgName, userId, jobId);
+            return ret;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -277,6 +328,18 @@
         pw.println("    Return the last storage update sequence number that was received.");
         pw.println("  get-storage-not-low");
         pw.println("    Return whether storage is currently considered to not be low.");
+        pw.println("  get-job-state [-u | --user USER_ID] PACKAGE JOB_ID");
+        pw.println("    Return the current state of a job, may be any combination of:");
+        pw.println("      pending: currently on the pending list, waiting to be active");
+        pw.println("      active: job is actively running");
+        pw.println("      user-stopped: job can't run because its user is stopped");
+        pw.println("      backing-up: job can't run because app is currently backing up its data");
+        pw.println("      no-component: job can't run because its component is not available");
+        pw.println("      ready: job is ready to run (all constraints satisfied or bypassed)");
+        pw.println("      waiting: if nothing else above is printed, job not ready to run");
+        pw.println("    Options:");
+        pw.println("      -u or --user: specify which user's job is to be run; the default is");
+        pw.println("         the primary or system user");
         pw.println();
     }
 
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 497d36f..22eed3b 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -35,6 +35,7 @@
 import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.IoThread;
 import com.android.server.job.controllers.JobStatus;
@@ -171,6 +172,14 @@
         return removed;
     }
 
+    /**
+     * Remove the jobs of users not specified in the whitelist.
+     * @param whitelist Array of User IDs whose jobs are not to be removed.
+     */
+    public void removeJobsOfNonUsers(int[] whitelist) {
+        mJobSet.removeJobsOfNonUsers(whitelist);
+    }
+
     @VisibleForTesting
     public void clear() {
         mJobSet.clear();
@@ -839,6 +848,17 @@
             return didRemove;
         }
 
+        // Remove the jobs all users not specified by the whitelist of user ids
+        public void removeJobsOfNonUsers(int[] whitelist) {
+            for (int jobIndex = mJobs.size() - 1; jobIndex >= 0; jobIndex--) {
+                int jobUserId = UserHandle.getUserId(mJobs.keyAt(jobIndex));
+                // check if job's user id is not in the whitelist
+                if (!ArrayUtils.contains(whitelist, jobUserId)) {
+                    mJobs.removeAt(jobIndex);
+                }
+            }
+        }
+
         public boolean contains(JobStatus job) {
             final int uid = job.getUid();
             ArraySet<JobStatus> jobs = mJobs.get(uid);
diff --git a/services/core/java/com/android/server/job/controllers/BatteryController.java b/services/core/java/com/android/server/job/controllers/BatteryController.java
index b1f8f6b..d275bd9 100644
--- a/services/core/java/com/android/server/job/controllers/BatteryController.java
+++ b/services/core/java/com/android/server/job/controllers/BatteryController.java
@@ -93,34 +93,31 @@
         }
     }
 
-    private void maybeReportNewChargingState() {
+    private void maybeReportNewChargingStateLocked() {
         final boolean stablePower = mChargeTracker.isOnStablePower();
         final boolean batteryNotLow = mChargeTracker.isBatteryNotLow();
         if (DEBUG) {
-            Slog.d(TAG, "maybeReportNewChargingState: " + stablePower);
+            Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
         }
         boolean reportChange = false;
-        synchronized (mLock) {
-            for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
-                final JobStatus ts = mTrackedTasks.valueAt(i);
-                boolean previous = ts.setChargingConstraintSatisfied(stablePower);
-                if (previous != stablePower) {
-                    reportChange = true;
-                }
-                previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
-                if (previous != batteryNotLow) {
-                    reportChange = true;
-                }
+        for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
+            final JobStatus ts = mTrackedTasks.valueAt(i);
+            boolean previous = ts.setChargingConstraintSatisfied(stablePower);
+            if (previous != stablePower) {
+                reportChange = true;
+            }
+            previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
+            if (previous != batteryNotLow) {
+                reportChange = true;
             }
         }
-        // Let the scheduler know that state has changed. This may or may not result in an
-        // execution.
-        if (reportChange) {
-            mStateChangedListener.onControllerStateChanged();
-        }
-        // Also tell the scheduler that any ready jobs should be flushed.
         if (stablePower || batteryNotLow) {
+            // If one of our conditions has been satisfied, always schedule any newly ready jobs.
             mStateChangedListener.onRunJobNow(null);
+        } else if (reportChange) {
+            // Otherwise, just let the job scheduler know the state has changed and take care of it
+            // as it thinks is best.
+            mStateChangedListener.onControllerStateChanged();
         }
     }
 
@@ -201,38 +198,42 @@
 
         @VisibleForTesting
         public void onReceiveInternal(Intent intent) {
-            final String action = intent.getAction();
-            if (Intent.ACTION_BATTERY_LOW.equals(action)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Battery life too low to do work. @ "
-                            + SystemClock.elapsedRealtime());
+            synchronized (mLock) {
+                final String action = intent.getAction();
+                if (Intent.ACTION_BATTERY_LOW.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Battery life too low to do work. @ "
+                                + SystemClock.elapsedRealtime());
+                    }
+                    // If we get this action, the battery is discharging => it isn't plugged in so
+                    // there's no work to cancel. We track this variable for the case where it is
+                    // charging, but hasn't been for long enough to be healthy.
+                    mBatteryHealthy = false;
+                    maybeReportNewChargingStateLocked();
+                } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Battery life healthy enough to do work. @ "
+                                + SystemClock.elapsedRealtime());
+                    }
+                    mBatteryHealthy = true;
+                    maybeReportNewChargingStateLocked();
+                } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Received charging intent, fired @ "
+                                + SystemClock.elapsedRealtime());
+                    }
+                    mCharging = true;
+                    maybeReportNewChargingStateLocked();
+                } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Disconnected from power.");
+                    }
+                    mCharging = false;
+                    maybeReportNewChargingStateLocked();
                 }
-                // If we get this action, the battery is discharging => it isn't plugged in so
-                // there's no work to cancel. We track this variable for the case where it is
-                // charging, but hasn't been for long enough to be healthy.
-                mBatteryHealthy = false;
-            } else if (Intent.ACTION_BATTERY_OKAY.equals(action)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Battery life healthy enough to do work. @ "
-                            + SystemClock.elapsedRealtime());
-                }
-                mBatteryHealthy = true;
-                maybeReportNewChargingState();
-            } else if (BatteryManager.ACTION_CHARGING.equals(action)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Received charging intent, fired @ "
-                            + SystemClock.elapsedRealtime());
-                }
-                mCharging = true;
-                maybeReportNewChargingState();
-            } else if (BatteryManager.ACTION_DISCHARGING.equals(action)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "Disconnected from power.");
-                }
-                mCharging = false;
-                maybeReportNewChargingState();
+                mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE,
+                        mLastBatterySeq);
             }
-            mLastBatterySeq = intent.getIntExtra(BatteryManager.EXTRA_SEQUENCE, mLastBatterySeq);
         }
     }
 
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 51bebb09..3fd91dc 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -937,9 +937,9 @@
                     long time = mNtpTime.getCachedNtpTime();
                     long timeReference = mNtpTime.getCachedNtpTimeReference();
                     long certainty = mNtpTime.getCacheCertainty();
-                    long now = System.currentTimeMillis();
 
                     if (DEBUG) {
+                        long now = System.currentTimeMillis();
                         Log.d(TAG, "NTP server returned: "
                                 + time + " (" + new Date(time)
                                 + ") reference: " + timeReference
@@ -1444,7 +1444,8 @@
 
             // reset SV count to zero
             updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
-            mFixRequestTime = System.currentTimeMillis();
+            mFixRequestTime = SystemClock.elapsedRealtime();
+
             if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
                 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
                 // and our fix interval is not short
@@ -1514,7 +1515,7 @@
             }
         }
 
-        mLastFixTime = System.currentTimeMillis();
+        mLastFixTime = SystemClock.elapsedRealtime();
         // report time to first fix
         if (mTimeToFirstFix == 0 && hasLatLong) {
             mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
@@ -1629,7 +1630,7 @@
         updateStatus(mStatus, usedInFixCount);
 
         if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
-            System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
+            SystemClock.elapsedRealtime() - mLastFixTime > RECENT_FIX_TIMEOUT) {
             // send an intent to notify that the GPS is no longer receiving fixes.
             Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
             intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index e0017b5..38c6157 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -171,19 +171,63 @@
     public void updateSession(MediaSessionRecord record) {
         synchronized (mLock) {
             FullUserRecord user = getFullUserRecordLocked(record.getUserId());
-            if (user == null || !user.mPriorityStack.contains(record)) {
-                Log.d(TAG, "Unknown session updated. Ignoring.");
+            if (user == null) {
+                Log.w(TAG, "Unknown session updated. Ignoring.");
                 return;
             }
-            user.mPriorityStack.onSessionStateChange(record);
             if ((record.getFlags() & MediaSession.FLAG_EXCLUSIVE_GLOBAL_PRIORITY) != 0) {
-                mGlobalPrioritySession = record;
+                if (mGlobalPrioritySession != record) {
+                    Log.d(TAG, "Global priority session is changed from " + mGlobalPrioritySession
+                            + " to " + record);
+                    mGlobalPrioritySession = record;
+                    if (user != null && user.mPriorityStack.contains(record)) {
+                        // Handle the global priority session separately.
+                        // Otherwise, it will be the media button session even after it becomes
+                        // inactive because it has been the lastly played media app.
+                        user.mPriorityStack.removeSession(record);
+                    }
+                }
+                if (DEBUG_KEY_EVENT) {
+                    Log.d(TAG, "Global priority session is updated, active=" + record.isActive());
+                }
                 user.pushAddressedPlayerChangedLocked();
+            } else {
+                if (!user.mPriorityStack.contains(record)) {
+                    Log.w(TAG, "Unknown session updated. Ignoring.");
+                    return;
+                }
+                user.mPriorityStack.onSessionStateChange(record);
             }
             mHandler.postSessionsChanged(record.getUserId());
         }
     }
 
+    private List<MediaSessionRecord> getActiveSessionsLocked(int userId) {
+        List<MediaSessionRecord> records;
+        if (userId == UserHandle.USER_ALL) {
+            records = new ArrayList<>();
+            int size = mUserRecords.size();
+            for (int i = 0; i < size; i++) {
+                records.addAll(mUserRecords.valueAt(i).mPriorityStack.getActiveSessions(userId));
+            }
+        } else {
+            FullUserRecord user = getFullUserRecordLocked(userId);
+            if (user == null) {
+                Log.w(TAG, "getSessions failed. Unknown user " + userId);
+                return new ArrayList<>();
+            }
+            records = user.mPriorityStack.getActiveSessions(userId);
+        }
+
+        // Return global priority session at the first whenever it's asked.
+        if (isGlobalPriorityActiveLocked()
+                && (userId == UserHandle.USER_ALL
+                    || userId == mGlobalPrioritySession.getUserId())) {
+            records.add(0, mGlobalPrioritySession);
+        }
+        return records;
+    }
+
     /**
      * Tells the system UI that volume has changed on an active remote session.
      */
@@ -339,16 +383,16 @@
         if (DEBUG) {
             Log.d(TAG, "Destroying " + session);
         }
-        int userId = session.getUserId();
-        FullUserRecord user = getFullUserRecordLocked(userId);
-        if (user != null) {
-            user.removeSessionLocked(session);
-        }
+        FullUserRecord user = getFullUserRecordLocked(session.getUserId());
         if (mGlobalPrioritySession == session) {
             mGlobalPrioritySession = null;
             if (session.isActive() && user != null) {
                 user.pushAddressedPlayerChangedLocked();
             }
+        } else {
+            if (user != null) {
+                user.mPriorityStack.removeSession(session);
+            }
         }
 
         try {
@@ -484,7 +528,7 @@
             throw new RuntimeException("Media Session owner died prematurely.", e);
         }
 
-        user.addSessionLocked(session);
+        user.mPriorityStack.addSession(session);
         mHandler.postSessionsChanged(userId);
 
         if (DEBUG) {
@@ -509,7 +553,7 @@
                 Log.w(TAG, "pushSessionsChanged failed. No user with id=" + userId);
                 return;
             }
-            List<MediaSessionRecord> records = user.mPriorityStack.getActiveSessions(userId);
+            List<MediaSessionRecord> records = getActiveSessionsLocked(userId);
             int size = records.size();
             ArrayList<MediaSession.Token> tokens = new ArrayList<MediaSession.Token>();
             for (int i = 0; i < size; i++) {
@@ -637,14 +681,6 @@
             }
         }
 
-        public void addSessionLocked(MediaSessionRecord session) {
-            mPriorityStack.addSession(session);
-        }
-
-        public void removeSessionLocked(MediaSessionRecord session) {
-            mPriorityStack.removeSession(session);
-        }
-
         public void dumpLocked(PrintWriter pw, String prefix) {
             pw.print(prefix + "Record for full_user=" + mFullUserId);
             // Dump managed profile user ids associated with this user.
@@ -816,27 +852,9 @@
                 int resolvedUserId = verifySessionsRequest(componentName, userId, pid, uid);
                 ArrayList<IBinder> binders = new ArrayList<IBinder>();
                 synchronized (mLock) {
-                    if (resolvedUserId == UserHandle.USER_ALL) {
-                        int size = mUserRecords.size();
-                        for (int i = 0; i < size; i++) {
-                            List<MediaSessionRecord> records =
-                                    mUserRecords.valueAt(i).mPriorityStack.getActiveSessions(
-                                            resolvedUserId);
-                            for (MediaSessionRecord record : records) {
-                                binders.add(record.getControllerBinder().asBinder());
-                            }
-                        }
-                    } else {
-                        FullUserRecord user = getFullUserRecordLocked(resolvedUserId);
-                        if (user == null) {
-                            Log.w(TAG, "getSessions failed. Unknown user " + userId);
-                            return binders;
-                        }
-                        List<MediaSessionRecord> records = user.mPriorityStack
-                                .getActiveSessions(resolvedUserId);
-                        for (MediaSessionRecord record : records) {
-                            binders.add(record.getControllerBinder().asBinder());
-                        }
+                    List<MediaSessionRecord> records = getActiveSessionsLocked(resolvedUserId);
+                    for (MediaSessionRecord record : records) {
+                        binders.add(record.getControllerBinder().asBinder());
                     }
                 }
                 return binders;
@@ -1292,6 +1310,9 @@
             synchronized (mLock) {
                 pw.println(mSessionsListeners.size() + " sessions listeners.");
                 pw.println("Global priority session is " + mGlobalPrioritySession);
+                if (mGlobalPrioritySession != null) {
+                    mGlobalPrioritySession.dump(pw, "  ");
+                }
                 pw.println("User Records:");
                 int count = mUserRecords.size();
                 for (int i = 0; i < count; i++) {
diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java
index f474769..f03f630 100644
--- a/services/core/java/com/android/server/media/MediaSessionStack.java
+++ b/services/core/java/com/android/server/media/MediaSessionStack.java
@@ -310,7 +310,6 @@
      * Get a priority sorted list of sessions. Can filter to only return active
      * sessions or sessions.
      * <p>Here's the priority order.
-     * <li>System priority session (session with FLAG_EXCLUSIVE_GLOBAL_PRIORITY)</li>
      * <li>Active sessions whose PlaybackState is active</li>
      * <li>Active sessions whose PlaybackState is inactive</li>
      * <li>Inactive sessions</li>
@@ -344,13 +343,7 @@
                 continue;
             }
 
-            if (session.isSystemPriority()) {
-                // System priority sessions are special and always go at the
-                // front. We expect there to only be one of these at a time.
-                result.add(0, session);
-                lastPlaybackActiveIndex++;
-                lastActiveIndex++;
-            } else if (session.isPlaybackActive()) {
+            if (session.isPlaybackActive()) {
                 result.add(lastPlaybackActiveIndex++, session);
                 lastActiveIndex++;
             } else {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9cd0dff..4668156 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -90,7 +90,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
-import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.media.AudioManager;
@@ -114,7 +113,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.os.Vibrator;
 import android.os.VibrationEffect;
 import android.provider.Settings;
@@ -473,19 +471,6 @@
         out.endDocument();
     }
 
-    /** Use this when you actually want to post a notification or toast.
-     *
-     * Unchecked. Not exposed via Binder, but can be called in the course of enqueue*().
-     */
-    private boolean noteNotificationOp(String pkg, int uid) {
-        if (mAppOps.noteOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
-                != AppOpsManager.MODE_ALLOWED) {
-            Slog.v(TAG, "notifications are disabled by AppOps for " + pkg);
-            return false;
-        }
-        return true;
-    }
-
     /** Use this to check if a package can post a notification or toast. */
     private boolean checkNotificationOp(String pkg, int uid) {
         return mAppOps.checkOp(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
@@ -1154,7 +1139,7 @@
         final File systemDir = new File(Environment.getDataDirectory(), "system");
         mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
 
-        syncBlockDb();
+        loadPolicyFile();
 
         // This is a ManagedServices object that keeps track of the listeners.
         mListeners = notificationListeners;
@@ -1267,46 +1252,6 @@
                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), UserHandle.ALL, null);
     }
 
-    /**
-     * Make sure the XML config and the the AppOps system agree about blocks.
-     */
-    private void syncBlockDb() {
-        loadPolicyFile();
-
-        // sync bans from ranker into app opps
-        Map<Integer, String> packageBans = mRankingHelper.getPackageBans();
-        for(Entry<Integer, String> ban : packageBans.entrySet()) {
-            final int uid = ban.getKey();
-            final String packageName = ban.getValue();
-            setNotificationsEnabledForPackageImpl(packageName, uid, false);
-        }
-
-        // sync bans from app opps into ranker
-        packageBans.clear();
-        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
-            final int userId = user.getUserHandle().getIdentifier();
-            final PackageManager packageManager = getContext().getPackageManager();
-            List<PackageInfo> packages = packageManager.getInstalledPackagesAsUser(0, userId);
-            final int packageCount = packages.size();
-            for (int p = 0; p < packageCount; p++) {
-                final String packageName = packages.get(p).packageName;
-                try {
-                    final int uid = packageManager.getPackageUidAsUser(packageName, userId);
-                    if (!checkNotificationOp(packageName, uid)) {
-                        packageBans.put(uid, packageName);
-                    }
-                } catch (NameNotFoundException e) {
-                    // forget you
-                }
-            }
-        }
-        for (Entry<Integer, String> ban : packageBans.entrySet()) {
-            mRankingHelper.setImportance(ban.getValue(), ban.getKey(), IMPORTANCE_NONE);
-        }
-
-        savePolicyFile();
-    }
-
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
@@ -1328,19 +1273,6 @@
         }
     }
 
-    void setNotificationsEnabledForPackageImpl(String pkg, int uid, boolean enabled) {
-        Slog.v(TAG, (enabled?"en":"dis") + "abling notifications for " + pkg);
-
-        mAppOps.setMode(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg,
-                enabled ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
-
-        // Now, cancel any outstanding notifications that are part of a just-disabled app
-        if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
-            cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true,
-                    UserHandle.getUserId(uid), REASON_PACKAGE_BANNED, null);
-        }
-    }
-
     private void updateListenerHintsLocked() {
         final int hints = calculateHints();
         if (hints == mListenerHints) return;
@@ -1521,15 +1453,14 @@
             final boolean isPackageSuspended =
                     isPackageSuspendedForUser(pkg, Binder.getCallingUid());
 
-            if (ENABLE_BLOCKED_TOASTS && (!noteNotificationOp(pkg, Binder.getCallingUid())
-                    || isPackageSuspended)) {
-                if (!isSystemToast) {
-                    Slog.e(TAG, "Suppressing toast from package " + pkg
-                            + (isPackageSuspended
-                                    ? " due to package suspended by administrator."
-                                    : " by user request."));
-                    return;
-                }
+            if (ENABLE_BLOCKED_TOASTS && !isSystemToast &&
+                    (!areNotificationsEnabledForPackage(pkg, Binder.getCallingUid())
+                            || isPackageSuspended)) {
+                Slog.e(TAG, "Suppressing toast from package " + pkg
+                        + (isPackageSuspended
+                                ? " due to package suspended by administrator."
+                                : " by user request."));
+                return;
             }
 
             synchronized (mToastQueue) {
@@ -1645,8 +1576,12 @@
         public void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled) {
             checkCallerIsSystem();
 
-            setNotificationsEnabledForPackageImpl(pkg, uid, enabled);
             mRankingHelper.setEnabled(pkg, uid, enabled);
+            // Now, cancel any outstanding notifications that are part of a just-disabled app
+            if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
+                cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true,
+                        UserHandle.getUserId(uid), REASON_PACKAGE_BANNED, null);
+            }
             savePolicyFile();
         }
 
@@ -1664,8 +1599,8 @@
         @Override
         public boolean areNotificationsEnabledForPackage(String pkg, int uid) {
             checkCallerIsSystemOrSameApp(pkg);
-            return (mAppOps.checkOpNoThrow(AppOpsManager.OP_POST_NOTIFICATION, uid, pkg)
-                    == AppOpsManager.MODE_ALLOWED) && !isPackageSuspendedForUser(pkg, uid);
+
+            return mRankingHelper.getImportance(pkg, uid) != IMPORTANCE_NONE;
         }
 
         @Override
@@ -3238,6 +3173,8 @@
             final String noChannelStr = "No Channel found for "
                     + "pkg=" + pkg
                     + ", channelId=" + channelId
+                    + ", id=" + id
+                    + ", tag=" + tag
                     + ", opPkg=" + opPkg
                     + ", callingUid=" + callingUid
                     + ", userId=" + userId
@@ -3282,10 +3219,12 @@
     }
 
     private void doChannelWarningToast(CharSequence toastText) {
-        final boolean warningEnabled = Settings.System.getInt(getContext().getContentResolver(),
-                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, 0) != 0;
-        if (warningEnabled || Build.IS_DEBUGGABLE) {
-            Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText, Toast.LENGTH_LONG);
+        final int defaultWarningEnabled = Build.IS_DEBUGGABLE ? 1 : 0;
+        final boolean warningEnabled = Settings.Global.getInt(getContext().getContentResolver(),
+                Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0;
+        if (warningEnabled) {
+            Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText,
+                    Toast.LENGTH_LONG);
             toast.show();
         }
     }
@@ -3398,8 +3337,7 @@
         }
 
         final boolean isBlocked = r.getImportance() == NotificationManager.IMPORTANCE_NONE
-                || r.getChannel().getImportance() == NotificationManager.IMPORTANCE_NONE
-                || !noteNotificationOp(pkg, callingUid);
+                || r.getChannel().getImportance() == NotificationManager.IMPORTANCE_NONE;
         if (isBlocked) {
             Slog.e(TAG, "Suppressing notification from package by user request.");
             usageStats.registerBlocked(r);
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 5a5e658..803b0dc 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -153,7 +153,7 @@
                   final ApplicationInfo applicationInfo =
                         mContext.getPackageManager().getApplicationInfoAsUser(sbn.getPackageName(),
                                 0, UserHandle.getUserId(sbn.getUid()));
-                if (applicationInfo.targetSdkVersion <= Build.VERSION_CODES.N_MR1) {
+                if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
                     return true;
                 }
             }
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index e184f83..3dea783 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -21,8 +21,6 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.util.Preconditions;
 
-import android.annotation.UserIdInt;
-import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationChannelGroup;
@@ -35,8 +33,6 @@
 import android.metrics.LogMaker;
 import android.os.Build;
 import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.service.notification.NotificationListenerService.Ranking;
 import android.text.TextUtils;
@@ -189,6 +185,10 @@
                                 safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY),
                                 safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY),
                                 safeBool(parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE));
+                        r.importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
+                        r.priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY);
+                        r.visibility = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY);
+                        r.showBadge = safeBool(parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE);
 
                         final int innerDepth = parser.getDepth();
                         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -286,7 +286,7 @@
     private boolean shouldHaveDefaultChannel(Record r) throws NameNotFoundException {
         final int userId = UserHandle.getUserId(r.uid);
         final ApplicationInfo applicationInfo = mPm.getApplicationInfoAsUser(r.pkg, 0, userId);
-        if (applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+        if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
             // O apps should not have the default channel.
             return false;
         }
@@ -1115,6 +1115,7 @@
                     Record fullRecord = getRecord(pkg,
                             mPm.getPackageUidAsUser(pkg, changeUserId));
                     if (fullRecord != null) {
+                        createDefaultChannelIfNeeded(fullRecord);
                         deleteDefaultChannelIfNeeded(fullRecord);
                     }
                 } catch (NameNotFoundException e) {}
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 353b710..c059b37 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -319,7 +319,7 @@
         private static final String ATTR_USER_ID = "userId";
         private static final String ATTR_VERSION = "version";
 
-        private static final int CURRENT_VERSION = 2;
+        private static final int CURRENT_VERSION = 3;
 
         public static void restore(@NonNull final ArrayList<SettingsItem> table,
                 @NonNull final InputStream is) throws IOException, XmlPullParserException {
@@ -350,6 +350,7 @@
             switch (oldVersion) {
                 case 0:
                 case 1:
+                case 2:
                     // Throw an exception which will cause the overlay file to be ignored
                     // and overwritten.
                     throw new XmlPullParserException("old version " + oldVersion + "; ignoring");
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index d364d17..0d1f58a 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -36,6 +36,8 @@
 import android.util.Log;
 
 import com.android.server.pm.dex.DexManager;
+import com.android.server.LocalServices;
+import com.android.server.PinnerService;
 
 import java.io.File;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -175,6 +177,7 @@
 
         mAbortPostBootUpdate.set(false);
 
+        ArraySet<String> updatedPackages = new ArraySet<>();
         for (String pkg : pkgs) {
             if (mAbortPostBootUpdate.get()) {
                 // JobScheduler requested an early abort.
@@ -208,11 +211,15 @@
             // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
             // behave differently than "pm.dexopt.bg-dexopt=speed-profile" but that's a
             // trade-off worth doing to save boot time work.
-            pm.performDexOpt(pkg,
+            int result = pm.performDexOptWithStatus(pkg,
                     /* checkProfiles */ false,
                     PackageManagerService.REASON_BOOT,
                     /* force */ false);
+            if (result == PackageDexOptimizer.DEX_OPT_PERFORMED)  {
+                updatedPackages.add(pkg);
+            }
         }
+        notifyPinService(updatedPackages);
         // Ran to completion, so we abandon our timeslice and do not reschedule.
         jobFinished(jobParams, /* reschedule */ false);
     }
@@ -265,6 +272,7 @@
     private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
             long lowStorageThreshold, boolean is_for_primary_dex,
             ArraySet<String> failedPackageNames) {
+        ArraySet<String> updatedPackages = new ArraySet<>();
         for (String pkg : pkgs) {
             int abort_code = abortIdleOptimizations(lowStorageThreshold);
             if (abort_code != OPTIMIZE_CONTINUE) {
@@ -284,14 +292,21 @@
 
             // Optimize package if needed. Note that there can be no race between
             // concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
-            boolean success = is_for_primary_dex
-                    ? pm.performDexOpt(pkg,
-                            /* checkProfiles */ true,
-                            PackageManagerService.REASON_BACKGROUND_DEXOPT,
-                            /* force */ false)
-                    : pm.performDexOptSecondary(pkg,
-                            PackageManagerService.REASON_BACKGROUND_DEXOPT,
-                            /* force */ false);
+            boolean success;
+            if (is_for_primary_dex) {
+                int result = pm.performDexOptWithStatus(pkg,
+                        /* checkProfiles */ true,
+                        PackageManagerService.REASON_BACKGROUND_DEXOPT,
+                        /* force */ false);
+                success = result != PackageDexOptimizer.DEX_OPT_FAILED;
+                if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) {
+                    updatedPackages.add(pkg);
+                }
+            } else {
+                success = pm.performDexOptSecondary(pkg,
+                        PackageManagerService.REASON_BACKGROUND_DEXOPT,
+                        /* force */ false);
+            }
             if (success) {
                 // Dexopt succeeded, remove package from the list of failing ones.
                 synchronized (failedPackageNames) {
@@ -299,6 +314,7 @@
                 }
             }
         }
+        notifyPinService(updatedPackages);
         return OPTIMIZE_PROCESSED;
     }
 
@@ -366,11 +382,14 @@
             return false;
         }
 
+        boolean result;
         if (params.getJobId() == JOB_POST_BOOT_UPDATE) {
-            return runPostBootUpdate(params, pm, pkgs);
+            result = runPostBootUpdate(params, pm, pkgs);
         } else {
-            return runIdleOptimization(params, pm, pkgs);
+            result = runIdleOptimization(params, pm, pkgs);
         }
+
+        return result;
     }
 
     @Override
@@ -386,4 +405,12 @@
         }
         return false;
     }
+
+    private void notifyPinService(ArraySet<String> updatedPackages) {
+        PinnerService pinnerService = LocalServices.getService(PinnerService.class);
+        if (pinnerService != null) {
+            Log.i(TAG, "Pinning optimized code " + updatedPackages);
+            pinnerService.update(updatedPackages);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 6625331..ac7b763 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -77,8 +77,9 @@
     private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
-    private static final int DEFAULT_FLAGS = PackageManager.MATCH_DIRECT_BOOT_AWARE
-            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+    private static final int DEFAULT_FLAGS =
+            PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                    | PackageManager.MATCH_UNINSTALLED_PACKAGES;
 
     private static final String AUDIO_MIME_TYPE = "audio/mpeg";
 
diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
index 1de3936..562ab33 100644
--- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
+++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java
@@ -96,7 +96,7 @@
                 return mGetEphemeralResolveInfoCaller
                         .getEphemeralResolveInfoList(target, hashPrefix, token);
             } catch (TimeoutException e) {
-                throw new ConnectionException(ConnectionException.FAILURE_BIND);
+                throw new ConnectionException(ConnectionException.FAILURE_CALL);
             } catch (RemoteException ignore) {
             }
         } finally {
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 85be4a2..34cc6e3 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -182,6 +182,7 @@
                     failureIntent = null;
                 }
                 final Intent installerIntent = buildEphemeralInstallerIntent(
+                        Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE,
                         requestObj.origIntent,
                         failureIntent,
                         requestObj.callingPackage,
@@ -226,6 +227,7 @@
      * Builds and returns an intent to launch the instant installer.
      */
     public static Intent buildEphemeralInstallerIntent(
+            @NonNull String action,
             @NonNull Intent origIntent,
             @NonNull Intent failureIntent,
             @NonNull String callingPackage,
@@ -239,7 +241,7 @@
             boolean needsPhaseTwo) {
         // Construct the intent that launches the instant installer
         int flags = origIntent.getFlags();
-        final Intent intent = new Intent();
+        final Intent intent = new Intent(action);
         intent.setFlags(flags
                 | Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_CLEAR_TASK
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2975758..3ff91ef 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -20,7 +20,6 @@
 import static android.Manifest.permission.INSTALL_PACKAGES;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
-import static android.Manifest.permission.REQUEST_INSTALL_PACKAGES;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
 import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
@@ -100,10 +99,10 @@
 import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE;
 import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS;
 import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
-
 import static dalvik.system.DexFile.getNonProfileGuidedCompilerFilter;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -126,10 +125,8 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.AppsQueryHelper;
-import android.content.pm.ChangedPackages;
-import android.content.pm.ComponentInfo;
-import android.content.pm.InstantAppRequest;
 import android.content.pm.AuxiliaryResolveInfo;
+import android.content.pm.ChangedPackages;
 import android.content.pm.FallbackCategoryProvider;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IOnPermissionsChangeListener;
@@ -142,6 +139,7 @@
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstantAppInfo;
+import android.content.pm.InstantAppRequest;
 import android.content.pm.InstantAppResolveInfo;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.IntentFilterVerificationInfo;
@@ -303,6 +301,8 @@
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.nio.charset.StandardCharsets;
 import java.security.DigestInputStream;
 import java.security.MessageDigest;
@@ -441,6 +441,21 @@
 
     private static final int[] EMPTY_INT_ARRAY = new int[0];
 
+    private static final int TYPE_UNKNOWN = 0;
+    private static final int TYPE_ACTIVITY = 1;
+    private static final int TYPE_RECEIVER = 2;
+    private static final int TYPE_SERVICE = 3;
+    private static final int TYPE_PROVIDER = 4;
+    @IntDef(prefix = { "TYPE_" }, value = {
+            TYPE_UNKNOWN,
+            TYPE_ACTIVITY,
+            TYPE_RECEIVER,
+            TYPE_SERVICE,
+            TYPE_PROVIDER,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ComponentType {}
+
     /**
      * Timeout (in milliseconds) after which the watchdog should declare that
      * our handler thread is wedged.  The usual default for such things is one
@@ -2026,15 +2041,17 @@
             EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
                     getUnknownSourcesSettings());
 
-            // Force a gc to clear up things
-            Runtime.getRuntime().gc();
-
             // Remove the replaced package's older resources safely now
             // We delete after a gc for applications  on sdcard.
             if (res.removedInfo != null && res.removedInfo.args != null) {
+                Runtime.getRuntime().gc();
                 synchronized (mInstallLock) {
                     res.removedInfo.args.doPostDeleteLI(true);
                 }
+            } else {
+                // Force a gc to clear up things. Ask for a background one, it's fine to go on
+                // and not block here.
+                VMRuntime.getRuntime().requestConcurrentGC();
             }
 
             // Notify DexManager that the package was installed for new users.
@@ -3084,16 +3101,19 @@
 
     @Override
     public boolean isFirstBoot() {
+        // allow instant applications
         return mFirstBoot;
     }
 
     @Override
     public boolean isOnlyCoreApps() {
+        // allow instant applications
         return mOnlyCore;
     }
 
     @Override
     public boolean isUpgrade() {
+        // allow instant applications
         return mIsUpgrade;
     }
 
@@ -3187,6 +3207,9 @@
 
     @Override
     public @Nullable ComponentName getInstantAppResolverComponent() {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         synchronized (mPackages) {
             final Pair<ComponentName, String> instantAppResolver = getInstantAppResolverLPr();
             if (instantAppResolver == null) {
@@ -3480,44 +3503,59 @@
         return cur;
     }
 
+    /**
+     * Returns whether or not a full application can see an instant application.
+     * <p>
+     * Currently, there are three cases in which this can occur:
+     * <ol>
+     * <li>The calling application is a "special" process. The special
+     *     processes are {@link Process#SYSTEM_UID}, {@link Process#SHELL_UID}
+     *     and {@code 0}</li>
+     * <li>The calling application has the permission
+     *     {@link android.Manifest.permission#ACCESS_INSTANT_APPS}</li>
+     * <li>[TODO] The calling application is the default launcher on the
+     *     system partition.</li>
+     * </ol>
+     */
+    private boolean canViewInstantApps(int callingUid, int userId) {
+        if (callingUid == Process.SYSTEM_UID
+                || callingUid == Process.SHELL_UID
+                || callingUid == Process.ROOT_UID) {
+            return true;
+        }
+        if (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED) {
+            return true;
+        }
+        if (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.VIEW_INSTANT_APPS) == PERMISSION_GRANTED) {
+            final ComponentName homeComponent = getDefaultHomeActivity(userId);
+            if (homeComponent != null
+                    && isCallerSameApp(homeComponent.getPackageName(), callingUid)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private PackageInfo generatePackageInfo(PackageSetting ps, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         if (ps == null) {
             return null;
         }
-        final PackageParser.Package p = ps.pkg;
+        PackageParser.Package p = ps.pkg;
         if (p == null) {
             return null;
         }
+        final int callingUid = Binder.getCallingUid();
         // Filter out ephemeral app metadata:
         //   * The system/shell/root can see metadata for any app
         //   * An installed app can see metadata for 1) other installed apps
         //     and 2) ephemeral apps that have explicitly interacted with it
         //   * Ephemeral apps can only see their own data and exposed installed apps
         //   * Holding a signature permission allows seeing instant apps
-        final int callingAppId = UserHandle.getAppId(Binder.getCallingUid());
-        if (callingAppId != Process.SYSTEM_UID
-                && callingAppId != Process.SHELL_UID
-                && callingAppId != Process.ROOT_UID
-                && checkUidPermission(Manifest.permission.ACCESS_INSTANT_APPS,
-                        Binder.getCallingUid()) != PackageManager.PERMISSION_GRANTED) {
-            final String instantAppPackageName = getInstantAppPackageName(Binder.getCallingUid());
-            if (instantAppPackageName != null) {
-                // ephemeral apps can only get information on themselves or
-                // installed apps that are exposed.
-                if (!instantAppPackageName.equals(p.packageName)
-                        && (ps.getInstantApp(userId) || !p.visibleToInstantApps)) {
-                    return null;
-                }
-            } else {
-                if (ps.getInstantApp(userId)) {
-                    // only get access to the ephemeral app if we've been granted access
-                    if (!mInstantAppRegistry.isInstantAccessGranted(
-                            userId, callingAppId, ps.appId)) {
-                        return null;
-                    }
-                }
-            }
+        if (filterAppAccessLPr(ps, callingUid, userId)) {
+            return null;
         }
 
         final PermissionsState permissionsState = ps.getPermissionsState();
@@ -3552,8 +3590,10 @@
 
     @Override
     public void checkPackageStartable(String packageName, int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            throw new SecurityException("Instant applications don't have access to this method");
+        }
         final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
-
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
             if (ps == null) {
@@ -3583,12 +3623,16 @@
     @Override
     public boolean isPackageAvailable(String packageName, int userId) {
         if (!sUserManager.exists(userId)) return false;
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
-                false /* requireFullPermission */, false /* checkShell */, "is package available");
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
+                false /*requireFullPermission*/, false /*checkShell*/, "is package available");
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
             if (p != null) {
                 final PackageSetting ps = (PackageSetting) p.mExtras;
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    return false;
+                }
                 if (ps != null) {
                     final PackageUserState state = ps.readUserState(userId);
                     if (state != null) {
@@ -3616,8 +3660,9 @@
     private PackageInfo getPackageInfoInternal(String packageName, int versionCode,
             int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get package info");
 
         // reader
@@ -3629,7 +3674,10 @@
             if (matchFactoryOnly) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 if (ps != null) {
-                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                        return null;
+                    }
+                    if (filterAppAccessLPr(ps, callingUid, userId)) {
                         return null;
                     }
                     return generatePackageInfo(ps, flags, userId);
@@ -3643,15 +3691,22 @@
             if (DEBUG_PACKAGE_INFO)
                 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
             if (p != null) {
-                if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
-                        Binder.getCallingUid(), userId, flags)) {
+                final PackageSetting ps = (PackageSetting) p.mExtras;
+                if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                    return null;
+                }
+                if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
                     return null;
                 }
                 return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
             }
             if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
-                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                if (ps == null) return null;
+                if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                    return null;
+                }
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
                     return null;
                 }
                 return generatePackageInfo(ps, flags, userId);
@@ -3660,6 +3715,105 @@
         return null;
     }
 
+    private boolean isComponentVisibleToInstantApp(@Nullable ComponentName component) {
+        if (isComponentVisibleToInstantApp(component, TYPE_ACTIVITY)) {
+            return true;
+        }
+        if (isComponentVisibleToInstantApp(component, TYPE_SERVICE)) {
+            return true;
+        }
+        if (isComponentVisibleToInstantApp(component, TYPE_PROVIDER)) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isComponentVisibleToInstantApp(
+            @Nullable ComponentName component, @ComponentType int type) {
+        if (type == TYPE_ACTIVITY) {
+            final PackageParser.Activity activity = mActivities.mActivities.get(component);
+            return activity != null
+                    ? (activity.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
+                    : false;
+        } else if (type == TYPE_RECEIVER) {
+            final PackageParser.Activity activity = mReceivers.mActivities.get(component);
+            return activity != null
+                    ? (activity.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
+                    : false;
+        } else if (type == TYPE_SERVICE) {
+            final PackageParser.Service service = mServices.mServices.get(component);
+            return service != null
+                    ? (service.info.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
+                    : false;
+        } else if (type == TYPE_PROVIDER) {
+            final PackageParser.Provider provider = mProviders.mProviders.get(component);
+            return provider != null
+                    ? (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
+                    : false;
+        } else if (type == TYPE_UNKNOWN) {
+            return isComponentVisibleToInstantApp(component);
+        }
+        return false;
+    }
+
+    /**
+     * Returns whether or not access to the application should be filtered.
+     * <p>
+     * Access may be limited based upon whether the calling or target applications
+     * are instant applications.
+     *
+     * @see #canAccessInstantApps(int)
+     */
+    private boolean filterAppAccessLPr(@Nullable PackageSetting ps, int callingUid,
+            @Nullable ComponentName component, @ComponentType int componentType, int userId) {
+        // if we're in an isolated process, get the real calling UID
+        if (Process.isIsolated(callingUid)) {
+            callingUid = mIsolatedOwners.get(callingUid);
+        }
+        final String instantAppPkgName = getInstantAppPackageName(callingUid);
+        final boolean callerIsInstantApp = instantAppPkgName != null;
+        if (ps == null) {
+            if (callerIsInstantApp) {
+                // pretend the application exists, but, needs to be filtered
+                return true;
+            }
+            return false;
+        }
+        // if the target and caller are the same application, don't filter
+        if (isCallerSameApp(ps.name, callingUid)) {
+            return false;
+        }
+        if (callerIsInstantApp) {
+            // request for a specific component; if it hasn't been explicitly exposed, filter
+            if (component != null) {
+                return !isComponentVisibleToInstantApp(component, componentType);
+            }
+            // request for application; if no components have been explicitly exposed, filter
+            return ps.getInstantApp(userId) || !ps.pkg.visibleToInstantApps;
+        }
+        if (ps.getInstantApp(userId)) {
+            // caller can see all components of all instant applications, don't filter
+            if (canViewInstantApps(callingUid, userId)) {
+                return false;
+            }
+            // request for a specific instant application component, filter
+            if (component != null) {
+                return true;
+            }
+            // request for an instant application; if the caller hasn't been granted access, filter
+            return !mInstantAppRegistry.isInstantAccessGranted(
+                    userId, UserHandle.getAppId(callingUid), ps.appId);
+        }
+        return false;
+    }
+
+    /**
+     * @see #filterAppAccessLPr(PackageSetting, int, ComponentName, boolean, int)
+     */
+    private boolean filterAppAccessLPr(@Nullable PackageSetting ps, int callingUid, int userId) {
+        return filterAppAccessLPr(ps, callingUid, null, TYPE_UNKNOWN, userId);
+    }
+
     private boolean filterSharedLibPackageLPr(@Nullable PackageSetting ps, int uid, int userId,
             int flags) {
         // Callers can access only the libs they depend on, otherwise they need to explicitly
@@ -3711,6 +3865,9 @@
 
     @Override
     public String[] currentToCanonicalPackageNames(String[] names) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return names;
+        }
         String[] out = new String[names.length];
         // reader
         synchronized (mPackages) {
@@ -3724,6 +3881,9 @@
 
     @Override
     public String[] canonicalToCurrentPackageNames(String[] names) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return names;
+        }
         String[] out = new String[names.length];
         // reader
         synchronized (mPackages) {
@@ -3738,19 +3898,25 @@
     @Override
     public int getPackageUid(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return -1;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
-                false /* requireFullPermission */, false /* checkShell */, "get package uid");
+        enforceCrossUserPermission(callingUid, userId,
+                false /*requireFullPermission*/, false /*checkShell*/, "getPackageUid");
 
         // reader
         synchronized (mPackages) {
             final PackageParser.Package p = mPackages.get(packageName);
             if (p != null && p.isMatch(flags)) {
+                PackageSetting ps = (PackageSetting) p.mExtras;
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    return -1;
+                }
                 return UserHandle.getUid(userId, p.applicationInfo.uid);
             }
             if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
-                if (ps != null && ps.isMatch(flags)) {
+                if (ps != null && ps.isMatch(flags)
+                        && !filterAppAccessLPr(ps, callingUid, userId)) {
                     return UserHandle.getUid(userId, ps.appId);
                 }
             }
@@ -3762,23 +3928,27 @@
     @Override
     public int[] getPackageGids(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
-                false /* requireFullPermission */, false /* checkShell */,
-                "getPackageGids");
+        enforceCrossUserPermission(callingUid, userId,
+                false /*requireFullPermission*/, false /*checkShell*/, "getPackageGids");
 
         // reader
         synchronized (mPackages) {
             final PackageParser.Package p = mPackages.get(packageName);
             if (p != null && p.isMatch(flags)) {
                 PackageSetting ps = (PackageSetting) p.mExtras;
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    return null;
+                }
                 // TODO: Shouldn't this be checking for package installed state for userId and
                 // return null?
                 return ps.getPermissionsState().computeGids(userId);
             }
             if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
-                if (ps != null && ps.isMatch(flags)) {
+                if (ps != null && ps.isMatch(flags)
+                        && !filterAppAccessLPr(ps, callingUid, userId)) {
                     return ps.getPermissionsState().computeGids(userId);
                 }
             }
@@ -3801,6 +3971,9 @@
 
     @Override
     public PermissionInfo getPermissionInfo(String name, int flags) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         // reader
         synchronized (mPackages) {
             final BasePermission p = mSettings.mPermissions.get(name);
@@ -3814,6 +3987,9 @@
     @Override
     public @Nullable ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String group,
             int flags) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         // reader
         synchronized (mPackages) {
             if (group != null && !mPermissionGroups.containsKey(group)) {
@@ -3839,6 +4015,9 @@
 
     @Override
     public PermissionGroupInfo getPermissionGroupInfo(String name, int flags) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         // reader
         synchronized (mPackages) {
             return PackageParser.generatePermissionGroupInfo(
@@ -3848,6 +4027,9 @@
 
     @Override
     public @NonNull ParceledListSlice<PermissionGroupInfo> getAllPermissionGroups(int flags) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return ParceledListSlice.emptyList();
+        }
         // reader
         synchronized (mPackages) {
             final int N = mPermissionGroups.size();
@@ -3868,6 +4050,9 @@
             if (filterSharedLibPackageLPr(ps, uid, userId, flags)) {
                 return null;
             }
+            if (filterAppAccessLPr(ps, uid, userId)) {
+                return null;
+            }
             if (ps.pkg == null) {
                 final PackageInfo pInfo = generatePackageInfo(ps, flags, userId);
                 if (pInfo != null) {
@@ -3909,6 +4094,9 @@
                 if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                     return null;
                 }
+                if (filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                    return null;
+                }
                 // Note: isEnabledLP() does not apply here - always return info
                 ApplicationInfo ai = PackageParser.generateApplicationInfo(
                         p, flags, ps.readUserState(userId), userId);
@@ -4208,15 +4396,15 @@
      */
     int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid) {
         return updateFlagsForResolve(flags, userId, intent, callingUid,
-                false /*includeInstantApps*/, false /*onlyExposedExplicitly*/);
+                false /*wantInstantApps*/, false /*onlyExposedExplicitly*/);
     }
     int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
-            boolean includeInstantApps) {
+            boolean wantInstantApps) {
         return updateFlagsForResolve(flags, userId, intent, callingUid,
-                includeInstantApps, false /*onlyExposedExplicitly*/);
+                wantInstantApps, false /*onlyExposedExplicitly*/);
     }
     int updateFlagsForResolve(int flags, int userId, Intent intent, int callingUid,
-            boolean includeInstantApps, boolean onlyExposedExplicitly) {
+            boolean wantInstantApps, boolean onlyExposedExplicitly) {
         // Safe mode means we shouldn't match any third-party components
         if (mSafeMode) {
             flags |= PackageManager.MATCH_SYSTEM_ONLY;
@@ -4229,18 +4417,12 @@
             flags |= PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY;
             flags |= PackageManager.MATCH_INSTANT;
         } else {
-            // Otherwise, prevent leaking ephemeral components
-            final boolean isSpecialProcess =
-                    callingUid == Process.SYSTEM_UID
-                    || callingUid == Process.SHELL_UID
-                    || callingUid == 0;
+            final boolean wantMatchInstant = (flags & PackageManager.MATCH_INSTANT) != 0;
             final boolean allowMatchInstant =
-                    (includeInstantApps
+                    (wantInstantApps
                             && Intent.ACTION_VIEW.equals(intent.getAction())
                             && hasWebURI(intent))
-                    || isSpecialProcess
-                    || mContext.checkCallingOrSelfPermission(
-                            android.Manifest.permission.ACCESS_INSTANT_APPS) == PERMISSION_GRANTED;
+                    || (wantMatchInstant && canViewInstantApps(callingUid, userId));
             flags &= ~(PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY
                     | PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY);
             if (!allowMatchInstant) {
@@ -4271,8 +4453,9 @@
     @Override
     public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get activity info");
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
@@ -4281,6 +4464,9 @@
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
+                if (filterAppAccessLPr(ps, callingUid, component, TYPE_ACTIVITY, userId)) {
+                    return null;
+                }
                 return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
             }
             if (mResolveComponentName.equals(component)) {
@@ -4299,10 +4485,19 @@
                 // The resolver supports EVERYTHING!
                 return true;
             }
+            final int callingUid = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getUserId(callingUid);
             PackageParser.Activity a = mActivities.mActivities.get(component);
             if (a == null) {
                 return false;
             }
+            PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+            if (ps == null) {
+                return false;
+            }
+            if (filterAppAccessLPr(ps, callingUid, component, TYPE_ACTIVITY, callingUserId)) {
+                return false;
+            }
             for (int i=0; i<a.intents.size(); i++) {
                 if (a.intents.get(i).match(intent.getAction(), resolvedType, intent.getScheme(),
                         intent.getData(), intent.getCategories(), TAG) >= 0) {
@@ -4316,8 +4511,9 @@
     @Override
     public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get receiver info");
         synchronized (mPackages) {
             PackageParser.Activity a = mReceivers.mActivities.get(component);
@@ -4326,6 +4522,9 @@
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
+                if (filterAppAccessLPr(ps, callingUid, component, TYPE_RECEIVER, userId)) {
+                    return null;
+                }
                 return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
             }
         }
@@ -4337,6 +4536,9 @@
             int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         Preconditions.checkArgumentNonnegative(userId, "userId must be >= 0");
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
 
         flags = updateFlagsForPackage(flags, userId, null);
 
@@ -4445,8 +4647,9 @@
     @Override
     public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get service info");
         synchronized (mPackages) {
             PackageParser.Service s = mServices.mServices.get(component);
@@ -4455,6 +4658,9 @@
             if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
+                if (filterAppAccessLPr(ps, callingUid, component, TYPE_SERVICE, userId)) {
+                    return null;
+                }
                 ServiceInfo si = PackageParser.generateServiceInfo(s, flags,
                         ps.readUserState(userId), userId);
                 if (si != null) {
@@ -4469,8 +4675,9 @@
     @Override
     public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
+        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get provider info");
         synchronized (mPackages) {
             PackageParser.Provider p = mProviders.mProviders.get(component);
@@ -4479,6 +4686,9 @@
             if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
+                if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
+                    return null;
+                }
                 ProviderInfo pi = PackageParser.generateProviderInfo(p, flags,
                         ps.readUserState(userId), userId);
                 if (pi != null) {
@@ -4492,6 +4702,7 @@
 
     @Override
     public String[] getSystemSharedLibraryNames() {
+        // allow instant applications
         synchronized (mPackages) {
             Set<String> libs = null;
             final int libCount = mSharedLibraries.size();
@@ -4535,6 +4746,7 @@
 
     @Override
     public @NonNull String getServicesSystemSharedLibraryPackageName() {
+        // allow instant applications
         synchronized (mPackages) {
             return mServicesSystemSharedLibraryPackageName;
         }
@@ -4542,6 +4754,7 @@
 
     @Override
     public @NonNull String getSharedSystemSharedLibraryPackageName() {
+        // allow instant applications
         synchronized (mPackages) {
             return mSharedSystemSharedLibraryPackageName;
         }
@@ -4572,6 +4785,9 @@
 
     @Override
     public ChangedPackages getChangedPackages(int sequenceNumber, int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         synchronized (mPackages) {
             if (sequenceNumber >= mChangedPackagesSequenceNumber) {
                 return null;
@@ -4595,6 +4811,7 @@
 
     @Override
     public @NonNull ParceledListSlice<FeatureInfo> getSystemAvailableFeatures() {
+        // allow instant applications
         ArrayList<FeatureInfo> res;
         synchronized (mAvailableFeatures) {
             res = new ArrayList<>(mAvailableFeatures.size() + 1);
@@ -4610,6 +4827,7 @@
 
     @Override
     public boolean hasSystemFeature(String name, int version) {
+        // allow instant applications
         synchronized (mAvailableFeatures) {
             final FeatureInfo feat = mAvailableFeatures.get(name);
             if (feat == null) {
@@ -4625,11 +4843,15 @@
         if (!sUserManager.exists(userId)) {
             return PackageManager.PERMISSION_DENIED;
         }
+        final int callingUid = Binder.getCallingUid();
 
         synchronized (mPackages) {
             final PackageParser.Package p = mPackages.get(pkgName);
             if (p != null && p.mExtras != null) {
                 final PackageSetting ps = (PackageSetting) p.mExtras;
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    return PackageManager.PERMISSION_DENIED;
+                }
                 final PermissionsState permissionsState = ps.getPermissionsState();
                 if (permissionsState.hasPermission(permName, userId)) {
                     return PackageManager.PERMISSION_GRANTED;
@@ -4647,8 +4869,10 @@
 
     @Override
     public int checkUidPermission(String permName, int uid) {
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
         final int userId = UserHandle.getUserId(uid);
-
         if (!sUserManager.exists(userId)) {
             return PackageManager.PERMISSION_DENIED;
         }
@@ -4656,8 +4880,18 @@
         synchronized (mPackages) {
             Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
             if (obj != null) {
-                final SettingBase ps = (SettingBase) obj;
-                final PermissionsState permissionsState = ps.getPermissionsState();
+                if (obj instanceof SharedUserSetting) {
+                    if (isCallerInstantApp) {
+                        return PackageManager.PERMISSION_DENIED;
+                    }
+                } else if (obj instanceof PackageSetting) {
+                    final PackageSetting ps = (PackageSetting) obj;
+                    if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
+                        return PackageManager.PERMISSION_DENIED;
+                    }
+                }
+                final SettingBase settingBase = (SettingBase) obj;
+                final PermissionsState permissionsState = settingBase.getPermissionsState();
                 if (permissionsState.hasPermission(permName, userId)) {
                     return PackageManager.PERMISSION_GRANTED;
                 }
@@ -4696,6 +4930,17 @@
             return false;
         }
 
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
+            if (!isCallerSameApp(packageName, callingUid)) {
+                return false;
+            }
+        } else {
+            if (isInstantApp(packageName, userId)) {
+                return false;
+            }
+        }
+
         final long identity = Binder.clearCallingIdentity();
         try {
             final int flags = getPermissionFlags(permission, packageName, userId);
@@ -4707,6 +4952,9 @@
 
     @Override
     public String getPermissionControllerPackageName() {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            throw new SecurityException("Instant applications don't have access to this method");
+        }
         synchronized (mPackages) {
             return mRequiredInstallerPackage;
         }
@@ -4841,6 +5089,9 @@
     }
 
     boolean addPermissionLocked(PermissionInfo info, boolean async) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            throw new SecurityException("Instant apps can't add permissions");
+        }
         if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
             throw new SecurityException("Label must be specified in permission");
         }
@@ -4900,6 +5151,9 @@
 
     @Override
     public void removePermission(String name) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            throw new SecurityException("Instant applications don't have access to this method");
+        }
         synchronized (mPackages) {
             checkPermissionTreeLP(name);
             BasePermission bp = mSettings.mPermissions.get(name);
@@ -4915,8 +5169,8 @@
         }
     }
 
-    private static void enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(PackageParser.Package pkg,
-            BasePermission bp) {
+    private static void enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(
+            PackageParser.Package pkg, BasePermission bp) {
         int index = pkg.requestedPermissions.indexOf(bp.name);
         if (index == -1) {
             throw new SecurityException("Package " + pkg.packageName
@@ -5433,6 +5687,9 @@
 
     @Override
     public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            throw new SecurityException("Instant applications don't have access to this method");
+        }
         synchronized (mPackages) {
             mOnPermissionChangeListeners.removeListenerLocked(listener);
         }
@@ -5440,6 +5697,7 @@
 
     @Override
     public boolean isProtectedBroadcast(String actionName) {
+        // allow instant applications
         synchronized (mPackages) {
             if (mProtectedBroadcasts.contains(actionName)) {
                 return true;
@@ -5465,12 +5723,23 @@
                     || p2 == null || p2.mExtras == null) {
                 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
             }
+            final int callingUid = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final PackageSetting ps1 = (PackageSetting) p1.mExtras;
+            final PackageSetting ps2 = (PackageSetting) p2.mExtras;
+            if (filterAppAccessLPr(ps1, callingUid, callingUserId)
+                    || filterAppAccessLPr(ps2, callingUid, callingUserId)) {
+                return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+            }
             return compareSignatures(p1.mSignatures, p2.mSignatures);
         }
     }
 
     @Override
     public int checkUidSignatures(int uid1, int uid2) {
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
         // Map to base uids.
         uid1 = UserHandle.getAppId(uid1);
         uid2 = UserHandle.getAppId(uid2);
@@ -5481,9 +5750,16 @@
             Object obj = mSettings.getUserIdLPr(uid1);
             if (obj != null) {
                 if (obj instanceof SharedUserSetting) {
+                    if (isCallerInstantApp) {
+                        return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+                    }
                     s1 = ((SharedUserSetting)obj).signatures.mSignatures;
                 } else if (obj instanceof PackageSetting) {
-                    s1 = ((PackageSetting)obj).signatures.mSignatures;
+                    final PackageSetting ps = (PackageSetting) obj;
+                    if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
+                        return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+                    }
+                    s1 = ps.signatures.mSignatures;
                 } else {
                     return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
                 }
@@ -5493,9 +5769,16 @@
             obj = mSettings.getUserIdLPr(uid2);
             if (obj != null) {
                 if (obj instanceof SharedUserSetting) {
+                    if (isCallerInstantApp) {
+                        return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+                    }
                     s2 = ((SharedUserSetting)obj).signatures.mSignatures;
                 } else if (obj instanceof PackageSetting) {
-                    s2 = ((PackageSetting)obj).signatures.mSignatures;
+                    final PackageSetting ps = (PackageSetting) obj;
+                    if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
+                        return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+                    }
+                    s2 = ps.signatures.mSignatures;
                 } else {
                     return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
                 }
@@ -5661,19 +5944,53 @@
 
     @Override
     public List<String> getAllPackages() {
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
         synchronized (mPackages) {
-            return new ArrayList<String>(mPackages.keySet());
+            if (canViewInstantApps(callingUid, callingUserId)) {
+                return new ArrayList<String>(mPackages.keySet());
+            }
+            final String instantAppPkgName = getInstantAppPackageName(callingUid);
+            final List<String> result = new ArrayList<>();
+            if (instantAppPkgName != null) {
+                // caller is an instant application; filter unexposed applications
+                for (PackageParser.Package pkg : mPackages.values()) {
+                    if (!pkg.visibleToInstantApps) {
+                        continue;
+                    }
+                    result.add(pkg.packageName);
+                }
+            } else {
+                // caller is a normal application; filter instant applications
+                for (PackageParser.Package pkg : mPackages.values()) {
+                    final PackageSetting ps =
+                            pkg.mExtras != null ? (PackageSetting) pkg.mExtras : null;
+                    if (ps != null
+                            && ps.getInstantApp(callingUserId)
+                            && !mInstantAppRegistry.isInstantAccessGranted(
+                                    callingUserId, UserHandle.getAppId(callingUid), ps.appId)) {
+                        continue;
+                    }
+                    result.add(pkg.packageName);
+                }
+            }
+            return result;
         }
     }
 
     @Override
     public String[] getPackagesForUid(int uid) {
+        final int callingUid = Binder.getCallingUid();
+        final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
         final int userId = UserHandle.getUserId(uid);
         uid = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
             Object obj = mSettings.getUserIdLPr(uid);
             if (obj instanceof SharedUserSetting) {
+                if (isCallerInstantApp) {
+                    return null;
+                }
                 final SharedUserSetting sus = (SharedUserSetting) obj;
                 final int N = sus.packages.size();
                 String[] res = new String[N];
@@ -5690,7 +6007,7 @@
                 return res;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
-                if (ps.getInstalled(userId)) {
+                if (ps.getInstalled(userId) && !filterAppAccessLPr(ps, callingUid, userId)) {
                     return new String[]{ps.name};
                 }
             }
@@ -5700,7 +6017,10 @@
 
     @Override
     public String getNameForUid(int uid) {
-        // reader
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
+            return null;
+        }
         synchronized (mPackages) {
             Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
             if (obj instanceof SharedUserSetting) {
@@ -5708,6 +6028,9 @@
                 return sus.name + ":" + sus.userId;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
+                if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                    return null;
+                }
                 return ps.name;
             }
         }
@@ -5716,7 +6039,10 @@
 
     @Override
     public int getUidForSharedUser(String sharedUserName) {
-        if(sharedUserName == null) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return -1;
+        }
+        if (sharedUserName == null) {
             return -1;
         }
         // reader
@@ -5736,6 +6062,9 @@
 
     @Override
     public int getFlagsForUid(int uid) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return 0;
+        }
         synchronized (mPackages) {
             Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
             if (obj instanceof SharedUserSetting) {
@@ -5751,6 +6080,9 @@
 
     @Override
     public int getPrivateFlagsForUid(int uid) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return 0;
+        }
         synchronized (mPackages) {
             Object obj = mSettings.getUserIdLPr(UserHandle.getAppId(uid));
             if (obj instanceof SharedUserSetting) {
@@ -5766,6 +6098,9 @@
 
     @Override
     public boolean isUidPrivileged(int uid) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        }
         uid = UserHandle.getAppId(uid);
         // reader
         synchronized (mPackages) {
@@ -5788,6 +6123,9 @@
 
     @Override
     public String[] getAppOpPermissionPackages(String permissionName) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         synchronized (mPackages) {
             ArraySet<String> pkgs = mAppOpPermissionPackages.get(permissionName);
             if (pkgs == null) {
@@ -5853,6 +6191,9 @@
     @Override
     public void setLastChosenActivity(Intent intent, String resolvedType, int flags,
             IntentFilter filter, int match, ComponentName activity) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return;
+        }
         final int userId = UserHandle.getCallingUserId();
         if (DEBUG_PREFERRED) {
             Log.v(TAG, "setLastChosenActivity intent=" + intent
@@ -5876,6 +6217,9 @@
 
     @Override
     public ResolveInfo getLastChosenActivity(Intent intent, String resolvedType, int flags) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         final int userId = UserHandle.getCallingUserId();
         if (DEBUG_PREFERRED) Log.v(TAG, "Querying last chosen activity for " + intent);
         final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
@@ -6337,12 +6681,12 @@
      * instant, returns {@code null}.
      */
     private String getInstantAppPackageName(int callingUid) {
-        // If the caller is an isolated app use the owner's uid for the lookup.
-        if (Process.isIsolated(callingUid)) {
-            callingUid = mIsolatedOwners.get(callingUid);
-        }
-        final int appId = UserHandle.getAppId(callingUid);
         synchronized (mPackages) {
+            // If the caller is an isolated app use the owner's uid for the lookup.
+            if (Process.isIsolated(callingUid)) {
+                callingUid = mIsolatedOwners.get(callingUid);
+            }
+            final int appId = UserHandle.getAppId(callingUid);
             final Object obj = mSettings.getUserIdLPr(appId);
             if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
@@ -7257,6 +7601,7 @@
             String resolvedType, int flags, int userId) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
         final int callingUid = Binder.getCallingUid();
+        final String instantAppPkgName = getInstantAppPackageName(callingUid);
         flags = updateFlagsForResolve(flags, userId, intent, callingUid,
                 false /*includeInstantApps*/);
         ComponentName comp = intent.getComponent();
@@ -7267,26 +7612,61 @@
             }
         }
         if (comp != null) {
-            List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
-            ActivityInfo ai = getReceiverInfo(comp, flags, userId);
+            final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
+            final ActivityInfo ai = getReceiverInfo(comp, flags, userId);
             if (ai != null) {
-                ResolveInfo ri = new ResolveInfo();
-                ri.activityInfo = ai;
-                list.add(ri);
+                // When specifying an explicit component, we prevent the activity from being
+                // used when either 1) the calling package is normal and the activity is within
+                // an instant application or 2) the calling package is ephemeral and the
+                // activity is not visible to instant applications.
+                final boolean matchInstantApp =
+                        (flags & PackageManager.MATCH_INSTANT) != 0;
+                final boolean matchVisibleToInstantAppOnly =
+                        (flags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+                final boolean matchExplicitlyVisibleOnly =
+                        (flags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
+                final boolean isCallerInstantApp =
+                        instantAppPkgName != null;
+                final boolean isTargetSameInstantApp =
+                        comp.getPackageName().equals(instantAppPkgName);
+                final boolean isTargetInstantApp =
+                        (ai.applicationInfo.privateFlags
+                                & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
+                final boolean isTargetVisibleToInstantApp =
+                        (ai.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+                final boolean isTargetExplicitlyVisibleToInstantApp =
+                        isTargetVisibleToInstantApp
+                        && (ai.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
+                final boolean isTargetHiddenFromInstantApp =
+                        !isTargetVisibleToInstantApp
+                        || (matchExplicitlyVisibleOnly && !isTargetExplicitlyVisibleToInstantApp);
+                final boolean blockResolution =
+                        !isTargetSameInstantApp
+                        && ((!matchInstantApp && !isCallerInstantApp && isTargetInstantApp)
+                                || (matchVisibleToInstantAppOnly && isCallerInstantApp
+                                        && isTargetHiddenFromInstantApp));
+                if (!blockResolution) {
+                    ResolveInfo ri = new ResolveInfo();
+                    ri.activityInfo = ai;
+                    list.add(ri);
+                }
             }
-            return list;
+            return applyPostResolutionFilter(list, instantAppPkgName);
         }
 
         // reader
         synchronized (mPackages) {
             String pkgName = intent.getPackage();
             if (pkgName == null) {
-                return mReceivers.queryIntent(intent, resolvedType, flags, userId);
+                final List<ResolveInfo> result =
+                        mReceivers.queryIntent(intent, resolvedType, flags, userId);
+                return applyPostResolutionFilter(result, instantAppPkgName);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,
-                        userId);
+                final List<ResolveInfo> result = mReceivers.queryIntentForPackage(
+                        intent, resolvedType, flags, pkg.receivers, userId);
+                return applyPostResolutionFilter(result, instantAppPkgName);
             }
             return Collections.emptyList();
         }
@@ -7559,6 +7939,9 @@
 
     @Override
     public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return ParceledListSlice.emptyList();
+        }
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForPackage(flags, userId, null);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
@@ -7673,6 +8056,9 @@
 
     @Override
     public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return ParceledListSlice.emptyList();
+        }
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForApplication(flags, userId, null);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
@@ -7736,7 +8122,6 @@
         if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
             return null;
         }
-
         mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_INSTANT_APPS,
                 "getEphemeralApplications");
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -7760,9 +8145,9 @@
         if (HIDE_EPHEMERAL_APIS || isEphemeralDisabled()) {
             return false;
         }
-        int uid = Binder.getCallingUid();
-        if (Process.isIsolated(uid)) {
-            uid = mIsolatedOwners.get(uid);
+        int callingUid = Binder.getCallingUid();
+        if (Process.isIsolated(callingUid)) {
+            callingUid = mIsolatedOwners.get(callingUid);
         }
 
         synchronized (mPackages) {
@@ -7770,12 +8155,10 @@
             PackageParser.Package pkg = mPackages.get(packageName);
             final boolean returnAllowed =
                     ps != null
-                    && (isCallerSameApp(packageName, uid)
-                            || mContext.checkCallingOrSelfPermission(
-                                    android.Manifest.permission.ACCESS_INSTANT_APPS)
-                                            == PERMISSION_GRANTED
+                    && (isCallerSameApp(packageName, callingUid)
+                            || canViewInstantApps(callingUid, userId)
                             || mInstantAppRegistry.isInstantAccessGranted(
-                                    userId, UserHandle.getAppId(uid), ps.appId));
+                                    userId, UserHandle.getAppId(callingUid), ps.appId));
             if (returnAllowed) {
                 return ps.getInstantApp(userId);
             }
@@ -7846,6 +8229,9 @@
 
     @Override
     public @NonNull ParceledListSlice<ApplicationInfo> getPersistentApplications(int flags) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return ParceledListSlice.emptyList();
+        }
         return new ParceledListSlice<>(getPersistentApplicationsInternal(flags));
     }
 
@@ -7929,6 +8315,9 @@
      */
     @Deprecated
     public void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return;
+        }
         // reader
         synchronized (mPackages) {
             final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProvidersByAuthority
@@ -7956,11 +8345,11 @@
     @Override
     public @NonNull ParceledListSlice<ProviderInfo> queryContentProviders(String processName,
             int uid, int flags, String metaDataKey) {
+        final int callingUid = Binder.getCallingUid();
         final int userId = processName != null ? UserHandle.getUserId(uid)
                 : UserHandle.getCallingUserId();
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForComponent(flags, userId, processName);
-
         ArrayList<ProviderInfo> finalList = null;
         // reader
         synchronized (mPackages) {
@@ -7980,7 +8369,11 @@
                             && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) {
                         continue;
                     }
-
+                    final ComponentName component =
+                            new ComponentName(p.info.packageName, p.info.name);
+                    if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
+                        continue;
+                    }
                     if (finalList == null) {
                         finalList = new ArrayList<ProviderInfo>(3);
                     }
@@ -8002,10 +8395,17 @@
     }
 
     @Override
-    public InstrumentationInfo getInstrumentationInfo(ComponentName name, int flags) {
+    public InstrumentationInfo getInstrumentationInfo(ComponentName component, int flags) {
         // reader
         synchronized (mPackages) {
-            final PackageParser.Instrumentation i = mInstrumentation.get(name);
+            final int callingUid = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
+            if (ps == null) return null;
+            if (filterAppAccessLPr(ps, callingUid, component, TYPE_UNKNOWN, callingUserId)) {
+                return null;
+            }
+            final PackageParser.Instrumentation i = mInstrumentation.get(component);
             return PackageParser.generateInstrumentationInfo(i, flags);
         }
     }
@@ -8013,6 +8413,12 @@
     @Override
     public @NonNull ParceledListSlice<InstrumentationInfo> queryInstrumentation(
             String targetPackage, int flags) {
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
+        final PackageSetting ps = mSettings.mPackages.get(targetPackage);
+        if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
+            return ParceledListSlice.emptyList();
+        }
         return new ParceledListSlice<>(queryInstrumentationInternal(targetPackage, flags));
     }
 
@@ -8624,7 +9030,7 @@
      */
     private static final void enforceSystemOrRoot(String message) {
         final int uid = Binder.getCallingUid();
-        if (uid != Process.SYSTEM_UID && uid != 0) {
+        if (uid != Process.SYSTEM_UID && uid != Process.ROOT_UID) {
             throw new SecurityException(message);
         }
     }
@@ -8799,7 +9205,18 @@
     @Override
     public void notifyPackageUse(String packageName, int reason) {
         synchronized (mPackages) {
-            PackageParser.Package p = mPackages.get(packageName);
+            final int callingUid = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            if (getInstantAppPackageName(callingUid) != null) {
+                if (!isCallerSameApp(packageName, callingUid)) {
+                    return;
+                }
+            } else {
+                if (isInstantApp(packageName, callingUserId)) {
+                    return;
+                }
+            }
+            final PackageParser.Package p = mPackages.get(packageName);
             if (p == null) {
                 return;
             }
@@ -8822,14 +9239,28 @@
     @Override
     public boolean performDexOpt(String packageName,
             boolean checkProfiles, int compileReason, boolean force) {
-        int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
+        return performDexOptWithStatus(packageName, checkProfiles, compileReason, force) !=
+                PackageDexOptimizer.DEX_OPT_FAILED;
+    }
+
+    /**
+     * Perform dexopt on the given package and return one of following result:
+     *  {@link PackageDexOptimizer#DEX_OPT_SKIPPED}
+     *  {@link PackageDexOptimizer#DEX_OPT_PERFORMED}
+     *  {@link PackageDexOptimizer#DEX_OPT_FAILED}
+     */
+    /* package */ int performDexOptWithStatus(String packageName,
+            boolean checkProfiles, int compileReason, boolean force) {
+        return performDexOptTraced(packageName, checkProfiles,
                 getCompilerFilterForReason(compileReason), force);
-        return dexOptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
     }
 
     @Override
     public boolean performDexOptMode(String packageName,
             boolean checkProfiles, String targetCompilerFilter, boolean force) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        }
         int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
                 targetCompilerFilter, force);
         return dexOptStatus != PackageDexOptimizer.DEX_OPT_FAILED;
@@ -8923,6 +9354,9 @@
     @Override
     public boolean performDexOptSecondary(String packageName, String compilerFilter,
             boolean force) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        }
         mDexManager.reconcileSecondaryDexFiles(packageName);
         return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
     }
@@ -8939,6 +9373,9 @@
      */
     @Override
     public void reconcileSecondaryDexFiles(String packageName) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return;
+        }
         mDexManager.reconcileSecondaryDexFiles(packageName);
     }
 
@@ -8953,6 +9390,9 @@
      */
     @Override
     public boolean runBackgroundDexoptJob() {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        }
         return BackgroundDexOptService.runIdleOptimizationsNow(this, mContext);
     }
 
@@ -13406,6 +13846,9 @@
 
     @Override
     public PackageCleanItem nextPackageToClean(PackageCleanItem lastPackage) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         // writer
         synchronized (mPackages) {
             if (!isExternalMediaAvailable()) {
@@ -13987,15 +14430,16 @@
 
     @Override
     public boolean isPackageSuspendedForUser(String packageName, int userId) {
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "isPackageSuspendedForUser for user " + userId);
         synchronized (mPackages) {
-            final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
-            if (pkgSetting == null) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) {
                 throw new IllegalArgumentException("Unknown target package: " + packageName);
             }
-            return pkgSetting.getSuspended(userId);
+            return ps.getSuspended(userId);
         }
     }
 
@@ -14320,6 +14764,9 @@
 
     @Override
     public int getIntentVerificationStatus(String packageName, int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+        }
         synchronized (mPackages) {
             return mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
         }
@@ -14343,6 +14790,9 @@
     @Override
     public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
             String packageName) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return ParceledListSlice.emptyList();
+        }
         synchronized (mPackages) {
             return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
         }
@@ -14353,11 +14803,20 @@
         if (TextUtils.isEmpty(packageName)) {
             return ParceledListSlice.emptyList();
         }
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
         synchronized (mPackages) {
             PackageParser.Package pkg = mPackages.get(packageName);
             if (pkg == null || pkg.activities == null) {
                 return ParceledListSlice.emptyList();
             }
+            if (pkg.mExtras == null) {
+                return ParceledListSlice.emptyList();
+            }
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
+                return ParceledListSlice.emptyList();
+            }
             final int count = pkg.activities.size();
             ArrayList<IntentFilter> result = new ArrayList<>();
             for (int n=0; n<count; n++) {
@@ -14387,6 +14846,9 @@
 
     @Override
     public String getDefaultBrowserPackageName(int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         synchronized (mPackages) {
             return mSettings.getDefaultBrowserPackageNameLPw(userId);
         }
@@ -14405,7 +14867,10 @@
 
     @Override
     public void setInstallerPackageName(String targetPackage, String installerPackageName) {
-        final int uid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
+            return;
+        }
         // writer
         synchronized (mPackages) {
             PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
@@ -14425,17 +14890,17 @@
             }
 
             Signature[] callerSignature;
-            Object obj = mSettings.getUserIdLPr(uid);
+            Object obj = mSettings.getUserIdLPr(callingUid);
             if (obj != null) {
                 if (obj instanceof SharedUserSetting) {
                     callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
                 } else if (obj instanceof PackageSetting) {
                     callerSignature = ((PackageSetting)obj).signatures.mSignatures;
                 } else {
-                    throw new SecurityException("Bad object " + obj + " for uid " + uid);
+                    throw new SecurityException("Bad object " + obj + " for uid " + callingUid);
                 }
             } else {
-                throw new SecurityException("Unknown calling UID: " + uid);
+                throw new SecurityException("Unknown calling UID: " + callingUid);
             }
 
             // Verify: can't set installerPackageName to a package that is
@@ -14480,6 +14945,9 @@
     @Override
     public void setApplicationCategoryHint(String packageName, int categoryHint,
             String callerPackageName) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            throw new SecurityException("Instant applications don't have access to this method");
+        }
         mContext.getSystemService(AppOpsManager.class).checkPackage(Binder.getCallingUid(),
                 callerPackageName);
         synchronized (mPackages) {
@@ -16489,9 +16957,13 @@
         }
     }
 
+    @Override
     public List<String> getPreviousCodePaths(String packageName) {
+        final List<String> result = new ArrayList<>();
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return result;
+        }
         final PackageSetting ps = mSettings.mPackages.get(packageName);
-        final List<String> result = new ArrayList<String>();
         if (ps != null && ps.oldCodePaths != null) {
             result.addAll(ps.oldCodePaths);
         }
@@ -17423,17 +17895,24 @@
                 }
             }
 
-            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
-            // Do not run PackageDexOptimizer through the local performDexOpt
-            // method because `pkg` may not be in `mPackages` yet.
-            //
-            // Also, don't fail application installs if the dexopt step fails.
-            mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
-                    null /* instructionSets */, false /* checkProfiles */,
-                    getCompilerFilterForReason(REASON_INSTALL),
-                    getOrCreateCompilerPackageStats(pkg),
-                    mDexManager.isUsedByOtherApps(pkg.packageName));
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            // dexopt can take some time to complete, so, for instant apps, we skip this
+            // step during installation. Instead, we'll take extra time the first time the
+            // instant app starts. It's preferred to do it this way to provide continuous
+            // progress to the user instead of mysteriously blocking somewhere in the
+            // middle of running an instant app.
+            if (!instantApp) {
+                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+                // Do not run PackageDexOptimizer through the local performDexOpt
+                // method because `pkg` may not be in `mPackages` yet.
+                //
+                // Also, don't fail application installs if the dexopt step fails.
+                mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles,
+                        null /* instructionSets */, false /* checkProfiles */,
+                        getCompilerFilterForReason(REASON_INSTALL),
+                        getOrCreateCompilerPackageStats(pkg),
+                        mDexManager.isUsedByOtherApps(pkg.packageName));
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            }
 
             // Notify BackgroundDexOptService that the package has been changed.
             // If this is an update of a package which used to fail to compile,
@@ -17892,7 +18371,7 @@
 
     private boolean isCallerAllowedToSilentlyUninstall(int callingUid, String pkgName) {
         if (callingUid == Process.SHELL_UID || callingUid == Process.ROOT_UID
-              || callingUid == Process.SYSTEM_UID) {
+              || UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
             return true;
         }
         final int callingUserId = UserHandle.getUserId(callingUid);
@@ -17933,6 +18412,11 @@
 
     @Override
     public boolean isPackageDeviceAdminOnAnyUser(String packageName) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null
+                && !isCallerSameApp(packageName, callingUid)) {
+            return false;
+        }
         return isPackageDeviceAdmin(packageName, UserHandle.USER_ALL);
     }
 
@@ -18609,11 +19093,7 @@
 
     @Override
     public boolean setRequiredForSystemUser(String packageName, boolean systemUserApp) {
-        int callingUid = Binder.getCallingUid();
-        if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
-            throw new SecurityException(
-                    "setRequiredForSystemUser can only be run by the system or root");
-        }
+        enforceSystemOrRoot("setRequiredForSystemUser can only be run by the system or root");
         synchronized (mPackages) {
             PackageSetting ps = mSettings.mPackages.get(packageName);
             if (ps == null) {
@@ -19467,18 +19947,21 @@
 
     @Override
     public void clearPackagePreferredActivities(String packageName) {
-        final int uid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
+            return;
+        }
         // writer
         synchronized (mPackages) {
             PackageParser.Package pkg = mPackages.get(packageName);
-            if (pkg == null || pkg.applicationInfo.uid != uid) {
+            if (pkg == null || pkg.applicationInfo.uid != callingUid) {
                 if (mContext.checkCallingOrSelfPermission(
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
                         != PackageManager.PERMISSION_GRANTED) {
-                    if (getUidTargetSdkVersionLockedLPr(Binder.getCallingUid())
+                    if (getUidTargetSdkVersionLockedLPr(callingUid)
                             < Build.VERSION_CODES.FROYO) {
                         Slog.w(TAG, "Ignoring clearPackagePreferredActivities() from uid "
-                                + Binder.getCallingUid());
+                                + callingUid);
                         return;
                     }
                     mContext.enforceCallingOrSelfPermission(
@@ -19601,7 +20084,9 @@
     @Override
     public int getPreferredActivities(List<IntentFilter> outFilters,
             List<ComponentName> outActivities, String packageName) {
-
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return 0;
+        }
         int num = 0;
         final int userId = UserHandle.getCallingUserId();
         // reader
@@ -20170,6 +20655,9 @@
 
     @Override
     public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
     }
 
@@ -20254,6 +20742,9 @@
 
     @Override
     public void setHomeActivity(ComponentName comp, int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return;
+        }
         ArrayList<ResolveInfo> homeActivities = new ArrayList<>();
         getHomeActivitiesAsUser(homeActivities, userId);
 
@@ -20351,43 +20842,58 @@
                     + newState);
         }
         PackageSetting pkgSetting;
-        final int uid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
         final int permission;
-        if (uid == Process.SYSTEM_UID) {
+        if (callingUid == Process.SYSTEM_UID) {
             permission = PackageManager.PERMISSION_GRANTED;
         } else {
             permission = mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
         }
-        enforceCrossUserPermission(uid, userId,
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, true /* checkShell */, "set enabled");
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
         boolean sendNow = false;
         boolean isApp = (className == null);
+        final boolean isCallerInstantApp = (getInstantAppPackageName(callingUid) != null);
         String componentName = isApp ? packageName : className;
         int packageUid = -1;
         ArrayList<String> components;
 
-        // writer
+        // reader
         synchronized (mPackages) {
             pkgSetting = mSettings.mPackages.get(packageName);
             if (pkgSetting == null) {
-                if (className == null) {
-                    throw new IllegalArgumentException("Unknown package: " + packageName);
+                if (!isCallerInstantApp) {
+                    if (className == null) {
+                        throw new IllegalArgumentException("Unknown package: " + packageName);
+                    }
+                    throw new IllegalArgumentException(
+                            "Unknown component: " + packageName + "/" + className);
+                } else {
+                    // throw SecurityException to prevent leaking package information
+                    throw new SecurityException(
+                            "Attempt to change component state; "
+                            + "pid=" + Binder.getCallingPid()
+                            + ", uid=" + callingUid
+                            + (className == null
+                                    ? ", package=" + packageName
+                                    : ", component=" + packageName + "/" + className));
                 }
-                throw new IllegalArgumentException(
-                        "Unknown component: " + packageName + "/" + className);
             }
         }
 
         // Limit who can change which apps
-        if (!UserHandle.isSameApp(uid, pkgSetting.appId)) {
+        if (!UserHandle.isSameApp(callingUid, pkgSetting.appId)) {
             // Don't allow apps that don't have permission to modify other apps
             if (!allowedByPermission) {
                 throw new SecurityException(
-                        "Permission Denial: attempt to change component state from pid="
-                        + Binder.getCallingPid()
-                        + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
+                        "Attempt to change component state; "
+                        + "pid=" + Binder.getCallingPid()
+                        + ", uid=" + callingUid
+                        + (className == null
+                                ? ", package=" + packageName
+                                : ", component=" + packageName + "/" + className));
             }
             // Don't allow changing protected packages.
             if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
@@ -20396,7 +20902,7 @@
         }
 
         synchronized (mPackages) {
-            if (uid == Process.SHELL_UID
+            if (callingUid == Process.SHELL_UID
                     && (pkgSetting.pkgFlags & ApplicationInfo.FLAG_TEST_ONLY) == 0) {
                 // Shell can only change whole packages between ENABLED and DISABLED_USER states
                 // unless it is a test package.
@@ -20512,6 +21018,9 @@
 
     @Override
     public void flushPackageRestrictionsAsUser(int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return;
+        }
         if (!sUserManager.exists(userId)) {
             return;
         }
@@ -20550,16 +21059,19 @@
     @Override
     public void setPackageStoppedState(String packageName, boolean stopped, int userId) {
         if (!sUserManager.exists(userId)) return;
-        final int uid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
+            return;
+        }
         final int permission = mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
-        enforceCrossUserPermission(uid, userId,
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */, "stop package");
         // writer
         synchronized (mPackages) {
             if (mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
-                    allowedByPermission, uid, userId)) {
+                    allowedByPermission, callingUid, userId)) {
                 scheduleWritePackageRestrictionsLocked(userId);
             }
         }
@@ -20567,6 +21079,9 @@
 
     @Override
     public String getInstallerPackageName(String packageName) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         // reader
         synchronized (mPackages) {
             return mSettings.getInstallerPackageNameLPr(packageName);
@@ -20583,24 +21098,30 @@
     @Override
     public int getApplicationEnabledSetting(String packageName, int userId) {
         if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
-        int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId,
+        int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get enabled");
         // reader
         synchronized (mPackages) {
+            if (filterAppAccessLPr(mSettings.getPackageLPr(packageName), callingUid, userId)) {
+                return COMPONENT_ENABLED_STATE_DISABLED;
+            }
             return mSettings.getApplicationEnabledSettingLPr(packageName, userId);
         }
     }
 
     @Override
-    public int getComponentEnabledSetting(ComponentName componentName, int userId) {
+    public int getComponentEnabledSetting(ComponentName component, int userId) {
         if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
-        int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId,
-                false /* requireFullPermission */, false /* checkShell */, "get component enabled");
-        // reader
+        int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
+                false /*requireFullPermission*/, false /*checkShell*/, "getComponentEnabled");
         synchronized (mPackages) {
-            return mSettings.getComponentEnabledSettingLPr(componentName, userId);
+            if (filterAppAccessLPr(mSettings.getPackageLPr(component.getPackageName()), callingUid,
+                    component, TYPE_UNKNOWN, userId)) {
+                return COMPONENT_ENABLED_STATE_DISABLED;
+            }
+            return mSettings.getComponentEnabledSettingLPr(component, userId);
         }
     }
 
@@ -20615,6 +21136,8 @@
 
     @Override
     public void systemReady() {
+        enforceSystemOrRoot("Only the system can claim the system is ready");
+
         mSystemReady = true;
         final ContentResolver resolver = mContext.getContentResolver();
         ContentObserver co = new ContentObserver(mHandler) {
@@ -20762,11 +21285,13 @@
 
     @Override
     public boolean isSafeMode() {
+        // allow instant applications
         return mSafeMode;
     }
 
     @Override
     public boolean hasSystemUidErrors() {
+        // allow instant applications
         return mHasSystemUidErrors;
     }
 
@@ -21728,10 +22253,7 @@
      */
     @Override
     public void updateExternalMediaStatus(final boolean mediaStatus, final boolean reportStatus) {
-        int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != Process.SYSTEM_UID) {
-            throw new SecurityException("Media status can only be updated by the system");
-        }
+        enforceSystemOrRoot("Media status can only be updated by the system");
         // reader; this apparently protects mMediaMounted, but should probably
         // be a different lock in that case.
         synchronized (mPackages) {
@@ -23063,6 +23585,7 @@
 
     @Override
     public int getInstallLocation() {
+        // allow instant app access
         return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
                 android.provider.Settings.Global.DEFAULT_INSTALL_LOCATION,
                 PackageHelper.APP_INSTALL_AUTO);
@@ -23203,11 +23726,13 @@
     @Override
     @Deprecated
     public boolean isPermissionEnforced(String permission) {
+        // allow instant applications
         return true;
     }
 
     @Override
     public boolean isStorageLow() {
+        // allow instant applications
         final long token = Binder.clearCallingIdentity();
         try {
             final DeviceStorageMonitorInternal
@@ -23224,6 +23749,9 @@
 
     @Override
     public IPackageInstaller getPackageInstaller() {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         return mInstallerService;
     }
 
@@ -23271,13 +23799,22 @@
             return null;
         }
         synchronized(mPackages) {
+            final int callingUid = Binder.getCallingUid();
+            final int callingUserId = UserHandle.getUserId(callingUid);
             final PackageParser.Package pkg = mPackages.get(packageName);
             if (pkg == null) {
                 Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
-            if (pkg.applicationInfo.uid != Binder.getCallingUid()
-                    && Process.SYSTEM_UID != Binder.getCallingUid()) {
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
+                // filter and pretend the package doesn't exist
+                Slog.w(TAG, "KeySet requested for filtered package: " + packageName
+                        + ", uid:" + callingUid);
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
+            if (pkg.applicationInfo.uid != callingUid
+                    && Process.SYSTEM_UID != callingUid) {
                 throw new SecurityException("May not access signing KeySet of other apps.");
             }
             KeySetManagerService ksms = mSettings.mKeySetManagerService;
@@ -23287,6 +23824,9 @@
 
     @Override
     public boolean isPackageSignedByKeySet(String packageName, KeySet ks) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        }
         if (packageName == null || ks == null) {
             return false;
         }
@@ -23307,6 +23847,9 @@
 
     @Override
     public boolean isPackageSignedByKeySetExactly(String packageName, KeySet ks) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        }
         if (packageName == null || ks == null) {
             return false;
         }
@@ -23844,6 +24387,11 @@
                 return getUidTargetSdkVersionLockedLPr(uid);
             }
         }
+
+        @Override
+        public boolean canAccessInstantApps(int callingUid, int userId) {
+            return PackageManagerService.this.canViewInstantApps(callingUid, userId);
+        }
     }
 
     @Override
@@ -23900,8 +24448,12 @@
      * Logs process start information (including base APK hash) to the security log.
      * @hide
      */
+    @Override
     public void logAppProcessStartIfNeeded(String processName, int uid, String seinfo,
             String apkFile, int pid) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return;
+        }
         if (!SecurityLog.isLoggingEnabled()) {
             return;
         }
@@ -23936,11 +24488,15 @@
 
     @Override
     public int getInstallReason(String packageName, int userId) {
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "get install reason");
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (filterAppAccessLPr(ps, callingUid, userId)) {
+                return PackageManager.INSTALL_REASON_UNKNOWN;
+            }
             if (ps != null) {
                 return ps.getInstallReason(userId);
             }
@@ -23950,6 +24506,9 @@
 
     @Override
     public boolean canRequestPackageInstalls(String packageName, int userId) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        }
         return canRequestPackageInstallsInternal(packageName, 0, userId,
                 true /* throwIfPermNotDeclared*/);
     }
@@ -24000,6 +24559,9 @@
 
     @Override
     public ComponentName getInstantAppInstallerComponent() {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return null;
+        }
         return mInstantAppInstallerActivity == null
                 ? null : mInstantAppInstallerActivity.getComponentName();
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 44bcff2..24cbdbf 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -987,11 +987,11 @@
         // Update static shared library dependencies if needed
         if (pkg.usesStaticLibraries != null && pkg.usesStaticLibrariesVersions != null
                 && pkg.usesStaticLibraries.size() == pkg.usesStaticLibrariesVersions.length) {
-            String[] usesStaticLibraries = new String[pkg.usesStaticLibraries.size()];
-            pkg.usesStaticLibraries.toArray(usesStaticLibraries);
+            p.usesStaticLibraries = new String[pkg.usesStaticLibraries.size()];
+            pkg.usesStaticLibraries.toArray(p.usesStaticLibraries);
             p.usesStaticLibrariesVersions = pkg.usesStaticLibrariesVersions;
         } else {
-            pkg.usesStaticLibraries = null;
+            p.usesStaticLibraries = null;
             p.usesStaticLibrariesVersions = null;
         }
         addPackageSettingLPw(p, p.sharedUser);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 30c4009..b115422 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3684,6 +3684,11 @@
         }
 
         @Override
+        public int[] getUserIds() {
+            return UserManagerService.this.getUserIds();
+        }
+
+        @Override
         public boolean isUserUnlockingOrUnlocked(int userId) {
             synchronized (mUserStates) {
                 int state = mUserStates.get(userId, -1);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8e058ad..908e517 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -234,6 +234,7 @@
 import com.android.internal.widget.PointerLocationView;
 import com.android.server.GestureLauncherService;
 import com.android.server.LocalServices;
+import com.android.server.SystemServiceManager;
 import com.android.server.policy.keyguard.KeyguardServiceDelegate;
 import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
 import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
@@ -476,6 +477,7 @@
 
     boolean mBootMessageNeedsHiding;
     KeyguardServiceDelegate mKeyguardDelegate;
+    private boolean mKeyguardBound;
     final Runnable mWindowManagerDrawCallback = new Runnable() {
         @Override
         public void run() {
@@ -530,7 +532,6 @@
 
     boolean mSystemReady;
     boolean mSystemBooted;
-    private boolean mDeferBindKeyguard;
     boolean mHdmiPlugged;
     HdmiControl mHdmiControl;
     IUiModeManager mUiModeManager;
@@ -2087,6 +2088,13 @@
                 handleStartTransitionForKeyguardLw(transit, null /* transit */);
             }
         });
+        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
+                new StateCallback() {
+                    @Override
+                    public void onTrustedChanged() {
+                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
+                    }
+                });
     }
 
     /**
@@ -5325,11 +5333,12 @@
     @Override
     public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
             WindowState attached, WindowState imeTarget) {
-        final boolean visible = win.isVisibleLw() && win.getAttrs().alpha > 0f;
-        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible);
+        final boolean affectsSystemUi = win.canAffectSystemUiFlags();
+        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": affectsSystemUi=" + affectsSystemUi);
         applyKeyguardPolicyLw(win, imeTarget);
         final int fl = PolicyControl.getWindowFlags(win, attrs);
-        if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) {
+        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi
+                && attrs.type == TYPE_INPUT_METHOD) {
             mForcingShowNavBar = true;
             mForcingShowNavBarLayer = win.getSurfaceLayer();
         }
@@ -5345,7 +5354,7 @@
         boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
                 && attrs.type < FIRST_SYSTEM_WINDOW;
         final int stackId = win.getStackId();
-        if (mTopFullscreenOpaqueWindowState == null && visible) {
+        if (mTopFullscreenOpaqueWindowState == null && affectsSystemUi) {
             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
                 mForceStatusBar = true;
             }
@@ -5377,7 +5386,7 @@
         }
 
         // Voice interaction overrides both top fullscreen and top docked.
-        if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
+        if (affectsSystemUi && win.getAttrs().type == TYPE_VOICE_INTERACTION) {
             if (mTopFullscreenOpaqueWindowState == null) {
                 mTopFullscreenOpaqueWindowState = win;
                 if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
@@ -5393,7 +5402,7 @@
         }
 
         // Keep track of the window if it's dimming but not necessarily fullscreen.
-        if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible
+        if (mTopFullscreenOpaqueOrDimmingWindowState == null && affectsSystemUi
                 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) {
             mTopFullscreenOpaqueOrDimmingWindowState = win;
         }
@@ -5401,7 +5410,7 @@
         // We need to keep track of the top "fullscreen" opaque window for the docked stack
         // separately, because both the "real fullscreen" opaque window and the one for the docked
         // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
-        if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null
+        if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
                 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
             mTopDockedOpaqueWindowState = win;
             if (mTopDockedOpaqueOrDimmingWindowState == null) {
@@ -5411,7 +5420,7 @@
 
         // Also keep track of any windows that are dimming but not necessarily fullscreen in the
         // docked stack.
-        if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming()
+        if (mTopDockedOpaqueOrDimmingWindowState == null && affectsSystemUi && win.isDimming()
                 && stackId == DOCKED_STACK_ID) {
             mTopDockedOpaqueOrDimmingWindowState = win;
         }
@@ -6631,6 +6640,13 @@
         reportScreenStateToVrManager(false);
     }
 
+    private long getKeyguardDrawnTimeout() {
+        final boolean bootCompleted =
+                LocalServices.getService(SystemServiceManager.class).isBootCompleted();
+        // Set longer timeout if it has not booted yet to prevent showing empty window.
+        return bootCompleted ? 1000 : 5000;
+    }
+
     // Called on the DisplayManager's DisplayPowerController thread.
     @Override
     public void screenTurningOn(final ScreenOnListener screenOnListener) {
@@ -6646,7 +6662,8 @@
 
             if (mKeyguardDelegate != null) {
                 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
-                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
+                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT,
+                        getKeyguardDrawnTimeout());
                 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback);
             } else {
                 if (DEBUG_WAKEUP) Slog.d(TAG,
@@ -6667,6 +6684,11 @@
         reportScreenStateToVrManager(true);
     }
 
+    @Override
+    public void screenTurningOff(ScreenOffListener screenOffListener) {
+        mWindowManagerFuncs.screenTurningOff(screenOffListener);
+    }
+
     private void reportScreenStateToVrManager(boolean isScreenOn) {
         if (mVrManagerInternal == null) {
             return;
@@ -7154,16 +7176,26 @@
         return out;
     }
 
+    private void bindKeyguard() {
+        synchronized (mLock) {
+            if (mKeyguardBound) {
+                return;
+            }
+            mKeyguardBound = true;
+        }
+        mKeyguardDelegate.bindService(mContext);
+    }
+
+    @Override
+    public void onSystemUiStarted() {
+        bindKeyguard();
+    }
+
     /** {@inheritDoc} */
     @Override
     public void systemReady() {
-        mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
-                new StateCallback() {
-                    @Override
-                    public void onTrustedChanged() {
-                        mWindowManagerFuncs.notifyKeyguardTrustedChanged();
-                    }
-                });
+        // In normal flow, systemReady is called before other system services are ready.
+        // So it is better not to bind keyguard here.
         mKeyguardDelegate.onSystemReady();
 
         mVrManagerInternal = LocalServices.getService(VrManagerInternal.class);
@@ -7173,7 +7205,6 @@
 
         readCameraLensCoverState();
         updateUiMode();
-        boolean bindKeyguardNow;
         synchronized (mLock) {
             updateOrientationListenerLp();
             mSystemReady = true;
@@ -7183,18 +7214,13 @@
                     updateSettings();
                 }
             });
-
-            bindKeyguardNow = mDeferBindKeyguard;
-            if (bindKeyguardNow) {
-                // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now.
-                mDeferBindKeyguard = false;
+            // If this happens, for whatever reason, systemReady came later than systemBooted.
+            // And keyguard should be already bound from systemBooted
+            if (mSystemBooted) {
+                mKeyguardDelegate.onBootCompleted();
             }
         }
 
-        if (bindKeyguardNow) {
-            mKeyguardDelegate.bindService(mContext);
-            mKeyguardDelegate.onBootCompleted();
-        }
         mSystemGestures.systemReady();
         mImmersiveModeConfirmation.systemReady();
     }
@@ -7202,30 +7228,25 @@
     /** {@inheritDoc} */
     @Override
     public void systemBooted() {
-        boolean bindKeyguardNow = false;
-        synchronized (mLock) {
-            // Time to bind Keyguard; take care to only bind it once, either here if ready or
-            // in systemReady if not.
-            if (mKeyguardDelegate != null) {
-                bindKeyguardNow = true;
-            } else {
-                // Because mKeyguardDelegate is null, we know that the synchronized block in
-                // systemReady didn't run yet and setting this will actually have an effect.
-                mDeferBindKeyguard = true;
-            }
-        }
-        if (bindKeyguardNow) {
-            mKeyguardDelegate.bindService(mContext);
-            mKeyguardDelegate.onBootCompleted();
-        }
+        bindKeyguard();
         synchronized (mLock) {
             mSystemBooted = true;
+            if (mSystemReady) {
+                mKeyguardDelegate.onBootCompleted();
+            }
         }
         startedWakingUp();
         screenTurningOn(null);
         screenTurnedOn();
     }
 
+    @Override
+    public boolean canDismissBootAnimation() {
+        synchronized (mLock) {
+            return mKeyguardDrawComplete;
+        }
+    }
+
     ProgressDialog mBootMsgDialog = null;
 
     /** {@inheritDoc} */
@@ -7670,7 +7691,10 @@
             default:
                 return null;
         }
-        if (pattern.length == 1) {
+        if (pattern.length == 0) {
+            // No vibration
+            return null;
+        } else if (pattern.length == 1) {
             // One-shot vibration
             return VibrationEffect.createOneShot(pattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
         } else {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a8d19e9..c8ade2d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3122,10 +3122,6 @@
         if (reason == null) {
             reason = "";
         }
-        if (reason.equals(PowerManager.REBOOT_RECOVERY)
-                || reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) {
-            reason = "recovery";
-        }
 
         // If the reason is "quiescent", it means that the boot process should proceed
         // without turning on the screen/lights.
@@ -3134,6 +3130,15 @@
         if (reason.equals(PowerManager.REBOOT_QUIESCENT)) {
             sQuiescent = true;
             reason = "";
+        } else if (reason.endsWith("," + PowerManager.REBOOT_QUIESCENT)) {
+            sQuiescent = true;
+            reason = reason.substring(0,
+                    reason.length() - PowerManager.REBOOT_QUIESCENT.length() - 1);
+        }
+
+        if (reason.equals(PowerManager.REBOOT_RECOVERY)
+                || reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) {
+            reason = "recovery";
         }
 
         if (sQuiescent) {
diff --git a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
index 82dd9ac..7a35bf7 100644
--- a/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
+++ b/services/core/java/com/android/server/storage/CacheQuotaStrategy.java
@@ -177,7 +177,7 @@
             UserInfo info = users.get(i);
             List<UsageStats> stats =
                     mUsageStats.queryUsageStatsForUser(info.id, UsageStatsManager.INTERVAL_BEST,
-                            oneYearAgo, timeNow);
+                            oneYearAgo, timeNow, /*obfuscateInstantApps=*/ false);
             if (stats == null) {
                 continue;
             }
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 8e06a51..e12dc1d 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -795,6 +795,10 @@
             // coalesce refresh messages.
             mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
             mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED);
+
+            // Make sure handler processes the message before returning, such that isDeviceLocked
+            // after this call will retrieve the correct value.
+            mHandler.runWithScissors(() -> {}, 0);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index fb7ccc7..4044fdb 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -368,7 +368,7 @@
 
             // There is an active service, update it if needed
             updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
-                    mCurrentVrService.getUserId(), null);
+                    mCurrentVrService.getUserId(), mCurrentVrModeComponent);
         }
     }
 
@@ -675,7 +675,7 @@
      * @param enabled new state for VR mode.
      * @param component new component to be bound as a VR listener.
      * @param userId user owning the component to be bound.
-     * @param calling the component currently using VR mode, or null to leave unchanged.
+     * @param calling the component currently using VR mode.
      *
      * @return {@code true} if the component/user combination specified is valid.
      */
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index 50b1520..7ed3eac 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -16,14 +16,15 @@
 
 package com.android.server.wm;
 
+import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
 import static android.content.Context.NOTIFICATION_SERVICE;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;
-import static com.android.internal.notification.SystemNotificationChannels.ALERT_WINDOW;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -40,7 +41,7 @@
 
 /** Displays an ongoing notification for a process displaying an alert window */
 class AlertWindowNotification {
-    private static final String TAG_PREFIX = "com.android.server.wm.AlertWindowNotification: ";
+    private static final String CHANNEL_PREFIX = "com.android.server.wm.AlertWindowNotification - ";
     private static final int NOTIFICATION_ID = 0;
 
     private static int sNextRequestCode = 0;
@@ -57,7 +58,7 @@
         mPackageName = packageName;
         mNotificationManager =
                 (NotificationManager) mService.mContext.getSystemService(NOTIFICATION_SERVICE);
-        mNotificationTag = TAG_PREFIX + mPackageName;
+        mNotificationTag = CHANNEL_PREFIX + mPackageName;
         mRequestCode = sNextRequestCode++;
         mIconUtilities = new IconUtilities(mService.mContext);
     }
@@ -99,9 +100,11 @@
         final String appName = (aInfo != null)
                 ? pm.getApplicationLabel(aInfo).toString() : mPackageName;
 
+        createNotificationChannelIfNeeded(context, appName);
+
         final String message = context.getString(R.string.alert_windows_notification_message,
                 appName);
-        final Notification.Builder builder = new Notification.Builder(context, ALERT_WINDOW)
+        final Notification.Builder builder = new Notification.Builder(context, mNotificationTag)
                 .setOngoing(true)
                 .setContentTitle(
                         context.getString(R.string.alert_windows_notification_title, appName))
@@ -131,6 +134,20 @@
         return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT);
     }
 
+    private void createNotificationChannelIfNeeded(Context context, String appName) {
+        if (mNotificationManager.getNotificationChannel(mNotificationTag) != null) {
+            return;
+        }
+        final String nameChannel =
+                context.getString(R.string.alert_windows_notification_channel_name, appName);
+        final NotificationChannel channel =
+                new NotificationChannel(mNotificationTag, nameChannel, IMPORTANCE_MIN);
+        channel.enableLights(false);
+        channel.enableVibration(false);
+        mNotificationManager.createNotificationChannel(channel);
+    }
+
+
     private ApplicationInfo getApplicationInfo(PackageManager pm, String packageName) {
         try {
             return pm.getApplicationInfo(packageName, 0);
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 65e3ec0..f769261 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -78,6 +78,9 @@
     // requires that the duration of the two animations are the same.
     SurfaceControl thumbnail;
     int thumbnailTransactionSeq;
+    // TODO(b/62029108): combine both members into a private one. Create a member function to set
+    // the thumbnail layer to +1 to the highest layer position and replace all setter instances
+    // with this function. Remove all unnecessary calls to both variables in other classes.
     int thumbnailLayer;
     int thumbnailForceAboveLayer;
     Animation thumbnailAnimation;
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 5545e2b..1a685eb 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -19,6 +19,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -98,18 +99,27 @@
     private final Runnable mRemoveStartingWindow = () -> {
         StartingSurface surface = null;
         synchronized (mWindowMap) {
+            if (mContainer == null) {
+                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
+                        + " remove starting window");
+                return;
+            }
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " + mContainer
                     + ": startingWindow=" + mContainer.startingWindow
                     + " startingView=" + mContainer.startingSurface);
-            if (mContainer == null) {
-                return;
-            }
-            if (mContainer.startingWindow != null) {
+            if (mContainer.startingData != null) {
                 surface = mContainer.startingSurface;
                 mContainer.startingData = null;
                 mContainer.startingSurface = null;
                 mContainer.startingWindow = null;
                 mContainer.startingDisplayed = false;
+                if (surface == null && DEBUG_STARTING_WINDOW) {
+                    Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
+                            + "remove");
+                }
+            } else if (DEBUG_STARTING_WINDOW) {
+                Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
+                        + mContainer);
             }
         }
         if (surface != null) {
@@ -127,6 +137,8 @@
 
         synchronized (mWindowMap) {
             if (mContainer == null) {
+                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
+                        + " add starting window");
                 return;
             }
             startingData = mContainer.startingData;
@@ -135,6 +147,8 @@
 
         if (startingData == null) {
             // Animation has been canceled... do nothing.
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "startingData was nulled out before handling"
+                    + " mAddStartingWindow: " + mContainer);
             return;
         }
 
@@ -150,18 +164,16 @@
         if (surface != null) {
             boolean abort = false;
             synchronized(mWindowMap) {
+                // If the window was successfully added, then
+                // we need to remove it.
                 if (container.removed || container.startingData == null) {
-                    // If the window was successfully added, then
-                    // we need to remove it.
-                    if (container.startingWindow != null) {
-                        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
-                                "Aborted starting " + container
-                                        + ": removed=" + container.removed
-                                        + " startingData=" + container.startingData);
-                        container.startingWindow = null;
-                        container.startingData = null;
-                        abort = true;
-                    }
+                    if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM,
+                            "Aborted starting " + container
+                                    + ": removed=" + container.removed
+                                    + " startingData=" + container.startingData);
+                    container.startingWindow = null;
+                    container.startingData = null;
+                    abort = true;
                 } else {
                     container.startingSurface = surface;
                 }
@@ -174,6 +186,8 @@
             if (abort) {
                 surface.remove();
             }
+        } else if (DEBUG_STARTING_WINDOW) {
+            Slog.v(TAG_WM, "Surface returned was null: " + mContainer);
         }
     };
 
@@ -332,6 +346,24 @@
 
             final AppWindowToken wtoken = mContainer;
 
+            // Don't set visibility to false if we were already not visible. This prevents WM from
+            // adding the app to the closing app list which doesn't make sense for something that is
+            // already not visible. However, set visibility to true even if we are already visible.
+            // This makes sure the app is added to the opening apps list so that the right
+            // transition can be selected.
+            // TODO: Probably a good idea to separate the concept of opening/closing apps from the
+            // concept of setting visibility...
+            if (!visible && wtoken.hiddenRequested) {
+
+                if (!deferHidingClient && wtoken.mDeferHidingClient) {
+                    // We previously deferred telling the client to hide itself when visibility was
+                    // initially set to false. Now we would like it to hide, so go ahead and set it.
+                    wtoken.mDeferHidingClient = deferHidingClient;
+                    wtoken.setClientHidden(true);
+                }
+                return;
+            }
+
             if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG_WM, "setAppVisibility("
                     + mToken + ", visible=" + visible + "): " + mService.mAppTransition
                     + " hidden=" + wtoken.hidden + " hiddenRequested="
@@ -450,7 +482,9 @@
             boolean allowTaskSnapshot, boolean activityCreated) {
         synchronized(mWindowMap) {
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "setAppStartingWindow: token=" + mToken
-                    + " pkg=" + pkg + " transferFrom=" + transferFrom);
+                    + " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask
+                    + " taskSwitch=" + taskSwitch + " processRunning=" + processRunning
+                    + " allowTaskSnapshot=" + allowTaskSnapshot);
 
             if (mContainer == null) {
                 Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + mToken);
@@ -536,7 +570,7 @@
                 return false;
             }
 
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData");
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SplashScreenStartingData");
             mContainer.startingData = new SplashScreenStartingData(mService, pkg, theme,
                     compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                     mContainer.getMergedOverrideConfiguration());
@@ -574,6 +608,7 @@
             return false;
         }
 
+        if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating SnapshotStartingData");
         mContainer.startingData = new SnapshotStartingData(mService, snapshot);
         scheduleAddStartingWindow();
         return true;
@@ -583,6 +618,8 @@
         synchronized (mWindowMap) {
             if (mHandler.hasCallbacks(mRemoveStartingWindow)) {
                 // Already scheduled.
+                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Trying to remove starting window but "
+                        + "already scheduled");
                 return;
             }
 
@@ -597,8 +634,7 @@
                 return;
             }
 
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1)
-                    + ": Schedule remove starting " + mContainer
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Schedule remove starting " + mContainer
                     + " startingWindow=" + mContainer.startingWindow);
             mHandler.post(mRemoveStartingWindow);
         }
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 96ea5e5..f0e0e14 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -38,6 +38,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
@@ -53,7 +54,6 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Debug;
 import android.os.IBinder;
 import android.os.SystemClock;
@@ -155,6 +155,9 @@
     StartingSurface startingSurface;
     boolean startingDisplayed;
     boolean startingMoved;
+    // True if the hidden state of this token was forced to false due to a transferred starting
+    // window.
+    private boolean mHiddenSetFromTransferredStartingWindow;
     boolean firstWindowDrawn;
     private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
             new WindowState.UpdateReportedVisibilityResults();
@@ -185,7 +188,7 @@
     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
     ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
 
-    private boolean mDisbalePreviewScreenshots;
+    private boolean mDisablePreviewScreenshots;
 
     Task mLastParent;
 
@@ -338,7 +341,9 @@
 
         boolean delayed = false;
         inPendingTransaction = false;
-
+        // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
+        // been set by the app now.
+        mHiddenSetFromTransferredStartingWindow = false;
         setClientHidden(!visible);
 
         // Allow for state changes and animation to be applied if:
@@ -560,6 +565,9 @@
             // with it will be removed as soon as their animations are complete
             mAppAnimator.clearAnimation();
             mAppAnimator.animating = false;
+            if (stack != null) {
+                stack.mExitingAppTokens.remove(this);
+            }
             removeIfPossible();
         }
 
@@ -787,14 +795,22 @@
             if (getController() != null) {
                 getController().removeStartingWindow();
             }
-        } else if (mChildren.size() == 0 && startingData != null) {
+        } else if (mChildren.size() == 0) {
             // If this is the last window and we had requested a starting transition window,
             // well there is no point now.
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingData");
             startingData = null;
+            if (mHiddenSetFromTransferredStartingWindow) {
+                // We set the hidden state to false for the token from a transferred starting window.
+                // We now reset it back to true since the starting window was the last window in the
+                // token.
+                hidden = true;
+            }
         } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
             // If this is the last window except for a starting transition window,
             // we need to get rid of the starting transition.
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Last window, removing starting window "
+                    + win);
             if (getController() != null) {
                 getController().removeStartingWindow();
             }
@@ -1168,6 +1184,7 @@
                     "Removing starting " + tStartingWindow + " from " + fromToken);
             fromToken.removeChild(tStartingWindow);
             fromToken.postWindowRemoveStartingWindowCleanup(tStartingWindow);
+            fromToken.mHiddenSetFromTransferredStartingWindow = false;
             addWindow(tStartingWindow);
 
             // Propagate other interesting state between the tokens. If the old token is displayed,
@@ -1183,6 +1200,7 @@
             if (!fromToken.hidden) {
                 hidden = false;
                 hiddenRequested = false;
+                mHiddenSetFromTransferredStartingWindow = true;
             }
             setClientHidden(fromToken.mClientHidden);
             fromToken.mAppAnimator.transferCurrentAnimation(
@@ -1359,7 +1377,7 @@
      *         windows in this app token where not considered drawn as of the last pass.
      */
     boolean updateDrawnWindowStates(WindowState w) {
-        if (DEBUG_STARTING_WINDOW && w == startingWindow) {
+        if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
             Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
                     + " allDrawn=" + allDrawn + " freezingScreen=" + mAppAnimator.freezingScreen);
         }
@@ -1541,7 +1559,7 @@
      * See {@link Activity#setDisablePreviewScreenshots}.
      */
     void setDisablePreviewScreenshots(boolean disable) {
-        mDisbalePreviewScreenshots = disable;
+        mDisablePreviewScreenshots = disable;
     }
 
     /**
@@ -1553,7 +1571,7 @@
      *         screenshot.
      */
     boolean shouldUseAppThemeSnapshot() {
-        return mDisbalePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
+        return mDisablePreviewScreenshots || forAllWindows(w -> (w.mAttrs.flags & FLAG_SECURE) != 0,
                 true /* topToBottom */);
     }
 
@@ -1601,11 +1619,13 @@
                     pw.print(" mIsExiting="); pw.println(mIsExiting);
         }
         if (startingWindow != null || startingSurface != null
-                || startingDisplayed || startingMoved) {
+                || startingDisplayed || startingMoved || mHiddenSetFromTransferredStartingWindow) {
             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
                     pw.print(" startingSurface="); pw.print(startingSurface);
                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
-                    pw.print(" startingMoved="); pw.println(startingMoved);
+                    pw.print(" startingMoved="); pw.print(startingMoved);
+                    pw.println(" mHiddenSetFromTransferredStartingWindow="
+                            + mHiddenSetFromTransferredStartingWindow);
         }
         if (!mFrozenBounds.isEmpty()) {
             pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index bbf7d9f..221e795 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1899,6 +1899,11 @@
         return true;
     }
 
+    /** @return 'true' if removal of this display content is deferred due to active animation. */
+    boolean isRemovalDeferred() {
+        return mDeferredRemoval;
+    }
+
     boolean animateForIme(float interpolatedValue, float animationTarget,
             float dividerAnimationTarget) {
         boolean updated = false;
@@ -2898,6 +2903,11 @@
                 * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
         final MutableBoolean mutableIncludeFullDisplay = new MutableBoolean(includeFullDisplay);
         synchronized(mService.mWindowMap) {
+            if (!mService.mPolicy.isScreenOn()) {
+                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Attempted to take screenshot while display"
+                        + " was off.");
+                return null;
+            }
             // Figure out the part of the screen that is actually the app.
             mScreenshotApplicationState.appWin = null;
             forAllWindows(w -> {
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index e300256..2d7fc68 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -191,12 +191,16 @@
                 mTmpRect);
         int dividerSize = mDividerWindowWidth - 2 * mDividerInsets;
         Configuration configuration = mDisplayContent.getConfiguration();
+        // The offset in the left (landscape)/top (portrait) is calculated with the minimized
+        // offset value with the divider size and any system insets in that direction.
         if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
             outBounds.set(0, mTaskHeightInMinimizedMode + dividerSize + mTmpRect.top,
                     di.logicalWidth, di.logicalHeight);
         } else {
-            outBounds.set(mTaskHeightInMinimizedMode + dividerSize + mTmpRect.left, 0,
-                    di.logicalWidth, di.logicalHeight);
+            // In landscape append the left position with the statusbar height to match the
+            // minimized size height in portrait mode.
+            outBounds.set(mTaskHeightInMinimizedMode + dividerSize + mTmpRect.left + mTmpRect.top,
+                    0, di.logicalWidth, di.logicalHeight);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index be3558b..233e75b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -181,7 +181,12 @@
 
         final int size = mChildren.size();
         for (int i = 0; i < size; ++i) {
-            displaysInFocusOrder.put(i, mChildren.get(i).getDisplayId());
+            final DisplayContent displayContent = mChildren.get(i);
+            if (displayContent.isRemovalDeferred()) {
+                // Don't report displays that are going to be removed soon.
+                continue;
+            }
+            displaysInFocusOrder.put(i, displayContent.getDisplayId());
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 27661e2..818df01 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -41,6 +41,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
+import java.util.function.Consumer;
 
 class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerUser {
     static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
@@ -684,6 +685,11 @@
     }
 
     @Override
+    void forAllTasks(Consumer<Task> callback) {
+        callback.accept(this);
+    }
+
+    @Override
     public String toString() {
         return "{taskId=" + mTaskId + " appTokens=" + mChildren + " mdr=" + mDeferRemoval + "}";
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 1bbe1d0..b266778 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -17,21 +17,22 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
-import static android.graphics.GraphicBuffer.USAGE_HW_TEXTURE;
-import static android.graphics.GraphicBuffer.USAGE_SW_READ_NEVER;
-import static android.graphics.GraphicBuffer.USAGE_SW_WRITE_RARELY;
-import static android.graphics.PixelFormat.RGBA_8888;
+import static android.graphics.Bitmap.Config.ARGB_8888;
+import static android.graphics.Bitmap.Config.HARDWARE;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManager.StackId;
 import android.app.ActivityManager.TaskSnapshot;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.os.Environment;
+import android.os.Handler;
 import android.util.ArraySet;
 import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerPolicy.ScreenOffListener;
 import android.view.WindowManagerPolicy.StartingSurface;
 
 import com.google.android.collect.Sets;
@@ -83,6 +84,7 @@
             Environment::getDataSystemCeDirectory);
     private final TaskSnapshotLoader mLoader = new TaskSnapshotLoader(mPersister);
     private final ArraySet<Task> mTmpTasks = new ArraySet<>();
+    private final Handler mHandler = new Handler();
 
     TaskSnapshotController(WindowManagerService service) {
         mService = service;
@@ -114,8 +116,13 @@
         // We need to take a snapshot of the task if and only if all activities of the task are
         // either closing or hidden.
         getClosingTasks(closingApps, mTmpTasks);
-        for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
-            final Task task = mTmpTasks.valueAt(i);
+        snapshotTasks(mTmpTasks);
+
+    }
+
+    private void snapshotTasks(ArraySet<Task> tasks) {
+        for (int i = tasks.size() - 1; i >= 0; i--) {
+            final Task task = tasks.valueAt(i);
             final int mode = getSnapshotMode(task);
             final TaskSnapshot snapshot;
             switch (mode) {
@@ -231,22 +238,22 @@
         final int color = task.getTaskDescription().getBackgroundColor();
         final int statusBarColor = task.getTaskDescription().getStatusBarColor();
         final int navigationBarColor = task.getTaskDescription().getNavigationBarColor();
-        final GraphicBuffer buffer = GraphicBuffer.create(mainWindow.getFrameLw().width(),
-                mainWindow.getFrameLw().height(),
-                RGBA_8888, USAGE_HW_TEXTURE | USAGE_SW_WRITE_RARELY | USAGE_SW_READ_NEVER);
-        if (buffer == null) {
-            return null;
-        }
-        final Canvas c = buffer.lockCanvas();
+        final Bitmap b = Bitmap.createBitmap(mainWindow.getFrameLw().width(),
+                mainWindow.getFrameLw().height(), ARGB_8888);
+        final Canvas c = new Canvas(b);
         c.drawColor(color);
         final LayoutParams attrs = mainWindow.getAttrs();
         final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
                 attrs.privateFlags, attrs.systemUiVisibility, statusBarColor, navigationBarColor);
         decorPainter.setInsets(mainWindow.mContentInsets, mainWindow.mStableInsets);
         decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
-        buffer.unlockCanvasAndPost(c);
-        return new TaskSnapshot(buffer, topChild.getConfiguration().orientation,
-                mainWindow.mStableInsets, false /* reduced */, 1.0f /* scale */);
+
+        // Flush writer.
+        c.setBitmap(null);
+        final Bitmap hwBitmap = b.copy(HARDWARE, false /* isMutable */);
+        return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
+                topChild.getConfiguration().orientation, mainWindow.mStableInsets,
+                false /* reduced */, 1.0f /* scale */);
     }
 
     /**
@@ -284,6 +291,33 @@
         mPersister.setPaused(paused);
     }
 
+    /**
+     * Called when screen is being turned off.
+     */
+    void screenTurningOff(ScreenOffListener listener) {
+        if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+            listener.onScreenOff();
+            return;
+        }
+
+        // We can't take a snapshot when screen is off, so take a snapshot now!
+        mHandler.post(() -> {
+            try {
+                synchronized (mService.mWindowMap) {
+                    mTmpTasks.clear();
+                    mService.mRoot.forAllTasks(task -> {
+                        if (task.isVisible()) {
+                            mTmpTasks.add(task);
+                        }
+                    });
+                    snapshotTasks(mTmpTasks);
+                }
+            } finally {
+                listener.onScreenOff();
+            }
+        });
+    }
+
     void dump(PrintWriter pw, String prefix) {
         mCache.dump(pw, prefix);
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 866bfc0..297e288 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -39,6 +39,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayDeque;
+import java.util.ArrayList;
 
 /**
  * Persists {@link TaskSnapshot}s to disk.
@@ -55,10 +56,13 @@
     private static final int QUALITY = 95;
     private static final String PROTO_EXTENSION = ".proto";
     private static final String BITMAP_EXTENSION = ".jpg";
+    private static final int MAX_STORE_QUEUE_DEPTH = 2;
 
     @GuardedBy("mLock")
     private final ArrayDeque<WriteQueueItem> mWriteQueue = new ArrayDeque<>();
     @GuardedBy("mLock")
+    private final ArrayDeque<StoreWriteQueueItem> mStoreQueueItems = new ArrayDeque<>();
+    @GuardedBy("mLock")
     private boolean mQueueIdling;
     @GuardedBy("mLock")
     private boolean mPaused;
@@ -153,11 +157,22 @@
     @GuardedBy("mLock")
     private void sendToQueueLocked(WriteQueueItem item) {
         mWriteQueue.offer(item);
+        item.onQueuedLocked();
+        ensureStoreQueueDepthLocked();
         if (!mPaused) {
             mLock.notifyAll();
         }
     }
 
+    @GuardedBy("mLock")
+    private void ensureStoreQueueDepthLocked() {
+        while (mStoreQueueItems.size() > MAX_STORE_QUEUE_DEPTH) {
+            final StoreWriteQueueItem item = mStoreQueueItems.poll();
+            mWriteQueue.remove(item);
+            Slog.i(TAG, "Queue is too deep! Purged item with taskid=" + item.mTaskId);
+        }
+    }
+
     private File getDirectory(int userId) {
         return new File(mDirectoryResolver.getSystemDirectoryForUser(userId), SNAPSHOTS_DIRNAME);
     }
@@ -202,6 +217,9 @@
                         next = null;
                     } else {
                         next = mWriteQueue.poll();
+                        if (next != null) {
+                            next.onDequeuedLocked();
+                        }
                     }
                 }
                 if (next != null) {
@@ -226,6 +244,18 @@
 
     private abstract class WriteQueueItem {
         abstract void write();
+
+        /**
+         * Called when this queue item has been put into the queue.
+         */
+        void onQueuedLocked() {
+        }
+
+        /**
+         * Called when this queue item has been taken out of the queue.
+         */
+        void onDequeuedLocked() {
+        }
     }
 
     private class StoreWriteQueueItem extends WriteQueueItem {
@@ -240,6 +270,16 @@
         }
 
         @Override
+        void onQueuedLocked() {
+            mStoreQueueItems.offer(this);
+        }
+
+        @Override
+        void onDequeuedLocked() {
+            mStoreQueueItems.remove(this);
+        }
+
+        @Override
         void write() {
             if (!createDirectory(mUserId)) {
                 Slog.e(TAG, "Unable to create snapshot directory for user dir="
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 5e7b910..3a116bb 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -39,6 +39,7 @@
 import static com.android.internal.policy.DecorView.getColorViewLeftInset;
 import static com.android.internal.policy.DecorView.getColorViewTopInset;
 import static com.android.internal.policy.DecorView.getNavigationBarRect;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -113,7 +114,7 @@
     private final Rect mStableInsets = new Rect();
     private final Rect mContentInsets = new Rect();
     private final Rect mFrame = new Rect();
-    private final TaskSnapshot mSnapshot;
+    private TaskSnapshot mSnapshot;
     private final CharSequence mTitle;
     private boolean mHasDrawn;
     private long mShownTime;
@@ -232,10 +233,14 @@
             final long now = SystemClock.uptimeMillis();
             if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS) {
                 mHandler.postAtTime(this::remove, mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
+                if (DEBUG_STARTING_WINDOW) {
+                    Slog.v(TAG, "Defer removing snapshot surface in "  + (now - mShownTime) + "ms");
+                }
                 return;
             }
         }
         try {
+            if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing snapshot surface");
             mSession.remove(mWindow);
         } catch (RemoteException e) {
             // Local call.
@@ -254,6 +259,8 @@
 
     private void drawSnapshot() {
         final GraphicBuffer buffer = mSnapshot.getSnapshot();
+        if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Drawing snapshot surface sizeMismatch="
+                + mSizeMismatch);
         if (mSizeMismatch) {
             // The dimensions of the buffer and the window don't match, so attaching the buffer
             // will fail. Better create a child window with the exact dimensions and fill the parent
@@ -267,6 +274,9 @@
             mHasDrawn = true;
         }
         reportDrawn();
+
+        // In case window manager leaks us, make sure we don't retain the snapshot.
+        mSnapshot = null;
     }
 
     private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 9d48ce5..d189ff8 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -738,7 +738,8 @@
 
         // When the home stack is resizable, should always have the same stack and task bounds
         if (mStackId == HOME_STACK_ID) {
-            if (findHomeTask().isResizeable()) {
+            final Task homeTask = findHomeTask();
+            if (homeTask != null && homeTask.isResizeable()) {
                 // Calculate the home stack bounds when in docked mode and the home stack is
                 // resizeable.
                 getDisplayContent().mDividerControllerLocked
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 84ba139..600bc5c 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -16,6 +16,11 @@
 
 package com.android.server.wm;
 
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.res.Configuration.EMPTY;
+
 import android.annotation.CallSuper;
 import android.content.res.Configuration;
 import android.util.Pools;
@@ -27,11 +32,6 @@
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.res.Configuration.EMPTY;
-
 /**
  * Defines common functionality for classes that can hold windows directly or through their
  * children in a hierarchy form.
@@ -52,7 +52,7 @@
 
     // List of children for this window container. List is in z-order as the children appear on
     // screen with the top-most window container at the tail of the list.
-    protected final LinkedList<E> mChildren = new LinkedList();
+    protected final WindowList<E> mChildren = new WindowList<E>();
 
     /** Contains override configuration settings applied to this window container. */
     private Configuration mOverrideConfiguration = new Configuration();
@@ -258,7 +258,7 @@
             case POSITION_TOP:
                 if (mChildren.peekLast() != child) {
                     mChildren.remove(child);
-                    mChildren.addLast(child);
+                    mChildren.add(child);
                 }
                 if (includingParents && getParent() != null) {
                     getParent().positionChildAt(POSITION_TOP, this /* child */,
@@ -627,6 +627,17 @@
         wrapper.release();
     }
 
+    /**
+     * For all tasks at or below this container call the callback.
+     *
+     * @param callback Callback to be called for every task.
+     */
+    void forAllTasks(Consumer<Task> callback) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            mChildren.get(i).forAllTasks(callback);
+        }
+    }
+
     WindowState getWindow(Predicate<WindowState> callback) {
         for (int i = mChildren.size() - 1; i >= 0; --i) {
             final WindowState w = mChildren.get(i).getWindow(callback);
@@ -649,45 +660,50 @@
         }
 
         if (mParent != null && mParent == other.mParent) {
-            final LinkedList<WindowContainer> list = mParent.mChildren;
+            final WindowList<WindowContainer> list = mParent.mChildren;
             return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
         }
 
         final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
         final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
-        getParents(thisParentChain);
-        other.getParents(otherParentChain);
+        try {
+            getParents(thisParentChain);
+            other.getParents(otherParentChain);
 
-        // Find the common ancestor of both containers.
-        WindowContainer commonAncestor = null;
-        WindowContainer thisTop = thisParentChain.peekLast();
-        WindowContainer otherTop = otherParentChain.peekLast();
-        while (thisTop != null && otherTop != null && thisTop == otherTop) {
-            commonAncestor = thisParentChain.removeLast();
-            otherParentChain.removeLast();
-            thisTop = thisParentChain.peekLast();
-            otherTop = otherParentChain.peekLast();
+            // Find the common ancestor of both containers.
+            WindowContainer commonAncestor = null;
+            WindowContainer thisTop = thisParentChain.peekLast();
+            WindowContainer otherTop = otherParentChain.peekLast();
+            while (thisTop != null && otherTop != null && thisTop == otherTop) {
+                commonAncestor = thisParentChain.removeLast();
+                otherParentChain.removeLast();
+                thisTop = thisParentChain.peekLast();
+                otherTop = otherParentChain.peekLast();
+            }
+
+            // Containers don't belong to the same hierarchy???
+            if (commonAncestor == null) {
+                throw new IllegalArgumentException("No in the same hierarchy this="
+                        + thisParentChain + " other=" + otherParentChain);
+            }
+
+            // Children are always considered greater than their parents, so if one of the containers
+            // we are comparing it the parent of the other then whichever is the child is greater.
+            if (commonAncestor == this) {
+                return -1;
+            } else if (commonAncestor == other) {
+                return 1;
+            }
+
+            // The position of the first non-common ancestor in the common ancestor list determines
+            // which is greater the which.
+            final WindowList<WindowContainer> list = commonAncestor.mChildren;
+            return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
+                    ? 1 : -1;
+        } finally {
+            mTmpChain1.clear();
+            mTmpChain2.clear();
         }
-
-        // Containers don't belong to the same hierarchy???
-        if (commonAncestor == null) {
-            throw new IllegalArgumentException("No in the same hierarchy this="
-                    + thisParentChain + " other=" + otherParentChain);
-        }
-
-        // Children are always considered greater than their parents, so if one of the containers
-        // we are comparing it the parent of the other then whichever is the child is greater.
-        if (commonAncestor == this) {
-            return -1;
-        } else if (commonAncestor == other) {
-            return 1;
-        }
-
-        // The position of the first non-common ancestor in the common ancestor list determines
-        // which is greater the which.
-        final LinkedList<WindowContainer> list = commonAncestor.mChildren;
-        return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
-                ? 1 : -1;
     }
 
     private void getParents(LinkedList<WindowContainer> parents) {
diff --git a/services/core/java/com/android/server/wm/WindowLayersController.java b/services/core/java/com/android/server/wm/WindowLayersController.java
index 172ec48..01a3143 100644
--- a/services/core/java/com/android/server/wm/WindowLayersController.java
+++ b/services/core/java/com/android/server/wm/WindowLayersController.java
@@ -257,9 +257,20 @@
         w.mLayer = layer;
         w.mWinAnimator.mAnimLayer = w.getAnimLayerAdjustment()
                 + w.getSpecialWindowAnimLayerAdjustment();
-        if (w.mAppToken != null && w.mAppToken.mAppAnimator.thumbnailForceAboveLayer > 0
-                && w.mWinAnimator.mAnimLayer > w.mAppToken.mAppAnimator.thumbnailForceAboveLayer) {
-            w.mAppToken.mAppAnimator.thumbnailForceAboveLayer = w.mWinAnimator.mAnimLayer;
+        if (w.mAppToken != null && w.mAppToken.mAppAnimator.thumbnailForceAboveLayer > 0) {
+            if (w.mWinAnimator.mAnimLayer > w.mAppToken.mAppAnimator.thumbnailForceAboveLayer) {
+                w.mAppToken.mAppAnimator.thumbnailForceAboveLayer = w.mWinAnimator.mAnimLayer;
+            }
+            // TODO(b/62029108): the entire contents of the if statement should call the refactored
+            // function to set the thumbnail layer for w.AppToken
+            int highestLayer = w.mAppToken.getHighestAnimLayer();
+            if (highestLayer > 0) {
+                if (w.mAppToken.mAppAnimator.thumbnail != null
+                        && w.mAppToken.mAppAnimator.thumbnailForceAboveLayer != highestLayer) {
+                    w.mAppToken.mAppAnimator.thumbnailForceAboveLayer = highestLayer;
+                    w.mAppToken.mAppAnimator.thumbnail.setLayer(highestLayer + 1);
+                }
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowList.java b/services/core/java/com/android/server/wm/WindowList.java
new file mode 100644
index 0000000..dfeba40
--- /dev/null
+++ b/services/core/java/com/android/server/wm/WindowList.java
@@ -0,0 +1,38 @@
+/*
+ * 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.wm;
+
+import java.util.ArrayList;
+
+/**
+ * An {@link ArrayList} with extended functionality to be used as the children data structure in
+ * {@link WindowContainer}.
+ */
+class WindowList<E> extends ArrayList<E> {
+
+    void addFirst(E e) {
+        add(0, e);
+    }
+
+    E peekLast() {
+        return size() > 0 ? get(size() - 1) : null;
+    }
+
+    E peekFirst() {
+        return size() > 0 ? get(0) : null;
+    }
+}
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 1b61fca..8279b51 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -51,7 +51,8 @@
     static final boolean DEBUG_APP_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
     static final boolean DEBUG_APP_TRANSITIONS = false;
-    static final boolean DEBUG_STARTING_WINDOW = false;
+    static final boolean DEBUG_STARTING_WINDOW_VERBOSE = false;
+    static final boolean DEBUG_STARTING_WINDOW = DEBUG_STARTING_WINDOW_VERBOSE || true;
     static final boolean DEBUG_WALLPAPER = false;
     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
     static final boolean DEBUG_DRAG = false;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 54bfeb5..a15891b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -203,6 +203,7 @@
 import android.view.WindowManagerInternal;
 import android.view.WindowManagerPolicy;
 import android.view.WindowManagerPolicy.PointerEventListener;
+import android.view.WindowManagerPolicy.ScreenOffListener;
 import android.view.animation.Animation;
 import android.view.inputmethod.InputMethodManagerInternal;
 
@@ -1521,7 +1522,7 @@
         // Try using the target SDK of the root window
         if (attachedWindow != null) {
             return attachedWindow.mAppToken != null
-                    && attachedWindow.mAppToken.mTargetSdk > Build.VERSION_CODES.N_MR1;
+                    && attachedWindow.mAppToken.mTargetSdk >= Build.VERSION_CODES.O;
         } else {
             // Otherwise, look at the package
             try {
@@ -1532,7 +1533,7 @@
                     throw new SecurityException("Package " + packageName + " not in UID "
                             + callingUid);
                 }
-                if (appInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+                if (appInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
                     return true;
                 }
             } catch (PackageManager.NameNotFoundException e) {
@@ -1685,6 +1686,10 @@
                 // re-factor.
                 atoken.firstWindowDrawn = false;
                 atoken.clearAllDrawn();
+                final TaskStack stack = atoken.getStack();
+                if (stack != null) {
+                    stack.mExitingAppTokens.remove(atoken);
+                }
             }
         }
 
@@ -2806,6 +2811,11 @@
         mH.sendEmptyMessage(H.NOTIFY_KEYGUARD_TRUSTED_CHANGED);
     }
 
+    @Override
+    public void screenTurningOff(ScreenOffListener listener) {
+        mTaskSnapshotController.screenTurningOff(listener);
+    }
+
     /**
      * Starts deferring layout passes. Useful when doing multiple changes but to optimize
      * performance, only one layout pass should be done. This can be called multiple times, and
@@ -3331,6 +3341,13 @@
         performEnableScreen();
     }
 
+    /**
+     * Called when System UI has been started.
+     */
+    public void onSystemUiStarted() {
+        mPolicy.onSystemUiStarted();
+    }
+
     private void performEnableScreen() {
         synchronized(mWindowMap) {
             if (DEBUG_BOOT) Slog.i(TAG_WM, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled
@@ -3346,6 +3363,10 @@
                 return;
             }
 
+            if (!mShowingBootMessages && !mPolicy.canDismissBootAnimation()) {
+                return;
+            }
+
             // Don't enable the screen until all existing windows have been drawn.
             if (!mForceDisplayEnabled
                     // TODO(multidisplay): Expand to all displays?
@@ -3359,7 +3380,7 @@
                 try {
                     IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
                     if (surfaceFlinger != null) {
-                        //Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
+                        Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
                         Parcel data = Parcel.obtain();
                         data.writeInterfaceToken("android.ui.ISurfaceComposer");
                         surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 344c616..acd7703 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -80,6 +80,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
@@ -138,6 +139,7 @@
 import com.android.server.input.InputWindowHandle;
 
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.LinkedList;
@@ -170,7 +172,7 @@
     final int mOwnerUid;
     /** The owner has {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW} */
     final boolean mOwnerCanAddInternalSystemWindow;
-    final IWindowId mWindowId;
+    final WindowId mWindowId;
     WindowToken mToken;
     // The same object as mToken if this is an app window and null for non-app windows.
     AppWindowToken mAppToken;
@@ -587,20 +589,7 @@
         mAppToken = mToken.asAppWindowToken();
         mOwnerUid = ownerId;
         mOwnerCanAddInternalSystemWindow = ownerCanAddInternalSystemWindow;
-        mWindowId = new IWindowId.Stub() {
-            @Override
-            public void registerFocusObserver(IWindowFocusObserver observer) {
-                WindowState.this.registerFocusObserver(observer);
-            }
-            @Override
-            public void unregisterFocusObserver(IWindowFocusObserver observer) {
-                WindowState.this.unregisterFocusObserver(observer);
-            }
-            @Override
-            public boolean isFocused() {
-                return WindowState.this.isFocused();
-            }
-        };
+        mWindowId = new WindowId(this);
         mAttrs.copyFrom(a);
         mViewVisibility = viewVisibility;
         mPolicy = mService.mPolicy;
@@ -1306,7 +1295,7 @@
      *         otherwise.
      */
     boolean wouldBeVisibleIfPolicyIgnored() {
-        return mHasSurface && mPolicyVisibility && !isParentWindowHidden()
+        return mHasSurface && !isParentWindowHidden()
                 && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible);
     }
 
@@ -1414,6 +1403,16 @@
                         || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null)));
     }
 
+    // TODO: Another visibility method that was added late in the release to minimize risk.
+    @Override
+    public boolean canAffectSystemUiFlags() {
+        final boolean shown = mWinAnimator.getShown();
+        final boolean exiting = mAnimatingExit || mDestroying
+                || mAppToken != null && mAppToken.hidden;
+        final boolean translucent = mAttrs.alpha == 0.0f;
+        return shown && !exiting && !translucent;
+    }
+
     /**
      * Like isOnScreen, but returns false if the surface hasn't yet
      * been drawn.
@@ -3797,7 +3796,7 @@
 
     private void logPerformShow(String prefix) {
         if (DEBUG_VISIBILITY
-                || (DEBUG_STARTING_WINDOW && mAttrs.type == TYPE_APPLICATION_STARTING)) {
+                || (DEBUG_STARTING_WINDOW_VERBOSE && mAttrs.type == TYPE_APPLICATION_STARTING)) {
             Slog.v(TAG, prefix + this
                     + ": mDrawState=" + mWinAnimator.drawStateToString()
                     + " readyForDisplay=" + isReadyForDisplay()
@@ -4435,6 +4434,40 @@
         }
     }
 
+    private static final class WindowId extends IWindowId.Stub {
+        private final WeakReference<WindowState> mOuter;
+
+        private WindowId(WindowState outer) {
+
+            // Use a weak reference for the outer class. This is important to prevent the following
+            // leak: Since we send this class to the client process, binder will keep it alive as
+            // long as the client keeps it alive. Now, if the window is removed, we need to clear
+            // out our reference so even though this class is kept alive we don't leak WindowState,
+            // which can keep a whole lot of classes alive.
+            mOuter = new WeakReference<>(outer);
+        }
+
+        @Override
+        public void registerFocusObserver(IWindowFocusObserver observer) {
+            final WindowState outer = mOuter.get();
+            if (outer != null) {
+                outer.registerFocusObserver(observer);
+            }
+        }
+        @Override
+        public void unregisterFocusObserver(IWindowFocusObserver observer) {
+            final WindowState outer = mOuter.get();
+            if (outer != null) {
+                outer.unregisterFocusObserver(observer);
+            }
+        }
+        @Override
+        public boolean isFocused() {
+            final WindowState outer = mOuter.get();
+            return outer != null && outer.isFocused();
+        }
+    }
+
     boolean usesRelativeZOrdering() {
         if (!isChildWindow()) {
             return false;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 8d3ef40..d75afcf 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -30,6 +30,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
@@ -519,7 +520,7 @@
 
     // This must be called while inside a transaction.
     boolean commitFinishDrawingLocked() {
-        if (DEBUG_STARTING_WINDOW &&
+        if (DEBUG_STARTING_WINDOW_VERBOSE &&
                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
             Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
                     + drawStateToString());
@@ -968,10 +969,8 @@
                 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
             }
 
-            //TODO (multidisplay): Magnification is supported only for the default display.
-            if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
-                MagnificationSpec spec = mService.mAccessibilityController
-                        .getMagnificationSpecForWindowLocked(mWin);
+            MagnificationSpec spec = getMagnificationSpec();
+            if (spec != null) {
                 applyMagnificationSpec(spec, tmpMatrix);
             }
 
@@ -1058,11 +1057,7 @@
                 TAG, "computeShownFrameLocked: " + this +
                 " not attached, mAlpha=" + mAlpha);
 
-        MagnificationSpec spec = null;
-        //TODO (multidisplay): Magnification is supported only for the default display.
-        if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
-            spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
-        }
+        MagnificationSpec spec = getMagnificationSpec();
         if (spec != null) {
             final Rect frame = mWin.mFrame;
             final float tmpFloats[] = mService.mTmpFloats;
@@ -1099,6 +1094,14 @@
         }
     }
 
+    private MagnificationSpec getMagnificationSpec() {
+        //TODO (multidisplay): Magnification is supported only for the default display.
+        if (mService.mAccessibilityController != null && mWin.getDisplayId() == DEFAULT_DISPLAY) {
+            return mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
+        }
+        return null;
+    }
+
     /**
      * In some scenarios we use a screen space clip rect (so called, final clip rect)
      * to crop to stack bounds. Generally because it's easier to deal with while
@@ -1136,6 +1139,27 @@
         if (StackId.tasksAreFloating(stack.mStackId)) {
             w.expandForSurfaceInsets(finalClipRect);
         }
+
+        // We may be applying a magnification spec to all windows,
+        // simulating a transformation in screen space, in which case
+        // we need to transform all other screen space values...including
+        // the final crop. This is kind of messed up and we should look
+        // in to actually transforming screen-space via a parent-layer.
+        // b/38322835
+        MagnificationSpec spec = getMagnificationSpec();
+        if (spec != null && !spec.isNop()) {
+            Matrix transform = mWin.mTmpMatrix;
+            RectF finalCrop = mService.mTmpRectF;
+            transform.reset();
+            transform.postScale(spec.scale, spec.scale);
+            transform.postTranslate(-spec.offsetX, -spec.offsetY);
+            transform.mapRect(finalCrop);
+            finalClipRect.top = (int)finalCrop.top;
+            finalClipRect.left = (int)finalCrop.left;
+            finalClipRect.right = (int)finalClipRect.right;
+            finalClipRect.bottom = (int)finalClipRect.bottom;
+        }
+
         return true;
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index e576f2f..4a1a705 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -15,6 +15,7 @@
 import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
 import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY;
 import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+import static com.android.server.wm.AppTransition.TRANSIT_NONE;
 import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE;
 import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
 import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
@@ -580,6 +581,11 @@
 
     private int maybeUpdateTransitToWallpaper(int transit, boolean openingAppHasWallpaper,
             boolean closingAppHasWallpaper) {
+        // Given no app transition pass it through instead of a wallpaper transition
+        if (transit == TRANSIT_NONE) {
+            return TRANSIT_NONE;
+        }
+
         // if wallpaper is animating in or out set oldWallpaper to null else to wallpaper
         final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
         final WindowState oldWallpaper = mWallpaperControllerLocked.isWallpaperTargetAnimating()
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0965f03..1d44a205 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -671,7 +671,6 @@
         VibratorService vibrator = null;
         IStorageManager storageManager = null;
         NetworkManagementService networkManagement = null;
-        IpSecService ipSecService = null;
         NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
         ConnectivityService connectivity = null;
@@ -1024,15 +1023,6 @@
                     reportWtf("starting NetworkManagement Service", e);
                 }
                 traceEnd();
-
-                traceBeginAndSlog("StartIpSecService");
-                try {
-                    ipSecService = IpSecService.create(context);
-                    ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService);
-                } catch (Throwable e) {
-                    reportWtf("starting IpSec Service", e);
-                }
-                traceEnd();
             }
 
             if (!disableNonCoreServices && !disableTextServices) {
@@ -1643,7 +1633,7 @@
         final TelephonyRegistry telephonyRegistryF = telephonyRegistry;
         final MediaRouterService mediaRouterF = mediaRouter;
         final MmsServiceBroker mmsServiceF = mmsService;
-        final IpSecService ipSecServiceF = ipSecService;
+        final WindowManagerService windowManagerF = wm;
 
         // We now tell the activity manager it is okay to run third party
         // code.  It will call back into us once it has gotten to the state
@@ -1683,7 +1673,7 @@
 
             traceBeginAndSlog("StartSystemUI");
             try {
-                startSystemUi(context);
+                startSystemUi(context, windowManagerF);
             } catch (Throwable e) {
                 reportWtf("starting System UI", e);
             }
@@ -1707,13 +1697,6 @@
                         .networkScoreAndNetworkManagementServiceReady();
             }
             traceEnd();
-            traceBeginAndSlog("MakeIpSecServiceReady");
-            try {
-                if (ipSecServiceF != null) ipSecServiceF.systemReady();
-            } catch (Throwable e) {
-                reportWtf("making IpSec Service ready", e);
-            }
-            traceEnd();
             traceBeginAndSlog("MakeNetworkStatsServiceReady");
             try {
                 if (networkStatsF != null) networkStatsF.systemReady();
@@ -1837,13 +1820,14 @@
         }, BOOT_TIMINGS_TRACE_LOG);
     }
 
-    static final void startSystemUi(Context context) {
+    static final void startSystemUi(Context context, WindowManagerService windowManager) {
         Intent intent = new Intent();
         intent.setComponent(new ComponentName("com.android.systemui",
                     "com.android.systemui.SystemUIService"));
         intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
         //Slog.d(TAG, "Starting service: " + intent);
         context.startServiceAsUser(intent, UserHandle.SYSTEM);
+        windowManager.onSystemUiStarted();
     }
 
     private static void traceBeginAndSlog(String name) {
diff --git a/services/net/java/android/net/util/SharedLog.java b/services/net/java/android/net/util/SharedLog.java
new file mode 100644
index 0000000..343d237
--- /dev/null
+++ b/services/net/java/android/net/util/SharedLog.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util;
+
+import android.text.TextUtils;
+import android.util.LocalLog;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.StringJoiner;
+
+
+/**
+ * Class to centralize logging functionality for tethering.
+ *
+ * All access to class methods other than dump() must be on the same thread.
+ *
+ * @hide
+ */
+public class SharedLog {
+    private final static int DEFAULT_MAX_RECORDS = 500;
+    private final static String COMPONENT_DELIMITER = ".";
+
+    private enum Category {
+        NONE,
+        ERROR,
+        MARK,
+        WARN,
+    };
+
+    private final LocalLog mLocalLog;
+    // The tag to use for output to the system log. This is not output to the
+    // LocalLog because that would be redundant.
+    private final String mTag;
+    // The component (or subcomponent) of a system that is sharing this log.
+    // This can grow in depth if components call forSubComponent() to obtain
+    // their SharedLog instance. The tag is not included in the component for
+    // brevity.
+    private final String mComponent;
+
+    public SharedLog(String tag) {
+        this(DEFAULT_MAX_RECORDS, tag);
+    }
+
+    public SharedLog(int maxRecords, String tag) {
+        this(new LocalLog(maxRecords), tag, tag);
+    }
+
+    private SharedLog(LocalLog localLog, String tag, String component) {
+        mLocalLog = localLog;
+        mTag = tag;
+        mComponent = component;
+    }
+
+    public SharedLog forSubComponent(String component) {
+        if (!isRootLogInstance()) {
+            component = mComponent + COMPONENT_DELIMITER + component;
+        }
+        return new SharedLog(mLocalLog, mTag, component);
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        mLocalLog.readOnlyLocalLog().dump(fd, writer, args);
+    }
+
+    //////
+    // Methods that both log an entry and emit it to the system log.
+    //////
+
+    public void e(Exception e) {
+        Log.e(mTag, record(Category.ERROR, e.toString()));
+    }
+
+    public void e(String msg) {
+        Log.e(mTag, record(Category.ERROR, msg));
+    }
+
+    public void i(String msg) {
+        Log.i(mTag, record(Category.NONE, msg));
+    }
+
+    public void w(String msg) {
+        Log.w(mTag, record(Category.WARN, msg));
+    }
+
+    //////
+    // Methods that only log an entry (and do NOT emit to the system log).
+    //////
+
+    public void log(String msg) {
+        record(Category.NONE, msg);
+    }
+
+    public void mark(String msg) {
+        record(Category.MARK, msg);
+    }
+
+    private String record(Category category, String msg) {
+        final String entry = logLine(category, msg);
+        mLocalLog.log(entry);
+        return entry;
+    }
+
+    private String logLine(Category category, String msg) {
+        final StringJoiner sj = new StringJoiner(" ");
+        if (!isRootLogInstance()) sj.add("[" + mComponent + "]");
+        if (category != Category.NONE) sj.add(category.toString());
+        return sj.add(msg).toString();
+    }
+
+    // Check whether this SharedLog instance is nominally the top level in
+    // a potential hierarchy of shared logs (the root of a tree),
+    // or is a subcomponent within the hierarchy.
+    private boolean isRootLogInstance() {
+        return TextUtils.isEmpty(mComponent) || mComponent.equals(mTag);
+    }
+}
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
index 267d2a6..0812783 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
@@ -99,7 +99,7 @@
         when(mMockContext.getPackageManager()).thenReturn(mPm);
 
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
-        upgrade.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
+        upgrade.targetSdkVersion = Build.VERSION_CODES.O;
         try {
             when(mPm.getApplicationInfoAsUser(eq(pkg), anyInt(), anyInt())).thenReturn(legacy);
             when(mPm.getApplicationInfoAsUser(eq(pkg2), anyInt(), anyInt())).thenReturn(upgrade);
diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
index cb0ee25..9f7c515 100644
--- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
@@ -27,6 +27,7 @@
 import org.json.JSONArray;
 import org.json.JSONObject;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -50,15 +51,11 @@
 import android.os.Build;
 import android.os.UserHandle;
 import android.provider.Settings.Secure;
-import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.TestableContext;
-import android.testing.TestableSettingsProvider;
 import android.util.ArrayMap;
-import android.util.Slog;
 import android.util.Xml;
 
 import java.io.BufferedInputStream;
@@ -87,10 +84,10 @@
 public class RankingHelperTest extends NotificationTestCase {
     private static final String PKG = "com.android.server.notification";
     private static final int UID = 0;
-    private static final UserHandle USER = UserHandle.getUserHandleForUid(UID);
+    private static final UserHandle USER = UserHandle.of(0);
     private static final String UPDATED_PKG = "updatedPkg";
-    private static final int UID2 = 1111111;
-    private static final UserHandle USER2 = UserHandle.getUserHandleForUid(UID2);
+    private static final int UID2 = 1111;
+    private static final UserHandle USER2 = UserHandle.of(10);
     private static final String TEST_CHANNEL_ID = "test_channel_id";
 
     @Mock NotificationUsageStats mUsageStats;
@@ -119,10 +116,11 @@
         final ApplicationInfo legacy = new ApplicationInfo();
         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
         final ApplicationInfo upgrade = new ApplicationInfo();
-        upgrade.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
+        upgrade.targetSdkVersion = Build.VERSION_CODES.O;
         when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy);
         when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(upgrade);
         when(mPm.getPackageUidAsUser(eq(PKG), anyInt())).thenReturn(UID);
+        when(mPm.getPackageUidAsUser(eq(UPDATED_PKG), anyInt())).thenReturn(UID2);
         when(mContext.getResources()).thenReturn(
                 InstrumentationRegistry.getContext().getResources());
         when(mContext.getPackageManager()).thenReturn(mPm);
@@ -198,24 +196,21 @@
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
         serializer.startDocument(null, true);
-        serializer.startTag(null, "ranking");
         mHelper.writeXml(serializer, forBackup);
-        serializer.endTag(null, "ranking");
         serializer.endDocument();
         serializer.flush();
-
         for (String channelId : channelIds) {
             mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId);
         }
         return baos;
     }
 
-    private void loadStreamXml(ByteArrayOutputStream stream) throws Exception {
+    private void loadStreamXml(ByteArrayOutputStream stream, boolean forRestore) throws Exception {
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(new ByteArrayInputStream(stream.toByteArray())),
                 null);
         parser.nextTag();
-        mHelper.readXml(parser, false);
+        mHelper.readXml(parser, forRestore);
     }
 
     private void compareChannels(NotificationChannel expected, NotificationChannel actual) {
@@ -322,7 +317,7 @@
                 channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
         mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID});
 
-        loadStreamXml(baos);
+        loadStreamXml(baos, false);
 
         assertTrue(mHelper.canShowBadge(PKG, UID));
         assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
@@ -353,6 +348,70 @@
     }
 
     @Test
+    public void testChannelXmlForBackup() throws Exception {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
+        NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
+        NotificationChannel channel1 =
+                new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+        NotificationChannel channel2 =
+                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+        channel2.setDescription("descriptions for all");
+        channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
+        channel2.enableLights(true);
+        channel2.setBypassDnd(true);
+        channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+        channel2.enableVibration(false);
+        channel2.setGroup(ncg.getId());
+        channel2.setLightColor(Color.BLUE);
+
+        mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
+        mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
+        mHelper.createNotificationChannel(PKG, UID, channel1, true);
+        mHelper.createNotificationChannel(PKG, UID, channel2, false);
+        mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true);
+
+        mHelper.setShowBadge(PKG, UID, true);
+
+        mHelper.setImportance(UPDATED_PKG, UID2, IMPORTANCE_NONE);
+
+        ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(),
+                channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
+        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG, UPDATED_PKG}, new int[]{UID, UID2});
+
+        mHelper.setShowBadge(UPDATED_PKG, UID2, true);
+
+        loadStreamXml(baos, true);
+
+        assertEquals(IMPORTANCE_NONE, mHelper.getImportance(UPDATED_PKG, UID2));
+        assertTrue(mHelper.canShowBadge(PKG, UID));
+        assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
+        compareChannels(channel2,
+                mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
+
+        List<NotificationChannelGroup> actualGroups =
+                mHelper.getNotificationChannelGroups(PKG, UID, false).getList();
+        boolean foundNcg = false;
+        for (NotificationChannelGroup actual : actualGroups) {
+            if (ncg.getId().equals(actual.getId())) {
+                foundNcg = true;
+                compareGroups(ncg, actual);
+            } else if (ncg2.getId().equals(actual.getId())) {
+                compareGroups(ncg2, actual);
+            }
+        }
+        assertTrue(foundNcg);
+
+        boolean foundChannel2Group = false;
+        for (NotificationChannelGroup actual : actualGroups) {
+            if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
+                foundChannel2Group = true;
+                break;
+            }
+        }
+        assertTrue(foundChannel2Group);
+    }
+
+    @Test
     public void testChannelXml_backup() throws Exception {
         NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
         NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
@@ -396,7 +455,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
                 NotificationChannel.DEFAULT_CHANNEL_ID);
 
-        loadStreamXml(baos);
+        loadStreamXml(baos, false);
 
         final NotificationChannel updated = mHelper.getNotificationChannel(PKG, UID,
                 NotificationChannel.DEFAULT_CHANNEL_ID, false);
@@ -416,7 +475,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
                 NotificationChannel.DEFAULT_CHANNEL_ID);
 
-        loadStreamXml(baos);
+        loadStreamXml(baos, false);
 
         assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
                 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance());
@@ -464,7 +523,7 @@
         final ApplicationInfo upgraded = new ApplicationInfo();
         upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
         when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded);
-        loadStreamXml(baos);
+        loadStreamXml(baos, false);
 
         // Default Channel should be gone.
         assertEquals(null, mHelper.getNotificationChannel(PKG, UID,
@@ -482,7 +541,7 @@
         final ApplicationInfo upgraded = new ApplicationInfo();
         upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
         when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded);
-        loadStreamXml(baos);
+        loadStreamXml(baos, false);
 
         // Default Channel should be gone.
         assertEquals(null, mHelper.getNotificationChannel(PKG, UID,
@@ -496,7 +555,7 @@
         mHelper.createNotificationChannel(PKG, UID,
                 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true);
 
-        loadStreamXml(baos);
+        loadStreamXml(baos, false);
 
         // Should still have the newly created channel that wasn't in the xml.
         assertTrue(mHelper.getNotificationChannel(PKG, UID, "bananas", false) != null);
@@ -1046,6 +1105,24 @@
     }
 
     @Test
+    public void testOnPackageChange_downgradeTargetSdk() throws Exception {
+        // create channel as api 26
+        mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true);
+
+        // install new app version targeting 25
+        final ApplicationInfo legacy = new ApplicationInfo();
+        legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+        when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(legacy);
+        mHelper.onPackagesChanged(
+                false, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
+
+        // make sure the default channel was readded
+        //assertEquals(2, mHelper.getNotificationChannels(UPDATED_PKG, UID2, false).getList().size());
+        assertNotNull(mHelper.getNotificationChannel(
+                UPDATED_PKG, UID2, NotificationChannel.DEFAULT_CHANNEL_ID, false));
+    }
+
+    @Test
     public void testRecordDefaults() throws Exception {
         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID));
         assertEquals(true, mHelper.canShowBadge(PKG, UID));
@@ -1252,5 +1329,4 @@
         assertFalse(mHelper.badgingEnabled(USER));
         assertTrue(mHelper.badgingEnabled(USER2));
     }
-
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
index 8afe853..72820f1 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ActionReplacingCallbackTest.java
@@ -25,6 +25,9 @@
 import android.view.accessibility.IAccessibilityInteractionConnection;
 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
 
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -45,12 +48,13 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
 import static org.mockito.MockitoAnnotations.initMocks;
 
 /**
@@ -63,15 +67,50 @@
     private static final int NON_ROOT_NODE_ID = 0xAAAA5555;
     private static final long INTERROGATING_TID = 0x1234FACE;
 
-    private static final AccessibilityAction[] ACTIONS_FROM_REPLACER =
-            {ACTION_CLICK, ACTION_EXPAND};
-    private static final AccessibilityAction[] A11Y_FOCUS_ACTIONS =
-            {ACTION_ACCESSIBILITY_FOCUS, ACTION_CLEAR_ACCESSIBILITY_FOCUS};
     // We expect both the replacer actions and a11y focus actions to appear
     private static final AccessibilityAction[] REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE =
             {ACTION_CLICK, ACTION_EXPAND, ACTION_ACCESSIBILITY_FOCUS,
                     ACTION_CLEAR_ACCESSIBILITY_FOCUS};
 
+    private static final Matcher<AccessibilityNodeInfo> HAS_NO_ACTIONS =
+            new BaseMatcher<AccessibilityNodeInfo>() {
+        @Override
+        public boolean matches(Object o) {
+            AccessibilityNodeInfo node = (AccessibilityNodeInfo) o;
+            if (!node.getActionList().isEmpty()) return false;
+            return (!node.isScrollable() && !node.isLongClickable() && !node.isClickable()
+                    && !node.isContextClickable() && !node.isDismissable() && !node.isFocusable());
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("Has no actions");
+        }
+    };
+
+    private static final Matcher<AccessibilityNodeInfo> HAS_EXPECTED_ACTIONS_ON_ROOT =
+            new BaseMatcher<AccessibilityNodeInfo>() {
+                @Override
+                public boolean matches(Object o) {
+                    AccessibilityNodeInfo node = (AccessibilityNodeInfo) o;
+                    List<AccessibilityAction> actions = node.getActionList();
+                    if ((actions.size() != 4) || !actions.contains(ACTION_CLICK)
+                            || !actions.contains(ACTION_EXPAND)
+                            || !actions.contains(ACTION_ACCESSIBILITY_FOCUS)) {
+                        return false;
+                    }
+                    return (!node.isScrollable() && !node.isLongClickable()
+                            && !node.isLongClickable() && node.isClickable()
+                            && !node.isContextClickable() && !node.isDismissable()
+                            && !node.isFocusable());
+                }
+
+                @Override
+                public void describeTo(Description description) {
+                    description.appendText("Has only 4 actions expected on root");
+                }
+            };
+
     @Mock IAccessibilityInteractionConnectionCallback mMockServiceCallback;
     @Mock IAccessibilityInteractionConnection mMockReplacerConnection;
 
@@ -118,9 +157,10 @@
                 eq(INTERACTION_ID));
         AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
         assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
-        assertInfoHasExactlyTheseActions(infoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+        assertThat(infoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
     }
 
+    @Test
     public void testCallbacks_singleNonrootNodeThenReplacer_returnsNodeWithNoActions()
             throws RemoteException {
         AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
@@ -136,9 +176,10 @@
                 eq(INTERACTION_ID));
         AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
         assertEquals(NON_ROOT_NODE_ID, infoSentToService.getSourceNodeId());
-        assertTrue(infoSentToService.getActionList().isEmpty());
+        assertThat(infoSentToService, HAS_NO_ACTIONS);
     }
 
+    @Test
     public void testCallbacks_replacerThenSingleRootNode_returnsNodeWithReplacedActions()
             throws RemoteException {
         mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
@@ -154,9 +195,10 @@
                 eq(INTERACTION_ID));
         AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
         assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
-        assertInfoHasExactlyTheseActions(infoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
+        assertThat(infoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
     }
 
+    @Test
     public void testCallbacks_multipleNodesThenReplacer_clearsActionsAndAddsSomeToRoot()
             throws RemoteException {
         mActionReplacingCallback
@@ -173,11 +215,11 @@
                 mInfoListCaptor.getValue(), AccessibilityNodeInfo.ROOT_NODE_ID);
         AccessibilityNodeInfo otherInfoSentToService = getNodeWithIdFromList(
                 mInfoListCaptor.getValue(), NON_ROOT_NODE_ID);
-        assertInfoHasExactlyTheseActions(
-                rootInfoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
-        assertTrue(otherInfoSentToService.getActionList().isEmpty());
+        assertThat(rootInfoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
+        assertThat(otherInfoSentToService, HAS_NO_ACTIONS);
     }
 
+    @Test
     public void testCallbacks_replacerThenMultipleNodes_clearsActionsAndAddsSomeToRoot()
             throws RemoteException {
         mActionReplacingCallback.setFindAccessibilityNodeInfosResult(getReplacerNodes(),
@@ -194,18 +236,18 @@
                 mInfoListCaptor.getValue(), AccessibilityNodeInfo.ROOT_NODE_ID);
         AccessibilityNodeInfo otherInfoSentToService = getNodeWithIdFromList(
                 mInfoListCaptor.getValue(), NON_ROOT_NODE_ID);
-        assertInfoHasExactlyTheseActions(
-                rootInfoSentToService, REQUIRED_ACTIONS_ON_ROOT_TO_SERVICE);
-        assertTrue(otherInfoSentToService.getActionList().isEmpty());
+        assertThat(rootInfoSentToService, HAS_EXPECTED_ACTIONS_ON_ROOT);
+        assertThat(otherInfoSentToService, HAS_NO_ACTIONS);
     }
 
+    @Test
     public void testConstructor_actionReplacerThrowsException_passesDataToService()
             throws RemoteException {
         doThrow(RemoteException.class).when(mMockReplacerConnection)
                 .findAccessibilityNodeInfoByAccessibilityId(eq(AccessibilityNodeInfo.ROOT_NODE_ID),
-                        (Region) anyObject(), mInteractionIdCaptor.capture(),
-                        eq(mActionReplacingCallback), eq(0), eq(INTERROGATING_PID),
-                        eq(INTERROGATING_TID), (MagnificationSpec) anyObject(), eq(null));
+                        (Region) anyObject(), anyInt(), (ActionReplacingCallback) anyObject(),
+                        eq(0),  eq(INTERROGATING_PID), eq(INTERROGATING_TID),
+                        (MagnificationSpec) anyObject(), eq(null));
         ActionReplacingCallback actionReplacingCallback = new ActionReplacingCallback(
                 mMockServiceCallback, mMockReplacerConnection, INTERACTION_ID, INTERROGATING_PID,
                 INTERROGATING_TID);
@@ -214,16 +256,17 @@
         AccessibilityNodeInfo infoFromApp = AccessibilityNodeInfo.obtain();
         infoFromApp.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID, APP_WINDOW_ID);
         infoFromApp.addAction(ACTION_CONTEXT_CLICK);
+        infoFromApp.setContextClickable(true);
         actionReplacingCallback.setFindAccessibilityNodeInfoResult(infoFromApp, INTERACTION_ID);
 
         verify(mMockServiceCallback).setFindAccessibilityNodeInfoResult(mInfoCaptor.capture(),
                 eq(INTERACTION_ID));
         AccessibilityNodeInfo infoSentToService = mInfoCaptor.getValue();
         assertEquals(AccessibilityNodeInfo.ROOT_NODE_ID, infoSentToService.getSourceNodeId());
-        assertEquals(1, infoSentToService.getActionList().size());
-        assertEquals(ACTION_CONTEXT_CLICK, infoSentToService.getActionList().get(0));
+        assertThat(infoSentToService, HAS_NO_ACTIONS);
     }
 
+    @Test
     public void testSetPerformAccessibilityActionResult_actsAsPassThrough() throws RemoteException {
         mActionReplacingCallback.setPerformAccessibilityActionResult(true, INTERACTION_ID);
         verify(mMockServiceCallback).setPerformAccessibilityActionResult(true, INTERACTION_ID);
@@ -236,9 +279,9 @@
         AccessibilityNodeInfo root = AccessibilityNodeInfo.obtain();
         root.setSourceNodeId(AccessibilityNodeInfo.ROOT_NODE_ID,
                 AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID);
-        for (AccessibilityAction action : ACTIONS_FROM_REPLACER) {
-            root.addAction(action);
-        }
+        root.addAction(ACTION_CLICK);
+        root.addAction(ACTION_EXPAND);
+        root.setClickable(true);
 
         // Second node should have no effect
         AccessibilityNodeInfo other = AccessibilityNodeInfo.obtain();
@@ -249,13 +292,6 @@
         return Arrays.asList(root, other);
     }
 
-    private void assertInfoHasExactlyTheseActions(
-            AccessibilityNodeInfo info, AccessibilityAction[] actions) {
-        List<AccessibilityAction> nodeActions = info.getActionList();
-        assertEquals(new HashSet<AccessibilityAction>(nodeActions),
-                new HashSet<AccessibilityAction>(Arrays.asList(actions)));
-    }
-
     private AccessibilityNodeInfo getNodeWithIdFromList(
             List<AccessibilityNodeInfo> infos, long id) {
         for (AccessibilityNodeInfo info : infos) {
diff --git a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
index 19defe1..2f202d98 100644
--- a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
@@ -36,6 +36,7 @@
 
 import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -58,6 +59,7 @@
  * Run: adb shell am instrument -e class com.android.server.am.CoreSettingsObserverTest -w \
  *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
  */
+@Ignore
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class CoreSettingsObserverTest {
diff --git a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
index 9014539..f02cf51 100644
--- a/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/ConnOnActivityStartTest.java
@@ -54,6 +54,7 @@
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -78,6 +79,7 @@
  * Run: adb shell am instrument -e class com.android.server.net.ConnOnActivityStartTest -w \
  *     com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
  */
+@Ignore
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public class ConnOnActivityStartTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 5e4ba7be..25ba66e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -25,9 +25,12 @@
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import android.annotation.NonNull;
@@ -37,6 +40,7 @@
 import android.content.pm.UserInfo;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
+import android.security.keystore.ArrayUtils;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -57,6 +61,7 @@
 import java.io.IOException;
 import java.security.PublicKey;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 @RunWith(AndroidJUnit4.class)
@@ -527,6 +532,41 @@
                 false /*notLaunched*/, false /*stopped*/, true /*installed*/);
     }
 
+    @Test
+    public void testInsertPackageSetting() {
+        final PackageSetting ps = createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/);
+        final PackageParser.Package pkg = new PackageParser.Package(PACKAGE_NAME);
+        pkg.applicationInfo.setCodePath(ps.codePathString);
+        pkg.applicationInfo.setResourcePath(ps.resourcePathString);
+        final Settings settings =
+                new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object());
+        pkg.usesStaticLibraries = new ArrayList<>(
+                Arrays.asList("foo.bar1", "foo.bar2", "foo.bar3"));
+        pkg.usesStaticLibrariesVersions = new int[] {2, 4, 6};
+        settings.insertPackageSettingLPw(ps, pkg);
+        assertEquals(pkg, ps.pkg);
+        assertArrayEquals(pkg.usesStaticLibraries.toArray(new String[0]), ps.usesStaticLibraries);
+        assertArrayEquals(pkg.usesStaticLibrariesVersions, ps.usesStaticLibrariesVersions);
+
+        pkg.usesStaticLibraries = null;
+        pkg.usesStaticLibrariesVersions = null;
+        settings.insertPackageSettingLPw(ps, pkg);
+        assertEquals(pkg, ps.pkg);
+        assertNull("Actual: " + Arrays.toString(ps.usesStaticLibraries), ps.usesStaticLibraries);
+        assertNull("Actual: " + Arrays.toString(ps.usesStaticLibrariesVersions),
+                ps.usesStaticLibrariesVersions);
+    }
+
+    private <T> void assertArrayEquals(T[] a, T[] b) {
+        assertTrue("Expected: " + Arrays.toString(a) + ", actual: " + Arrays.toString(b),
+                Arrays.equals(a, b));
+    }
+
+    private void assertArrayEquals(int[] a, int[] b) {
+        assertTrue("Expected: " + Arrays.toString(a) + ", actual: " + Arrays.toString(b),
+                Arrays.equals(a, b));
+    }
+
     private void verifyUserState(PackageUserState userState, PackageUserState oldUserState,
             boolean userStateChanged) {
         verifyUserState(userState, oldUserState, userStateChanged, false /*notLaunched*/,
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
index da3b9c9..65a5632 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowContainerControllerTests.java
@@ -19,18 +19,24 @@
 import org.junit.Test;
 
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.SecurityTest;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.view.WindowManager;
 
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.content.res.Configuration.EMPTY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
+import java.util.function.Consumer;
+
 /**
  * Test class for {@link AppWindowContainerController}.
  *
@@ -90,6 +96,9 @@
         assertNull(atoken.startingSurface);
         assertNull(atoken.startingWindow);
         assertNull(atoken.startingData);
+        atoken.forAllWindows(windowState -> {
+            assertFalse(windowState.getBaseType() == TYPE_APPLICATION_STARTING);
+        }, true);
     }
 
     @Test
@@ -108,6 +117,22 @@
     }
 
     @Test
+    public void testAddRemoveRace() throws Exception {
+
+        // There was once a race condition between adding and removing starting windows
+        for (int i = 0; i < 1000; i++) {
+            final WindowTestUtils.TestAppWindowContainerController controller =
+                    createAppWindowController();
+            controller.addStartingWindow(InstrumentationRegistry.getContext().getPackageName(),
+                    android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
+                    false);
+            controller.removeStartingWindow();
+            waitUntilHandlersIdle();
+            assertNoStartingWindow(controller.getAppWindowToken(mDisplayContent));
+        }
+    }
+
+    @Test
     public void testTransferStartingWindow() throws Exception {
         final WindowTestUtils.TestAppWindowContainerController controller1 =
                 createAppWindowController();
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
index f9254ad..856e940 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java
@@ -34,6 +34,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.util.SparseIntArray;
 
 import java.util.Arrays;
 import java.util.LinkedList;
@@ -239,7 +240,7 @@
     @Test
     @Ignore
     public void testFocusedWindowMultipleDisplays() throws Exception {
-        // Create a focusable window and check that focus is calcualted correctly
+        // Create a focusable window and check that focus is calculated correctly
         final WindowState window1 =
                 createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "window1");
         assertEquals(window1, sWm.mRoot.computeFocusedWindow());
@@ -310,6 +311,24 @@
         assertEquals(afterStackCount - 1, mDisplayContent.getStaskPosById(PINNED_STACK_ID));
     }
 
+    /**
+     * Test that WM does not report displays to AM that are pending to be removed.
+     */
+    @Test
+    public void testDontReportDeferredRemoval() {
+        // Create a display and add an animating window to it.
+        final DisplayContent dc = createNewDisplay();
+        final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
+        window.mAnimatingExit = true;
+        // Request display removal, it should be deferred.
+        dc.removeIfPossible();
+        // Request ordered display ids from WM.
+        final SparseIntArray orderedDisplayIds = new SparseIntArray();
+        sWm.getDisplaysInFocusOrder(orderedDisplayIds);
+        // Make sure that display that is marked for removal is not reported.
+        assertEquals(-1, orderedDisplayIds.indexOfValue(dc.getDisplayId()));
+    }
+
     private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
                              int expectedBaseHeight, int expectedBaseDensity) {
         assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 8108909..39c0de8 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -90,14 +90,42 @@
         long ms = SystemClock.elapsedRealtime();
         mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
         mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
-        mPersister.persistSnapshot(3, mTestUserId, createSnapshot());
-        mPersister.persistSnapshot(4, mTestUserId, createSnapshot());
-        mPersister.persistSnapshot(5, mTestUserId, createSnapshot());
-        mPersister.persistSnapshot(6, mTestUserId, createSnapshot());
+        mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
+        mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
+        mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
+        mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
         mPersister.waitForQueueEmpty();
         assertTrue(SystemClock.elapsedRealtime() - ms > 500);
     }
 
+    /**
+     * Tests that too many store write queue items are being purged.
+     */
+    @Test
+    public void testPurging() {
+        mPersister.persistSnapshot(100, mTestUserId, createSnapshot());
+        mPersister.waitForQueueEmpty();
+        mPersister.setPaused(true);
+        mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
+        mPersister.removeObsoleteFiles(new ArraySet<>(), new int[] { mTestUserId });
+        mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
+        mPersister.persistSnapshot(3, mTestUserId, createSnapshot());
+        mPersister.persistSnapshot(4, mTestUserId, createSnapshot());
+        mPersister.setPaused(false);
+        mPersister.waitForQueueEmpty();
+
+        // Make sure 1,2 were purged but removeObsoleteFiles wasn't.
+        final File[] existsFiles = new File[] {
+                new File(sFilesDir.getPath() + "/snapshots/3.proto"),
+                new File(sFilesDir.getPath() + "/snapshots/4.proto")};
+        final File[] nonExistsFiles = new File[] {
+                new File(sFilesDir.getPath() + "/snapshots/100.proto"),
+                new File(sFilesDir.getPath() + "/snapshots/1.proto"),
+                new File(sFilesDir.getPath() + "/snapshots/1.proto")};
+        assertTrueForFiles(existsFiles, File::exists, " must exist");
+        assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
+    }
+
     @Test
     public void testGetTaskId() {
         RemoveObsoleteFilesQueueItem removeObsoleteFilesQueueItem =
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 be53667..c457cb3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -366,6 +366,11 @@
     }
 
     @Override
+    public void screenTurningOff(ScreenOffListener screenOffListener) {
+
+    }
+
+    @Override
     public void screenTurnedOff() {
 
     }
@@ -632,5 +637,14 @@
     @Override
     public void setRecentsVisibilityLw(boolean visible) {
 
-   }
+    }
+
+    @Override
+    public void onSystemUiStarted() {
+    }
+
+    @Override
+    public boolean canDismissBootAnimation() {
+        return true;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
index d9349ed..b83532c 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java
@@ -115,11 +115,11 @@
         }
 
         WindowState getFirstChild() {
-            return mChildren.getFirst();
+            return mChildren.peekFirst();
         }
 
         WindowState getLastChild() {
-            return mChildren.getLast();
+            return mChildren.peekLast();
         }
 
         int positionInParent() {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 32eee84..6618a69 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -115,6 +115,10 @@
                 "mChildAppWindowAbove");
         mChildAppWindowBelow = createCommonWindow(mAppWindow, TYPE_APPLICATION_MEDIA_OVERLAY,
                 "mChildAppWindowBelow");
+
+        // Adding a display will cause freezing the display. Make sure to wait until it's unfrozen
+        // to not run into race conditions with the tests.
+        waitUntilHandlersIdle();
     }
 
     @After
@@ -135,6 +139,9 @@
             mDisplayContent.removeImmediately();
             sWm.mInputMethodTarget = null;
         }
+
+        // Wait until everything is really cleaned up.
+        waitUntilHandlersIdle();
     }
 
     private WindowState createCommonWindow(WindowState parent, int type, String name) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 4ba457d..073a17e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -39,6 +39,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.UserInfo;
@@ -80,6 +81,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 
 import java.io.File;
@@ -137,6 +139,7 @@
     AppOpsManager mAppOps;
     UserManager mUserManager;
     PackageManager mPackageManager;
+    PackageManagerInternal mPackageManagerInternal;
     AppWidgetManager mAppWidgetManager;
     IDeviceIdleController mDeviceIdleController;
     private DisplayManager mDisplayManager;
@@ -179,6 +182,7 @@
         mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
         mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
         mPackageManager = getContext().getPackageManager();
+        mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mHandler = new H(BackgroundThread.get().getLooper());
 
         File systemDataDir = new File(Environment.getDataDirectory(), "system");
@@ -407,6 +411,10 @@
         }
     }
 
+    private boolean shouldObfuscateInstantAppsForCaller(int callingUid, int userId) {
+        return !mPackageManagerInternal.canAccessInstantApps(callingUid, userId);
+    }
+
     void clearAppIdleForPackage(String packageName, int userId) {
         synchronized (mAppIdleLock) {
             mAppIdleHistory.clearUsage(packageName, userId);
@@ -704,6 +712,11 @@
             final long elapsedRealtime = SystemClock.elapsedRealtime();
             convertToSystemTimeLocked(event);
 
+            if (event.getPackageName() != null
+                    && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) {
+                event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
+            }
+
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
             service.reportEvent(event);
@@ -807,7 +820,8 @@
     /**
      * Called by the Binder stub.
      */
-    List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) {
+    List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime,
+            boolean obfuscateInstantApps) {
         synchronized (mLock) {
             final long timeNow = checkAndGetTimeLocked();
             if (!validRange(timeNow, beginTime, endTime)) {
@@ -816,7 +830,23 @@
 
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            return service.queryUsageStats(bucketType, beginTime, endTime);
+            List<UsageStats> list = service.queryUsageStats(bucketType, beginTime, endTime);
+            if (list == null) {
+                return null;
+            }
+
+            // Mangle instant app names *using their current state (not whether they were ephemeral
+            // when the data was recorded)*.
+            if (obfuscateInstantApps) {
+                for (int i = list.size() - 1; i >= 0; i--) {
+                    final UsageStats stats = list.get(i);
+                    if (mPackageManagerInternal.isPackageEphemeral(userId, stats.mPackageName)) {
+                        list.set(i, stats.getObfuscatedForInstantApp());
+                    }
+                }
+            }
+
+            return list;
         }
     }
 
@@ -840,7 +870,8 @@
     /**
      * Called by the Binder stub.
      */
-    UsageEvents queryEvents(int userId, long beginTime, long endTime) {
+    UsageEvents queryEvents(int userId, long beginTime, long endTime,
+            boolean shouldObfuscateInstantApps) {
         synchronized (mLock) {
             final long timeNow = checkAndGetTimeLocked();
             if (!validRange(timeNow, beginTime, endTime)) {
@@ -849,7 +880,7 @@
 
             final UserUsageStatsService service =
                     getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            return service.queryEvents(beginTime, endTime);
+            return service.queryEvents(beginTime, endTime, shouldObfuscateInstantApps);
         }
     }
 
@@ -884,10 +915,15 @@
         }
     }
 
-    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime) {
+    boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime,
+            boolean shouldObfuscateInstantApps) {
         if (isParoledOrCharging()) {
             return false;
         }
+        if (shouldObfuscateInstantApps &&
+                mPackageManagerInternal.isPackageEphemeral(userId, packageName)) {
+            return false;
+        }
         return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
     }
 
@@ -1353,11 +1389,14 @@
                 return null;
             }
 
+            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+                    Binder.getCallingUid(), UserHandle.getCallingUserId());
+
             final int userId = UserHandle.getCallingUserId();
             final long token = Binder.clearCallingIdentity();
             try {
                 final List<UsageStats> results = UsageStatsService.this.queryUsageStats(
-                        userId, bucketType, beginTime, endTime);
+                        userId, bucketType, beginTime, endTime, obfuscateInstantApps);
                 if (results != null) {
                     return new ParceledListSlice<>(results);
                 }
@@ -1395,10 +1434,14 @@
                 return null;
             }
 
+            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+                    Binder.getCallingUid(), UserHandle.getCallingUserId());
+
             final int userId = UserHandle.getCallingUserId();
             final long token = Binder.clearCallingIdentity();
             try {
-                return UsageStatsService.this.queryEvents(userId, beginTime, endTime);
+                return UsageStatsService.this.queryEvents(userId, beginTime, endTime,
+                        obfuscateInstantApps);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1412,10 +1455,12 @@
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
+            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+                    Binder.getCallingUid(), userId);
             final long token = Binder.clearCallingIdentity();
             try {
                 return UsageStatsService.this.isAppIdleFilteredOrParoled(packageName, userId,
-                        SystemClock.elapsedRealtime());
+                        SystemClock.elapsedRealtime(), obfuscateInstantApps);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1647,9 +1692,10 @@
 
         @Override
         public List<UsageStats> queryUsageStatsForUser(
-                int userId, int intervalType, long beginTime, long endTime) {
+                int userId, int intervalType, long beginTime, long endTime,
+                boolean obfuscateInstantApps) {
             return UsageStatsService.this.queryUsageStats(
-                    userId, intervalType, beginTime, endTime);
+                    userId, intervalType, beginTime, endTime, obfuscateInstantApps);
         }
     }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
index 96f3305..cc53a9c 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXmlV1.java
@@ -26,7 +26,10 @@
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageStats;
 import android.content.res.Configuration;
+import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.Log;
+import android.util.LogWriter;
 
 import java.io.IOException;
 import java.net.ProtocolException;
@@ -35,6 +38,8 @@
  * UsageStats reader/writer for version 1 of the XML format.
  */
 final class UsageStatsXmlV1 {
+    private static final String TAG = "UsageStatsXmlV1";
+
     private static final String PACKAGES_TAG = "packages";
     private static final String PACKAGE_TAG = "package";
 
@@ -51,6 +56,7 @@
 
     // Attributes
     private static final String PACKAGE_ATTR = "package";
+    private static final String FLAGS_ATTR = "flags";
     private static final String CLASS_ATTR = "class";
     private static final String TOTAL_TIME_ACTIVE_ATTR = "timeActive";
     private static final String COUNT_ATTR = "count";
@@ -70,7 +76,6 @@
         if (pkg == null) {
             throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
         }
-
         final UsageStats stats = statsOut.getOrCreateUsageStats(pkg);
 
         // Apply the offset to the beginTime to find the absolute time.
@@ -149,11 +154,12 @@
         if (packageName == null) {
             throw new ProtocolException("no " + PACKAGE_ATTR + " attribute present");
         }
-
         final String className = XmlUtils.readStringAttribute(parser, CLASS_ATTR);
 
         final UsageEvents.Event event = statsOut.buildEvent(packageName, className);
 
+        event.mFlags = XmlUtils.readIntAttribute(parser, FLAGS_ATTR, 0);
+
         // Apply the offset to the beginTime to find the absolute time of this event.
         event.mTimeStamp = statsOut.beginTime + XmlUtils.readLongAttribute(parser, TIME_ATTR);
 
@@ -256,6 +262,7 @@
         if (event.mClass != null) {
             XmlUtils.writeStringAttribute(xml, CLASS_ATTR, event.mClass);
         }
+        XmlUtils.writeIntAttribute(xml, FLAGS_ATTR, event.mFlags);
         XmlUtils.writeIntAttribute(xml, TYPE_ATTR, event.mEventType);
 
         switch (event.mEventType) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 8d335a5..0abbb82 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -19,11 +19,8 @@
 import android.app.usage.ConfigurationStats;
 import android.app.usage.TimeSparseArray;
 import android.app.usage.UsageEvents;
-import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.os.SystemClock;
 import android.content.Context;
@@ -312,7 +309,8 @@
         return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner);
     }
 
-    UsageEvents queryEvents(final long beginTime, final long endTime) {
+    UsageEvents queryEvents(final long beginTime, final long endTime,
+            boolean obfuscateInstantApps) {
         final ArraySet<String> names = new ArraySet<>();
         List<UsageEvents.Event> results = queryStats(UsageStatsManager.INTERVAL_DAILY,
                 beginTime, endTime, new StatCombiner<UsageEvents.Event>() {
@@ -334,7 +332,10 @@
                                 return;
                             }
 
-                            final UsageEvents.Event event = stats.events.valueAt(i);
+                            UsageEvents.Event event = stats.events.valueAt(i);
+                            if (obfuscateInstantApps) {
+                                event = event.getObfuscatedIfInstantApp();
+                            }
                             names.add(event.mPackage);
                             if (event.mClass != null) {
                                 names.add(event.mClass);
@@ -586,6 +587,7 @@
             if (event.mShortcutId != null) {
                 pw.printPair("shortcutId", event.mShortcutId);
             }
+            pw.printHexPair("flags", event.mFlags);
             pw.println();
         }
         pw.decreaseIndent();
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 0a67669..26a406f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -63,7 +63,6 @@
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
-import java.util.Random;
 import java.util.Scanner;
 import java.util.Set;
 
@@ -538,7 +537,6 @@
                     oldFunctions = UsbManager.USB_FUNCTION_NONE;
                 }
 
-                Slog.i(TAG, "Setting adb to " + String.valueOf(enable));
                 setEnabledFunctions(oldFunctions, true, mUsbDataUnlocked);
                 updateAdbNotification();
             }
@@ -766,16 +764,15 @@
 
             // send broadcast intent only if the USB state has changed
             if (!isUsbStateChanged(intent)) {
-                Slog.i(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras());
+                if (DEBUG) {
+                    Slog.d(TAG, "skip broadcasting " + intent + " extras: " + intent.getExtras());
+                }
                 return;
             }
-            mBroadcastedIntent = intent;
 
-            Random rand = new Random();
-            intent.putExtra("random_tag", rand.nextInt(1000));
-            Slog.i(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
+            if (DEBUG) Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras());
             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
-            intent.removeExtra("random_tag");
+            mBroadcastedIntent = intent;
         }
 
         private void updateUsbFunctions() {
@@ -844,7 +841,6 @@
                     updateUsbNotification();
                     updateAdbNotification();
                     if (mBootCompleted) {
-                        Slog.i(TAG, "update state " + mConnected + " " + mConfigured);
                         updateUsbStateBroadcastIfNeeded(false);
                     }
                     if (UsbManager.containsFunction(mCurrentFunctions,
@@ -854,7 +850,6 @@
                     if (mBootCompleted) {
                         if (!mConnected) {
                             // restore defaults when USB is disconnected
-                            Slog.i(TAG, "Disconnect, setting usb functions to null");
                             setEnabledFunctions(null, !mAdbEnabled, false);
                         }
                         updateUsbFunctions();
@@ -887,7 +882,6 @@
                     break;
                 case MSG_SET_CURRENT_FUNCTIONS:
                     String functions = (String) msg.obj;
-                    Slog.i(TAG, "Getting setFunction command for " + functions);
                     setEnabledFunctions(functions, false, msg.arg1 == 1);
                     break;
                 case MSG_UPDATE_USER_RESTRICTIONS:
@@ -895,8 +889,6 @@
                     final boolean forceRestart = mUsbDataUnlocked
                             && isUsbDataTransferActive()
                             && !isUsbTransferAllowed();
-                    Slog.i(TAG, "Updating user restrictions, force restart is "
-                            + String.valueOf(forceRestart));
                     setEnabledFunctions(
                             mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart);
                     break;
@@ -911,7 +903,6 @@
                         updateUsbStateBroadcastIfNeeded(false);
                         mPendingBootBroadcast = false;
                     }
-                    Slog.i(TAG, "Boot complete, setting default functions");
                     setEnabledFunctions(null, false, false);
                     if (mCurrentAccessory != null) {
                         getCurrentSettings().accessoryAttached(mCurrentAccessory);
@@ -929,7 +920,6 @@
                             Slog.v(TAG, "Current user switched to " + msg.arg1
                                     + "; resetting USB host stack for MTP or PTP");
                             // avoid leaking sensitive data from previous user
-                            Slog.i(TAG, "User Switched, kicking usb stack");
                             setEnabledFunctions(mCurrentFunctions, true, false);
                         }
                         mCurrentUser = msg.arg1;
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index d203d19..a9655d8 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -100,6 +100,7 @@
     private static final String SESSION_ADD_CS_ADAPTER = "CS.aCSA";
     private static final String SESSION_REMOVE_CS_ADAPTER = "CS.rCSA";
     private static final String SESSION_CREATE_CONN = "CS.crCo";
+    private static final String SESSION_CREATE_CONN_COMPLETE = "CS.crCoC";
     private static final String SESSION_CREATE_CONN_FAILED = "CS.crCoF";
     private static final String SESSION_ABORT = "CS.ab";
     private static final String SESSION_ANSWER = "CS.an";
@@ -152,6 +153,7 @@
     private static final int MSG_ON_START_RTT = 26;
     private static final int MSG_ON_STOP_RTT = 27;
     private static final int MSG_RTT_UPGRADE_RESPONSE = 28;
+    private static final int MSG_CREATE_CONNECTION_COMPLETE = 29;
 
     private static Connection sNullConnection;
 
@@ -221,6 +223,19 @@
         }
 
         @Override
+        public void createConnectionComplete(String id, Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, SESSION_CREATE_CONN_COMPLETE);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = id;
+                args.arg2 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_CREATE_CONNECTION_COMPLETE, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
         public void createConnectionFailed(
                 PhoneAccountHandle connectionManagerPhoneAccount,
                 String callId,
@@ -630,6 +645,33 @@
                     }
                     break;
                 }
+                case MSG_CREATE_CONNECTION_COMPLETE: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Log.continueSession((Session) args.arg2,
+                            SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE);
+                    try {
+                        final String id = (String) args.arg1;
+                        if (!mAreAccountsInitialized) {
+                            Log.d(this, "Enqueueing pre-init request %s", id);
+                            mPreInitializationConnectionRequests.add(
+                                    new android.telecom.Logging.Runnable(
+                                            SESSION_HANDLER + SESSION_CREATE_CONN_COMPLETE
+                                                    + ".pICR",
+                                            null /*lock*/) {
+                                        @Override
+                                        public void loggedRun() {
+                                            notifyCreateConnectionComplete(id);
+                                        }
+                                    }.prepare());
+                        } else {
+                            notifyCreateConnectionComplete(id);
+                        }
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
                 case MSG_CREATE_CONNECTION_FAILED: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     Log.continueSession((Session) args.arg3, SESSION_HANDLER +
@@ -1373,6 +1415,17 @@
         }
     }
 
+    /**
+     * Called by Telecom when the creation of a new Connection has completed and it is now added
+     * to Telecom.
+     * @param callId The ID of the connection.
+     */
+    private void notifyCreateConnectionComplete(final String callId) {
+        Log.i(this, "notifyCreateConnectionComplete %s", callId);
+        onCreateConnectionComplete(findConnectionForAction(callId,
+                "notifyCreateConnectionComplete"));
+    }
+
     private void abort(String callId) {
         Log.d(this, "abort %s", callId);
         findConnectionForAction(callId, "abort").onAbort();
@@ -1855,6 +1908,18 @@
     }
 
     /**
+     * Called after the {@link Connection} returned by
+     * {@link #onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
+     * or {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)} has been
+     * added to the {@link ConnectionService} and sent to Telecom.
+     *
+     * @param connection the {@link Connection}.
+     * @hide
+     */
+    public void onCreateConnectionComplete(Connection connection) {
+    }
+
+    /**
      * Called by Telecom to inform the {@link ConnectionService} that its request to create a new
      * incoming {@link Connection} was denied.
      * <p>
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index c631d08..e428286 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -47,6 +47,8 @@
             boolean isUnknown,
             in Session.Info sessionInfo);
 
+    void createConnectionComplete(String callId, in Session.Info sessionInfo);
+
     void createConnectionFailed(in PhoneAccountHandle connectionManagerPhoneAccount, String callId,
             in ConnectionRequest request, boolean isIncoming, in Session.Info sessionInfo);
 
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index b4f3d69..9caf9d0 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -113,6 +113,15 @@
         </activity>
 
         <activity
+            android:name="DrawIntoHwBitmapActivity"
+            android:label="Bitmaps/DrawIntoHwBitmap">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.hwui.TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="PathOffsetActivity"
                 android:label="Path/Offset">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java
new file mode 100644
index 0000000..faabdfc
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DrawIntoHwBitmapActivity.java
@@ -0,0 +1,65 @@
+/*
+ * 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.test.hwui;
+
+import static android.graphics.GraphicBuffer.USAGE_HW_TEXTURE;
+import static android.graphics.GraphicBuffer.USAGE_SW_READ_NEVER;
+import static android.graphics.GraphicBuffer.USAGE_SW_WRITE_NEVER;
+import static android.graphics.GraphicBuffer.USAGE_SW_WRITE_RARELY;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.GraphicBuffer;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+import android.view.Surface;
+import android.view.ThreadedRenderer;
+import android.widget.ImageView;
+
+public class DrawIntoHwBitmapActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ImageView view = new ImageView(this);
+        view.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+        setContentView(view);
+        view.setImageBitmap(createBitmap());
+    }
+
+    Bitmap createBitmap() {
+        RenderNode node = RenderNode.create("HwuiCanvas", null);
+        node.setLeftTopRightBottom(0, 0, 500, 500);
+        node.setClipToBounds(false);
+        DisplayListCanvas canvas = node.start(500, 500);
+        Paint p = new Paint();
+        p.setColor(Color.BLACK);
+        p.setTextSize(20 * getResources().getDisplayMetrics().density);
+        canvas.drawColor(0xFF2196F3);
+        p.setColor(0xFFBBDEFB);
+        canvas.drawRect(0, 0, 500, 100, p);
+        p.setColor(Color.BLACK);
+        canvas.drawText("Hello, World!", 0, 90, p);
+        node.end(canvas);
+        return ThreadedRenderer.createHardwareBitmap(node, 500, 500);
+    }
+}
diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk
index 5f7467a..6b5c999 100644
--- a/tests/UsageStatsTest/Android.mk
+++ b/tests/UsageStatsTest/Android.mk
@@ -8,6 +8,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
 
+LOCAL_CERTIFICATE := platform
+
 LOCAL_PACKAGE_NAME := UsageStatsTest
 
 include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/AndroidManifest.xml b/tests/UsageStatsTest/AndroidManifest.xml
index 589674a..c27be7b 100644
--- a/tests/UsageStatsTest/AndroidManifest.xml
+++ b/tests/UsageStatsTest/AndroidManifest.xml
@@ -1,7 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 
+<!--
+  Note: Add android:sharedUserId="android.uid.system" to the root element to simulate the system UID
+  caller case.
+-->
+
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.tests.usagestats">
+    package="com.android.tests.usagestats"
+    >
 
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
diff --git a/tests/UsageStatsTest/res/menu/main.xml b/tests/UsageStatsTest/res/menu/main.xml
index e781058..4ccbc81 100644
--- a/tests/UsageStatsTest/res/menu/main.xml
+++ b/tests/UsageStatsTest/res/menu/main.xml
@@ -2,4 +2,6 @@
 <menu xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/log"
         android:title="View Log"/>
+    <item android:id="@+id/call_is_app_inactive"
+        android:title="Call isAppInactive()"/>
 </menu>
diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
index c08c1a3..9429d9b 100644
--- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
+++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java
@@ -16,12 +16,16 @@
 
 package com.android.tests.usagestats;
 
+import android.app.AlertDialog;
 import android.app.ListActivity;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
+import android.content.DialogInterface;
 import android.content.Intent;
 import android.os.Bundle;
+import android.text.InputType;
+import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -30,6 +34,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
+import android.widget.EditText;
 import android.widget.TextView;
 
 import java.util.ArrayList;
@@ -69,6 +74,9 @@
             case R.id.log:
                 startActivity(new Intent(this, UsageLogActivity.class));
                 return true;
+            case R.id.call_is_app_inactive:
+                callIsAppInactive();
+                return true;
 
             default:
                 return super.onOptionsItemSelected(item);
@@ -81,6 +89,41 @@
         updateAdapter();
     }
 
+    private void callIsAppInactive() {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        builder.setTitle("Enter package name");
+        final EditText input = new EditText(this);
+        input.setInputType(InputType.TYPE_CLASS_TEXT);
+        input.setHint("com.android.tests.usagestats");
+        builder.setView(input);
+
+        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                final String packageName = input.getText().toString().trim();
+                if (!TextUtils.isEmpty(packageName)) {
+                    showInactive(packageName);
+                }
+            }
+        });
+        builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int which) {
+                dialog.cancel();
+            }
+        });
+
+        builder.show();
+    }
+
+    private void showInactive(String packageName) {
+        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+        builder.setMessage(
+                "isAppInactive(\"" + packageName + "\") = "
+                        + (mUsageStatsManager.isAppInactive(packageName) ? "true" : "false"));
+        builder.show();
+    }
+
     private void updateAdapter() {
         long now = System.currentTimeMillis();
         long beginTime = now - USAGE_STATS_PERIOD;
diff --git a/tests/net/java/android/net/util/SharedLogTest.java b/tests/net/java/android/net/util/SharedLogTest.java
new file mode 100644
index 0000000..7fd7a63
--- /dev/null
+++ b/tests/net/java/android/net/util/SharedLogTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Vector;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SharedLogTest {
+    private static final String TIMESTAMP_PATTERN =
+            "^[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]";
+    private static final String TIMESTAMP = "mm-dd HH:MM:SS.xxx";
+
+    @Test
+    public void testBasicOperation() {
+        final SharedLog logTop = new SharedLog("top");
+        logTop.mark("first post!");
+
+        final SharedLog logLevel2a = logTop.forSubComponent("twoA");
+        final SharedLog logLevel2b = logTop.forSubComponent("twoB");
+        logLevel2b.e("2b or not 2b");
+        logLevel2a.w("second post?");
+
+        final SharedLog logLevel3 = logLevel2a.forSubComponent("three");
+        logTop.log("still logging");
+        logLevel3.log("3 >> 2");
+        logLevel2a.mark("ok: last post");
+
+        final String[] expected = {
+            TIMESTAMP + " - MARK first post!",
+            TIMESTAMP + " - [twoB] ERROR 2b or not 2b",
+            TIMESTAMP + " - [twoA] WARN second post?",
+            TIMESTAMP + " - still logging",
+            TIMESTAMP + " - [twoA.three] 3 >> 2",
+            TIMESTAMP + " - [twoA] MARK ok: last post",
+        };
+        // Verify the logs are all there and in the correct order.
+        verifyLogLines(expected, logTop);
+
+        // In fact, because they all share the same underlying LocalLog,
+        // every subcomponent SharedLog's dump() is identical.
+        verifyLogLines(expected, logLevel2a);
+        verifyLogLines(expected, logLevel2b);
+        verifyLogLines(expected, logLevel3);
+    }
+
+    private static void verifyLogLines(String[] expected, SharedLog log) {
+        final ByteArrayOutputStream ostream = new ByteArrayOutputStream();
+        final PrintWriter pw = new PrintWriter(ostream, true);
+        log.dump(null, pw, null);
+
+        final String dumpOutput = ostream.toString();
+        assertTrue(dumpOutput != null);
+        assertTrue(!"".equals(dumpOutput));
+
+        final String[] lines = dumpOutput.split("\n");
+        assertEquals(expected.length, lines.length);
+
+        for (int i = 0; i < lines.length; i++) {
+            // Fix up the timestamps.
+            lines[i] = lines[i].replaceAll(TIMESTAMP_PATTERN, TIMESTAMP);
+        }
+
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals(expected[i], lines[i]);
+        }
+    }
+}
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
index a3f33dc..27e683c 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachineTest.java
@@ -38,6 +38,7 @@
 import android.net.ConnectivityManager;
 import android.net.INetworkStatsService;
 import android.net.InterfaceConfiguration;
+import android.net.util.SharedLog;
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
 import android.os.test.TestLooper;
@@ -63,12 +64,14 @@
     @Mock private IControlsTethering mTetherHelper;
     @Mock private InterfaceConfiguration mInterfaceConfiguration;
     @Mock private IPv6TetheringInterfaceServices mIPv6TetheringInterfaceServices;
+    @Mock private SharedLog mSharedLog;
 
     private final TestLooper mLooper = new TestLooper();
     private TetherInterfaceStateMachine mTestedSm;
 
     private void initStateMachine(int interfaceType) throws Exception {
-        mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(), interfaceType,
+        mTestedSm = new TetherInterfaceStateMachine(
+                IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
                 mNMService, mStatsService, mTetherHelper, mIPv6TetheringInterfaceServices);
         mTestedSm.start();
         // Starting the state machine always puts us in a consistent state and notifies
@@ -90,12 +93,13 @@
 
     @Before public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+        when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
     }
 
     @Test
     public void startsOutAvailable() {
         mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
-                TETHERING_BLUETOOTH, mNMService, mStatsService, mTetherHelper,
+                TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mTetherHelper,
                 mIPv6TetheringInterfaceServices);
         mTestedSm.start();
         mLooper.dispatchAll();
diff --git a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
index 9fcd1b5..ddceea2 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/TetheringConfigurationTest.java
@@ -128,5 +128,8 @@
         assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_DUN));
         // Just to prove we haven't clobbered Wi-Fi:
         assertTrue(cfg.preferredUpstreamIfaceTypes.contains(TYPE_WIFI));
+        // Check that we have not added new cellular interface types
+        assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE));
+        assertFalse(cfg.preferredUpstreamIfaceTypes.contains(TYPE_MOBILE_HIPRI));
     }
 }
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index c72efb0..9bb392a 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -25,11 +25,13 @@
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.reset;
 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.content.Context;
 import android.os.Handler;
@@ -40,6 +42,7 @@
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.net.util.SharedLog;
 
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -69,6 +72,7 @@
 
     @Mock private Context mContext;
     @Mock private IConnectivityManager mCS;
+    @Mock private SharedLog mLog;
 
     private TestStateMachine mSM;
     private TestConnectivityManager mCM;
@@ -78,10 +82,12 @@
         MockitoAnnotations.initMocks(this);
         reset(mContext);
         reset(mCS);
+        reset(mLog);
+        when(mLog.forSubComponent(anyString())).thenReturn(mLog);
 
         mCM = spy(new TestConnectivityManager(mContext, mCS));
         mSM = new TestStateMachine();
-        mUNM = new UpstreamNetworkMonitor(mSM, EVENT_UNM_UPDATE, (ConnectivityManager) mCM);
+        mUNM = new UpstreamNetworkMonitor(mSM, EVENT_UNM_UPDATE, (ConnectivityManager) mCM, mLog);
     }
 
     @After public void tearDown() throws Exception {
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 90f713b..0d1850f 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -34,42 +34,43 @@
 
 namespace aapt {
 
-constexpr const char* sXliffNamespaceUri =
-    "urn:oasis:names:tc:xliff:document:1.2";
+constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2";
 
-/**
- * Returns true if the element is <skip> or <eat-comment> and can be safely
- * ignored.
- */
-static bool ShouldIgnoreElement(const StringPiece& ns,
-                                const StringPiece& name) {
+// Returns true if the element is <skip> or <eat-comment> and can be safely ignored.
+static bool ShouldIgnoreElement(const StringPiece& ns, const StringPiece& name) {
   return ns.empty() && (name == "skip" || name == "eat-comment");
 }
 
-static uint32_t ParseFormatType(const StringPiece& piece) {
-  if (piece == "reference")
+static uint32_t ParseFormatTypeNoEnumsOrFlags(const StringPiece& piece) {
+  if (piece == "reference") {
     return android::ResTable_map::TYPE_REFERENCE;
-  else if (piece == "string")
+  } else if (piece == "string") {
     return android::ResTable_map::TYPE_STRING;
-  else if (piece == "integer")
+  } else if (piece == "integer") {
     return android::ResTable_map::TYPE_INTEGER;
-  else if (piece == "boolean")
+  } else if (piece == "boolean") {
     return android::ResTable_map::TYPE_BOOLEAN;
-  else if (piece == "color")
+  } else if (piece == "color") {
     return android::ResTable_map::TYPE_COLOR;
-  else if (piece == "float")
+  } else if (piece == "float") {
     return android::ResTable_map::TYPE_FLOAT;
-  else if (piece == "dimension")
+  } else if (piece == "dimension") {
     return android::ResTable_map::TYPE_DIMENSION;
-  else if (piece == "fraction")
+  } else if (piece == "fraction") {
     return android::ResTable_map::TYPE_FRACTION;
-  else if (piece == "enum")
-    return android::ResTable_map::TYPE_ENUM;
-  else if (piece == "flags")
-    return android::ResTable_map::TYPE_FLAGS;
+  }
   return 0;
 }
 
+static uint32_t ParseFormatType(const StringPiece& piece) {
+  if (piece == "enum") {
+    return android::ResTable_map::TYPE_ENUM;
+  } else if (piece == "flags") {
+    return android::ResTable_map::TYPE_FLAGS;
+  }
+  return ParseFormatTypeNoEnumsOrFlags(piece);
+}
+
 static uint32_t ParseFormatAttribute(const StringPiece& str) {
   uint32_t mask = 0;
   for (StringPiece part : util::Tokenize(str, '|')) {
@@ -83,9 +84,7 @@
   return mask;
 }
 
-/**
- * A parsed resource ready to be added to the ResourceTable.
- */
+// A parsed resource ready to be added to the ResourceTable.
 struct ParsedResource {
   ResourceName name;
   ConfigDescription config;
@@ -416,8 +415,7 @@
     can_be_bag = false;
 
     // Items have their type encoded in the type attribute.
-    if (Maybe<StringPiece> maybe_type =
-            xml::FindNonEmptyAttribute(parser, "type")) {
+    if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
       resource_type = maybe_type.value().to_string();
     } else {
       diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
@@ -425,13 +423,11 @@
       return false;
     }
 
-    if (Maybe<StringPiece> maybe_format =
-            xml::FindNonEmptyAttribute(parser, "format")) {
+    if (Maybe<StringPiece> maybe_format = xml::FindNonEmptyAttribute(parser, "format")) {
       // An explicit format for this resource was specified. The resource will
-      // retain
-      // its type in its name, but the accepted value for this type is
+      // retain its type in its name, but the accepted value for this type is
       // overridden.
-      resource_format = ParseFormatType(maybe_format.value());
+      resource_format = ParseFormatTypeNoEnumsOrFlags(maybe_format.value());
       if (!resource_format) {
         diag_->Error(DiagMessage(out_resource->source)
                      << "'" << maybe_format.value()
@@ -1157,21 +1153,25 @@
   return true;
 }
 
-bool ResourceParser::ParseArray(xml::XmlPullParser* parser,
-                                ParsedResource* out_resource) {
-  return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_ANY);
+bool ResourceParser::ParseArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
+  uint32_t resource_format = android::ResTable_map::TYPE_ANY;
+  if (Maybe<StringPiece> format_attr = xml::FindNonEmptyAttribute(parser, "format")) {
+    resource_format = ParseFormatTypeNoEnumsOrFlags(format_attr.value());
+    if (resource_format == 0u) {
+      diag_->Error(DiagMessage(source_.WithLine(parser->line_number()))
+                   << "'" << format_attr.value() << "' is an invalid format");
+      return false;
+    }
+  }
+  return ParseArrayImpl(parser, out_resource, resource_format);
 }
 
-bool ResourceParser::ParseIntegerArray(xml::XmlPullParser* parser,
-                                       ParsedResource* out_resource) {
-  return ParseArrayImpl(parser, out_resource,
-                        android::ResTable_map::TYPE_INTEGER);
+bool ResourceParser::ParseIntegerArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
+  return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_INTEGER);
 }
 
-bool ResourceParser::ParseStringArray(xml::XmlPullParser* parser,
-                                      ParsedResource* out_resource) {
-  return ParseArrayImpl(parser, out_resource,
-                        android::ResTable_map::TYPE_STRING);
+bool ResourceParser::ParseStringArray(xml::XmlPullParser* parser, ParsedResource* out_resource) {
+  return ParseArrayImpl(parser, out_resource, android::ResTable_map::TYPE_STRING);
 }
 
 bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser,
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 8062c2e6..faa6607 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -571,14 +571,39 @@
 }
 
 TEST_F(ResourceParserTest, ParseStringArray) {
-  std::string input =
-      "<string-array name=\"foo\">\n"
-      "  <item>\"Werk\"</item>\n"
-      "</string-array>\n";
+  std::string input = R"EOF(
+      <string-array name="foo">
+        <item>"Werk"</item>"
+      </string-array>)EOF";
   ASSERT_TRUE(TestParse(input));
   EXPECT_NE(nullptr, test::GetValue<Array>(&table_, "array/foo"));
 }
 
+TEST_F(ResourceParserTest, ParseArrayWithFormat) {
+  std::string input = R"EOF(
+      <array name="foo" format="string">
+        <item>100</item>
+      </array>)EOF";
+  ASSERT_TRUE(TestParse(input));
+
+  Array* array = test::GetValue<Array>(&table_, "array/foo");
+  ASSERT_NE(nullptr, array);
+
+  ASSERT_EQ(1u, array->items.size());
+
+  String* str = ValueCast<String>(array->items[0].get());
+  ASSERT_NE(nullptr, str);
+  EXPECT_EQ(std::string("100"), *str->value);
+}
+
+TEST_F(ResourceParserTest, ParseArrayWithBadFormat) {
+  std::string input = R"EOF(
+      <array name="foo" format="integer">
+        <item>Hi</item>
+      </array>)EOF";
+  ASSERT_FALSE(TestParse(input));
+}
+
 TEST_F(ResourceParserTest, ParsePlural) {
   std::string input =
       "<plurals name=\"foo\">\n"
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index c192d69..5adf04a 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -372,6 +372,8 @@
     if (file_type == file::FileType::kDirectory) {
       context->GetDiagnostics()->Error(DiagMessage(input_path)
                                        << "resource file cannot be a directory");
+    } else if (file_type == file::FileType::kNonexistant) {
+      context->GetDiagnostics()->Error(DiagMessage(input_path) << "file not found");
     } else {
       context->GetDiagnostics()->Error(DiagMessage(input_path)
                                        << "not a valid resource file");
@@ -488,7 +490,7 @@
     // Ensure that we only keep the chunks we care about if we end up
     // using the original PNG instead of the crunched one.
     PngChunkFilter png_chunk_filter(content);
-    std::unique_ptr<Image> image = ReadPng(context, &png_chunk_filter);
+    std::unique_ptr<Image> image = ReadPng(context, path_data.source, &png_chunk_filter);
     if (!image) {
       return false;
     }
diff --git a/tools/aapt2/compile/Png.h b/tools/aapt2/compile/Png.h
index e4255e7..7ca1f0e 100644
--- a/tools/aapt2/compile/Png.h
+++ b/tools/aapt2/compile/Png.h
@@ -69,7 +69,12 @@
   bool Rewind() override;
   size_t ByteCount() const override { return window_start_; }
 
-  bool HadError() const override { return error_; }
+  bool HadError() const override {
+    return !error_msg_.empty();
+  }
+  std::string GetError() const override {
+    return error_msg_;
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PngChunkFilter);
@@ -79,13 +84,13 @@
   android::StringPiece data_;
   size_t window_start_ = 0;
   size_t window_end_ = 0;
-  bool error_ = false;
+  std::string error_msg_;
 };
 
 /**
  * Reads a PNG from the InputStream into memory as an RGBA Image.
  */
-std::unique_ptr<Image> ReadPng(IAaptContext* context, io::InputStream* in);
+std::unique_ptr<Image> ReadPng(IAaptContext* context, const Source& source, io::InputStream* in);
 
 /**
  * Writes the RGBA Image, with optional 9-patch meta-data, into the OutputStream
diff --git a/tools/aapt2/compile/PngChunkFilter.cpp b/tools/aapt2/compile/PngChunkFilter.cpp
index f9043b5..7073c13 100644
--- a/tools/aapt2/compile/PngChunkFilter.cpp
+++ b/tools/aapt2/compile/PngChunkFilter.cpp
@@ -16,11 +16,13 @@
 
 #include "compile/Png.h"
 
+#include "android-base/stringprintf.h"
 #include "androidfw/StringPiece.h"
 
 #include "io/Io.h"
 
 using android::StringPiece;
+using android::base::StringPrintf;
 
 namespace aapt {
 
@@ -73,7 +75,7 @@
     window_start_ = 0;
     window_end_ = kPngSignatureSize;
   } else {
-    error_ = true;
+    error_msg_ = "PNG does not start with PNG signature";
   }
 }
 
@@ -90,7 +92,7 @@
 }
 
 bool PngChunkFilter::Next(const void** buffer, size_t* len) {
-  if (error_) {
+  if (HadError()) {
     return false;
   }
 
@@ -106,16 +108,21 @@
     const size_t kMinChunkHeaderSize = 3 * sizeof(uint32_t);
 
     // Is there enough room for a chunk header?
-    if (data_.size() - window_start_ < kMinChunkHeaderSize) {
-      error_ = true;
+    if (data_.size() - window_end_ < kMinChunkHeaderSize) {
+      error_msg_ = StringPrintf("Not enough space for a PNG chunk @ byte %zu/%zu", window_end_,
+                                data_.size());
       return false;
     }
 
     // Verify the chunk length.
     const uint32_t chunk_len = Peek32LE(data_.data() + window_end_);
-    if (((uint64_t)chunk_len) + ((uint64_t)window_end_) + sizeof(uint32_t) > data_.size()) {
+    if ((size_t)chunk_len > data_.size() - window_end_ - kMinChunkHeaderSize) {
       // Overflow.
-      error_ = true;
+      const uint32_t chunk_type = Peek32LE(data_.data() + window_end_ + sizeof(uint32_t));
+      error_msg_ = StringPrintf(
+          "PNG chunk type %08x is too large: chunk length is %zu but chunk "
+          "starts at byte %zu/%zu",
+          chunk_type, (size_t)chunk_len, window_end_ + kMinChunkHeaderSize, data_.size());
       return false;
     }
 
@@ -124,6 +131,16 @@
     if (IsPngChunkWhitelisted(chunk_type)) {
       // Advance the window to include this chunk.
       window_end_ += kMinChunkHeaderSize + chunk_len;
+
+      // Special case the IEND chunk, which MUST appear last and libpng stops parsing once it hits
+      // such a chunk (let's do the same).
+      if (chunk_type == kPngChunkIEND) {
+        // Truncate the data to the end of this chunk. There may be garbage trailing after
+        // (b/38169876)
+        data_ = data_.substr(0, window_end_);
+        break;
+      }
+
     } else {
       // We want to strip this chunk. If we accumulated a window,
       // we must return the window now.
@@ -145,14 +162,14 @@
 }
 
 void PngChunkFilter::BackUp(size_t count) {
-  if (error_) {
+  if (HadError()) {
     return;
   }
   window_start_ -= count;
 }
 
 bool PngChunkFilter::Rewind() {
-  if (error_) {
+  if (HadError()) {
     return false;
   }
   window_start_ = 0;
diff --git a/tools/aapt2/compile/PngCrunch.cpp b/tools/aapt2/compile/PngCrunch.cpp
index ae98afc..42443d8 100644
--- a/tools/aapt2/compile/PngCrunch.cpp
+++ b/tools/aapt2/compile/PngCrunch.cpp
@@ -73,6 +73,11 @@
 static void LogError(png_structp png_ptr, png_const_charp error_msg) {
   IDiagnostics* diag = (IDiagnostics*)png_get_error_ptr(png_ptr);
   diag->Error(DiagMessage() << error_msg);
+
+  // Causes libpng to longjmp to the spot where setjmp was set. This is how libpng does
+  // error handling. If this custom error handler method were to return, libpng would, by
+  // default, print the error message to stdout and call the same png_longjmp method.
+  png_longjmp(png_ptr, 1);
 }
 
 static void ReadDataFromStream(png_structp png_ptr, png_bytep buffer, png_size_t len) {
@@ -82,7 +87,12 @@
   size_t in_len;
   if (!in->Next(&in_buffer, &in_len)) {
     if (in->HadError()) {
-      std::string err = in->GetError();
+      std::stringstream error_msg_builder;
+      error_msg_builder << "failed reading from input";
+      if (!in->GetError().empty()) {
+        error_msg_builder << ": " << in->GetError();
+      }
+      std::string err = error_msg_builder.str();
       png_error(png_ptr, err.c_str());
     }
     return;
@@ -103,6 +113,11 @@
   while (len > 0) {
     if (!out->Next(&out_buffer, &out_len)) {
       if (out->HadError()) {
+        std::stringstream err_msg_builder;
+        err_msg_builder << "failed writing to output";
+        if (!out->GetError().empty()) {
+          err_msg_builder << ": " << out->GetError();
+        }
         std::string err = out->GetError();
         png_error(png_ptr, err.c_str());
       }
@@ -126,7 +141,7 @@
   }
 }
 
-std::unique_ptr<Image> ReadPng(IAaptContext* context, io::InputStream* in) {
+std::unique_ptr<Image> ReadPng(IAaptContext* context, const Source& source, io::InputStream* in) {
   // Read the first 8 bytes of the file looking for the PNG signature.
   // Bail early if it does not match.
   const png_byte* signature;
@@ -163,6 +178,9 @@
     return {};
   }
 
+  // Create a diagnostics that has the source information encoded.
+  SourcePathDiagnostics source_diag(source, context->GetDiagnostics());
+
   // Automatically release PNG resources at end of scope.
   PngReadStructDeleter png_read_deleter(read_ptr, info_ptr);
 
@@ -174,7 +192,7 @@
   }
 
   // Handle warnings ourselves via IDiagnostics.
-  png_set_error_fn(read_ptr, (png_voidp)context->GetDiagnostics(), LogError, LogWarning);
+  png_set_error_fn(read_ptr, (png_voidp)&source_diag, LogError, LogWarning);
 
   // Set up the read functions which read from our custom data sources.
   png_set_read_fn(read_ptr, (png_voidp)in, ReadDataFromStream);
@@ -231,8 +249,8 @@
   // something
   // that can always be represented by 9-patch.
   if (width > std::numeric_limits<int32_t>::max() || height > std::numeric_limits<int32_t>::max()) {
-    context->GetDiagnostics()->Error(
-        DiagMessage() << "PNG image dimensions are too large: " << width << "x" << height);
+    source_diag.Error(DiagMessage()
+                      << "PNG image dimensions are too large: " << width << "x" << height);
     return {};
   }
 
diff --git a/tools/aapt2/filter/ConfigFilter.cpp b/tools/aapt2/filter/ConfigFilter.cpp
index 66aff82..5fbe77e 100644
--- a/tools/aapt2/filter/ConfigFilter.cpp
+++ b/tools/aapt2/filter/ConfigFilter.cpp
@@ -38,6 +38,43 @@
   config_mask_ |= diff_mask;
 }
 
+// Returns true if the locale script of the config should be considered matching
+// the locale script of entry.
+//
+// If both the scripts are empty, the scripts are considered matching for
+// backward compatibility reasons.
+//
+// If only one script is empty, we try to compute it based on the provided
+// language and country. If we could not compute it, we assume it's either a
+// new language we don't know about, or a private use language. We return true
+// since we don't know any better and they might as well be a match.
+//
+// Finally, when we have two scripts (one of which could be computed), we return
+// true if and only if they are an exact match.
+static bool ScriptsMatch(const ConfigDescription& config, const ConfigDescription& entry) {
+  const char* config_script = config.localeScript;
+  const char* entry_script = entry.localeScript;
+  if (config_script[0] == '\0' && entry_script[0] == '\0') {
+    return true;  // both scripts are empty. We match for backward compatibility reasons.
+  }
+
+  char script_buffer[sizeof(config.localeScript)];
+  if (config_script[0] == '\0') {
+    android::localeDataComputeScript(script_buffer, config.language, config.country);
+    if (script_buffer[0] == '\0') {  // We can't compute the script, so we match.
+      return true;
+    }
+    config_script = script_buffer;
+  } else if (entry_script[0] == '\0') {
+    android::localeDataComputeScript(script_buffer, entry.language, entry.country);
+    if (script_buffer[0] == '\0') {  // We can't compute the script, so we match.
+      return true;
+    }
+    entry_script = script_buffer;
+  }
+  return memcmp(config_script, entry_script, sizeof(config.localeScript)) == 0;
+}
+
 bool AxisConfigFilter::Match(const ConfigDescription& config) const {
   const uint32_t mask = ConfigDescription::DefaultConfig().diff(config);
   if ((config_mask_ & mask) == 0) {
@@ -57,12 +94,16 @@
       // If the locales differ, but the languages are the same and
       // the locale we are matching only has a language specified,
       // we match.
-      if (config.language[0] &&
-          memcmp(config.language, target.language, sizeof(config.language)) ==
-              0) {
-        if (config.country[0] == 0) {
-          matched_axis |= android::ResTable_config::CONFIG_LOCALE;
-        }
+      //
+      // Exception: we won't match if a script is specified for at least
+      // one of the locales and it's different from the other locale's
+      // script. (We will compute the other script if at least one of the
+      // scripts were explicitly set. In cases we can't compute an script,
+      // we match.)
+      if (config.language[0] != '\0' && config.country[0] == '\0' &&
+          config.localeVariant[0] == '\0' && config.language[0] == entry.first.language[0] &&
+          config.language[1] == entry.first.language[1] && ScriptsMatch(config, entry.first)) {
+        matched_axis |= android::ResTable_config::CONFIG_LOCALE;
       }
     } else if ((diff & diff_mask) ==
                android::ResTable_config::CONFIG_SMALLEST_SCREEN_SIZE) {
diff --git a/tools/aapt2/filter/ConfigFilter_test.cpp b/tools/aapt2/filter/ConfigFilter_test.cpp
index 586dd5f..4a31080 100644
--- a/tools/aapt2/filter/ConfigFilter_test.cpp
+++ b/tools/aapt2/filter/ConfigFilter_test.cpp
@@ -109,4 +109,20 @@
   EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("kok-rIN")));
 }
 
+TEST(ConfigFilterTest, MatchesScripts) {
+  AxisConfigFilter filter;
+
+  // "sr" gets automatically computed the script "Cyrl"
+  filter.AddConfig(test::ParseConfigOrDie("sr"));
+
+  // "sr" -> "b+sr+Cyrl"
+  EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("b+sr+Cyrl")));
+
+  // The incoming "sr" is also auto-computed to "b+sr+Cyrl".
+  EXPECT_TRUE(filter.Match(test::ParseConfigOrDie("sr")));
+
+  // "sr" -> "b+sr+Cyrl", which doesn't match "Latn".
+  EXPECT_FALSE(filter.Match(test::ParseConfigOrDie("b+sr+Latn")));
+}
+
 }  // namespace aapt
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index d942d05..088cbc6 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -131,7 +131,7 @@
 
     boolean stopSoftAp();
 
-    int startLocalOnlyHotspot(in Messenger messenger, in IBinder binder);
+    int startLocalOnlyHotspot(in Messenger messenger, in IBinder binder, in String packageName);
 
     void stopLocalOnlyHotspot();
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index e59b74f..25d61af 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -452,6 +452,15 @@
     public static final int SAP_START_FAILURE_NO_CHANNEL = 1;
 
     /**
+     * Interface IP mode unspecified.
+     *
+     * @see updateInterfaceIpState(String, int)
+     *
+     * @hide
+     */
+    public static final int IFACE_IP_MODE_UNSPECIFIED = -1;
+
+    /**
      * Interface IP mode for configuration error.
      *
      * @see updateInterfaceIpState(String, int)
@@ -1890,7 +1899,9 @@
             LocalOnlyHotspotCallbackProxy proxy =
                     new LocalOnlyHotspotCallbackProxy(this, looper, callback);
             try {
-                int returnCode = mService.startLocalOnlyHotspot(proxy.getMessenger(), new Binder());
+                String packageName = mContext.getOpPackageName();
+                int returnCode = mService.startLocalOnlyHotspot(
+                        proxy.getMessenger(), new Binder(), packageName);
                 if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
                     // Send message to the proxy to make sure we call back on the correct thread
                     proxy.notifyFailed(returnCode);
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
index 92c7e36..ebf5c2a 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pWfdInfo.java
@@ -139,7 +139,7 @@
 
     public String getDeviceInfoHex() {
         return String.format(
-                Locale.US, "%04x%04x%04x%04x", 6, mDeviceInfo, mCtrlPort, mMaxThroughput);
+                Locale.US, "%04x%04x%04x", mDeviceInfo, mCtrlPort, mMaxThroughput);
     }
 
     public String toString() {
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
index a0b5a6e..1020fd2 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.java
@@ -186,31 +186,23 @@
     /**
      * Create the list of  WifiP2pServiceResponse instance from supplicant event.
      *
-     * <pre>The format is as follows.
-     * P2P-SERV-DISC-RESP &lt;address&gt; &lt;update indicator&gt; &lt;response data&gt;
-     * e.g) P2P-SERV-DISC-RESP 02:03:7f:11:62:da 1 0300000101
-     *
-     * @param supplicantEvent wpa_supplicant event string.
+     * @param srcAddr source address of the service response
+     * @param tlvsBin byte array containing the binary tlvs data
      * @return if parse failed, return null
      * @hide
      */
-    public static List<WifiP2pServiceResponse> newInstance(String supplicantEvent) {
+    public static List<WifiP2pServiceResponse> newInstance(String srcAddr, byte[] tlvsBin) {
+        //updateIndicator not used, and not passed up from supplicant
 
         List<WifiP2pServiceResponse> respList = new ArrayList<WifiP2pServiceResponse>();
-        String[] args = supplicantEvent.split(" ");
-        if (args.length != 4) {
-            return null;
-        }
         WifiP2pDevice dev = new WifiP2pDevice();
-        String srcAddr = args[1];
         dev.deviceAddress = srcAddr;
-        //String updateIndicator = args[2];//not used.
-        byte[] bin = hexStr2Bin(args[3]);
-        if (bin == null) {
+        if (tlvsBin == null) {
             return null;
         }
 
-        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bin));
+
+        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(tlvsBin));
         try {
             while (dis.available() > 0) {
                 /*
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index adf897d..84ac118 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -58,6 +58,7 @@
 
     private static final int ERROR_NOT_SET = -1;
     private static final int ERROR_TEST_REASON = 5;
+    private static final String TEST_PACKAGE_NAME = "TestPackage";
 
     @Mock Context mContext;
     @Mock IWifiManager mWifiService;
@@ -76,6 +77,7 @@
         mLooper = new TestLooper();
         mHandler = spy(new Handler(mLooper.getLooper()));
         when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
+        when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
 
         mWifiServiceMessenger = new Messenger(mHandler);
         mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
@@ -126,8 +128,8 @@
     @Test
     public void testCreationAndCloseOfLocalOnlyHotspotReservation() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                            .thenReturn(REQUEST_REGISTERED);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
 
         callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig));
@@ -144,8 +146,8 @@
     public void testLocalOnlyHotspotReservationCallsStopProperlyInTryWithResources()
             throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(REQUEST_REGISTERED);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
 
         callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig));
@@ -304,7 +306,8 @@
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
 
-        verify(mWifiService).startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class));
+        verify(mWifiService)
+                .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString());
     }
 
     /**
@@ -315,7 +318,7 @@
     public void testStartLocalOnlyHotspotThrowsSecurityException() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
         doThrow(new SecurityException()).when(mWifiService)
-                .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class));
+                .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString());
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
     }
 
@@ -327,7 +330,7 @@
     public void testStartLocalOnlyHotspotThrowsIllegalStateException() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
         doThrow(new IllegalStateException()).when(mWifiService)
-                .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class));
+                .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString());
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
     }
 
@@ -337,8 +340,8 @@
     @Test
     public void testCorrectLooperIsUsedForHandler() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(ERROR_INCOMPATIBLE_MODE);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
         mLooper.dispatchAll();
         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -355,8 +358,8 @@
         TestLooper altLooper = new TestLooper();
         when(mContext.getMainLooper()).thenReturn(altLooper.getLooper());
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(ERROR_INCOMPATIBLE_MODE);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
         mWifiManager.startLocalOnlyHotspot(callback, null);
         altLooper.dispatchAll();
         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -374,7 +377,7 @@
         TestLooper callbackLooper = new TestLooper();
         Handler callbackHandler = new Handler(callbackLooper.getLooper());
         when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
-                  any(IBinder.class))).thenReturn(REQUEST_REGISTERED);
+                  any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
         callbackLooper.dispatchAll();
         mLooper.dispatchAll();
@@ -401,7 +404,7 @@
         TestLooper callbackLooper = new TestLooper();
         Handler callbackHandler = new Handler(callbackLooper.getLooper());
         when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
-                  any(IBinder.class))).thenReturn(REQUEST_REGISTERED);
+                  any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
         callbackLooper.dispatchAll();
         mLooper.dispatchAll();
@@ -426,7 +429,7 @@
         TestLooper callbackLooper = new TestLooper();
         Handler callbackHandler = new Handler(callbackLooper.getLooper());
         when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
-                  any(IBinder.class))).thenReturn(REQUEST_REGISTERED);
+                  any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
         callbackLooper.dispatchAll();
         mLooper.dispatchAll();
@@ -449,7 +452,7 @@
         TestLooper callbackLooper = new TestLooper();
         Handler callbackHandler = new Handler(callbackLooper.getLooper());
         when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(),
-                  any(IBinder.class))).thenReturn(REQUEST_REGISTERED);
+                  any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
         callbackLooper.dispatchAll();
         mLooper.dispatchAll();
@@ -470,8 +473,8 @@
     @Test
     public void testLocalOnlyHotspotCallbackFullOnIncompatibleMode() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(ERROR_INCOMPATIBLE_MODE);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
         mLooper.dispatchAll();
         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -486,8 +489,8 @@
     @Test
     public void testLocalOnlyHotspotCallbackFullOnTetheringDisallowed() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(ERROR_TETHERING_DISALLOWED);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(ERROR_TETHERING_DISALLOWED);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
         mLooper.dispatchAll();
         assertEquals(ERROR_TETHERING_DISALLOWED, callback.mFailureReason);
@@ -504,7 +507,7 @@
     public void testLocalOnlyHotspotCallbackFullOnSecurityException() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
         doThrow(new SecurityException()).when(mWifiService)
-                .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class));
+                .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString());
         try {
             mWifiManager.startLocalOnlyHotspot(callback, mHandler);
         } catch (SecurityException e) {
@@ -524,8 +527,8 @@
     @Test
     public void testLocalOnlyHotspotCallbackFullOnNoChannelError() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(REQUEST_REGISTERED);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
         mLooper.dispatchAll();
         //assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
@@ -540,8 +543,8 @@
     @Test
     public void testCancelLocalOnlyHotspotRequestCallsStopOnWifiService() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(REQUEST_REGISTERED);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
         mWifiManager.cancelLocalOnlyHotspotRequest();
         verify(mWifiService).stopLocalOnlyHotspot();
@@ -562,8 +565,8 @@
     @Test
     public void testCallbackAfterLocalOnlyHotspotWasCancelled() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(REQUEST_REGISTERED);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(REQUEST_REGISTERED);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
         mWifiManager.cancelLocalOnlyHotspotRequest();
         verify(mWifiService).stopLocalOnlyHotspot();
@@ -581,8 +584,8 @@
     @Test
     public void testCancelAfterLocalOnlyHotspotCallbackTriggered() throws Exception {
         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
-        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)))
-                .thenReturn(ERROR_INCOMPATIBLE_MODE);
+        when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class),
+                anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
         mLooper.dispatchAll();
         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);