Merge "Set app op mode to allowed when granting permissions to reset state."
diff --git a/Android.bp b/Android.bp
index 7219ef5..7693a66 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1420,7 +1420,6 @@
     libs: [
         "ext",
         "framework",
-        "voip-common",
     ],
     local_sourcepaths: frameworks_base_subdirs,
     installable: false,
diff --git a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
index 1f12ae6..f0c474b 100644
--- a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
@@ -39,7 +39,6 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.rule.ActivityTestRule;
 
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -51,9 +50,7 @@
 
 @RunWith(Parameterized.class)
 @LargeTest
-public class RelayoutPerfTest {
-    private static final IWindowSession sSession = WindowManagerGlobal.getWindowSession();
-
+public class RelayoutPerfTest extends WindowManagerPerfTestBase {
     private int mIteration;
 
     @Rule
@@ -85,12 +82,6 @@
         });
     }
 
-    @Before
-    public void setUp() {
-        getInstrumentation().getUiAutomation().executeShellCommand("input keyevent KEYCODE_WAKEUP");
-        getInstrumentation().getUiAutomation().executeShellCommand("wm dismiss-keyguard");
-    }
-
     @Test
     public void testRelayout() throws Throwable {
         final Activity activity = mActivityRule.getActivity();
@@ -154,8 +145,9 @@
         }
 
         void runBenchmark(BenchmarkState state) throws RemoteException {
+            final IWindowSession session = WindowManagerGlobal.getWindowSession();
             while (state.keepRunning()) {
-                sSession.relayout(mWindow, mSeq, mParams, mWidth, mHeight,
+                session.relayout(mWindow, mSeq, mParams, mWidth, mHeight,
                         mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrame,
                         mOutOverscanInsets, mOutContentInsets, mOutVisibleInsets, mOutStableInsets,
                         mOutOutsets, mOutBackDropFrame, mOutDisplayCutout, mOutMergedConfiguration,
diff --git a/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java
new file mode 100644
index 0000000..a951869
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/wm/WindowAddRemovePerfTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.wm;
+
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.perftests.utils.ManualBenchmarkState;
+import android.perftests.utils.ManualBenchmarkState.ManualBenchmarkTest;
+import android.perftests.utils.PerfManualStatusReporter;
+import android.view.Display;
+import android.view.DisplayCutout;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.InsetsState;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+
+import androidx.test.filters.LargeTest;
+
+import com.android.internal.view.BaseIWindow;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+
+@LargeTest
+public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase {
+    @Rule
+    public final PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter();
+
+    @BeforeClass
+    public static void setUpClass() {
+        // Get the permission to use most window types.
+        sUiAutomation.adoptShellPermissionIdentity();
+    }
+
+    @AfterClass
+    public static void tearDownClass() {
+        sUiAutomation.dropShellPermissionIdentity();
+    }
+
+    @Test
+    @ManualBenchmarkTest(warmupDurationNs = WARMUP_DURATION, targetTestDurationNs = TEST_DURATION)
+    public void testAddRemoveWindow() throws Throwable {
+        new TestWindow().runBenchmark(mPerfStatusReporter.getBenchmarkState());
+    }
+
+    private static class TestWindow extends BaseIWindow {
+        final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
+        final Rect mOutFrame = new Rect();
+        final Rect mOutContentInsets = new Rect();
+        final Rect mOutStableInsets = new Rect();
+        final Rect mOutOutsets = new Rect();
+        final DisplayCutout.ParcelableWrapper mOutDisplayCutout =
+                new DisplayCutout.ParcelableWrapper();
+        final InsetsState mOutInsetsState = new InsetsState();
+
+        TestWindow() {
+            mLayoutParams.setTitle(TestWindow.class.getName());
+            mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+            // Simulate as common phone window.
+            mLayoutParams.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+        }
+
+        void runBenchmark(ManualBenchmarkState state) throws RemoteException {
+            final IWindowSession session = WindowManagerGlobal.getWindowSession();
+            long elapsedTimeNs = 0;
+            while (state.keepRunning(elapsedTimeNs)) {
+                // InputChannel cannot be reused.
+                final InputChannel inputChannel = new InputChannel();
+
+                long startTime = SystemClock.elapsedRealtimeNanos();
+                session.addToDisplay(this, mSeq, mLayoutParams, View.VISIBLE,
+                        Display.DEFAULT_DISPLAY, mOutFrame, mOutContentInsets, mOutStableInsets,
+                        mOutOutsets, mOutDisplayCutout, inputChannel, mOutInsetsState);
+                final long elapsedTimeNsOfAdd = SystemClock.elapsedRealtimeNanos() - startTime;
+                state.addExtraResult("add", elapsedTimeNsOfAdd);
+
+                startTime = SystemClock.elapsedRealtimeNanos();
+                session.remove(this);
+                final long elapsedTimeNsOfRemove = SystemClock.elapsedRealtimeNanos() - startTime;
+                state.addExtraResult("remove", elapsedTimeNsOfRemove);
+
+                elapsedTimeNs = elapsedTimeNsOfAdd + elapsedTimeNsOfRemove;
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java b/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java
new file mode 100644
index 0000000..b2c6168
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/wm/WindowManagerPerfTestBase.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.wm;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import android.app.UiAutomation;
+
+import org.junit.Before;
+
+public class WindowManagerPerfTestBase {
+    static final UiAutomation sUiAutomation = getInstrumentation().getUiAutomation();
+    static final long NANOS_PER_S = 1000L * 1000 * 1000;
+    static final long WARMUP_DURATION = 1 * NANOS_PER_S;
+    static final long TEST_DURATION = 5 * NANOS_PER_S;
+
+    @Before
+    public void setUp() {
+        // In order to be closer to the real use case.
+        sUiAutomation.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+        sUiAutomation.executeShellCommand("wm dismiss-keyguard");
+    }
+}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
index 40778de..dd43ae7 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/ManualBenchmarkState.java
@@ -19,8 +19,13 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.os.Bundle;
+import android.util.ArrayMap;
 import android.util.Log;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 
@@ -71,6 +76,8 @@
 
     private int mState = NOT_STARTED;  // Current benchmark state.
 
+    private long mWarmupDurationNs = WARMUP_DURATION_NS;
+    private long mTargetTestDurationNs = TARGET_TEST_DURATION_NS;
     private long mWarmupStartTime = 0;
     private int mWarmupIterations = 0;
 
@@ -79,12 +86,30 @@
     // Individual duration in nano seconds.
     private ArrayList<Long> mResults = new ArrayList<>();
 
+    /** @see #addExtraResult(String, long) */
+    private ArrayMap<String, ArrayList<Long>> mExtraResults;
+
     // Statistics. These values will be filled when the benchmark has finished.
     // The computation needs double precision, but long int is fine for final reporting.
     private Stats mStats;
 
+    void configure(ManualBenchmarkTest testAnnotation) {
+        if (testAnnotation == null) {
+            return;
+        }
+
+        final long warmupDurationNs = testAnnotation.warmupDurationNs();
+        if (warmupDurationNs >= 0) {
+            mWarmupDurationNs = warmupDurationNs;
+        }
+        final long targetTestDurationNs = testAnnotation.targetTestDurationNs();
+        if (targetTestDurationNs >= 0) {
+            mTargetTestDurationNs = targetTestDurationNs;
+        }
+    }
+
     private void beginBenchmark(long warmupDuration, int iterations) {
-        mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations));
+        mMaxIterations = (int) (mTargetTestDurationNs / (warmupDuration / iterations));
         mMaxIterations = Math.min(MAX_TEST_ITERATIONS,
                 Math.max(mMaxIterations, MIN_TEST_ITERATIONS));
         mState = RUNNING;
@@ -108,7 +133,7 @@
                 final long timeSinceStartingWarmup = System.nanoTime() - mWarmupStartTime;
                 ++mWarmupIterations;
                 if (mWarmupIterations >= WARMUP_MIN_ITERATIONS
-                        && timeSinceStartingWarmup >= WARMUP_DURATION_NS) {
+                        && timeSinceStartingWarmup >= mWarmupDurationNs) {
                     beginBenchmark(timeSinceStartingWarmup, mWarmupIterations);
                 }
                 return true;
@@ -129,31 +154,69 @@
         }
     }
 
-    private String summaryLine() {
-        final StringBuilder sb = new StringBuilder();
-        sb.append("Summary: ");
-        sb.append("median=").append(mStats.getMedian()).append("ns, ");
-        sb.append("mean=").append(mStats.getMean()).append("ns, ");
-        sb.append("min=").append(mStats.getMin()).append("ns, ");
-        sb.append("max=").append(mStats.getMax()).append("ns, ");
-        sb.append("sigma=").append(mStats.getStandardDeviation()).append(", ");
-        sb.append("iteration=").append(mResults.size()).append(", ");
-        sb.append("values=").append(mResults.toString());
+    /**
+     * Adds additional result while this benchmark is running. It is used when a sequence of
+     * operations is executed consecutively, the duration of each operation can also be recorded.
+     */
+    public void addExtraResult(String key, long duration) {
+        if (mState != RUNNING) {
+            return;
+        }
+        if (mExtraResults == null) {
+            mExtraResults = new ArrayMap<>();
+        }
+        mExtraResults.computeIfAbsent(key, k -> new ArrayList<>()).add(duration);
+    }
+
+    private static String summaryLine(String key, Stats stats, ArrayList<Long> results) {
+        final StringBuilder sb = new StringBuilder(key);
+        sb.append(" Summary: ");
+        sb.append("median=").append(stats.getMedian()).append("ns, ");
+        sb.append("mean=").append(stats.getMean()).append("ns, ");
+        sb.append("min=").append(stats.getMin()).append("ns, ");
+        sb.append("max=").append(stats.getMax()).append("ns, ");
+        sb.append("sigma=").append(stats.getStandardDeviation()).append(", ");
+        sb.append("iteration=").append(results.size()).append(", ");
+        sb.append("values=");
+        if (results.size() > 100) {
+            sb.append(results.subList(0, 100)).append(" ...");
+        } else {
+            sb.append(results);
+        }
         return sb.toString();
     }
 
+    private static void fillStatus(Bundle status, String key, Stats stats) {
+        status.putLong(key + "_median", stats.getMedian());
+        status.putLong(key + "_mean", (long) stats.getMean());
+        status.putLong(key + "_percentile90", stats.getPercentile90());
+        status.putLong(key + "_percentile95", stats.getPercentile95());
+        status.putLong(key + "_stddev", (long) stats.getStandardDeviation());
+    }
+
     public void sendFullStatusReport(Instrumentation instrumentation, String key) {
         if (mState != FINISHED) {
             throw new IllegalStateException("The benchmark hasn't finished");
         }
-        Log.i(TAG, key + summaryLine());
+        Log.i(TAG, summaryLine(key, mStats, mResults));
         final Bundle status = new Bundle();
-        status.putLong(key + "_median", mStats.getMedian());
-        status.putLong(key + "_mean", (long) mStats.getMean());
-        status.putLong(key + "_percentile90", mStats.getPercentile90());
-        status.putLong(key + "_percentile95", mStats.getPercentile95());
-        status.putLong(key + "_stddev", (long) mStats.getStandardDeviation());
+        fillStatus(status, key, mStats);
+        if (mExtraResults != null) {
+            for (int i = 0; i < mExtraResults.size(); i++) {
+                final String subKey = key + "_" + mExtraResults.keyAt(i);
+                final Stats stats = new Stats(mExtraResults.valueAt(i));
+                Log.i(TAG, summaryLine(subKey, mStats, mResults));
+                fillStatus(status, subKey, stats);
+            }
+        }
         instrumentation.sendStatus(Activity.RESULT_OK, status);
     }
-}
 
+    /** The annotation to customize the test, e.g. the duration of warm-up and target test. */
+    @Target(ElementType.METHOD)
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface ManualBenchmarkTest {
+        long warmupDurationNs() default -1;
+        long targetTestDurationNs() default -1;
+    }
+}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/PerfManualStatusReporter.java b/apct-tests/perftests/utils/src/android/perftests/utils/PerfManualStatusReporter.java
index 8187c6f..8ff6a16 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/PerfManualStatusReporter.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/PerfManualStatusReporter.java
@@ -16,7 +16,7 @@
 
 package android.perftests.utils;
 
-import androidx.test.InstrumentationRegistry;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
@@ -59,15 +59,15 @@
 
     @Override
     public Statement apply(Statement base, Description description) {
+        mState.configure(description.getAnnotation(ManualBenchmarkState.ManualBenchmarkTest.class));
+
         return new Statement() {
             @Override
             public void evaluate() throws Throwable {
                 base.evaluate();
 
-                mState.sendFullStatusReport(InstrumentationRegistry.getInstrumentation(),
-                        description.getMethodName());
+                mState.sendFullStatusReport(getInstrumentation(), description.getMethodName());
             }
         };
     }
 }
-
diff --git a/api/current.txt b/api/current.txt
index 7c13dc1..a7b38a5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10834,7 +10834,9 @@
     method @Nullable public String getString(String, @Nullable String);
     method @Nullable public java.util.Set<java.lang.String> getStringSet(String, @Nullable java.util.Set<java.lang.String>);
     method public void registerOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener);
+    method public default void registerOnSharedPreferencesClearListener(@NonNull android.content.SharedPreferences.OnSharedPreferencesClearListener);
     method public void unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener);
+    method public default void unregisterOnSharedPreferencesClearListener(@NonNull android.content.SharedPreferences.OnSharedPreferencesClearListener);
   }
 
   public static interface SharedPreferences.Editor {
@@ -10854,6 +10856,10 @@
     method public void onSharedPreferenceChanged(android.content.SharedPreferences, String);
   }
 
+  public static interface SharedPreferences.OnSharedPreferencesClearListener {
+    method public void onSharedPreferencesClear(@NonNull android.content.SharedPreferences, @NonNull java.util.Set<java.lang.String>);
+  }
+
   public class SyncAdapterType implements android.os.Parcelable {
     ctor public SyncAdapterType(String, String, boolean, boolean);
     ctor public SyncAdapterType(android.os.Parcel);
@@ -13123,8 +13129,11 @@
     method @Nullable public android.database.sqlite.SQLiteDatabase.CursorFactory getCursorFactory();
     method @Nullable public java.util.Map<java.lang.String,java.lang.String> getProjectionMap();
     method @Nullable public String getTables();
+    method public long insert(@NonNull android.database.sqlite.SQLiteDatabase, @NonNull android.content.ContentValues);
     method public boolean isDistinct();
     method public boolean isStrict();
+    method public boolean isStrictColumns();
+    method public boolean isStrictGrammar();
     method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String);
     method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String, String);
     method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, String[], String, String[], String, String, String, String, android.os.CancellationSignal);
@@ -13132,6 +13141,8 @@
     method public void setDistinct(boolean);
     method public void setProjectionMap(@Nullable java.util.Map<java.lang.String,java.lang.String>);
     method public void setStrict(boolean);
+    method public void setStrictColumns(boolean);
+    method public void setStrictGrammar(boolean);
     method public void setTables(@Nullable String);
     method public int update(@NonNull android.database.sqlite.SQLiteDatabase, @NonNull android.content.ContentValues, @Nullable String, @Nullable String[]);
   }
@@ -41053,6 +41064,7 @@
     method public int getType();
     field public static final int TYPE_AUTHENTICATION_SELECTED = 2; // 0x2
     field public static final int TYPE_CONTEXT_COMMITTED = 4; // 0x4
+    field public static final int TYPE_DATASETS_SHOWN = 5; // 0x5
     field public static final int TYPE_DATASET_AUTHENTICATION_SELECTED = 1; // 0x1
     field public static final int TYPE_DATASET_SELECTED = 0; // 0x0
     field public static final int TYPE_SAVE_SHOWN = 3; // 0x3
@@ -52435,6 +52447,7 @@
     method public int getId();
     method public int getLayer();
     method public android.view.accessibility.AccessibilityWindowInfo getParent();
+    method public void getRegionInScreen(@NonNull android.graphics.Region);
     method public android.view.accessibility.AccessibilityNodeInfo getRoot();
     method @Nullable public CharSequence getTitle();
     method public int getType();
diff --git a/api/removed.txt b/api/removed.txt
index 7b1d241..b075f9e 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -73,10 +73,6 @@
 
 package android.content {
 
-  public class ClipData implements android.os.Parcelable {
-    method @Deprecated public void addItem(android.content.ClipData.Item, android.content.ContentResolver);
-  }
-
   public abstract class Context {
     method public abstract android.content.SharedPreferences getSharedPreferences(java.io.File, int);
     method public abstract java.io.File getSharedPreferencesPath(String);
diff --git a/api/system-current.txt b/api/system-current.txt
index 48804b6..eef6b3f 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5179,7 +5179,8 @@
     method @NonNull public static java.io.File getOdmDirectory();
     method @NonNull public static java.io.File getOemDirectory();
     method @NonNull public static java.io.File getProductDirectory();
-    method @NonNull public static java.io.File getProductServicesDirectory();
+    method @Deprecated @NonNull public static java.io.File getProductServicesDirectory();
+    method @NonNull public static java.io.File getSystemExtDirectory();
     method @NonNull public static java.io.File getVendorDirectory();
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index d2179d3..b393fcc 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -697,6 +697,7 @@
     method public void setEnableRollback(boolean);
     method @RequiresPermission("android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS") public void setGrantedRuntimePermissions(String[]);
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
+    method public void setRequestDowngrade(boolean);
     method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
   }
 
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 680ccfc..76b905d 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -64,6 +64,10 @@
 
     private static final String BMGR_NOT_RUNNING_ERR =
             "Error: Could not access the Backup Manager.  Is the system running?";
+    private static final String BMGR_NOT_ACTIVATED_FOR_USER =
+            "Error: Backup Manager is not activated for user ";
+    private static final String BMGR_ERR_NO_RESTORESESSION_FOR_USER =
+            "Error: Could not get restore session for user ";
     private static final String TRANSPORT_NOT_RUNNING_ERR =
             "Error: Could not access the backup transport.  Is the system running?";
     private static final String PM_NOT_RUNNING_ERR =
@@ -190,15 +194,19 @@
         showUsage();
     }
 
-    boolean isBackupActive(@UserIdInt int userId) {
+    private void handleRemoteException(RemoteException e) {
+        System.err.println(e.toString());
+        System.err.println(BMGR_NOT_RUNNING_ERR);
+    }
+
+    private boolean isBackupActive(@UserIdInt int userId) {
         try {
             if (!mBmgr.isBackupServiceActive(userId)) {
-                System.err.println(BMGR_NOT_RUNNING_ERR);
+                System.err.println(BMGR_NOT_ACTIVATED_FOR_USER + userId);
                 return false;
             }
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
             return false;
         }
 
@@ -214,8 +222,7 @@
             System.out.println("Backup Manager currently "
                     + activatedToString(mBmgr.isBackupServiceActive(userId)));
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
 
     }
@@ -230,8 +237,7 @@
             System.out.println("Backup Manager currently "
                     + enableToString(isEnabled));
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -250,8 +256,7 @@
             showUsage();
             return;
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -259,8 +264,7 @@
         try {
             mBmgr.backupNowForUser(userId);
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -274,8 +278,7 @@
         try {
             mBmgr.dataChangedForUser(userId, pkg);
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -292,8 +295,7 @@
                 mBmgr.fullTransportBackupForUser(
                         userId, allPkgs.toArray(new String[allPkgs.size()]));
             } catch (RemoteException e) {
-                System.err.println(e.toString());
-                System.err.println(BMGR_NOT_RUNNING_ERR);
+                handleRemoteException(e);
             }
         }
     }
@@ -421,8 +423,7 @@
             try {
                 filteredPackages = mBmgr.filterAppsEligibleForBackupForUser(userId, packages);
             } catch (RemoteException e) {
-                System.err.println(e.toString());
-                System.err.println(BMGR_NOT_RUNNING_ERR);
+                handleRemoteException(e);
             }
             backupNowPackages(userId, Arrays.asList(filteredPackages), nonIncrementalBackup,
                     monitorState);
@@ -455,8 +456,7 @@
                 System.err.println("Unable to run backup");
             }
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -506,8 +506,7 @@
             try {
                 mBmgr.cancelBackupsForUser(userId);
             } catch (RemoteException e) {
-                System.err.println(e.toString());
-                System.err.println(BMGR_NOT_RUNNING_ERR);
+                handleRemoteException(e);
             }
             return;
         }
@@ -537,8 +536,7 @@
             }
 
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -569,8 +567,7 @@
                         }
                     });
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
             return;
         }
 
@@ -598,8 +595,7 @@
             mBmgr.clearBackupDataForUser(userId, transport, pkg);
             System.out.println("Wiped backup data for " + pkg + " on " + transport);
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -632,8 +628,7 @@
             observer.waitForCompletion(30*1000L);
             System.out.println("Initialization result: " + observer.result);
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -648,7 +643,7 @@
         try {
             mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
             if (mRestore == null) {
-                System.err.println(BMGR_NOT_RUNNING_ERR);
+                System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
                 return;
             }
 
@@ -658,8 +653,7 @@
 
             mRestore.endRestoreSession();
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -686,8 +680,7 @@
                 System.out.println(pad + t);
             }
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -805,7 +798,7 @@
             boolean didRestore = false;
             mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null);
             if (mRestore == null) {
-                System.err.println(BMGR_NOT_RUNNING_ERR);
+                System.err.println(BMGR_ERR_NO_RESTORESESSION_FOR_USER + userId);
                 return;
             }
             RestoreSet[] sets = null;
@@ -851,8 +844,7 @@
 
             System.out.println("done");
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -865,8 +857,7 @@
                 }
             }
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
@@ -886,8 +877,7 @@
                             + " for user "
                             + userId);
         } catch (RemoteException e) {
-            System.err.println(e.toString());
-            System.err.println(BMGR_NOT_RUNNING_ERR);
+            handleRemoteException(e);
         }
     }
 
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index 31bd612..c1f8654 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -79,7 +79,6 @@
         "libEGL",
         "libGLESv1_CM",
         "libgui",
-        "libtinyalsa",
     ],
 
     product_variables: {
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 30f4ad4..db384ba 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -63,6 +63,10 @@
 
 #include "BootAnimation.h"
 
+#define ANIM_PATH_MAX 255
+#define STR(x)   #x
+#define STRTO(x) STR(x)
+
 namespace android {
 
 static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
@@ -96,7 +100,7 @@
 static const int TEXT_CENTER_VALUE = INT_MAX;
 static const int TEXT_MISSING_VALUE = INT_MIN;
 static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
-static const int ANIM_ENTRY_NAME_MAX = 256;
+static const int ANIM_ENTRY_NAME_MAX = ANIM_PATH_MAX + 1;
 static constexpr size_t TEXT_POS_LEN_MAX = 16;
 
 // ---------------------------------------------------------------------------
@@ -694,7 +698,7 @@
             animation.width = width;
             animation.height = height;
             animation.fps = fps;
-        } else if (sscanf(l, " %c %d %d %s #%6s %16s %16s",
+        } else if (sscanf(l, " %c %d %d %" STRTO(ANIM_PATH_MAX) "s #%6s %16s %16s",
                           &pathType, &count, &pause, path, color, clockPos1, clockPos2) >= 4) {
             //SLOGD("> type=%c, count=%d, pause=%d, path=%s, color=%s, clockPos1=%s, clockPos2=%s",
             //    pathType, count, pause, path, color, clockPos1, clockPos2);
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index cfac5f3..0b349e1 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -103,6 +103,7 @@
       {"/oem/", kPolicyOem},
       {"/product/", kPolicyProduct},
       {"/system/", kPolicySystem},
+      {"/system_ext/", kPolicySystem},
       {"/vendor/", kPolicyVendor},
   };
 
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index ceabd39..f6c72ea 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -5309,6 +5309,9 @@
     // Additional pass-through fields opaque to statsd.
     // The DNS resolver Mainline module can add new fields here without requiring an OS update.
     optional android.stats.dnsresolver.DnsQueryEvents dns_query_events = 8 [(log_mode) = MODE_BYTES];
+
+    // The sample rate of DNS stats (to statsd) is 1/sampling_rate_denom.
+    optional int32 sampling_rate_denom = 9;
 }
 
 /**
diff --git a/config/preloaded-classes b/config/preloaded-classes
index b4fd031..03e3b82 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -2696,6 +2696,7 @@
 android.os.-$$Lambda$Trace$2zLZ-Lc2kAXsVjw_nLYeNhqmGq0
 android.os.-$$Lambda$q1UvBdLgHRZVzc68BxdksTmbuCw
 android.os.AsyncResult
+android.os.AsyncTask
 android.os.AsyncTask$1
 android.os.AsyncTask$2
 android.os.AsyncTask$3
diff --git a/config/preloaded-classes-blacklist b/config/preloaded-classes-blacklist
index b5f9950..f05edee 100644
--- a/config/preloaded-classes-blacklist
+++ b/config/preloaded-classes-blacklist
@@ -1,6 +1,5 @@
 android.content.AsyncTaskLoader$LoadTask
 android.net.ConnectivityThread$Singleton
-android.os.AsyncTask
 android.os.FileObserver
 android.speech.tts.TextToSpeech$Connection$SetupConnectionAsyncTask
 android.widget.Magnifier
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index cebe6e12..4aafa53 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -644,6 +644,32 @@
         }
     }
 
+    @Override
+    public Context createDisplayContext(Display display) {
+        final Context context = super.createDisplayContext(display);
+        final int displayId = display.getDisplayId();
+        setDefaultTokenInternal(context, displayId);
+        return context;
+    }
+
+    private void setDefaultTokenInternal(Context context, int displayId) {
+        final WindowManagerImpl wm = (WindowManagerImpl) context.getSystemService(WINDOW_SERVICE);
+        final IAccessibilityServiceConnection connection =
+                AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+        IBinder token = null;
+        if (connection != null) {
+            synchronized (mLock) {
+                try {
+                    token = connection.getOverlayWindowToken(displayId);
+                } catch (RemoteException re) {
+                    Log.w(LOG_TAG, "Failed to get window token", re);
+                    re.rethrowFromSystemServer();
+                }
+            }
+            wm.setDefaultToken(token);
+        }
+    }
+
     /**
      * Returns the magnification controller, which may be used to query and
      * modify the state of display magnification.
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 8c38fe4..c8e0132 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -96,4 +96,6 @@
     void sendGesture(int sequence, in ParceledListSlice gestureSteps);
 
     boolean isFingerprintGestureDetectionAvailable();
+
+    IBinder getOverlayWindowToken(int displayid);
 }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 91b98c7..cb99a3a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1822,7 +1822,8 @@
      * @hide
      */
     public static class TaskSnapshot implements Parcelable {
-
+        // Identifier of this snapshot
+        private final long mId;
         // Top activity in task when snapshot was taken
         private final ComponentName mTopActivityComponent;
         private final GraphicBuffer mSnapshot;
@@ -1841,10 +1842,12 @@
         // Must be one of the named color spaces, otherwise, always use SRGB color space.
         private final ColorSpace mColorSpace;
 
-        public TaskSnapshot(@NonNull ComponentName topActivityComponent, GraphicBuffer snapshot,
+        public TaskSnapshot(long id,
+                @NonNull ComponentName topActivityComponent, GraphicBuffer snapshot,
                 @NonNull ColorSpace colorSpace, int orientation, Rect contentInsets,
                 boolean reducedResolution, float scale, boolean isRealSnapshot, int windowingMode,
                 int systemUiVisibility, boolean isTranslucent) {
+            mId = id;
             mTopActivityComponent = topActivityComponent;
             mSnapshot = snapshot;
             mColorSpace = colorSpace.getId() < 0
@@ -1860,6 +1863,7 @@
         }
 
         private TaskSnapshot(Parcel source) {
+            mId = source.readLong();
             mTopActivityComponent = ComponentName.readFromParcel(source);
             mSnapshot = source.readParcelable(null /* classLoader */);
             int colorSpaceId = source.readInt();
@@ -1877,6 +1881,13 @@
         }
 
         /**
+         * @return Identifier of this snapshot.
+         */
+        public long getId() {
+            return mId;
+        }
+
+        /**
          * @return The top activity component for the task at the point this snapshot was taken.
          */
         public ComponentName getTopActivityComponent() {
@@ -1970,6 +1981,7 @@
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
+            dest.writeLong(mId);
             ComponentName.writeToParcel(mTopActivityComponent, dest);
             dest.writeParcelable(mSnapshot, 0);
             dest.writeInt(mColorSpace.getId());
@@ -1988,6 +2000,7 @@
             final int width = mSnapshot != null ? mSnapshot.getWidth() : 0;
             final int height = mSnapshot != null ? mSnapshot.getHeight() : 0;
             return "TaskSnapshot{"
+                    + " mId=" + mId
                     + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString()
                     + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
                     + " mColorSpace=" + mColorSpace.toString()
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d741b61..2b4d4f8b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -791,6 +791,8 @@
         @Nullable
         ContentCaptureOptions contentCaptureOptions;
 
+        long[] disabledCompatChanges;
+
         @Override
         public String toString() {
             return "AppBindData{appInfo=" + appInfo + "}";
@@ -1003,7 +1005,7 @@
                 boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                 CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                 String buildSerial, AutofillOptions autofillOptions,
-                ContentCaptureOptions contentCaptureOptions) {
+                ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
             if (services != null) {
                 if (false) {
                     // Test code to make sure the app could see the passed-in services.
@@ -1051,6 +1053,7 @@
             data.buildSerial = buildSerial;
             data.autofillOptions = autofillOptions;
             data.contentCaptureOptions = contentCaptureOptions;
+            data.disabledCompatChanges = disabledCompatChanges;
             sendMessage(H.BIND_APPLICATION, data);
         }
 
@@ -6144,10 +6147,10 @@
         if (data.trackAllocation) {
             DdmVmInternal.enableRecentAllocations(true);
         }
-
         // Note when this process has started.
         Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
 
+        AppCompatCallbacks.install(data.disabledCompatChanges);
         mBoundApplication = data;
         mConfiguration = new Configuration(data.config);
         mCompatConfiguration = new Configuration(data.config);
diff --git a/core/java/android/app/AppCompatCallbacks.java b/core/java/android/app/AppCompatCallbacks.java
new file mode 100644
index 0000000..17697db
--- /dev/null
+++ b/core/java/android/app/AppCompatCallbacks.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.compat.Compatibility;
+import android.os.Process;
+import android.util.Log;
+
+import java.util.Arrays;
+
+/**
+ * App process implementation of the {@link Compatibility} API.
+ *
+ * @hide
+ */
+public final class AppCompatCallbacks extends Compatibility.Callbacks {
+
+    private static final String TAG = "Compatibility";
+
+    private final long[] mDisabledChanges;
+
+    /**
+     * Install this class into the current process.
+     *
+     * @param disabledChanges Set of compatibility changes that are disabled for this process.
+     */
+    public static void install(long[] disabledChanges) {
+        Compatibility.setCallbacks(new AppCompatCallbacks(disabledChanges));
+    }
+
+    private AppCompatCallbacks(long[] disabledChanges) {
+        mDisabledChanges = Arrays.copyOf(disabledChanges, disabledChanges.length);
+        Arrays.sort(mDisabledChanges);
+    }
+
+    protected void reportChange(long changeId) {
+        Log.d(TAG, "Compat change reported: " + changeId + "; UID " + Process.myUid());
+        // TODO log via StatsLog
+    }
+
+    protected boolean isChangeEnabled(long changeId) {
+        if (Arrays.binarySearch(mDisabledChanges, changeId) < 0) {
+            // Not present in the disabled array
+            reportChange(changeId);
+            return true;
+        }
+        return false;
+    }
+
+}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 416aaa3..0478ac8 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -635,7 +635,7 @@
     @Override
     public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
         try {
-            return mPM.isPermissionRevokedByPolicy(permName, pkgName, getUserId());
+            return mPermissionManager.isPermissionRevokedByPolicy(permName, pkgName, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -795,10 +795,11 @@
 
     @Override
     @UnsupportedAppUsage
-    public boolean shouldShowRequestPermissionRationale(String permission) {
+    public boolean shouldShowRequestPermissionRationale(String permName) {
         try {
-            return mPM.shouldShowRequestPermissionRationale(permission,
-                    mContext.getPackageName(), getUserId());
+            final String packageName = mContext.getPackageName();
+            return mPermissionManager
+                    .shouldShowRequestPermissionRationale(permName, packageName, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2049,7 +2050,7 @@
     @Override
     public String getDefaultBrowserPackageNameAsUser(int userId) {
         try {
-            return mPM.getDefaultBrowserPackageName(userId);
+            return mPermissionManager.getDefaultBrowser(userId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2058,7 +2059,7 @@
     @Override
     public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
         try {
-            return mPM.setDefaultBrowserPackageName(packageName, userId);
+            return mPermissionManager.setDefaultBrowser(packageName, userId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 2957309..47b784b 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -153,6 +153,7 @@
     void moveTaskToFront(in IApplicationThread app, in String callingPackage, int task,
             int flags, in Bundle options);
     int getTaskForActivity(in IBinder token, in boolean onlyRoot);
+    /** Finish all activities that were started for result from the specified activity. */
     void finishSubActivity(in IBinder token, in String resultWho, int requestCode);
     ParceledListSlice getRecentTasks(int maxNum, int flags, int userId);
     boolean willActivityBeVisible(in IBinder token);
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 66c4383..cfa065b 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -73,7 +73,7 @@
             boolean restrictedBackupMode, boolean persistent, in Configuration config,
             in CompatibilityInfo compatInfo, in Map services,
             in Bundle coreSettings, in String buildSerial, in AutofillOptions autofillOptions,
-            in ContentCaptureOptions contentCaptureOptions);
+            in ContentCaptureOptions contentCaptureOptions, in long[] disabledCompatChanges);
     void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs);
     void scheduleExit();
     void scheduleServiceArgs(IBinder token, in ParceledListSlice args);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ccea964..5aa1f8f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8101,8 +8101,7 @@
          */
         @Override
         public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
-            RemoteViews expanded = makeMediaBigContentView();
-            return expanded != null ? expanded : makeMediaContentView();
+            return makeMediaContentView();
         }
 
         /** @hide */
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 0f8976f..9162626 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.SharedPreferences;
@@ -25,6 +26,7 @@
 import android.system.Os;
 import android.system.StructStat;
 import android.system.StructTimespec;
+import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -92,6 +94,10 @@
     private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
             new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
 
+    @GuardedBy("mLock")
+    private final WeakHashMap<OnSharedPreferencesClearListener, Object> mClearListeners =
+            new WeakHashMap<>();
+
     /** Current memory state (always increasing) */
     @GuardedBy("this")
     private long mCurrentMemoryStateGeneration;
@@ -252,6 +258,28 @@
         }
     }
 
+    @Override
+    public void registerOnSharedPreferencesClearListener(
+            @NonNull OnSharedPreferencesClearListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener cannot be null.");
+        }
+        synchronized (mLock) {
+            mClearListeners.put(listener, CONTENT);
+        }
+    }
+
+    @Override
+    public void unregisterOnSharedPreferencesClearListener(
+            @NonNull OnSharedPreferencesClearListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener cannot be null.");
+        }
+        synchronized (mLock) {
+            mClearListeners.remove(listener);
+        }
+    }
+
     @GuardedBy("mLock")
     private void awaitLoadedLocked() {
         if (!mLoaded) {
@@ -361,7 +389,9 @@
     private static class MemoryCommitResult {
         final long memoryStateGeneration;
         @Nullable final List<String> keysModified;
+        @Nullable final Set<String> keysCleared;
         @Nullable final Set<OnSharedPreferenceChangeListener> listeners;
+        @Nullable final Set<OnSharedPreferencesClearListener> clearListeners;
         final Map<String, Object> mapToWriteToDisk;
         final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);
 
@@ -371,10 +401,14 @@
 
         private MemoryCommitResult(long memoryStateGeneration, @Nullable List<String> keysModified,
                 @Nullable Set<OnSharedPreferenceChangeListener> listeners,
+                @Nullable Set<String> keysCleared,
+                @Nullable Set<OnSharedPreferencesClearListener> clearListeners,
                 Map<String, Object> mapToWriteToDisk) {
             this.memoryStateGeneration = memoryStateGeneration;
             this.keysModified = keysModified;
             this.listeners = listeners;
+            this.keysCleared = keysCleared;
+            this.clearListeners = clearListeners;
             this.mapToWriteToDisk = mapToWriteToDisk;
         }
 
@@ -492,13 +526,16 @@
             // SharedPreferences instance back, which has the
             // changes reflected in memory.
             notifyListeners(mcr);
+            notifyClearListeners(mcr);
         }
 
         // Returns true if any changes were made
         private MemoryCommitResult commitToMemory() {
             long memoryStateGeneration;
             List<String> keysModified = null;
+            Set<String> keysCleared = null;
             Set<OnSharedPreferenceChangeListener> listeners = null;
+            Set<OnSharedPreferencesClearListener> clearListeners = null;
             Map<String, Object> mapToWriteToDisk;
 
             synchronized (SharedPreferencesImpl.this.mLock) {
@@ -520,12 +557,20 @@
                     keysModified = new ArrayList<String>();
                     listeners = new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
                 }
+                boolean hasClearListeners = !mClearListeners.isEmpty();
+                if (hasClearListeners) {
+                    keysCleared = new ArraySet<>();
+                    clearListeners = new HashSet<>(mClearListeners.keySet());
+                }
 
                 synchronized (mEditorLock) {
                     boolean changesMade = false;
 
                     if (mClear) {
                         if (!mapToWriteToDisk.isEmpty()) {
+                            if (hasClearListeners) {
+                                keysCleared.addAll(mapToWriteToDisk.keySet());
+                            }
                             changesMade = true;
                             mapToWriteToDisk.clear();
                         }
@@ -569,7 +614,7 @@
                 }
             }
             return new MemoryCommitResult(memoryStateGeneration, keysModified, listeners,
-                    mapToWriteToDisk);
+                    keysCleared, clearListeners, mapToWriteToDisk);
         }
 
         @Override
@@ -596,6 +641,7 @@
                 }
             }
             notifyListeners(mcr);
+            notifyClearListeners(mcr);
             return mcr.writeToDiskResult;
         }
 
@@ -618,6 +664,24 @@
                 ActivityThread.sMainThreadHandler.post(() -> notifyListeners(mcr));
             }
         }
+
+        private void notifyClearListeners(final MemoryCommitResult mcr) {
+            if (mcr.clearListeners == null || mcr.keysCleared == null
+                    || mcr.keysCleared.isEmpty()) {
+                return;
+            }
+            if (Looper.myLooper() == Looper.getMainLooper()) {
+                for (OnSharedPreferencesClearListener listener : mcr.clearListeners) {
+                    if (listener != null) {
+                        listener.onSharedPreferencesClear(SharedPreferencesImpl.this,
+                                mcr.keysCleared);
+                    }
+                }
+            } else {
+                // Run this function on the main thread.
+                ActivityThread.sMainThreadHandler.post(() -> notifyClearListeners(mcr));
+            }
+        }
     }
 
     /**
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index 88e2c22..fdef2a1 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -892,12 +892,6 @@
         mItems.add(item);
     }
 
-    /** @removed use #addItem(ContentResolver, Item) instead */
-    @Deprecated
-    public void addItem(Item item, ContentResolver resolver) {
-        addItem(resolver, item);
-    }
-
     /**
      * Add a new Item to the overall ClipData container.
      * <p> Unlike {@link #addItem(Item)}, this method will update the list of available MIME types
diff --git a/core/java/android/content/SharedPreferences.java b/core/java/android/content/SharedPreferences.java
index 877dfee..9d87e25 100644
--- a/core/java/android/content/SharedPreferences.java
+++ b/core/java/android/content/SharedPreferences.java
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 
 import java.util.Map;
@@ -58,7 +59,9 @@
          * <p>This callback will be run on your main thread.
          *
          * <p><em>Note: This callback will not be triggered when preferences are cleared via
-         * {@link Editor#clear()}.</em>
+         * {@link Editor#clear()}. However, from {@link android.os.Build.VERSION_CODES#R Android R}
+         * onwards, you can use {@link OnSharedPreferencesClearListener} to register for
+         * {@link Editor#clear()} callbacks.</em>
          *
          * @param sharedPreferences The {@link SharedPreferences} that received
          *            the change.
@@ -67,7 +70,23 @@
          */
         void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
     }
-    
+
+    /**
+     * Interface definition for a callback to be invoked when shared preferences are cleared.
+     */
+    public interface OnSharedPreferencesClearListener {
+        /**
+         * Called when shared preferences are cleared via {@link Editor#clear()}.
+         *
+         * <p>This callback will be run on your main thread.
+         *
+         * @param sharedPreferences The {@link SharedPreferences} that received the change.
+         * @param keys The set of keys that were cleared.
+         */
+        void onSharedPreferencesClear(@NonNull SharedPreferences sharedPreferences,
+                @NonNull Set<String> keys);
+    }
+
     /**
      * Interface used for modifying values in a {@link SharedPreferences}
      * object.  All changes you make in an editor are batched, and not copied
@@ -378,12 +397,43 @@
      * @see #unregisterOnSharedPreferenceChangeListener
      */
     void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
-    
+
     /**
      * Unregisters a previous callback.
-     * 
+     *
      * @param listener The callback that should be unregistered.
      * @see #registerOnSharedPreferenceChangeListener
      */
     void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
+
+    /**
+     * Registers a callback to be invoked when preferences are cleared via {@link Editor#clear()}.
+     *
+     * <p class="caution"><strong>Caution:</strong> The preference manager does
+     * not currently store a strong reference to the listener. You must store a
+     * strong reference to the listener, or it will be susceptible to garbage
+     * collection. We recommend you keep a reference to the listener in the
+     * instance data of an object that will exist as long as you need the
+     * listener.</p>
+     *
+     * @param listener The callback that will run.
+     * @see #unregisterOnSharedPreferencesClearListener
+     */
+    default void registerOnSharedPreferencesClearListener(
+            @NonNull OnSharedPreferencesClearListener listener) {
+        throw new UnsupportedOperationException(
+                "registerOnSharedPreferencesClearListener not implemented");
+    }
+
+    /**
+     * Unregisters a previous callback for {@link Editor#clear()}.
+     *
+     * @param listener The callback that should be unregistered.
+     * @see #registerOnSharedPreferencesClearListener
+     */
+    default void unregisterOnSharedPreferencesClearListener(
+            @NonNull OnSharedPreferencesClearListener listener) {
+        throw new UnsupportedOperationException(
+                "unregisterOnSharedPreferencesClearListener not implemented");
+    }
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index f75cd23..d0a61eb 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -614,10 +614,10 @@
 
     /**
      * Value for {@link #privateFlags}: whether this app is pre-installed on the
-     * google partition of the system image.
+     * system_ext partition of the system image.
      * @hide
      */
-    public static final int PRIVATE_FLAG_PRODUCT_SERVICES = 1 << 21;
+    public static final int PRIVATE_FLAG_SYSTEM_EXT = 1 << 21;
 
     /**
      * Indicates whether this package requires access to non-SDK APIs.
@@ -713,7 +713,7 @@
             PRIVATE_FLAG_USE_EMBEDDED_DEX,
             PRIVATE_FLAG_PRIVILEGED,
             PRIVATE_FLAG_PRODUCT,
-            PRIVATE_FLAG_PRODUCT_SERVICES,
+            PRIVATE_FLAG_SYSTEM_EXT,
             PRIVATE_FLAG_PROFILEABLE_BY_SHELL,
             PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
             PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY,
@@ -2046,8 +2046,8 @@
     }
 
     /** @hide */
-    public boolean isProductServices() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
+    public boolean isSystemExt() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0;
     }
 
     /** @hide */
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 904bd16..c6beee2 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -94,8 +94,6 @@
 
     @UnsupportedAppUsage
     ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);
-    boolean shouldShowRequestPermissionRationale(String permName,
-            String packageName, int userId);
 
     boolean isProtectedBroadcast(String actionName);
 
@@ -594,18 +592,12 @@
     ParceledListSlice getIntentFilterVerifications(String packageName);
     ParceledListSlice getAllIntentFilters(String packageName);
 
-    boolean setDefaultBrowserPackageName(String packageName, int userId);
-    String getDefaultBrowserPackageName(int userId);
-
     VerifierDeviceIdentity getVerifierDeviceIdentity();
 
     boolean isFirstBoot();
     boolean isOnlyCoreApps();
     boolean isDeviceUpgrading();
 
-    void setPermissionEnforced(String permission, boolean enforced);
-    boolean isPermissionEnforced(String permission);
-
     /** Reflects current DeviceStorageMonitorService state */
     @UnsupportedAppUsage
     boolean isStorageLow();
@@ -629,17 +621,6 @@
     boolean isPackageSignedByKeySet(String packageName, in KeySet ks);
     boolean isPackageSignedByKeySetExactly(String packageName, in KeySet ks);
 
-    void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId);
-    void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId);
-    void grantDefaultPermissionsToEnabledTelephonyDataServices(
-            in String[] packageNames, int userId);
-    void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
-            in String[] packageNames, int userId);
-    void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId);
-    void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId);
-
-    boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId);
-
     @UnsupportedAppUsage
     String getPermissionControllerPackageName();
 
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 3cecd7f..1099d8b 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1565,7 +1565,7 @@
         }
 
         /** {@hide} */
-        @SystemApi
+        @SystemApi @TestApi
         public void setRequestDowngrade(boolean requestDowngrade) {
             if (requestDowngrade) {
                 installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b845a37..4d8a0c4 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3571,7 +3571,7 @@
     /**
      * Retrieve all of the information we know about a particular permission.
      *
-     * @param permissionName The fully qualified name (i.e. com.google.permission.LOGIN)
+     * @param permName The fully qualified name (i.e. com.google.permission.LOGIN)
      *            of the permission you are interested in.
      * @param flags Additional option flags to modify the data returned.
      * @return Returns a {@link PermissionInfo} containing information about the
@@ -3579,7 +3579,7 @@
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
      */
-    public abstract PermissionInfo getPermissionInfo(@NonNull String permissionName,
+    public abstract PermissionInfo getPermissionInfo(@NonNull String permName,
             @PermissionInfoFlags int flags) throws NameNotFoundException;
 
     /**
@@ -3620,7 +3620,7 @@
      * Retrieve all of the information we know about a particular group of
      * permissions.
      *
-     * @param permissionName The fully qualified name (i.e.
+     * @param permName The fully qualified name (i.e.
      *            com.google.permission_group.APPS) of the permission you are
      *            interested in.
      * @param flags Additional option flags to modify the data returned.
@@ -3630,7 +3630,7 @@
      *             found on the system.
      */
     @NonNull
-    public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String permissionName,
+    public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String permName,
             @PermissionGroupInfoFlags int flags) throws NameNotFoundException;
 
     /**
@@ -3858,7 +3858,7 @@
      * Check whether a particular package has been granted a particular
      * permission.
      *
-     * @param permissionName The name of the permission you are checking for.
+     * @param permName The name of the permission you are checking for.
      * @param packageName The name of the package you are checking against.
      *
      * @return If the package has the permission, PERMISSION_GRANTED is
@@ -3870,7 +3870,7 @@
      */
     @CheckResult
     @PermissionResult
-    public abstract int checkPermission(@NonNull String permissionName,
+    public abstract int checkPermission(@NonNull String permName,
             @NonNull String packageName);
 
     /**
@@ -3880,13 +3880,13 @@
      * permissions, hence the only way for an app to get such a permission
      * is by a policy change.
      *
-     * @param permissionName The name of the permission you are checking for.
+     * @param permName The name of the permission you are checking for.
      * @param packageName The name of the package you are checking against.
      *
      * @return Whether the permission is restricted by policy.
      */
     @CheckResult
-    public abstract boolean isPermissionRevokedByPolicy(@NonNull String permissionName,
+    public abstract boolean isPermissionRevokedByPolicy(@NonNull String permName,
             @NonNull String packageName);
 
     /**
@@ -3949,14 +3949,14 @@
      * -- you are only allowed to remove permissions that you are allowed
      * to add.
      *
-     * @param permissionName The name of the permission to remove.
+     * @param permName The name of the permission to remove.
      *
      * @throws SecurityException if you are not allowed to remove the
      * given permission name.
      *
      * @see #addPermission(PermissionInfo)
      */
-    public abstract void removePermission(@NonNull String permissionName);
+    public abstract void removePermission(@NonNull String permName);
 
     /**
      * Permission flags set when granting or revoking a permission.
@@ -3998,7 +3998,7 @@
      * </p>
      *
      * @param packageName The package to which to grant the permission.
-     * @param permissionName The permission name to grant.
+     * @param permName The permission name to grant.
      * @param user The user for which to grant the permission.
      *
      * @see #revokeRuntimePermission(String, String, android.os.UserHandle)
@@ -4009,7 +4009,7 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
     public abstract void grantRuntimePermission(@NonNull String packageName,
-            @NonNull String permissionName, @NonNull UserHandle user);
+            @NonNull String permName, @NonNull UserHandle user);
 
     /**
      * Revoke a runtime permission that was previously granted by {@link
@@ -4025,7 +4025,7 @@
      * </p>
      *
      * @param packageName The package from which to revoke the permission.
-     * @param permissionName The permission name to revoke.
+     * @param permName The permission name to revoke.
      * @param user The user for which to revoke the permission.
      *
      * @see #grantRuntimePermission(String, String, android.os.UserHandle)
@@ -4036,12 +4036,12 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
     public abstract void revokeRuntimePermission(@NonNull String packageName,
-            @NonNull String permissionName, @NonNull UserHandle user);
+            @NonNull String permName, @NonNull UserHandle user);
 
     /**
      * Gets the state flags associated with a permission.
      *
-     * @param permissionName The permission for which to get the flags.
+     * @param permName The permission for which to get the flags.
      * @param packageName The package name for which to get the flags.
      * @param user The user for which to get permission flags.
      * @return The permission flags.
@@ -4056,14 +4056,14 @@
             android.Manifest.permission.GET_RUNTIME_PERMISSIONS
     })
     @PermissionFlags
-    public abstract int getPermissionFlags(@NonNull String permissionName,
+    public abstract int getPermissionFlags(@NonNull String permName,
             @NonNull String packageName, @NonNull UserHandle user);
 
     /**
      * Updates the flags associated with a permission by replacing the flags in
      * the specified mask with the provided flag values.
      *
-     * @param permissionName The permission for which to update the flags.
+     * @param permName The permission for which to update the flags.
      * @param packageName The package name for which to update the flags.
      * @param flagMask The flags which to replace.
      * @param flagValues The flags with which to replace.
@@ -4077,7 +4077,7 @@
             android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
             android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
     })
-    public abstract void updatePermissionFlags(@NonNull String permissionName,
+    public abstract void updatePermissionFlags(@NonNull String permName,
             @NonNull String packageName, @PermissionFlags int flagMask,
             @PermissionFlags int flagValues, @NonNull UserHandle user);
 
@@ -4164,7 +4164,7 @@
      * provided ones.
      *
      * @param packageName The app for which to get whitelisted permissions.
-     * @param permission The whitelisted permission to add.
+     * @param permName The whitelisted permission to add.
      * @param whitelistFlags The whitelists to which to add. Passing multiple flags
      * updates all specified whitelists.
      * @return Whether the permission was added to the whitelist.
@@ -4180,7 +4180,7 @@
     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
             conditional = true)
     public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
-            @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags) {
+            @NonNull String permName, @PermissionWhitelistFlags int whitelistFlags) {
         return false;
     }
 
@@ -4218,7 +4218,7 @@
      * provided ones.
      *
      * @param packageName The app for which to get whitelisted permissions.
-     * @param permission The whitelisted permission to remove.
+     * @param permName The whitelisted permission to remove.
      * @param whitelistFlags The whitelists from which to remove. Passing multiple flags
      * updates all specified whitelists.
      * @return Whether the permission was removed from the whitelist.
@@ -4234,7 +4234,7 @@
     @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
         conditional = true)
     public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
-        @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags) {
+            @NonNull String permName, @PermissionWhitelistFlags int whitelistFlags) {
         return false;
     }
 
@@ -4244,13 +4244,13 @@
      * which the permission is requested does not clearly communicate to the user
      * what would be the benefit from grating this permission.
      *
-     * @param permissionName A permission your app wants to request.
+     * @param permName A permission your app wants to request.
      * @return Whether you can show permission rationale UI.
      *
      * @hide
      */
     @UnsupportedAppUsage
-    public abstract boolean shouldShowRequestPermissionRationale(@NonNull String permissionName);
+    public abstract boolean shouldShowRequestPermissionRationale(@NonNull String permName);
 
     /**
      * Returns an {@link android.content.Intent} suitable for passing to
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index e21d4c41..2f198ac 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -84,139 +84,6 @@
     }
 
     /**
-     * Provider for package names.
-     */
-    public interface PackagesProvider {
-
-        /**
-         * Gets the packages for a given user.
-         * @param userId The user id.
-         * @return The package names.
-         */
-        public String[] getPackages(int userId);
-    }
-
-    /**
-     * Provider for package names.
-     */
-    public interface SyncAdapterPackagesProvider {
-
-        /**
-         * Gets the sync adapter packages for given authority and user.
-         * @param authority The authority.
-         * @param userId The user id.
-         * @return The package names.
-         */
-        public String[] getPackages(String authority, int userId);
-    }
-
-    /**
-     * Provider for default browser
-     */
-    public interface DefaultBrowserProvider {
-
-        /**
-         * Get the package name of the default browser.
-         *
-         * @param userId the user id
-         *
-         * @return the package name of the default browser, or {@code null} if none
-         */
-        @Nullable
-        String getDefaultBrowser(@UserIdInt int userId);
-
-        /**
-         * Set the package name of the default browser.
-         *
-         * @param packageName package name of the default browser, or {@code null} to remove
-         * @param userId the user id
-         *
-         * @return whether the default browser was successfully set.
-         */
-        boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId);
-
-        /**
-         * Set the package name of the default browser asynchronously.
-         *
-         * @param packageName package name of the default browser, or {@code null} to remove
-         * @param userId the user id
-         */
-        void setDefaultBrowserAsync(@Nullable String packageName, @UserIdInt int userId);
-    }
-
-    /**
-     * Provider for default dialer
-     */
-    public interface DefaultDialerProvider {
-
-        /**
-         * Get the package name of the default dialer.
-         *
-         * @param userId the user id
-         *
-         * @return the package name of the default dialer, or {@code null} if none
-         */
-        @Nullable
-        String getDefaultDialer(@UserIdInt int userId);
-    }
-
-    /**
-     * Provider for default home
-     */
-    public interface DefaultHomeProvider {
-
-        /**
-         * Get the package name of the default home.
-         *
-         * @param userId the user id
-         *
-         * @return the package name of the default home, or {@code null} if none
-         */
-        @Nullable
-        String getDefaultHome(@UserIdInt int userId);
-
-        /**
-         * Set the package name of the default home.
-         *
-         * @param packageName package name of the default home, or {@code null} to remove
-         * @param userId the user id
-         * @param callback the callback made after the default home as been updated
-         */
-        void setDefaultHomeAsync(@Nullable String packageName, @UserIdInt int userId,
-                @NonNull Consumer<Boolean> callback);
-    }
-
-    /**
-     * Sets the location provider packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setLocationPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Set the location extra packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract  void setLocationExtraPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the voice interaction packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the Use Open Wifi packages provider.
-     * @param provider The packages provider.
-     */
-    public abstract void setUseOpenWifiAppPackagesProvider(PackagesProvider provider);
-
-    /**
-     * Sets the sync adapter packages provider.
-     * @param provider The provider.
-     */
-    public abstract void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider);
-
-    /**
      * Called when the package for the default SMS handler changed
      *
      * @param packageName the new sms package
@@ -233,14 +100,6 @@
     public void onDefaultSimCallManagerAppChanged(String packageName, int userId) {}
 
     /**
-     * Requests granting of the default permissions to the current default Use Open Wifi app.
-     * @param packageName The default use open wifi package name.
-     * @param userId The user for which to grant the permissions.
-     */
-    public abstract void grantDefaultPermissionsToDefaultUseOpenWifiApp(String packageName,
-            int userId);
-
-    /**
      * Sets a list of apps to keep in PM's internal data structures and as APKs even if no user has
      * currently installed it. The apps are not preloaded.
      * @param packageList List of package names to keep cached.
@@ -697,7 +556,15 @@
      * @see #canAccessInstantApps
      */
     public abstract boolean filterAppAccess(
-            @Nullable PackageParser.Package pkg, int callingUid, int userId);
+            @NonNull PackageParser.Package pkg, int callingUid, int userId);
+
+    /**
+     * Returns whether or not access to the application should be filtered.
+     *
+     * @see #filterAppAccess(android.content.pm.PackageParser.Package, int, int)
+     */
+    public abstract boolean filterAppAccess(
+            @NonNull String packageName, int callingUid, int userId);
 
     /** Returns whether the given package was signed by the platform */
     public abstract boolean isPlatformSigned(String pkg);
@@ -872,27 +739,6 @@
     public abstract String removeLegacyDefaultBrowserPackageName(int userId);
 
     /**
-     * Sets the default browser provider.
-     *
-     * @param provider the provider
-     */
-    public abstract void setDefaultBrowserProvider(@NonNull DefaultBrowserProvider provider);
-
-    /**
-     * Sets the default dialer provider.
-     *
-     * @param provider the provider
-     */
-    public abstract void setDefaultDialerProvider(@NonNull DefaultDialerProvider provider);
-
-    /**
-     * Sets the default home provider.
-     *
-     * @param provider the provider
-     */
-    public abstract void setDefaultHomeProvider(@NonNull DefaultHomeProvider provider);
-
-    /**
      * Returns {@code true} if given {@code packageName} is an apex package.
      */
     public abstract boolean isApexPackage(String packageName);
@@ -910,15 +756,6 @@
             IntentSender intentSender);
 
     /**
-     * Whether default permission grants have been performed for a user
-     * since the device booted.
-     *
-     * @param userId The user id.
-     * @return true if default permissions
-     */
-    public abstract boolean wereDefaultPermissionsGrantedSinceBoot(int userId);
-
-    /**
      * Get fingerprint of build that updated the runtime permissions for a user.
      *
      * @param userId The user to update
@@ -960,4 +797,10 @@
      */
     public abstract boolean isCallerInstallerOfRecord(
             @NonNull PackageParser.Package pkg, int callingUid);
+
+    /** Returns whether or not default runtime permissions are granted for the given user */
+    public abstract boolean areDefaultRuntimePermissionsGranted(@UserIdInt int userId);
+
+    /** Sets the enforcement of reading external storage */
+    public abstract void setReadExternalStorageEnforced(boolean enforced);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a74c34f..e690a7f 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -254,6 +254,8 @@
 
     /** @hide */
     public static final String APK_FILE_EXTENSION = ".apk";
+    /** @hide */
+    public static final String APEX_FILE_EXTENSION = ".apex";
 
     /** @hide */
     public static class NewPermissionInfo {
@@ -6897,8 +6899,8 @@
         }
 
         /** @hide */
-        public boolean isProductServices() {
-            return applicationInfo.isProductServices();
+        public boolean isSystemExt() {
+            return applicationInfo.isSystemExt();
         }
 
         /** @hide */
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 2b1b32e..7865d75 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -19,7 +19,6 @@
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 
@@ -232,7 +231,7 @@
         if (isManagedProfile() || isGuest() || isRestricted()) {
             return false;
         }
-        if (UserManager.isSplitSystemUser()) {
+        if (UserManager.isSplitSystemUser() || UserManager.isHeadlessSystemUserMode()) {
             return id != UserHandle.USER_SYSTEM;
         } else {
             return id == UserHandle.USER_SYSTEM;
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index a99a0b5..f3b7553 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -32,8 +32,8 @@
 import android.view.WindowManager.LayoutParams;
 
 /**
- * CompatibilityInfo class keeps the information about compatibility mode that the application is
- * running under.
+ * CompatibilityInfo class keeps the information about the screen compatibility mode that the
+ * application is running under.
  * 
  *  {@hide} 
  */
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 3523e95..48d8867 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -30,11 +30,14 @@
 import android.util.ArrayMap;
 import android.util.Log;
 
+import com.android.internal.util.ArrayUtils;
+
 import libcore.util.EmptyArray;
 
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
@@ -49,14 +52,11 @@
 public class SQLiteQueryBuilder {
     private static final String TAG = "SQLiteQueryBuilder";
 
-    private static final Pattern sLimitPattern =
-            Pattern.compile("\\s*\\d+\\s*(,\\s*\\d+\\s*)?");
     private static final Pattern sAggregationPattern = Pattern.compile(
             "(?i)(AVG|COUNT|MAX|MIN|SUM|TOTAL|GROUP_CONCAT)\\((.+)\\)");
 
     private Map<String, String> mProjectionMap = null;
     private List<Pattern> mProjectionGreylist = null;
-    private boolean mProjectionAggregationAllowed = false;
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private String mTables = "";
@@ -65,7 +65,12 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private boolean mDistinct;
     private SQLiteDatabase.CursorFactory mFactory;
-    private boolean mStrict;
+
+    private static final int STRICT_PARENTHESES = 1 << 0;
+    private static final int STRICT_COLUMNS = 1 << 1;
+    private static final int STRICT_GRAMMAR = 1 << 2;
+
+    private int mStrictFlags;
 
     public SQLiteQueryBuilder() {
         mDistinct = false;
@@ -209,13 +214,14 @@
     }
 
     /** {@hide} */
+    @Deprecated
     public void setProjectionAggregationAllowed(boolean projectionAggregationAllowed) {
-        mProjectionAggregationAllowed = projectionAggregationAllowed;
     }
 
     /** {@hide} */
+    @Deprecated
     public boolean isProjectionAggregationAllowed() {
-        return mProjectionAggregationAllowed;
+        return true;
     }
 
     /**
@@ -258,8 +264,12 @@
      * </ul>
      * By default, this value is false.
      */
-    public void setStrict(boolean flag) {
-        mStrict = flag;
+    public void setStrict(boolean strict) {
+        if (strict) {
+            mStrictFlags |= STRICT_PARENTHESES;
+        } else {
+            mStrictFlags &= ~STRICT_PARENTHESES;
+        }
     }
 
     /**
@@ -267,7 +277,67 @@
      * {@link #setStrict(boolean)}.
      */
     public boolean isStrict() {
-        return mStrict;
+        return (mStrictFlags & STRICT_PARENTHESES) != 0;
+    }
+
+    /**
+     * When enabled, verify that all projections and {@link ContentValues} only
+     * contain valid columns as defined by {@link #setProjectionMap(Map)}.
+     * <p>
+     * This enforcement applies to {@link #insert}, {@link #query}, and
+     * {@link #update} operations. Any enforcement failures will throw an
+     * {@link IllegalArgumentException}.
+     */
+    public void setStrictColumns(boolean strictColumns) {
+        if (strictColumns) {
+            mStrictFlags |= STRICT_COLUMNS;
+        } else {
+            mStrictFlags &= ~STRICT_COLUMNS;
+        }
+    }
+
+    /**
+     * Get if the query is marked as strict, as last configured by
+     * {@link #setStrictColumns(boolean)}.
+     */
+    public boolean isStrictColumns() {
+        return (mStrictFlags & STRICT_COLUMNS) != 0;
+    }
+
+    /**
+     * When enabled, verify that all untrusted SQL conforms to a restricted SQL
+     * grammar. Here are the restrictions applied:
+     * <ul>
+     * <li>In {@code WHERE} and {@code HAVING} clauses: subqueries, raising, and
+     * windowing terms are rejected.
+     * <li>In {@code GROUP BY} clauses: only valid columns are allowed.
+     * <li>In {@code ORDER BY} clauses: only valid columns, collation, and
+     * ordering terms are allowed.
+     * <li>In {@code LIMIT} clauses: only numerical values and offset terms are
+     * allowed.
+     * </ul>
+     * All column references must be valid as defined by
+     * {@link #setProjectionMap(Map)}.
+     * <p>
+     * This enforcement applies to {@link #query}, {@link #update} and
+     * {@link #delete} operations. This enforcement does not apply to trusted
+     * inputs, such as those provided by {@link #appendWhere}. Any enforcement
+     * failures will throw an {@link IllegalArgumentException}.
+     */
+    public void setStrictGrammar(boolean strictGrammar) {
+        if (strictGrammar) {
+            mStrictFlags |= STRICT_GRAMMAR;
+        } else {
+            mStrictFlags &= ~STRICT_GRAMMAR;
+        }
+    }
+
+    /**
+     * Get if the query is marked as strict, as last configured by
+     * {@link #setStrictGrammar(boolean)}.
+     */
+    public boolean isStrictGrammar() {
+        return (mStrictFlags & STRICT_GRAMMAR) != 0;
     }
 
     /**
@@ -303,9 +373,6 @@
             throw new IllegalArgumentException(
                     "HAVING clauses are only permitted when using a groupBy clause");
         }
-        if (!TextUtils.isEmpty(limit) && !sLimitPattern.matcher(limit).matches()) {
-            throw new IllegalArgumentException("invalid LIMIT clauses:" + limit);
-        }
 
         StringBuilder query = new StringBuilder(120);
 
@@ -479,7 +546,13 @@
                 projectionIn, selection, groupBy, having,
                 sortOrder, limit);
 
-        if (mStrict && selection != null && selection.length() > 0) {
+        if (isStrictColumns()) {
+            enforceStrictColumns(projectionIn);
+        }
+        if (isStrictGrammar()) {
+            enforceStrictGrammar(selection, groupBy, having, sortOrder, limit);
+        }
+        if (isStrict()) {
             // Validate the user-supplied selection to detect syntactic anomalies
             // in the selection string that could indicate a SQL injection attempt.
             // The idea is to ensure that the selection clause is a valid SQL expression
@@ -497,7 +570,7 @@
 
             // Execute wrapped query for extra protection
             final String wrappedSql = buildQuery(projectionIn, wrap(selection), groupBy,
-                    having, sortOrder, limit);
+                    wrap(having), sortOrder, limit);
             sql = wrappedSql;
         } else {
             // Execute unwrapped query
@@ -519,6 +592,40 @@
     }
 
     /**
+     * Perform an insert by combining all current settings and the
+     * information passed into this method.
+     *
+     * @param db the database to insert on
+     * @return the row ID of the newly inserted row, or -1 if an error occurred
+     */
+    public long insert(@NonNull SQLiteDatabase db, @NonNull ContentValues values) {
+        Objects.requireNonNull(mTables, "No tables defined");
+        Objects.requireNonNull(db, "No database defined");
+        Objects.requireNonNull(values, "No values defined");
+
+        if (isStrictColumns()) {
+            enforceStrictColumns(values);
+        }
+
+        final String sql = buildInsert(values);
+
+        final ArrayMap<String, Object> rawValues = values.getValues();
+        final int valuesLength = rawValues.size();
+        final Object[] sqlArgs = new Object[valuesLength];
+        for (int i = 0; i < sqlArgs.length; i++) {
+            sqlArgs[i] = rawValues.valueAt(i);
+        }
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            if (Build.IS_DEBUGGABLE) {
+                Log.d(TAG, sql + " with args " + Arrays.toString(sqlArgs));
+            } else {
+                Log.d(TAG, sql);
+            }
+        }
+        return db.executeSql(sql, sqlArgs);
+    }
+
+    /**
      * Perform an update by combining all current settings and the
      * information passed into this method.
      *
@@ -541,7 +648,13 @@
         final String sql;
         final String unwrappedSql = buildUpdate(values, selection);
 
-        if (mStrict) {
+        if (isStrictColumns()) {
+            enforceStrictColumns(values);
+        }
+        if (isStrictGrammar()) {
+            enforceStrictGrammar(selection, null, null, null, null);
+        }
+        if (isStrict()) {
             // Validate the user-supplied selection to detect syntactic anomalies
             // in the selection string that could indicate a SQL injection attempt.
             // The idea is to ensure that the selection clause is a valid SQL expression
@@ -610,7 +723,10 @@
         final String sql;
         final String unwrappedSql = buildDelete(selection);
 
-        if (mStrict) {
+        if (isStrictGrammar()) {
+            enforceStrictGrammar(selection, null, null, null, null);
+        }
+        if (isStrict()) {
             // Validate the user-supplied selection to detect syntactic anomalies
             // in the selection string that could indicate a SQL injection attempt.
             // The idea is to ensure that the selection clause is a valid SQL expression
@@ -645,6 +761,81 @@
         return db.executeSql(sql, sqlArgs);
     }
 
+    private void enforceStrictColumns(@Nullable String[] projection) {
+        Objects.requireNonNull(mProjectionMap, "No projection map defined");
+
+        computeProjection(projection);
+    }
+
+    private void enforceStrictColumns(@NonNull ContentValues values) {
+        Objects.requireNonNull(mProjectionMap, "No projection map defined");
+
+        final ArrayMap<String, Object> rawValues = values.getValues();
+        for (int i = 0; i < rawValues.size(); i++) {
+            final String column = rawValues.keyAt(i);
+            if (!mProjectionMap.containsKey(column)) {
+                throw new IllegalArgumentException("Invalid column " + column);
+            }
+        }
+    }
+
+    private void enforceStrictGrammar(@Nullable String selection, @Nullable String groupBy,
+            @Nullable String having, @Nullable String sortOrder, @Nullable String limit) {
+        SQLiteTokenizer.tokenize(selection, SQLiteTokenizer.OPTION_NONE,
+                this::enforceStrictGrammarWhereHaving);
+        SQLiteTokenizer.tokenize(groupBy, SQLiteTokenizer.OPTION_NONE,
+                this::enforceStrictGrammarGroupBy);
+        SQLiteTokenizer.tokenize(having, SQLiteTokenizer.OPTION_NONE,
+                this::enforceStrictGrammarWhereHaving);
+        SQLiteTokenizer.tokenize(sortOrder, SQLiteTokenizer.OPTION_NONE,
+                this::enforceStrictGrammarOrderBy);
+        SQLiteTokenizer.tokenize(limit, SQLiteTokenizer.OPTION_NONE,
+                this::enforceStrictGrammarLimit);
+    }
+
+    private void enforceStrictGrammarWhereHaving(@NonNull String token) {
+        if (isTableOrColumn(token)) return;
+        if (SQLiteTokenizer.isFunction(token)) return;
+        if (SQLiteTokenizer.isType(token)) return;
+
+        // NOTE: we explicitly don't allow SELECT subqueries, since they could
+        // leak data that should have been filtered by the trusted where clause
+        switch (token.toUpperCase(Locale.US)) {
+            case "AND": case "AS": case "BETWEEN": case "BINARY":
+            case "CASE": case "CAST": case "COLLATE": case "DISTINCT":
+            case "ELSE": case "END": case "ESCAPE": case "EXISTS":
+            case "GLOB": case "IN": case "IS": case "ISNULL":
+            case "LIKE": case "MATCH": case "NOCASE": case "NOT":
+            case "NOTNULL": case "NULL": case "OR": case "REGEXP":
+            case "RTRIM": case "THEN": case "WHEN":
+                return;
+        }
+        throw new IllegalArgumentException("Invalid token " + token);
+    }
+
+    private void enforceStrictGrammarGroupBy(@NonNull String token) {
+        if (isTableOrColumn(token)) return;
+        throw new IllegalArgumentException("Invalid token " + token);
+    }
+
+    private void enforceStrictGrammarOrderBy(@NonNull String token) {
+        if (isTableOrColumn(token)) return;
+        switch (token.toUpperCase(Locale.US)) {
+            case "COLLATE": case "ASC": case "DESC":
+            case "BINARY": case "RTRIM": case "NOCASE":
+                return;
+        }
+        throw new IllegalArgumentException("Invalid token " + token);
+    }
+
+    private void enforceStrictGrammarLimit(@NonNull String token) {
+        switch (token.toUpperCase(Locale.US)) {
+            case "OFFSET":
+                return;
+        }
+        throw new IllegalArgumentException("Invalid token " + token);
+    }
+
     /**
      * Construct a {@code SELECT} statement suitable for use in a group of
      * {@code SELECT} statements that will be joined through {@code UNION} operators
@@ -698,6 +889,35 @@
     }
 
     /** {@hide} */
+    public String buildInsert(ContentValues values) {
+        if (values == null || values.isEmpty()) {
+            throw new IllegalArgumentException("Empty values");
+        }
+
+        StringBuilder sql = new StringBuilder(120);
+        sql.append("INSERT INTO ");
+        sql.append(SQLiteDatabase.findEditTable(mTables));
+        sql.append(" (");
+
+        final ArrayMap<String, Object> rawValues = values.getValues();
+        for (int i = 0; i < rawValues.size(); i++) {
+            if (i > 0) {
+                sql.append(',');
+            }
+            sql.append(rawValues.keyAt(i));
+        }
+        sql.append(") VALUES (");
+        for (int i = 0; i < rawValues.size(); i++) {
+            if (i > 0) {
+                sql.append(',');
+            }
+            sql.append('?');
+        }
+        sql.append(")");
+        return sql.toString();
+    }
+
+    /** {@hide} */
     public String buildUpdate(ContentValues values, String selection) {
         if (values == null || values.isEmpty()) {
             throw new IllegalArgumentException("Empty values");
@@ -705,7 +925,7 @@
 
         StringBuilder sql = new StringBuilder(120);
         sql.append("UPDATE ");
-        sql.append(mTables);
+        sql.append(SQLiteDatabase.findEditTable(mTables));
         sql.append(" SET ");
 
         final ArrayMap<String, Object> rawValues = values.getValues();
@@ -726,7 +946,7 @@
     public String buildDelete(String selection) {
         StringBuilder sql = new StringBuilder(120);
         sql.append("DELETE FROM ");
-        sql.append(mTables);
+        sql.append(SQLiteDatabase.findEditTable(mTables));
 
         final String where = computeWhere(selection);
         appendClause(sql, " WHERE ", where);
@@ -868,65 +1088,13 @@
 
     /** {@hide} */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public String[] computeProjection(String[] projectionIn) {
-        if (projectionIn != null && projectionIn.length > 0) {
-            if (mProjectionMap != null) {
-                String[] projection = new String[projectionIn.length];
-                int length = projectionIn.length;
-
-                for (int i = 0; i < length; i++) {
-                    String operator = null;
-                    String userColumn = projectionIn[i];
-                    String column = mProjectionMap.get(userColumn);
-
-                    // If aggregation is allowed, extract the underlying column
-                    // that may be aggregated
-                    if (mProjectionAggregationAllowed) {
-                        final Matcher matcher = sAggregationPattern.matcher(userColumn);
-                        if (matcher.matches()) {
-                            operator = matcher.group(1);
-                            userColumn = matcher.group(2);
-                            column = mProjectionMap.get(userColumn);
-                        }
-                    }
-
-                    if (column != null) {
-                        projection[i] = maybeWithOperator(operator, column);
-                        continue;
-                    }
-
-                    if (!mStrict &&
-                            ( userColumn.contains(" AS ") || userColumn.contains(" as "))) {
-                        /* A column alias already exist */
-                        projection[i] = maybeWithOperator(operator, userColumn);
-                        continue;
-                    }
-
-                    // If greylist is configured, we might be willing to let
-                    // this custom column bypass our strict checks.
-                    if (mProjectionGreylist != null) {
-                        boolean match = false;
-                        for (Pattern p : mProjectionGreylist) {
-                            if (p.matcher(userColumn).matches()) {
-                                match = true;
-                                break;
-                            }
-                        }
-
-                        if (match) {
-                            Log.w(TAG, "Allowing abusive custom column: " + userColumn);
-                            projection[i] = maybeWithOperator(operator, userColumn);
-                            continue;
-                        }
-                    }
-
-                    throw new IllegalArgumentException("Invalid column "
-                            + projectionIn[i]);
-                }
-                return projection;
-            } else {
-                return projectionIn;
+    public @Nullable String[] computeProjection(@Nullable String[] projectionIn) {
+        if (!ArrayUtils.isEmpty(projectionIn)) {
+            String[] projectionOut = new String[projectionIn.length];
+            for (int i = 0; i < projectionIn.length; i++) {
+                projectionOut[i] = computeSingleProjectionOrThrow(projectionIn[i]);
             }
+            return projectionOut;
         } else if (mProjectionMap != null) {
             // Return all columns in projection map.
             Set<Entry<String, String>> entrySet = mProjectionMap.entrySet();
@@ -948,6 +1116,69 @@
         return null;
     }
 
+    private @NonNull String computeSingleProjectionOrThrow(@NonNull String userColumn) {
+        final String column = computeSingleProjection(userColumn);
+        if (column != null) {
+            return column;
+        } else {
+            throw new IllegalArgumentException("Invalid column " + userColumn);
+        }
+    }
+
+    private @Nullable String computeSingleProjection(@NonNull String userColumn) {
+        // When no mapping provided, anything goes
+        if (mProjectionMap == null) {
+            return userColumn;
+        }
+
+        String operator = null;
+        String column = mProjectionMap.get(userColumn);
+
+        // When no direct match found, look for aggregation
+        if (column == null) {
+            final Matcher matcher = sAggregationPattern.matcher(userColumn);
+            if (matcher.matches()) {
+                operator = matcher.group(1);
+                userColumn = matcher.group(2);
+                column = mProjectionMap.get(userColumn);
+            }
+        }
+
+        if (column != null) {
+            return maybeWithOperator(operator, column);
+        }
+
+        if (mStrictFlags == 0 &&
+                (userColumn.contains(" AS ") || userColumn.contains(" as "))) {
+            /* A column alias already exist */
+            return maybeWithOperator(operator, userColumn);
+        }
+
+        // If greylist is configured, we might be willing to let
+        // this custom column bypass our strict checks.
+        if (mProjectionGreylist != null) {
+            boolean match = false;
+            for (Pattern p : mProjectionGreylist) {
+                if (p.matcher(userColumn).matches()) {
+                    match = true;
+                    break;
+                }
+            }
+
+            if (match) {
+                Log.w(TAG, "Allowing abusive custom column: " + userColumn);
+                return maybeWithOperator(operator, userColumn);
+            }
+        }
+
+        return null;
+    }
+
+    private boolean isTableOrColumn(String token) {
+        if (mTables.equals(token)) return true;
+        return computeSingleProjection(token) != null;
+    }
+
     /** {@hide} */
     public @Nullable String computeWhere(@Nullable String selection) {
         final boolean hasInternal = !TextUtils.isEmpty(mWhereClause);
diff --git a/core/java/android/database/sqlite/SQLiteTokenizer.java b/core/java/android/database/sqlite/SQLiteTokenizer.java
new file mode 100644
index 0000000..7e7c3fb
--- /dev/null
+++ b/core/java/android/database/sqlite/SQLiteTokenizer.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database.sqlite;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.function.Consumer;
+
+/**
+ * SQL Tokenizer specialized to extract tokens from SQL (snippets).
+ * <p>
+ * Based on sqlite3GetToken() in tokenzie.c in SQLite.
+ * <p>
+ * Source for v3.8.6 (which android uses): http://www.sqlite.org/src/artifact/ae45399d6252b4d7
+ * (Latest source as of now: http://www.sqlite.org/src/artifact/78c8085bc7af1922)
+ * <p>
+ * Also draft spec: http://www.sqlite.org/draft/tokenreq.html
+ *
+ * @hide
+ */
+public class SQLiteTokenizer {
+    private static boolean isAlpha(char ch) {
+        return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || (ch == '_');
+    }
+
+    private static boolean isNum(char ch) {
+        return ('0' <= ch && ch <= '9');
+    }
+
+    private static boolean isAlNum(char ch) {
+        return isAlpha(ch) || isNum(ch);
+    }
+
+    private static boolean isAnyOf(char ch, String set) {
+        return set.indexOf(ch) >= 0;
+    }
+
+    private static IllegalArgumentException genException(String message, String sql) {
+        throw new IllegalArgumentException(message + " in '" + sql + "'");
+    }
+
+    private static char peek(String s, int index) {
+        return index < s.length() ? s.charAt(index) : '\0';
+    }
+
+    public static final int OPTION_NONE = 0;
+
+    /**
+     * Require that SQL contains only tokens; any comments or values will result
+     * in an exception.
+     */
+    public static final int OPTION_TOKEN_ONLY = 1 << 0;
+
+    /**
+     * Tokenize the given SQL, returning the list of each encountered token.
+     *
+     * @throws IllegalArgumentException if invalid SQL is encountered.
+     */
+    public static List<String> tokenize(@Nullable String sql, int options) {
+        final ArrayList<String> res = new ArrayList<>();
+        tokenize(sql, options, res::add);
+        return res;
+    }
+
+    /**
+     * Tokenize the given SQL, sending each encountered token to the given
+     * {@link Consumer}.
+     *
+     * @throws IllegalArgumentException if invalid SQL is encountered.
+     */
+    public static void tokenize(@Nullable String sql, int options, Consumer<String> checker) {
+        if (sql == null) {
+            return;
+        }
+        int pos = 0;
+        final int len = sql.length();
+        while (pos < len) {
+            final char ch = peek(sql, pos);
+
+            // Regular token.
+            if (isAlpha(ch)) {
+                final int start = pos;
+                pos++;
+                while (isAlNum(peek(sql, pos))) {
+                    pos++;
+                }
+                final int end = pos;
+
+                final String token = sql.substring(start, end);
+                checker.accept(token);
+
+                continue;
+            }
+
+            // Handle quoted tokens
+            if (isAnyOf(ch, "'\"`")) {
+                final int quoteStart = pos;
+                pos++;
+
+                for (;;) {
+                    pos = sql.indexOf(ch, pos);
+                    if (pos < 0) {
+                        throw genException("Unterminated quote", sql);
+                    }
+                    if (peek(sql, pos + 1) != ch) {
+                        break;
+                    }
+                    // Quoted quote char -- e.g. "abc""def" is a single string.
+                    pos += 2;
+                }
+                final int quoteEnd = pos;
+                pos++;
+
+                if (ch != '\'') {
+                    // Extract the token
+                    final String tokenUnquoted = sql.substring(quoteStart + 1, quoteEnd);
+
+                    final String token;
+
+                    // Unquote if needed. i.e. "aa""bb" -> aa"bb
+                    if (tokenUnquoted.indexOf(ch) >= 0) {
+                        token = tokenUnquoted.replaceAll(
+                                String.valueOf(ch) + ch, String.valueOf(ch));
+                    } else {
+                        token = tokenUnquoted;
+                    }
+                    checker.accept(token);
+                } else {
+                    if ((options &= OPTION_TOKEN_ONLY) != 0) {
+                        throw genException("Non-token detected", sql);
+                    }
+                }
+                continue;
+            }
+            // Handle tokens enclosed in [...]
+            if (ch == '[') {
+                final int quoteStart = pos;
+                pos++;
+
+                pos = sql.indexOf(']', pos);
+                if (pos < 0) {
+                    throw genException("Unterminated quote", sql);
+                }
+                final int quoteEnd = pos;
+                pos++;
+
+                final String token = sql.substring(quoteStart + 1, quoteEnd);
+
+                checker.accept(token);
+                continue;
+            }
+            if ((options &= OPTION_TOKEN_ONLY) != 0) {
+                throw genException("Non-token detected", sql);
+            }
+
+            // Detect comments.
+            if (ch == '-' && peek(sql, pos + 1) == '-') {
+                pos += 2;
+                pos = sql.indexOf('\n', pos);
+                if (pos < 0) {
+                    // We disallow strings ending in an inline comment.
+                    throw genException("Unterminated comment", sql);
+                }
+                pos++;
+
+                continue;
+            }
+            if (ch == '/' && peek(sql, pos + 1) == '*') {
+                pos += 2;
+                pos = sql.indexOf("*/", pos);
+                if (pos < 0) {
+                    throw genException("Unterminated comment", sql);
+                }
+                pos += 2;
+
+                continue;
+            }
+
+            // Semicolon is never allowed.
+            if (ch == ';') {
+                throw genException("Semicolon is not allowed", sql);
+            }
+
+            // For this purpose, we can simply ignore other characters.
+            // (Note it doesn't handle the X'' literal properly and reports this X as a token,
+            // but that should be fine...)
+            pos++;
+        }
+    }
+
+    /**
+     * Test if given token is a
+     * <a href="https://www.sqlite.org/lang_keywords.html">SQLite reserved
+     * keyword</a>.
+     */
+    public static boolean isKeyword(@NonNull String token) {
+        switch (token.toUpperCase(Locale.US)) {
+            case "ABORT": case "ACTION": case "ADD": case "AFTER":
+            case "ALL": case "ALTER": case "ANALYZE": case "AND":
+            case "AS": case "ASC": case "ATTACH": case "AUTOINCREMENT":
+            case "BEFORE": case "BEGIN": case "BETWEEN": case "BINARY":
+            case "BY": case "CASCADE": case "CASE": case "CAST":
+            case "CHECK": case "COLLATE": case "COLUMN": case "COMMIT":
+            case "CONFLICT": case "CONSTRAINT": case "CREATE": case "CROSS":
+            case "CURRENT": case "CURRENT_DATE": case "CURRENT_TIME": case "CURRENT_TIMESTAMP":
+            case "DATABASE": case "DEFAULT": case "DEFERRABLE": case "DEFERRED":
+            case "DELETE": case "DESC": case "DETACH": case "DISTINCT":
+            case "DO": case "DROP": case "EACH": case "ELSE":
+            case "END": case "ESCAPE": case "EXCEPT": case "EXCLUDE":
+            case "EXCLUSIVE": case "EXISTS": case "EXPLAIN": case "FAIL":
+            case "FILTER": case "FOLLOWING": case "FOR": case "FOREIGN":
+            case "FROM": case "FULL": case "GLOB": case "GROUP":
+            case "GROUPS": case "HAVING": case "IF": case "IGNORE":
+            case "IMMEDIATE": case "IN": case "INDEX": case "INDEXED":
+            case "INITIALLY": case "INNER": case "INSERT": case "INSTEAD":
+            case "INTERSECT": case "INTO": case "IS": case "ISNULL":
+            case "JOIN": case "KEY": case "LEFT": case "LIKE":
+            case "LIMIT": case "MATCH": case "NATURAL": case "NO":
+            case "NOCASE": case "NOT": case "NOTHING": case "NOTNULL":
+            case "NULL": case "OF": case "OFFSET": case "ON":
+            case "OR": case "ORDER": case "OTHERS": case "OUTER":
+            case "OVER": case "PARTITION": case "PLAN": case "PRAGMA":
+            case "PRECEDING": case "PRIMARY": case "QUERY": case "RAISE":
+            case "RANGE": case "RECURSIVE": case "REFERENCES": case "REGEXP":
+            case "REINDEX": case "RELEASE": case "RENAME": case "REPLACE":
+            case "RESTRICT": case "RIGHT": case "ROLLBACK": case "ROW":
+            case "ROWS": case "RTRIM": case "SAVEPOINT": case "SELECT":
+            case "SET": case "TABLE": case "TEMP": case "TEMPORARY":
+            case "THEN": case "TIES": case "TO": case "TRANSACTION":
+            case "TRIGGER": case "UNBOUNDED": case "UNION": case "UNIQUE":
+            case "UPDATE": case "USING": case "VACUUM": case "VALUES":
+            case "VIEW": case "VIRTUAL": case "WHEN": case "WHERE":
+            case "WINDOW": case "WITH": case "WITHOUT":
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Test if given token is a
+     * <a href="https://www.sqlite.org/lang_corefunc.html">SQLite reserved
+     * function</a>.
+     */
+    public static boolean isFunction(@NonNull String token) {
+        switch (token.toLowerCase(Locale.US)) {
+            case "abs": case "avg": case "char": case "coalesce":
+            case "count": case "glob": case "group_concat": case "hex":
+            case "ifnull": case "instr": case "length": case "like":
+            case "likelihood": case "likely": case "lower": case "ltrim":
+            case "max": case "min": case "nullif": case "random":
+            case "randomblob": case "replace": case "round": case "rtrim":
+            case "substr": case "sum": case "total": case "trim":
+            case "typeof": case "unicode": case "unlikely": case "upper":
+            case "zeroblob":
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Test if given token is a
+     * <a href="https://www.sqlite.org/datatype3.html">SQLite reserved type</a>.
+     */
+    public static boolean isType(@NonNull String token) {
+        switch (token.toUpperCase(Locale.US)) {
+            case "INT": case "INTEGER": case "TINYINT": case "SMALLINT":
+            case "MEDIUMINT": case "BIGINT": case "INT2": case "INT8":
+            case "CHARACTER": case "VARCHAR": case "NCHAR": case "NVARCHAR":
+            case "TEXT": case "CLOB": case "BLOB": case "REAL":
+            case "DOUBLE": case "FLOAT": case "NUMERIC": case "DECIMAL":
+            case "BOOLEAN": case "DATE": case "DATETIME":
+                return true;
+            default:
+                return false;
+        }
+    }
+}
diff --git a/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl b/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
index d22e7e2..62d727c 100644
--- a/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl
@@ -22,5 +22,5 @@
  * @hide
  */
 oneway interface IBiometricEnabledOnKeyguardCallback {
-    void onChanged(in BiometricSourceType type, boolean enabled);
+    void onChanged(in BiometricSourceType type, boolean enabled, int userId);
 }
\ No newline at end of file
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 9f4118e..b3125d8 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1191,7 +1191,7 @@
         ArrayList<Partition> partitions = new ArrayList();
 
         String[] names = new String[] {
-            "bootimage", "odm", "product", "product_services", Partition.PARTITION_NAME_SYSTEM,
+            "bootimage", "odm", "product", "system_ext", Partition.PARTITION_NAME_SYSTEM,
             "vendor"
         };
         for (String name : names) {
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 0ee9a11..3462d1f 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -54,7 +54,7 @@
     private static final String ENV_ODM_ROOT = "ODM_ROOT";
     private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
     private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT";
-    private static final String ENV_PRODUCT_SERVICES_ROOT = "PRODUCT_SERVICES_ROOT";
+    private static final String ENV_SYSTEM_EXT_ROOT = "SYSTEM_EXT_ROOT";
 
     /** {@hide} */
     public static final String DIR_ANDROID = "Android";
@@ -77,8 +77,8 @@
     private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
     private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
     private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product");
-    private static final File DIR_PRODUCT_SERVICES_ROOT = getDirectory(ENV_PRODUCT_SERVICES_ROOT,
-                                                           "/product_services");
+    private static final File DIR_SYSTEM_EXT_ROOT = getDirectory(ENV_SYSTEM_EXT_ROOT,
+                                                           "/system_ext");
 
     @UnsupportedAppUsage
     private static UserEnvironment sCurrentUser;
@@ -222,11 +222,26 @@
      * Return root directory of the "product_services" partition holding middleware
      * services if any. If present, the partition is mounted read-only.
      *
+     * @deprecated This directory is not guaranteed to exist.
+     *             Its name is changed to "system_ext" because the partition's purpose is changed.
+     *             {@link #getSystemExtDirectory()}
      * @hide
      */
     @SystemApi
+    @Deprecated
     public static @NonNull File getProductServicesDirectory() {
-        return DIR_PRODUCT_SERVICES_ROOT;
+        return getDirectory("PRODUCT_SERVICES_ROOT", "/product_services");
+    }
+
+    /**
+     * Return root directory of the "system_ext" partition holding system partition's extension
+     * If present, the partition is mounted read-only.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static @NonNull File getSystemExtDirectory() {
+        return DIR_SYSTEM_EXT_ROOT;
     }
 
     /**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9c9829f..a7fa96b 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1283,6 +1283,16 @@
     }
 
     /**
+     * @hide
+     * @return Whether the device is running in a headless system user mode. It means the headless
+     * user (system user) runs system services and system UI, but is not associated with any real
+     * person. Secondary users can be created to be associated with real person.
+     */
+    public static boolean isHeadlessSystemUserMode() {
+        return RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER;
+    }
+
+    /**
      * @deprecated use {@link #getUserSwitchability()} instead.
      *
      * @removed
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index d31cee0..9fa5f16 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -70,4 +70,31 @@
     void revokeRuntimePermission(String packageName, String permName, int userId);
 
     void resetRuntimePermissions();
+
+    boolean setDefaultBrowser(String packageName, int userId);
+
+    String getDefaultBrowser(int userId);
+
+    void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId);
+
+    void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId);
+
+    void grantDefaultPermissionsToEnabledTelephonyDataServices(
+            in String[] packageNames, int userId);
+
+    void revokeDefaultPermissionsFromDisabledTelephonyDataServices(
+            in String[] packageNames, int userId);
+
+    void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId);
+
+    void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId);
+
+    void setPermissionEnforced(String permName, boolean enforced);
+
+    boolean isPermissionEnforced(String permName);
+
+    boolean shouldShowRequestPermissionRationale(String permName,
+            String packageName, int userId);
+
+    boolean isPermissionRevokedByPolicy(String permName, String packageName, int userId);
 }
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index 2f68eb4..d862d602 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -40,7 +40,7 @@
 import android.net.Uri;
 import android.os.RemoteException;
 import android.text.format.DateUtils;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
 import android.util.Log;
 
 import com.android.internal.util.Preconditions;
@@ -1680,7 +1680,7 @@
      * <h3>Writing to Events</h3> There are further restrictions on all Updates
      * and Inserts in the Events table:
      * <ul>
-     * <li>If allDay is set to 1 eventTimezone must be {@link Time#TIMEZONE_UTC}
+     * <li>If allDay is set to 1 eventTimezone must be "UTC"
      * and the time must correspond to a midnight boundary.</li>
      * <li>Exceptions are not allowed to recur. If rrule or rdate is not empty,
      * original_id and original_sync_id must be empty.</li>
@@ -2608,9 +2608,7 @@
         @UnsupportedAppUsage
         public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
             if (DEBUG) {
-                Time time = new Time();
-                time.set(alarmTime);
-                String schedTime = time.format(" %a, %b %d, %Y %I:%M%P");
+                String schedTime = TimeMigrationUtils.formatMillisWithFixedFormat(alarmTime);
                 Log.d(TAG, "Schedule alarm at " + alarmTime + " " + schedTime);
             }
 
diff --git a/core/java/android/service/autofill/FillEventHistory.java b/core/java/android/service/autofill/FillEventHistory.java
index c65e773..1cd2d62 100644
--- a/core/java/android/service/autofill/FillEventHistory.java
+++ b/core/java/android/service/autofill/FillEventHistory.java
@@ -224,13 +224,21 @@
          */
         public static final int TYPE_CONTEXT_COMMITTED = 4;
 
+        /**
+         * A dataset selector was shown.
+         *
+         * <p>This event is fired whenever the autofill UI was presented to the user.</p>
+         */
+        public static final int TYPE_DATASETS_SHOWN = 5;
+
         /** @hide */
         @IntDef(prefix = { "TYPE_" }, value = {
                 TYPE_DATASET_SELECTED,
                 TYPE_DATASET_AUTHENTICATION_SELECTED,
                 TYPE_AUTHENTICATION_SELECTED,
                 TYPE_SAVE_SHOWN,
-                TYPE_CONTEXT_COMMITTED
+                TYPE_CONTEXT_COMMITTED,
+                TYPE_DATASETS_SHOWN
         })
         @Retention(RetentionPolicy.SOURCE)
         @interface EventIds{}
@@ -473,7 +481,7 @@
                 @Nullable ArrayList<ArrayList<String>> manuallyFilledDatasetIds,
                 @Nullable AutofillId[] detectedFieldIds,
                 @Nullable FieldClassification[] detectedFieldClassifications) {
-            mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_CONTEXT_COMMITTED,
+            mEventType = Preconditions.checkArgumentInRange(eventType, 0, TYPE_DATASETS_SHOWN,
                     "eventType");
             mDatasetId = datasetId;
             mClientState = clientState;
diff --git a/core/java/android/text/format/TimeFormatter.java b/core/java/android/text/format/TimeFormatter.java
index 5a14092..f7fd89d 100644
--- a/core/java/android/text/format/TimeFormatter.java
+++ b/core/java/android/text/format/TimeFormatter.java
@@ -26,6 +26,9 @@
 import libcore.util.ZoneInfo;
 
 import java.nio.CharBuffer;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.Formatter;
 import java.util.Locale;
 import java.util.TimeZone;
@@ -86,6 +89,59 @@
     }
 
     /**
+     * The implementation of {@link TimeMigrationUtils#formatMillisWithFixedFormat(long)} for
+     * 2038-safe formatting with the pattern "%Y-%m-%d %H:%M:%S" and including the historic
+     * incorrect digit localization behavior.
+     */
+    String formatMillisWithFixedFormat(long timeMillis) {
+        // This method is deliberately not a general purpose replacement for
+        // format(String, ZoneInfo.WallTime, ZoneInfo): It hard-codes the pattern used; many of the
+        // pattern characters supported by Time.format() have unusual behavior which would make
+        // using java.time.format or similar packages difficult. It would be a lot of work to share
+        // behavior and many internal Android usecases can be covered by this common pattern
+        // behavior.
+
+        // No need to worry about overflow / underflow: long millis is representable by Instant and
+        // LocalDateTime with room to spare.
+        Instant instant = Instant.ofEpochMilli(timeMillis);
+
+        // Date/times are calculated in the current system default time zone.
+        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+
+        // You'd think it would be as simple as:
+        // DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", locale);
+        // return formatter.format(localDateTime);
+        // but we retain Time's behavior around digits.
+
+        StringBuilder stringBuilder = new StringBuilder(19);
+
+        // This effectively uses the US locale because number localization is handled separately
+        // (see below).
+        stringBuilder.append(localDateTime.getYear());
+        stringBuilder.append('-');
+        append2DigitNumber(stringBuilder, localDateTime.getMonthValue());
+        stringBuilder.append('-');
+        append2DigitNumber(stringBuilder, localDateTime.getDayOfMonth());
+        stringBuilder.append(' ');
+        append2DigitNumber(stringBuilder, localDateTime.getHour());
+        stringBuilder.append(':');
+        append2DigitNumber(stringBuilder, localDateTime.getMinute());
+        stringBuilder.append(':');
+        append2DigitNumber(stringBuilder, localDateTime.getSecond());
+
+        String result = stringBuilder.toString();
+        return localizeDigits(result);
+    }
+
+    /** Zero-pads value as needed to achieve a 2-digit number. */
+    private static void append2DigitNumber(StringBuilder builder, int value) {
+        if (value < 10) {
+            builder.append('0');
+        }
+        builder.append(value);
+    }
+
+    /**
      * Format the specified {@code wallTime} using {@code pattern}. The output is returned.
      */
     public String format(String pattern, ZoneInfo.WallTime wallTime, ZoneInfo zoneInfo) {
@@ -99,12 +155,9 @@
 
             formatInternal(pattern, wallTime, zoneInfo);
             String result = stringBuilder.toString();
-            // This behavior is the source of a bug since some formats are defined as being
-            // in ASCII and not localized.
-            if (localeData.zeroDigit != '0') {
-                result = localizeDigits(result);
-            }
-            return result;
+            // The localizeDigits() behavior is the source of a bug since some formats are defined
+            // as being in ASCII and not localized.
+            return localizeDigits(result);
         } finally {
             outputBuilder = null;
             numberFormatter = null;
@@ -112,6 +165,10 @@
     }
 
     private String localizeDigits(String s) {
+        if (localeData.zeroDigit == '0') {
+            return s;
+        }
+
         int length = s.length();
         int offsetToLocalizedDigits = localeData.zeroDigit - '0';
         StringBuilder result = new StringBuilder(length);
diff --git a/core/java/android/text/format/TimeMigrationUtils.java b/core/java/android/text/format/TimeMigrationUtils.java
new file mode 100644
index 0000000..17bac8d
--- /dev/null
+++ b/core/java/android/text/format/TimeMigrationUtils.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text.format;
+
+/**
+ * Logic to ease migration away from {@link Time} in Android internal code. {@link Time} is
+ * afflicted by the Y2038 issue and deprecated. The methods here are intended to allow minimal
+ * changes to classes that use {@link Time} for common behavior.
+ *
+ * @hide
+ */
+public class TimeMigrationUtils {
+
+    private TimeMigrationUtils() {}
+
+    /**
+     * A Y2038-safe replacement for various users of the {@link Time#format(String)} with the
+     * pattern "%Y-%m-%d %H:%M:%S". Note, this method retains the unusual localization behavior
+     * originally implemented by Time, which can lead to non-latin numbers being produced if the
+     * default locale does not use latin numbers.
+     */
+    public static String formatMillisWithFixedFormat(long timeMillis) {
+        // Delegate to TimeFormatter so that the unusual localization / threading behavior can be
+        // reused.
+        return new TimeFormatter().formatMillisWithFixedFormat(timeMillis);
+    }
+}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 4bfd138..f73f28a 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -308,7 +308,7 @@
     /**
      * Called when the system gesture exclusion has changed.
      */
-    void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
+    oneway void reportSystemGestureExclusionChanged(IWindow window, in List<Rect> exclusionRects);
 
     /**
     * Request the server to call setInputWindowInfo on a given Surface, and return
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 9cc6b28..1a66898 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -96,7 +96,7 @@
  * artifacts may occur on previous versions of the platform when its window is
  * positioned asynchronously.</p>
  */
-public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallback {
+public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCallback {
     private static final String TAG = "SurfaceView";
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_POSITION = false;
@@ -227,9 +227,7 @@
         mRequestedVisible = mViewVisibility && mWindowVisibility && !mWindowStopped;
     }
 
-    /** @hide */
-    @Override
-    public void windowStopped(boolean stopped) {
+    private void setWindowStopped(boolean stopped) {
         mWindowStopped = stopped;
         updateRequestedVisibility();
         updateSurface();
@@ -239,7 +237,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
-        getViewRootImpl().addWindowStoppedCallback(this);
+        getViewRootImpl().addSurfaceChangedCallback(this);
         mWindowStopped = false;
 
         mViewVisibility = getVisibility() == VISIBLE;
@@ -459,7 +457,7 @@
         // the lifecycle. Instead of attaching it to a view, he/she can just pass
         // the SurfaceHolder forward, most live wallpapers do it.
         if (viewRoot != null) {
-            viewRoot.removeWindowStoppedCallback(this);
+            viewRoot.removeSurfaceChangedCallback(this);
         }
 
         mAttachedToWindow = false;
@@ -1349,4 +1347,33 @@
     public SurfaceControl getSurfaceControl() {
         return mSurfaceControl;
     }
+
+    /**
+     * Set window stopped to false and update surface visibility when ViewRootImpl surface is
+     * created.
+     * @hide
+     */
+    @Override
+    public void surfaceCreated(SurfaceControl.Transaction t) {
+        setWindowStopped(false);
+    }
+
+    /**
+     * Set window stopped to true and update surface visibility when ViewRootImpl surface is
+     * destroyed.
+     * @hide
+     */
+    @Override
+    public void surfaceDestroyed() {
+        setWindowStopped(true);
+    }
+
+    /**
+     * Called when a valid ViewRootImpl surface is replaced by another valid surface.
+     * @hide
+     */
+    @Override
+    public void surfaceReplaced(SurfaceControl.Transaction t) {
+
+    }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 613ddcf..354cc964 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -478,6 +478,12 @@
     private final SurfaceControl mSurfaceControl = new SurfaceControl();
 
     /**
+     * Transaction object that can be used to synchronize child SurfaceControl changes with
+     * ViewRootImpl SurfaceControl changes by the server. The object is passed along with
+     * the SurfaceChangedCallback.
+     */
+    private final Transaction mSurfaceChangedTransaction = new Transaction();
+    /**
      * Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds
      * are set to the parent's bounds adjusted for surface insets. This surface is created when
      * {@link ViewRootImpl#createBoundsSurface(int)} is called.
@@ -1541,19 +1547,6 @@
         mIsAmbientMode = ambient;
     }
 
-    interface WindowStoppedCallback {
-        public void windowStopped(boolean stopped);
-    }
-    private final ArrayList<WindowStoppedCallback> mWindowStoppedCallbacks =  new ArrayList<>();
-
-    void addWindowStoppedCallback(WindowStoppedCallback c) {
-        mWindowStoppedCallbacks.add(c);
-    }
-
-    void removeWindowStoppedCallback(WindowStoppedCallback c) {
-        mWindowStoppedCallbacks.remove(c);
-    }
-
     void setWindowStopped(boolean stopped) {
         checkThread();
         if (mStopped != stopped) {
@@ -1570,14 +1563,11 @@
                 if (renderer != null) {
                     renderer.destroyHardwareResources(mView);
                 }
-            }
 
-            for (int i = 0; i < mWindowStoppedCallbacks.size(); i++) {
-                mWindowStoppedCallbacks.get(i).windowStopped(stopped);
-            }
-
-            if (mStopped) {
-                if (mSurfaceHolder != null && mSurface.isValid()) {
+                if (mSurface.isValid()) {
+                    if (mSurfaceHolder != null) {
+                        notifyHolderSurfaceDestroyed();
+                    }
                     notifySurfaceDestroyed();
                 }
                 destroySurface();
@@ -1585,6 +1575,46 @@
         }
     }
 
+    /** Register callbacks to be notified when the ViewRootImpl surface changes. */
+    interface SurfaceChangedCallback {
+        void surfaceCreated(Transaction t);
+        void surfaceReplaced(Transaction t);
+        void surfaceDestroyed();
+    }
+
+    private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>();
+    void addSurfaceChangedCallback(SurfaceChangedCallback c) {
+        mSurfaceChangedCallbacks.add(c);
+    }
+
+    void removeSurfaceChangedCallback(SurfaceChangedCallback c) {
+        mSurfaceChangedCallbacks.remove(c);
+    }
+
+    private void notifySurfaceCreated() {
+        for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
+            mSurfaceChangedCallbacks.get(i).surfaceCreated(mSurfaceChangedTransaction);
+        }
+    }
+
+    /**
+     * Notify listeners when the ViewRootImpl surface has been replaced. This callback will not be
+     * called if a new surface is created, only if the valid surface has been replaced with another
+     * valid surface.
+     */
+    private void notifySurfaceReplaced() {
+        for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
+            mSurfaceChangedCallbacks.get(i).surfaceReplaced(mSurfaceChangedTransaction);
+        }
+    }
+
+    private void notifySurfaceDestroyed() {
+        for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
+            mSurfaceChangedCallbacks.get(i).surfaceDestroyed();
+        }
+    }
+
+
     /**
      * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and
      * crop bounds set to the parent's bounds adjusted for surface insets.
@@ -1984,7 +2014,7 @@
         mIsInTraversal = true;
         mWillDrawSoon = true;
         boolean windowSizeMayChange = false;
-        boolean surfaceChanged = false;
+        final boolean windowAttributesChanged = mWindowAttributesChanged;
         WindowManager.LayoutParams lp = mWindowAttributes;
 
         int desiredWindowWidth;
@@ -2003,7 +2033,6 @@
         WindowManager.LayoutParams params = null;
         if (mWindowAttributesChanged) {
             mWindowAttributesChanged = false;
-            surfaceChanged = true;
             params = lp;
         }
         CompatibilityInfo compatibilityInfo =
@@ -2244,6 +2273,10 @@
         final boolean isViewVisible = viewVisibility == View.VISIBLE;
         final boolean windowRelayoutWasForced = mForceNextWindowRelayout;
         boolean surfaceSizeChanged = false;
+        boolean surfaceCreated = false;
+        boolean surfaceDestroyed = false;
+        /* True if surface generation id changes. */
+        boolean surfaceReplaced = false;
 
         if (mFirst || windowShouldResize || insetsChanged ||
                 viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
@@ -2325,10 +2358,14 @@
                 final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
                 surfaceSizeChanged = (relayoutResult
                         & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
-                surfaceChanged |= surfaceSizeChanged;
                 final boolean alwaysConsumeSystemBarsChanged =
                         mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars;
                 final boolean colorModeChanged = hasColorModeChanged(lp.getColorMode());
+                surfaceCreated = !hadSurface && mSurface.isValid();
+                surfaceDestroyed = hadSurface && !mSurface.isValid();
+                surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId())
+                        && mSurface.isValid();
+
                 if (contentInsetsChanged) {
                     mAttachInfo.mContentInsets.set(mPendingContentInsets);
                     if (DEBUG_LAYOUT) Log.v(mTag, "Content insets changing to: "
@@ -2383,33 +2420,32 @@
                             lp.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
                 }
 
-                if (!hadSurface) {
-                    if (mSurface.isValid()) {
-                        // If we are creating a new surface, then we need to
-                        // completely redraw it.
-                        mFullRedrawNeeded = true;
-                        mPreviousTransparentRegion.setEmpty();
+                if (surfaceCreated) {
+                    // If we are creating a new surface, then we need to
+                    // completely redraw it.
+                    mFullRedrawNeeded = true;
+                    mPreviousTransparentRegion.setEmpty();
 
-                        // Only initialize up-front if transparent regions are not
-                        // requested, otherwise defer to see if the entire window
-                        // will be transparent
-                        if (mAttachInfo.mThreadedRenderer != null) {
-                            try {
-                                hwInitialized = mAttachInfo.mThreadedRenderer.initialize(
-                                        mSurface);
-                                if (hwInitialized && (host.mPrivateFlags
-                                        & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
-                                    // Don't pre-allocate if transparent regions
-                                    // are requested as they may not be needed
-                                    mAttachInfo.mThreadedRenderer.allocateBuffers();
-                                }
-                            } catch (OutOfResourcesException e) {
-                                handleOutOfResourcesException(e);
-                                return;
+                    // Only initialize up-front if transparent regions are not
+                    // requested, otherwise defer to see if the entire window
+                    // will be transparent
+                    if (mAttachInfo.mThreadedRenderer != null) {
+                        try {
+                            hwInitialized = mAttachInfo.mThreadedRenderer.initialize(
+                                    mSurface);
+                            if (hwInitialized && (host.mPrivateFlags
+                                    & View.PFLAG_REQUEST_TRANSPARENT_REGIONS) == 0) {
+                                // Don't pre-allocate if transparent regions
+                                // are requested as they may not be needed
+                                mAttachInfo.mThreadedRenderer.allocateBuffers();
                             }
+                        } catch (OutOfResourcesException e) {
+                            handleOutOfResourcesException(e);
+                            return;
                         }
                     }
-                } else if (!mSurface.isValid()) {
+                    notifySurfaceCreated();
+                } else if (surfaceDestroyed) {
                     // If the surface has been removed, then reset the scroll
                     // positions.
                     if (mLastScrolledFocus != null) {
@@ -2427,10 +2463,12 @@
                             mAttachInfo.mThreadedRenderer.isEnabled()) {
                         mAttachInfo.mThreadedRenderer.destroy();
                     }
-                } else if ((surfaceGenerationId != mSurface.getGenerationId()
+                    notifySurfaceDestroyed();
+                } else if ((surfaceReplaced
                         || surfaceSizeChanged || windowRelayoutWasForced || colorModeChanged)
                         && mSurfaceHolder == null
-                        && mAttachInfo.mThreadedRenderer != null) {
+                        && mAttachInfo.mThreadedRenderer != null
+                        && mSurface.isValid()) {
                     mFullRedrawNeeded = true;
                     try {
                         // Need to do updateSurface (which leads to CanvasContext::setSurface and
@@ -2448,6 +2486,10 @@
                     }
                 }
 
+                if (!surfaceCreated && surfaceReplaced) {
+                    notifySurfaceReplaced();
+                }
+
                 final boolean freeformResizing = (relayoutResult
                         & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM) != 0;
                 final boolean dockedResizing = (relayoutResult
@@ -2503,31 +2545,32 @@
                 }
                 mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
                 mSurfaceHolder.mSurfaceLock.unlock();
-                if (mSurface.isValid()) {
-                    if (!hadSurface) {
-                        mSurfaceHolder.ungetCallbacks();
+                if (surfaceCreated) {
+                    mSurfaceHolder.ungetCallbacks();
 
-                        mIsCreating = true;
-                        SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
-                        if (callbacks != null) {
-                            for (SurfaceHolder.Callback c : callbacks) {
-                                c.surfaceCreated(mSurfaceHolder);
-                            }
+                    mIsCreating = true;
+                    SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
+                    if (callbacks != null) {
+                        for (SurfaceHolder.Callback c : callbacks) {
+                            c.surfaceCreated(mSurfaceHolder);
                         }
-                        surfaceChanged = true;
                     }
-                    if (surfaceChanged || surfaceGenerationId != mSurface.getGenerationId()) {
-                        SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
-                        if (callbacks != null) {
-                            for (SurfaceHolder.Callback c : callbacks) {
-                                c.surfaceChanged(mSurfaceHolder, lp.format,
-                                        mWidth, mHeight);
-                            }
+                }
+
+                if ((surfaceCreated || surfaceReplaced || surfaceSizeChanged
+                        || windowAttributesChanged) && mSurface.isValid()) {
+                    SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
+                    if (callbacks != null) {
+                        for (SurfaceHolder.Callback c : callbacks) {
+                            c.surfaceChanged(mSurfaceHolder, lp.format,
+                                    mWidth, mHeight);
                         }
                     }
                     mIsCreating = false;
-                } else if (hadSurface) {
-                    notifySurfaceDestroyed();
+                }
+
+                if (surfaceDestroyed) {
+                    notifyHolderSurfaceDestroyed();
                     mSurfaceHolder.mSurfaceLock.lock();
                     try {
                         mSurfaceHolder.mSurface = new Surface();
@@ -2841,7 +2884,7 @@
         }
     }
 
-    private void notifySurfaceDestroyed() {
+    private void notifyHolderSurfaceDestroyed() {
         mSurfaceHolder.ungetCallbacks();
         SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
         if (callbacks != null) {
@@ -3447,7 +3490,7 @@
     private void reportDrawFinished() {
         try {
             mDrawsNeededToReport = 0;
-            mWindowSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+            mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
         } catch (RemoteException e) {
             // Have fun!
         }
diff --git a/core/java/android/view/WindowInfo.java b/core/java/android/view/WindowInfo.java
index abf5e3f..57dfc62 100644
--- a/core/java/android/view/WindowInfo.java
+++ b/core/java/android/view/WindowInfo.java
@@ -16,7 +16,7 @@
 
 package android.view;
 
-import android.graphics.Rect;
+import android.graphics.Region;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -44,7 +44,7 @@
     public IBinder parentToken;
     public IBinder activityToken;
     public boolean focused;
-    public final Rect boundsInScreen = new Rect();
+    public Region regionInScreen = new Region();
     public List<IBinder> childTokens;
     public CharSequence title;
     public long accessibilityIdOfAnchor = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -73,7 +73,7 @@
         window.parentToken = other.parentToken;
         window.activityToken = other.activityToken;
         window.focused = other.focused;
-        window.boundsInScreen.set(other.boundsInScreen);
+        window.regionInScreen.set(other.regionInScreen);
         window.title = other.title;
         window.accessibilityIdOfAnchor = other.accessibilityIdOfAnchor;
         window.inPictureInPicture = other.inPictureInPicture;
@@ -109,7 +109,7 @@
         parcel.writeStrongBinder(parentToken);
         parcel.writeStrongBinder(activityToken);
         parcel.writeInt(focused ? 1 : 0);
-        boundsInScreen.writeToParcel(parcel, flags);
+        regionInScreen.writeToParcel(parcel, flags);
         parcel.writeCharSequence(title);
         parcel.writeLong(accessibilityIdOfAnchor);
         parcel.writeInt(inPictureInPicture ? 1 : 0);
@@ -132,7 +132,8 @@
         builder.append(", type=").append(type);
         builder.append(", layer=").append(layer);
         builder.append(", token=").append(token);
-        builder.append(", bounds=").append(boundsInScreen);
+        builder.append(", region=").append(regionInScreen);
+        builder.append(", bounds=").append(regionInScreen.getBounds());
         builder.append(", parent=").append(parentToken);
         builder.append(", focused=").append(focused);
         builder.append(", children=").append(childTokens);
@@ -151,7 +152,7 @@
         parentToken = parcel.readStrongBinder();
         activityToken = parcel.readStrongBinder();
         focused = (parcel.readInt() == 1);
-        boundsInScreen.readFromParcel(parcel);
+        regionInScreen = Region.CREATOR.createFromParcel(parcel);
         title = parcel.readCharSequence();
         accessibilityIdOfAnchor = parcel.readLong();
         inPictureInPicture = (parcel.readInt() == 1);
@@ -174,7 +175,7 @@
         parentToken = null;
         activityToken = null;
         focused = false;
-        boundsInScreen.setEmpty();
+        regionInScreen.setEmpty();
         if (childTokens != null) {
             childTokens.clear();
         }
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index dfeb4b5..5844365 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -20,8 +20,8 @@
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.util.MergedConfiguration;
 import android.util.Log;
+import android.util.MergedConfiguration;
 import android.view.IWindowSession;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
@@ -35,7 +35,7 @@
 * By parcelling the root surface, the app can offer another app content for embedding.
 * @hide
 */
-class WindowlessWindowManager extends IWindowSession.Default {
+class WindowlessWindowManager implements IWindowSession {
     private final static String TAG = "WindowlessWindowManager";
 
     /**
@@ -83,6 +83,17 @@
     }
 
     @Override
+    public int addToDisplayWithoutInputChannel(android.view.IWindow window, int seq,
+            android.view.WindowManager.LayoutParams attrs, int viewVisibility, int layerStackId,
+            android.graphics.Rect outContentInsets, android.graphics.Rect outStableInsets,
+            android.view.InsetsState insetsState) {
+        return 0;
+    }
+
+    @Override
+    public void remove(android.view.IWindow window) {}
+
+    @Override
     public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs,
             int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
             Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets,
@@ -106,4 +117,154 @@
 
         return 0;
     }
+
+    @Override
+    public void prepareToReplaceWindows(android.os.IBinder appToken, boolean childrenOnly) {
+    }
+
+    @Override
+    public boolean outOfMemory(android.view.IWindow window) {
+        return false;
+    }
+
+    @Override
+    public void setTransparentRegion(android.view.IWindow window, android.graphics.Region region) {
+    }
+
+    @Override
+    public void setInsets(android.view.IWindow window, int touchableInsets,
+            android.graphics.Rect contentInsets, android.graphics.Rect visibleInsets,
+            android.graphics.Region touchableRegion) {
+    }
+
+    @Override
+    public void getDisplayFrame(android.view.IWindow window,
+            android.graphics.Rect outDisplayFrame) {
+    }
+
+    @Override
+    public void finishDrawing(android.view.IWindow window,
+            android.view.SurfaceControl.Transaction postDrawTransaction) {
+    }
+
+    @Override
+    public void setInTouchMode(boolean showFocus) {
+    }
+
+    @Override
+    public boolean getInTouchMode() {
+        return false;
+    }
+
+    @Override
+    public boolean performHapticFeedback(int effectId, boolean always) {
+        return false;
+    }
+
+    @Override
+    public android.os.IBinder performDrag(android.view.IWindow window, int flags,
+            android.view.SurfaceControl surface, int touchSource, float touchX, float touchY,
+            float thumbCenterX, float thumbCenterY, android.content.ClipData data) {
+        return null;
+    }
+
+    @Override
+    public void reportDropResult(android.view.IWindow window, boolean consumed) {
+    }
+
+    @Override
+    public void cancelDragAndDrop(android.os.IBinder dragToken, boolean skipAnimation) {
+    }
+
+    @Override
+    public void dragRecipientEntered(android.view.IWindow window) {
+    }
+
+    @Override
+    public void dragRecipientExited(android.view.IWindow window) {
+    }
+
+    @Override
+    public void setWallpaperPosition(android.os.IBinder windowToken, float x, float y,
+            float xstep, float ystep) {
+    }
+
+    @Override
+    public void wallpaperOffsetsComplete(android.os.IBinder window) {
+    }
+
+    @Override
+    public void setWallpaperDisplayOffset(android.os.IBinder windowToken, int x, int y) {
+    }
+
+    @Override
+    public android.os.Bundle sendWallpaperCommand(android.os.IBinder window,
+            java.lang.String action, int x, int y, int z, android.os.Bundle extras, boolean sync) {
+        return null;
+    }
+
+    @Override
+    public void wallpaperCommandComplete(android.os.IBinder window, android.os.Bundle result) {
+    }
+
+    @Override
+    public void onRectangleOnScreenRequested(android.os.IBinder token,
+            android.graphics.Rect rectangle) {
+    }
+
+    @Override
+    public android.view.IWindowId getWindowId(android.os.IBinder window) {
+        return null;
+    }
+
+    @Override
+    public void pokeDrawLock(android.os.IBinder window) {
+    }
+
+    @Override
+    public boolean startMovingTask(android.view.IWindow window, float startX, float startY) {
+        return false;
+    }
+
+    @Override
+    public void finishMovingTask(android.view.IWindow window) {
+    }
+
+    @Override
+    public void updatePointerIcon(android.view.IWindow window) {
+    }
+
+    @Override
+    public void reparentDisplayContent(android.view.IWindow window, android.view.SurfaceControl sc,
+            int displayId) {
+    }
+
+    @Override
+    public void updateDisplayContentLocation(android.view.IWindow window, int x, int y,
+            int displayId) {
+    }
+
+    @Override
+    public void updateTapExcludeRegion(android.view.IWindow window, int regionId,
+            android.graphics.Region region) {
+    }
+
+    @Override
+    public void insetsModified(android.view.IWindow window, android.view.InsetsState state) {
+    }
+
+    @Override
+    public void reportSystemGestureExclusionChanged(android.view.IWindow window,
+            java.util.List<android.graphics.Rect> exclusionRects) {
+    }
+
+    @Override
+    public void blessInputSurface(int displayId, SurfaceControl surface,
+            InputChannel outInputChannel) {
+    }
+
+    @Override
+    public android.os.IBinder asBinder() {
+        return null;
+    }
 }
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 985effb..fd09a87 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -622,6 +622,10 @@
     /**
      * Change type for {@link #TYPE_WINDOWS_CHANGED} event:
      * The window's bounds changed.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#R R}, this event implies the window's
+     * region changed. It's also possible that region changed but bounds doesn't.
+     * </p>
      */
     public static final int WINDOWS_CHANGE_BOUNDS = 0x00000008;
 
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index ea61ef8..6a3af34 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -16,9 +16,11 @@
 
 package android.view.accessibility;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -107,7 +109,7 @@
     private int mBooleanProperties;
     private int mId = UNDEFINED_WINDOW_ID;
     private int mParentId = UNDEFINED_WINDOW_ID;
-    private final Rect mBoundsInScreen = new Rect();
+    private Region mRegionInScreen = new Region();
     private LongArray mChildIds;
     private CharSequence mTitle;
     private long mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -305,23 +307,33 @@
     }
 
     /**
-     * Gets the bounds of this window in the screen.
+     * Gets the touchable region of this window in the screen.
+     *
+     * @param outRegion The out window region.
+     */
+    public void getRegionInScreen(@NonNull Region outRegion) {
+        outRegion.set(mRegionInScreen);
+    }
+
+    /**
+     * Sets the touchable region of this window in the screen.
+     *
+     * @param region The window region.
+     *
+     * @hide
+     */
+    public void setRegionInScreen(Region region) {
+        mRegionInScreen.set(region);
+    }
+
+    /**
+     * Gets the bounds of this window in the screen. This is equivalent to get the bounds of the
+     * Region from {@link #getRegionInScreen(Region)}.
      *
      * @param outBounds The out window bounds.
      */
     public void getBoundsInScreen(Rect outBounds) {
-        outBounds.set(mBoundsInScreen);
-    }
-
-    /**
-     * Sets the bounds of this window in the screen.
-     *
-     * @param bounds The out window bounds.
-     *
-     * @hide
-     */
-    public void setBoundsInScreen(Rect bounds) {
-        mBoundsInScreen.set(bounds);
+        outBounds.set(mRegionInScreen.getBounds());
     }
 
     /**
@@ -522,7 +534,7 @@
         parcel.writeInt(mBooleanProperties);
         parcel.writeInt(mId);
         parcel.writeInt(mParentId);
-        mBoundsInScreen.writeToParcel(parcel, flags);
+        mRegionInScreen.writeToParcel(parcel, flags);
         parcel.writeCharSequence(mTitle);
         parcel.writeLong(mAnchorId);
 
@@ -552,7 +564,7 @@
         mBooleanProperties = other.mBooleanProperties;
         mId = other.mId;
         mParentId = other.mParentId;
-        mBoundsInScreen.set(other.mBoundsInScreen);
+        mRegionInScreen.set(other.mRegionInScreen);
         mTitle = other.mTitle;
         mAnchorId = other.mAnchorId;
 
@@ -574,7 +586,7 @@
         mBooleanProperties = parcel.readInt();
         mId = parcel.readInt();
         mParentId = parcel.readInt();
-        mBoundsInScreen.readFromParcel(parcel);
+        mRegionInScreen = Region.CREATOR.createFromParcel(parcel);
         mTitle = parcel.readCharSequence();
         mAnchorId = parcel.readLong();
 
@@ -621,7 +633,8 @@
         builder.append(", id=").append(mId);
         builder.append(", type=").append(typeToString(mType));
         builder.append(", layer=").append(mLayer);
-        builder.append(", bounds=").append(mBoundsInScreen);
+        builder.append(", region=").append(mRegionInScreen);
+        builder.append(", bounds=").append(mRegionInScreen.getBounds());
         builder.append(", focused=").append(isFocused());
         builder.append(", active=").append(isActive());
         builder.append(", pictureInPicture=").append(isInPictureInPictureMode());
@@ -661,7 +674,7 @@
         mBooleanProperties = 0;
         mId = UNDEFINED_WINDOW_ID;
         mParentId = UNDEFINED_WINDOW_ID;
-        mBoundsInScreen.setEmpty();
+        mRegionInScreen.setEmpty();
         mChildIds = null;
         mConnectionId = UNDEFINED_WINDOW_ID;
         mAnchorId = AccessibilityNodeInfo.UNDEFINED_NODE_ID;
@@ -716,7 +729,6 @@
         }
     }
 
-
     /**
      * Reports how this window differs from a possibly different state of the same window. The
      * argument must have the same id and type as neither of those properties may change.
@@ -739,8 +751,7 @@
         if (!TextUtils.equals(mTitle, other.mTitle)) {
             changes |= AccessibilityEvent.WINDOWS_CHANGE_TITLE;
         }
-
-        if (!mBoundsInScreen.equals(other.mBoundsInScreen)) {
+        if (!mRegionInScreen.equals(other.mRegionInScreen)) {
             changes |= AccessibilityEvent.WINDOWS_CHANGE_BOUNDS;
         }
         if (mLayer != other.mLayer) {
diff --git a/core/java/android/widget/ArrayAdapter.java b/core/java/android/widget/ArrayAdapter.java
index c3c2c0d..2bf1ba5 100644
--- a/core/java/android/widget/ArrayAdapter.java
+++ b/core/java/android/widget/ArrayAdapter.java
@@ -50,7 +50,7 @@
  * override {@link #getView(int, View, ViewGroup)}
  * and inflate a view resource.
  * For a code example, see
- * the <a href="https://developer.android.com/samples/CustomChoiceList/index.html">
+ * the <a href="https://github.com/googlesamples/android-CustomChoiceList/#readme">
  * CustomChoiceList</a> sample.
  * </p>
  * <p>
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index d985528..6b324a5 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1202,13 +1202,13 @@
      * determine where to position the view on the screen.  If the view is not contained
      * within a relative layout, these attributes are ignored.
      *
-     * See the <a href="/guide/topics/ui/layout/relative.html">
-     * Relative Layout</a> guide for example code demonstrating how to use relative layout’s
+     * See the <a href="{@docRoot}guide/topics/ui/layout/relative.html">Relative
+     * Layout</a> guide for example code demonstrating how to use relative layout's
      * layout parameters in a layout XML.
      *
      * To learn more about layout parameters and how they differ from typical view attributes,
-     * see the <a href="/guide/topics/ui/declaring-layout.html#attributes">
-     *     Layouts guide</a>.
+     * see the <a href="{@docRoot}guide/topics/ui/declaring-layout.html#attributes">Layouts
+     * guide</a>.
      *
      *
      * @attr ref android.R.styleable#RelativeLayout_Layout_layout_alignWithParentIfMissing
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index 49a0f39..4c67b08 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -433,7 +433,7 @@
      * to the next tabbed view, in this example).
      * <p>
      * To move both the focus AND the selected tab at once, please use
-     * {@link #setCurrentTab}. Normally, the view logic takes care of
+     * {@link #focusCurrentTab}. Normally, the view logic takes care of
      * adjusting the focus, so unless you're circumventing the UI,
      * you'll probably just focus your interest here.
      *
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 430fa61..ee4666f 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -198,6 +198,89 @@
      */
     public static final String BRIGHTLINE_FALSING_MANAGER_ENABLED =
             "brightline_falsing_manager_enabled";
+    /**
+     * (float) Maximum fraction of the screen required to qualify as a real swipe.
+     */
+    public static final String BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE =
+            "brightline_falsing_distance_screen_fraction_max_distance";
+
+    /**
+     * (float) Multiplier for swipe velocity to convert it to pixels for a fling.
+     */
+    public static final String BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE =
+            "brightline_falsing_distance_velcoity_to_distance";
+
+    /**
+     * (float) How far, in inches, must a fling travel horizontally to qualify as intentional.
+     */
+    public static final String BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN =
+            "brightline_falsing_distance_horizontal_fling_threshold_in";
+
+    /**
+     * (float) Maximum fraction of the screen required to qualify as a real swipe.
+     */
+    public static final String BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN =
+            "brightline_falsing_distance_vertical_fling_threshold_in";
+
+    /**
+     * (float) How far, in inches, must a continuous swipe travel horizontally to be intentional.
+     */
+    public static final String BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN =
+            "brightline_falsing_distance_horizontal_swipe_threshold_in";
+
+    /**
+     * (float) How far, in inches, must a continuous swipe travel vertically to be intentional.
+     */
+    public static final String BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN =
+            "brightline_falsing_distance_horizontal_swipe_threshold_in";
+
+    /**
+     * (float) Percentage of swipe with the proximity sensor covered that triggers a higher
+     * swipe distance requirement.
+     */
+    public static final String BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD =
+            "brightline_falsing_proximity_percent_covered_threshold";
+
+    /**
+     * (float) Angle, in radians, that a swipe can vary from horizontal and sill be intentional.
+     */
+    public static final String BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE =
+            "brightline_falsing_diagonal_horizontal_angle_range";
+
+    /**
+     * (float) Angle, in radians, that a swipe can vary from vertical and sill be intentional.
+     */
+    public static final String BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE =
+            "brightline_falsing_diagonal_horizontal_angle_range";
+
+    /**
+     * (float) Distance, in inches, that a swipe is allowed to vary in the horizontal direction for
+     * horizontal swipes.
+     */
+    public static final String BRIGHTLINE_FALSING_ZIGZAG_X_PRIMARY_DEVIANCE =
+            "brightline_falsing_zigzag_x_primary_deviance";
+
+    /**
+     * (float) Distance, in inches, that a swipe is allowed to vary in the vertical direction for
+     * vertical swipes.
+     */
+    public static final String BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE =
+            "brightline_falsing_zigzag_y_primary_deviance";
+
+    /**
+     * (float) Distance, in inches, that a swipe is allowed to vary in the horizontal direction for
+     * horizontal swipes.
+     */
+    public static final String BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE =
+            "brightline_falsing_zigzag_x_secondary_deviance";
+
+    /**
+     * (float) Distance, in inches, that a swipe is allowed to vary in the vertical direction for
+     * vertical swipes.
+     */
+    public static final String BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE =
+            "brightline_falsing_zigzag_y_secondary_deviance";
+
 
     private SystemUiDeviceConfigFlags() { }
 }
diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java
index 8136cfc..d6862f0 100644
--- a/core/java/com/android/internal/infra/ServiceConnector.java
+++ b/core/java/com/android/internal/infra/ServiceConnector.java
@@ -228,7 +228,7 @@
         private final int mUserId;
         private final @Nullable Function<IBinder, I> mBinderAsInterface;
 
-        private I mService = null;
+        private volatile I mService = null;
         private boolean mBinding = false;
         private boolean mUnbinding = false;
 
@@ -506,11 +506,12 @@
 
         void unbindJobThread() {
             cancelTimeout();
-            boolean wasBound = isBound();
+            I service = mService;
+            boolean wasBound = service != null;
             if (wasBound) {
-                onServiceConnectionStatusChanged(mService, false);
+                onServiceConnectionStatusChanged(service, false);
                 mContext.unbindService(mServiceConnection);
-                mService.asBinder().unlinkToDeath(this, 0);
+                service.asBinder().unlinkToDeath(this, 0);
                 mService = null;
             }
             mBinding = false;
@@ -543,7 +544,7 @@
         }
 
         @Override
-        public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) {
+        public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder binder) {
             if (mUnbinding) {
                 Log.i(LOG_TAG, "Ignoring onServiceConnected due to ongoing unbinding: " + this);
                 return;
@@ -551,14 +552,15 @@
             if (DEBUG) {
                 logTrace();
             }
-            mService = binderAsInterface(service);
+            I service = binderAsInterface(binder);
+            mService = service;
             mBinding = false;
             try {
-                service.linkToDeath(ServiceConnector.Impl.this, 0);
+                binder.linkToDeath(ServiceConnector.Impl.this, 0);
             } catch (RemoteException e) {
                 Log.e(LOG_TAG, "onServiceConnected " + name + ": ", e);
             }
-            onServiceConnectionStatusChanged(mService, true);
+            onServiceConnectionStatusChanged(service, true);
             processQueue();
         }
 
@@ -568,8 +570,11 @@
                 logTrace();
             }
             mBinding = true;
-            onServiceConnectionStatusChanged(mService, false);
-            mService = null;
+            I service = mService;
+            if (service != null) {
+                onServiceConnectionStatusChanged(service, false);
+                mService = null;
+            }
         }
 
         @Override
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 480ff4d..599c354 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -249,6 +249,14 @@
     private Drawable mOriginalBackgroundDrawable;
     private Drawable mLastOriginalBackgroundDrawable;
     private Drawable mResizingBackgroundDrawable;
+
+    /**
+     * Temporary holder for a window background when it is set before {@link #mWindow} is
+     * initialized. It will be set as the actual background once {@link #setWindow(PhoneWindow)} is
+     * called.
+     */
+    @Nullable
+    private Drawable mPendingWindowBackground;
     private Drawable mCaptionBackgroundDrawable;
     private Drawable mUserCaptionBackgroundDrawable;
 
@@ -961,6 +969,10 @@
     }
 
     public void setWindowBackground(Drawable drawable) {
+        if (mWindow == null) {
+            mPendingWindowBackground = drawable;
+            return;
+        }
         if (mOriginalBackgroundDrawable != drawable) {
             mOriginalBackgroundDrawable = drawable;
             updateBackgroundDrawable();
@@ -2003,6 +2015,11 @@
             DecorContext decorContext = (DecorContext) context;
             decorContext.setPhoneWindow(mWindow);
         }
+        if (mPendingWindowBackground != null) {
+            Drawable background = mPendingWindowBackground;
+            mPendingWindowBackground = null;
+            setWindowBackground(background);
+        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/util/AnnotationValidations.java b/core/java/com/android/internal/util/AnnotationValidations.java
new file mode 100644
index 0000000..c8afdd4
--- /dev/null
+++ b/core/java/com/android/internal/util/AnnotationValidations.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.util;
+
+import static com.android.internal.util.BitUtils.flagsUpTo;
+
+import android.annotation.AppIdInt;
+import android.annotation.ColorInt;
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Size;
+import android.annotation.UserIdInt;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.PackageInfoFlags;
+import android.content.pm.PackageManager.PermissionResult;
+import android.os.UserHandle;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Validations for common annotations, e.g. {@link IntRange}, {@link UserIdInt}, etc.
+ *
+ * For usability from generated {@link DataClass} code, all validations are overloads of
+ * {@link #validate} with the following shape:
+ * {@code
+ *      <A extends Annotation> void validate(
+ *              Class<A> cls, A ignored, Object value[, (String, Object)... annotationParams])
+ * }
+ * The ignored {@link Annotation} parameter is used to differentiate between overloads that would
+ * otherwise have the same jvm signature. It's usually null at runtime.
+ */
+public class AnnotationValidations {
+    private AnnotationValidations() {}
+
+    public static void validate(Class<UserIdInt> annotation, UserIdInt ignored, int value) {
+        if ((value != UserHandle.USER_NULL && value < -3)
+                || value > Integer.MAX_VALUE / UserHandle.PER_USER_RANGE) {
+            invalid(annotation, value);
+        }
+    }
+
+    public static void validate(Class<AppIdInt> annotation, AppIdInt ignored, int value) {
+        if (value / UserHandle.PER_USER_RANGE != 0 || value < 0) {
+            invalid(annotation, value);
+        }
+    }
+
+    public static void validate(Class<IntRange> annotation, IntRange ignored, int value,
+            String paramName1, int param1, String paramName2, int param2) {
+        validate(annotation, ignored, value, paramName1, param1);
+        validate(annotation, ignored, value, paramName2, param2);
+    }
+
+    public static void validate(Class<IntRange> annotation, IntRange ignored, int value,
+            String paramName, int param) {
+        switch (paramName) {
+            case "from": if (value < param) invalid(annotation, value, paramName, param); break;
+            case "to": if (value > param) invalid(annotation, value, paramName, param); break;
+        }
+    }
+
+    public static void validate(Class<FloatRange> annotation, FloatRange ignored, float value,
+            String paramName1, float param1, String paramName2, float param2) {
+        validate(annotation, ignored, value, paramName1, param1);
+        validate(annotation, ignored, value, paramName2, param2);
+    }
+
+    public static void validate(Class<FloatRange> annotation, FloatRange ignored, float value,
+            String paramName, float param) {
+        switch (paramName) {
+            case "from": if (value < param) invalid(annotation, value, paramName, param); break;
+            case "to": if (value > param) invalid(annotation, value, paramName, param); break;
+        }
+    }
+
+    public static void validate(Class<NonNull> annotation, NonNull ignored, Object value) {
+        if (value == null) {
+            throw new NullPointerException();
+        }
+    }
+
+    public static void validate(Class<Size> annotation, Size ignored, int value,
+            String paramName1, int param1, String paramName2, int param2) {
+        validate(annotation, ignored, value, paramName1, param1);
+        validate(annotation, ignored, value, paramName2, param2);
+    }
+
+    public static void validate(Class<Size> annotation, Size ignored, int value,
+            String paramName, int param) {
+        switch (paramName) {
+            case "value": {
+                if (param != -1 && value != param) invalid(annotation, value, paramName, param);
+            } break;
+            case "min": {
+                if (value < param) invalid(annotation, value, paramName, param);
+            } break;
+            case "max": {
+                if (value > param) invalid(annotation, value, paramName, param);
+            } break;
+            case "multiple": {
+                if (value % param != 0) invalid(annotation, value, paramName, param);
+            } break;
+        }
+    }
+
+    public static void validate(
+            Class<PermissionResult> annotation, PermissionResult ignored, int value) {
+        validateIntEnum(annotation, value, PackageManager.PERMISSION_GRANTED);
+    }
+
+    public static void validate(
+            Class<PackageInfoFlags> annotation, PackageInfoFlags ignored, int value) {
+        validateIntFlags(annotation, value,
+                flagsUpTo(PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS));
+    }
+
+    public static void validate(
+            Class<Intent.Flags> annotation, Intent.Flags ignored, int value) {
+        validateIntFlags(annotation, value, flagsUpTo(Intent.FLAG_RECEIVER_OFFLOAD));
+    }
+
+
+    @Deprecated
+    public static void validate(Class<? extends Annotation> annotation,
+            Annotation ignored, Object value, Object... params) {}
+    @Deprecated
+    public static void validate(Class<? extends Annotation> annotation,
+            Annotation ignored, Object value) {}
+    @Deprecated
+    public static void validate(Class<? extends Annotation> annotation,
+            Annotation ignored, int value, Object... params) {}
+    public static void validate(Class<? extends Annotation> annotation,
+            Annotation ignored, int value) {
+        if (("android.annotation".equals(annotation.getPackageName$())
+                && annotation.getSimpleName().endsWith("Res"))
+                || ColorInt.class.equals(annotation)) {
+            if (value < 0) {
+                invalid(annotation, value);
+            }
+        }
+    }
+    public static void validate(Class<? extends Annotation> annotation,
+            Annotation ignored, long value) {
+        if ("android.annotation".equals(annotation.getPackageName$())
+                && annotation.getSimpleName().endsWith("Long")) {
+            if (value < 0L) {
+                invalid(annotation, value);
+            }
+        }
+    }
+
+    private static void validateIntEnum(
+            Class<? extends Annotation> annotation, int value, int lastValid) {
+        if (value > lastValid) {
+            invalid(annotation, value);
+        }
+    }
+    private static void validateIntFlags(
+            Class<? extends Annotation> annotation, int value, int validBits) {
+        if ((validBits & value) != validBits) {
+            invalid(annotation, "0x" + Integer.toHexString(value));
+        }
+    }
+
+    private static void invalid(Class<? extends Annotation> annotation, Object value) {
+        invalid("@" + annotation.getSimpleName(), value);
+    }
+
+    private static void invalid(Class<? extends Annotation> annotation, Object value,
+            String paramName, Object param) {
+        String paramPrefix = "value".equals(paramName) ? "" : paramName + " = ";
+        invalid("@" + annotation.getSimpleName() + "(" + paramPrefix + param + ")", value);
+    }
+
+    private static void invalid(String valueKind, Object value) {
+        throw new IllegalStateException("Invalid " + valueKind + ": " + value);
+    }
+}
diff --git a/core/java/com/android/internal/util/BitUtils.java b/core/java/com/android/internal/util/BitUtils.java
index 6158145..b4bab80 100644
--- a/core/java/com/android/internal/util/BitUtils.java
+++ b/core/java/com/android/internal/util/BitUtils.java
@@ -158,4 +158,18 @@
     public static byte[] toBytes(long l) {
         return ByteBuffer.allocate(8).putLong(l).array();
     }
+
+    /**
+     * 0b01000 -> 0b01111
+     */
+    public static int flagsUpTo(int lastFlag) {
+        return lastFlag <= 0 ? 0 : lastFlag | flagsUpTo(lastFlag >> 1);
+    }
+
+    /**
+     * 0b00010, 0b01000 -> 0b01110
+     */
+    public static int flagsWithin(int firstFlag, int lastFlag) {
+        return (flagsUpTo(lastFlag) & ~flagsUpTo(firstFlag)) | firstFlag;
+    }
 }
diff --git a/core/java/com/android/internal/util/DataClass.java b/core/java/com/android/internal/util/DataClass.java
new file mode 100644
index 0000000..146f546
--- /dev/null
+++ b/core/java/com/android/internal/util/DataClass.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.util;
+
+import static java.lang.annotation.ElementType.*;
+
+import android.annotation.IntDef;
+import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.os.Parcelable;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface DataClass {
+
+    /**
+     * Generates {@link Parcelable#writeToParcel}, {@link Parcelable#describeContents} and a
+     * {@link Parcelable.Creator}.
+     *
+     * Can be implicitly requested by adding "implements Parcelable" to class signature
+     *
+     * You can provide custom parceling logic by using a {@link ParcelWith} annotation with a
+     * custom {@link Parcelling} subclass.
+     *
+     * Alternatively, for one-off customizations you can declare methods like:
+     * {@code void parcelFieldName(Parcel dest, int flags)}
+     * {@code static FieldType unparcelFieldName(Parcel in)}
+     */
+    boolean genParcelable() default false;
+
+    /**
+     * Generates a simple "parcelable" .aidl file alongside the original .java file
+     *
+     * If not explicitly requested/suppressed, is on iff {@link #genParcelable} is on
+     */
+    boolean genAidl() default false;
+
+    /**
+     * Generates getters for each field.
+     *
+     * You can request for getter to lazily initialize your field by declaring a method like:
+     * {@code FieldType lazyInitFieldName()}
+     *
+     * You can request for the lazy initialization to be thread safe my marking the field volatile.
+     */
+    boolean genGetters() default true;
+
+    /**
+     * Generates setters for each field.
+     */
+    boolean genSetters() default false;
+
+    /**
+     * Generates a public constructor with each field initialized from a parameter and optionally
+     * some user-defined state validation at the end.
+     *
+     * Uses field {@link Nullable nullability}/default value presence to determine optional
+     * parameters.
+     *
+     * Requesting a {@link #genBuilder} suppresses public constructor generation by default.
+     *
+     * You receive a callback at the end of constructor call by declaring the method:
+     * {@code void onConstructed()}
+     * This is the place to put any custom validation logic.
+     */
+    boolean genConstructor() default true;
+
+    /**
+     * Generates a Builder for your class.
+     *
+     * Uses a package-private constructor under the hood, so same rules hold as for
+     * {@link #genConstructor()}
+     */
+    boolean genBuilder() default false;
+
+    /**
+     * Generates a structural {@link Object#equals} + {@link Object#hashCode}.
+     *
+     * You can customize individual fields' logic by declaring methods like:
+     * {@link boolean fieldNameEquals(ClassName otherInstance)}
+     * {@link boolean fieldNameEquals(FieldType otherValue)}
+     * {@link int fieldNameHashCode()}
+     */
+    boolean genEqualsHashCode() default false;
+
+    /**
+     * Generates a structural {@link Object#toString}.
+     *
+     * You can customize individual fields' logic by declaring methods like:
+     * {@link String fieldNameToString()}
+     */
+    boolean genToString() default false;
+
+    /**
+     * Generates a utility method that takes a {@link PerObjectFieldAction per-field callback}
+     * and calls it once for each field with its name and value.
+     *
+     * If some fields are of primitive types, and additional overload is generated that takes
+     * multiple callbacks, specialized for used primitive types to avoid auto-boxing, e.g.
+     * {@link PerIntFieldAction}.
+     */
+    boolean genForEachField() default false;
+
+    /**
+     * Generates a constructor that copies the given instance of the same class.
+     */
+    boolean genCopyConstructor() default false;
+
+    /**
+     * Generates constant annotations({@link IntDef}/{@link StringDef}) for any constant groups
+     * with common prefix.
+     * The annotation names are based on the common prefix.
+     *
+     * For int constants this additionally generates the corresponding static *ToString method and
+     * uses it in {@link Object#toString}.
+     *
+     * Additionally, any fields you annotate with the generated constants will be automatically
+     * validated in constructor.
+     *
+     * Int constants specified as hex(0x..) are considered to be flags, which is taken into account
+     * for in their *ToString and validation.
+     *
+     * You can optionally override the name of the generated annotation by annotating each constant
+     * with the desired annotation name.
+     *
+     * Unless suppressed, is implied by presence of constants with common prefix.
+     */
+    boolean genConstDefs() default true;
+
+
+    /**
+     * Allows specifying custom parcelling logic based on reusable
+     * {@link Parcelling} implementations
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @Target(FIELD)
+    @interface ParcelWith {
+        Class<? extends Parcelling> value();
+    }
+
+    /**
+     * Allows specifying a singular name for a builder's plural field name e.g. 'name' for 'mNames'
+     * Used for Builder's {@code addName(String name)} methods
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @Target(FIELD)
+    @interface PluralOf {
+        String value();
+    }
+
+    /**
+     * Marks that any annotations following it are applicable to each element of the
+     * collection/array, as opposed to itself.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
+    @interface Each {}
+
+    /**
+     * @deprecated to be used by code generator exclusively
+     * @hide
+     */
+    @Deprecated
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE, ANNOTATION_TYPE, CONSTRUCTOR, TYPE})
+    @interface Generated {
+        long time();
+        String codegenVersion();
+        String sourceFile();
+        String inputSignatures() default "";
+
+        /**
+         * @deprecated to be used by code generator exclusively
+         * @hide
+         */
+        @Deprecated
+        @Retention(RetentionPolicy.SOURCE)
+        @Target({FIELD, METHOD, ANNOTATION_TYPE, CONSTRUCTOR, TYPE})
+        @interface Member {}
+    }
+
+    /**
+     * Callback used by {@link #genForEachField}.
+     *
+     * @param <THIS> The enclosing data class instance.
+     *              Can be used to try and avoid capturing values from outside of the lambda,
+     *              minimizing allocations.
+     */
+    interface PerObjectFieldAction<THIS> {
+        void acceptObject(THIS self, String fieldName, Object fieldValue);
+    }
+
+    /**
+     * A specialization of {@link PerObjectFieldAction} called exclusively for int fields to avoid
+     * boxing.
+     */
+    interface PerIntFieldAction<THIS> {
+        void acceptInt(THIS self, String fieldName, int fieldValue);
+    }
+}
diff --git a/core/java/com/android/internal/util/Parcelling.java b/core/java/com/android/internal/util/Parcelling.java
new file mode 100644
index 0000000..63530dc
--- /dev/null
+++ b/core/java/com/android/internal/util/Parcelling.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.util;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.util.ArrayMap;
+
+import java.util.regex.Pattern;
+
+/**
+ * Describes a 2-way parcelling contract of type {@code T} into/out of a {@link Parcel}
+ *
+ * @param <T> the type being [un]parcelled
+ */
+public interface Parcelling<T> {
+
+    /**
+     * Write an item into parcel.
+     */
+    void parcel(T item, Parcel dest, int parcelFlags);
+
+    /**
+     * Read an item from parcel.
+     */
+    T unparcel(Parcel source);
+
+
+    /**
+     * A registry of {@link Parcelling} singletons.
+     */
+    class Cache {
+        private Cache() {}
+
+        private static ArrayMap<Class, Parcelling> sCache = new ArrayMap<>();
+
+        /**
+         * Retrieves an instance of a given {@link Parcelling} class if present.
+         */
+        public static @Nullable <P extends Parcelling<?>> P get(Class<P> clazz) {
+            return (P) sCache.get(clazz);
+        }
+
+        /**
+         * Stores an instance of a given {@link Parcelling}.
+         *
+         * @return the provided parcelling for convenience.
+         */
+        public static <P extends Parcelling<?>> P put(P parcelling) {
+            sCache.put(parcelling.getClass(), parcelling);
+            return parcelling;
+        }
+
+        /**
+         * Produces an instance of a given {@link Parcelling} class, by either retrieving a cached
+         * instance or reflectively creating one.
+         */
+        public static <P extends Parcelling<?>> P getOrCreate(Class<P> clazz) {
+            P cached = get(clazz);
+            if (cached != null) {
+                return cached;
+            } else {
+                try {
+                    return put(clazz.newInstance());
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Common {@link Parcelling} implementations.
+     */
+    interface BuiltIn {
+
+        class ForPattern implements Parcelling<Pattern> {
+
+            @Override
+            public void parcel(Pattern item, Parcel dest, int parcelFlags) {
+                dest.writeString(item == null ? null : item.pattern());
+            }
+
+            @Override
+            public Pattern unparcel(Parcel source) {
+                String s = source.readString();
+                return s == null ? null : Pattern.compile(s);
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 9fc79cb..364278d 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -194,9 +194,8 @@
     final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
     final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
 
-    final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppPermissions = new ArrayMap<>();
-    final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppDenyPermissions =
-            new ArrayMap<>();
+    final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
+    final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>();
 
     final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
 
@@ -321,12 +320,20 @@
         return mProductPrivAppDenyPermissions.get(packageName);
     }
 
-    public ArraySet<String> getProductServicesPrivAppPermissions(String packageName) {
-        return mProductServicesPrivAppPermissions.get(packageName);
+    /**
+     * Read from "permission" tags in /system_ext/etc/permissions/*.xml
+     * @return Set of privileged permissions that are explicitly granted.
+     */
+    public ArraySet<String> getSystemExtPrivAppPermissions(String packageName) {
+        return mSystemExtPrivAppPermissions.get(packageName);
     }
 
-    public ArraySet<String> getProductServicesPrivAppDenyPermissions(String packageName) {
-        return mProductServicesPrivAppDenyPermissions.get(packageName);
+    /**
+     * Read from "deny-permission" tags in /system_ext/etc/permissions/*.xml
+     * @return Set of privileged permissions that are explicitly denied.
+     */
+    public ArraySet<String> getSystemExtPrivAppDenyPermissions(String packageName) {
+        return mSystemExtPrivAppDenyPermissions.get(packageName);
     }
 
     public Map<String, Boolean> getOemPermissions(String packageName) {
@@ -398,11 +405,11 @@
         readPermissions(Environment.buildPath(
                 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
 
-        // Allow /product_services to customize all system configs
+        // Allow /system_ext to customize all system configs
         readPermissions(Environment.buildPath(
-                Environment.getProductServicesDirectory(), "etc", "sysconfig"), ALLOW_ALL);
+                Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
         readPermissions(Environment.buildPath(
-                Environment.getProductServicesDirectory(), "etc", "permissions"), ALLOW_ALL);
+                Environment.getSystemExtDirectory(), "etc", "permissions"), ALLOW_ALL);
     }
 
     void readPermissions(File libraryDir, int permissionFlag) {
@@ -848,7 +855,7 @@
                     } break;
                     case "privapp-permissions": {
                         if (allowPrivappPermissions) {
-                            // privapp permissions from system, vendor, product and product_services
+                            // privapp permissions from system, vendor, product and system_ext
                             // partitions are stored separately. This is to prevent xml files in
                             // the vendor partition from granting permissions to priv apps in the
                             // system partition and vice versa.
@@ -858,17 +865,17 @@
                                     Environment.getOdmDirectory().toPath() + "/");
                             boolean product = permFile.toPath().startsWith(
                                     Environment.getProductDirectory().toPath() + "/");
-                            boolean productServices = permFile.toPath().startsWith(
-                                    Environment.getProductServicesDirectory().toPath() + "/");
+                            boolean systemExt = permFile.toPath().startsWith(
+                                    Environment.getSystemExtDirectory().toPath() + "/");
                             if (vendor) {
                                 readPrivAppPermissions(parser, mVendorPrivAppPermissions,
                                         mVendorPrivAppDenyPermissions);
                             } else if (product) {
                                 readPrivAppPermissions(parser, mProductPrivAppPermissions,
                                         mProductPrivAppDenyPermissions);
-                            } else if (productServices) {
-                                readPrivAppPermissions(parser, mProductServicesPrivAppPermissions,
-                                        mProductServicesPrivAppDenyPermissions);
+                            } else if (systemExt) {
+                                readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
+                                        mSystemExtPrivAppDenyPermissions);
                             } else {
                                 readPrivAppPermissions(parser, mPrivAppPermissions,
                                         mPrivAppDenyPermissions);
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index 6934d26..06e31a1 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -18,8 +18,9 @@
 
 #include <jni.h>
 #include <android/bitmap.h>
-#include <SkBitmap.h>
-#include <SkImageInfo.h>
+
+class SkBitmap;
+struct SkImageInfo;
 
 namespace android {
 
@@ -34,8 +35,8 @@
 };
 
 jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
-            int bitmapCreateFlags, jbyteArray ninePatchChunk = NULL,
-            jobject ninePatchInsets = NULL, int density = -1);
+            int bitmapCreateFlags, jbyteArray ninePatchChunk = nullptr,
+            jobject ninePatchInsets = nullptr, int density = -1);
 
 
 void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap);
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index d29857d..d1b952130 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -100,8 +100,9 @@
         this->endRecording();
         SkASSERT(NULL != mPicture.get());
     }
-    if (NULL != mPicture.get()) {
-        mPicture->playback(canvas->asSkCanvas());
+
+    if (mPicture) {
+        canvas->drawPicture(*mPicture);
     }
 }
 
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 55abc93..58c5871 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -16,7 +16,6 @@
 
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
-#include "GraphicsJNI.h"
 
 #include <math.h>
 #include <stdio.h>
@@ -33,6 +32,7 @@
 #include <SkBitmap.h>
 
 #include "core_jni_helpers.h"
+#include "android/graphics/Bitmap.h"
 
 #undef LOG_TAG
 #define LOG_TAG "OpenGLUtil"
@@ -43,6 +43,10 @@
 
 namespace android {
 
+static void doThrowIAE(JNIEnv* env, const char* msg = nullptr) {
+    jniThrowException(env, "java/lang/IllegalArgumentException", msg);
+}
+
 static inline
 void mx4transform(float x, float y, float z, float w, const float* pM, float* pDest) {
     pDest[0] = pM[0 + 4 * 0] * x + pM[0 + 4 * 1] * y + pM[0 + 4 * 2] * z + pM[0 + 4 * 3] * w;
@@ -706,7 +710,7 @@
         jlong bitmapPtr)
 {
     SkBitmap nativeBitmap;
-    bitmap::toBitmap(bitmapPtr).getSkBitmap(&nativeBitmap);
+    bitmap::toSkBitmap(bitmapPtr, &nativeBitmap);
     return getInternalFormat(nativeBitmap.colorType());
 }
 
@@ -714,7 +718,7 @@
         jlong bitmapPtr)
 {
     SkBitmap nativeBitmap;
-    bitmap::toBitmap(bitmapPtr).getSkBitmap(&nativeBitmap);
+    bitmap::toSkBitmap(bitmapPtr, &nativeBitmap);
     return getType(nativeBitmap.colorType());
 }
 
@@ -723,7 +727,7 @@
         jlong bitmapPtr, jint type, jint border)
 {
     SkBitmap bitmap;
-    bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
+    bitmap::toSkBitmap(bitmapPtr, &bitmap);
     SkColorType colorType = bitmap.colorType();
     if (internalformat < 0) {
         internalformat = getInternalFormat(colorType);
@@ -751,7 +755,7 @@
         jlong bitmapPtr, jint format, jint type)
 {
     SkBitmap bitmap;
-    bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
+    bitmap::toSkBitmap(bitmapPtr, &bitmap);
     SkColorType colorType = bitmap.colorType();
     int internalFormat = getInternalFormat(colorType);
     if (format < 0) {
diff --git a/core/jni/android_app_ActivityThread.cpp b/core/jni/android_app_ActivityThread.cpp
index 93f2525..3a08148 100644
--- a/core/jni/android_app_ActivityThread.cpp
+++ b/core/jni/android_app_ActivityThread.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "jni.h"
-#include "GraphicsJNI.h"
 #include <nativehelper/JNIHelp.h>
 
 #include <minikin/Layout.h>
diff --git a/core/jni/android_nio_utils.h b/core/jni/android_nio_utils.h
index aa75dd0..4aaa0a7 100644
--- a/core/jni/android_nio_utils.h
+++ b/core/jni/android_nio_utils.h
@@ -17,7 +17,7 @@
 #ifndef _ANDROID_NIO_UTILS_H_
 #define _ANDROID_NIO_UTILS_H_
 
-#include <android_runtime/AndroidRuntime.h>
+#include <nativehelper/JNIHelp.h>
 
 namespace android {
 
@@ -68,12 +68,12 @@
     AutoBufferPointer() = delete;
     AutoBufferPointer(AutoBufferPointer&) = delete;
     AutoBufferPointer& operator=(AutoBufferPointer&) = delete;
-    static void* operator new(std::size_t);
-    static void* operator new[](std::size_t);
-    static void* operator new(std::size_t, void*);
-    static void* operator new[](std::size_t, void*);
-    static void operator delete(void*, std::size_t);
-    static void operator delete[](void*, std::size_t);
+    static void* operator new(size_t);
+    static void* operator new[](size_t);
+    static void* operator new(size_t, void*);
+    static void* operator new[](size_t, void*);
+    static void operator delete(void*, size_t);
+    static void operator delete[](void*, size_t);
 };
 
 }   /* namespace android */
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index c3e7a36..13e1dfa 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -259,6 +259,8 @@
             which_heap = HEAP_NATIVE;
         } else if (base::StartsWith(name, "[stack")) {
             which_heap = HEAP_STACK;
+        } else if (base::StartsWith(name, "[anon:stack_and_tls:")) {
+            which_heap = HEAP_STACK;
         } else if (base::EndsWith(name, ".so")) {
             which_heap = HEAP_SO;
             is_swappable = true;
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index d6d9391..bf4ffc7 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -161,7 +161,7 @@
       }
 
       // Generic idmap parameters
-      const char* argv[10];
+      const char* argv[11];
       int argc = 0;
       struct stat st;
 
@@ -193,8 +193,8 @@
         argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
       }
 
-      if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) {
-        argv[argc++] = AssetManager::PRODUCT_SERVICES_OVERLAY_DIR;
+      if (stat(AssetManager::SYSTEM_EXT_OVERLAY_DIR, &st) == 0) {
+        argv[argc++] = AssetManager::SYSTEM_EXT_OVERLAY_DIR;
       }
 
       if (stat(AssetManager::ODM_OVERLAY_DIR, &st) == 0) {
@@ -235,8 +235,8 @@
     input_dirs.push_back(AssetManager::PRODUCT_OVERLAY_DIR);
   }
 
-  if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) {
-    input_dirs.push_back(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR);
+  if (stat(AssetManager::SYSTEM_EXT_OVERLAY_DIR, &st) == 0) {
+    input_dirs.push_back(AssetManager::SYSTEM_EXT_OVERLAY_DIR);
   }
 
   if (stat(AssetManager::ODM_OVERLAY_DIR, &st) == 0) {
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
index c9eac79..ca32b00 100644
--- a/core/jni/android_view_RenderNodeAnimator.cpp
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "OpenGLRenderer"
 
 #include "jni.h"
-#include "GraphicsJNI.h"
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 78dd1aa..a579229 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -21,10 +21,10 @@
 #include "android_util_Binder.h"
 #include "android_hardware_input_InputWindowHandle.h"
 #include "android/graphics/Bitmap.h"
-#include "android/graphics/GraphicsJNI.h"
 #include "android/graphics/Region.h"
 #include "core_jni_helpers.h"
 
+#include <android_runtime/AndroidRuntime.h>
 #include <android-base/chrono_utils.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedUtfChars.h>
@@ -50,6 +50,14 @@
 
 namespace android {
 
+static void doThrowNPE(JNIEnv* env) {
+    jniThrowNullPointerException(env, NULL);
+}
+
+static void doThrowIAE(JNIEnv* env, const char* msg = nullptr) {
+    jniThrowException(env, "java/lang/IllegalArgumentException", msg);
+}
+
 static const char* const OutOfResourcesException =
     "android/view/Surface$OutOfResourcesException";
 
diff --git a/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp b/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
index d20bae2..d629d63 100644
--- a/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
+++ b/core/jni/com_android_internal_util_VirtualRefBasePtr.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "jni.h"
 #include <nativehelper/JNIHelp.h>
+#include <utils/LightRefBase.h>
 #include "core_jni_helpers.h"
 
 namespace android {
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 940ac22..5aea848 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -30,10 +30,6 @@
 #include <gui/GLConsumer.h>
 #include <gui/Surface.h>
 
-#include <GraphicsJNI.h>
-#include <SkBitmap.h>
-#include <SkPixelRef.h>
-
 #include <ui/ANativeObjectBase.h>
 
 namespace android {
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index e5d6393..ea4b252 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -100,8 +100,8 @@
   static const char* kVendorOverlaySubdir = "/system/vendor/overlay-subdir/";
   static const char* kSystemProductOverlayDir = "/system/product/overlay/";
   static const char* kProductOverlayDir = "/product/overlay";
-  static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/";
-  static const char* kProductServicesOverlayDir = "/product_services/overlay";
+  static const char* kSystemSystemExtOverlayDir = "/system/system_ext/overlay/";
+  static const char* kSystemExtOverlayDir = "/system_ext/overlay";
   static const char* kSystemOdmOverlayDir = "/system/odm/overlay";
   static const char* kOdmOverlayDir = "/odm/overlay";
   static const char* kSystemOemOverlayDir = "/system/oem/overlay";
@@ -113,8 +113,8 @@
        || android::base::StartsWith(path, kVendorOverlayDir)
        || android::base::StartsWith(path, kSystemProductOverlayDir)
        || android::base::StartsWith(path, kProductOverlayDir)
-       || android::base::StartsWith(path, kSystemProductServicesOverlayDir)
-       || android::base::StartsWith(path, kProductServicesOverlayDir)
+       || android::base::StartsWith(path, kSystemSystemExtOverlayDir)
+       || android::base::StartsWith(path, kSystemExtOverlayDir)
        || android::base::StartsWith(path, kSystemOdmOverlayDir)
        || android::base::StartsWith(path, kOdmOverlayDir)
        || android::base::StartsWith(path, kSystemOemOverlayDir)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ebf5b93..df45ec5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -727,7 +727,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
     -->
     <permission android:name="android.permission.SEND_SMS"
@@ -741,7 +741,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
     -->
     <permission android:name="android.permission.RECEIVE_SMS"
@@ -755,7 +755,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
     -->
     <permission android:name="android.permission.READ_SMS"
@@ -769,7 +769,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
     -->
     <permission android:name="android.permission.RECEIVE_WAP_PUSH"
@@ -783,7 +783,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
     -->
     <permission android:name="android.permission.RECEIVE_MMS"
@@ -806,7 +806,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
 
          @hide Pending API council approval -->
@@ -852,7 +852,7 @@
       targetSdkVersion}</a> is 4 or higher.
 
       <p> This is a soft restricted permission which cannot be held by an app it its
-      full form until the installer on record did not whitelist the permission.
+      full form until the installer on record whitelists the permission.
       Specifically, if the permission is whitelisted the holder app can access
       external storage and the visual and aural media collections while if the
       permission is not whitelisted the holder app can only access to the visual
@@ -860,7 +860,7 @@
       meaning that the whitelist state can be specified only at install time and
       cannot change until the app is installed. For more details see
       {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-     -->
+     <p>Protection level: dangerous -->
     <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
         android:permissionGroup="android.permission-group.UNDEFINED"
         android:label="@string/permlab_sdcardRead"
@@ -881,8 +881,9 @@
          read/write files in your application-specific directories returned by
          {@link android.content.Context#getExternalFilesDir} and
          {@link android.content.Context#getExternalCacheDir}.
-         <p>Is this permission is not whitelisted for an app that targets an API level before
+         <p>If this permission is not whitelisted for an app that targets an API level before
          {@link android.os.Build.VERSION_CODES#Q} this permission cannot be granted to apps.</p>
+         <p>Protection level: dangerous</p>
     -->
     <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
         android:permissionGroup="android.permission-group.UNDEFINED"
@@ -892,7 +893,8 @@
         android:protectionLevel="dangerous" />
 
     <!-- Allows an application to access any geographic locations persisted in the
-         user's shared collection. -->
+         user's shared collection.
+         <p>Protection level: dangerous -->
     <permission android:name="android.permission.ACCESS_MEDIA_LOCATION"
         android:permissionGroup="android.permission-group.UNDEFINED"
         android:label="@string/permlab_mediaLocation"
@@ -949,7 +951,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
     -->
     <permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
@@ -995,7 +997,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
     -->
     <permission android:name="android.permission.READ_CALL_LOG"
@@ -1019,7 +1021,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
     -->
     <permission android:name="android.permission.WRITE_CALL_LOG"
@@ -1035,7 +1037,7 @@
          <p>Protection level: dangerous
 
          <p> This is a hard restricted permission which cannot be held by an app until
-         the installer on record did not whitelist the permission. For more details see
+         the installer on record whitelists the permission. For more details see
          {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
 
          @deprecated Applications should use {@link android.telecom.CallRedirectionService} instead
@@ -1694,7 +1696,7 @@
 
     <!-- Allows applications to pair bluetooth devices without user interaction, and to
          allow or disallow phonebook access or message access.
-         This is not available to third party applications. -->
+         <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.BLUETOOTH_PRIVILEGED"
         android:protectionLevel="signature|privileged" />
 
@@ -2544,7 +2546,8 @@
         android:protectionLevel="signature" />
 
     <!-- Allows an application to modify the current configuration, such
-         as locale. -->
+         as locale.
+         <p>Protection level: signature|privileged|development -->
     <permission android:name="android.permission.CHANGE_CONFIGURATION"
         android:protectionLevel="signature|privileged|development" />
 
@@ -2843,7 +2846,8 @@
     <!-- ==================================== -->
     <eat-comment />
 
-    <!-- Allows access to the list of accounts in the Accounts Service. -->
+    <!-- Allows access to the list of accounts in the Accounts Service.
+         <p>Protection level: signature|privileged -->
     <permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED"
         android:protectionLevel="signature|privileged" />
 
@@ -3429,7 +3433,8 @@
         android:protectionLevel="signature" />
 
     <!-- Old permission for deleting an app's cache files, no longer used,
-         but signals for us to quietly ignore calls instead of throwing an exception. -->
+         but signals for us to quietly ignore calls instead of throwing an exception.
+         <p>Protection level: signature|privileged -->
     <permission android:name="android.permission.DELETE_CACHE_FILES"
         android:protectionLevel="signature|privileged" />
 
@@ -3792,7 +3797,8 @@
     <!-- Allows an application to collect component usage
          statistics
          <p>Declaring the permission implies intention to use the API and the user of the
-         device can grant permission through the Settings application. -->
+         device can grant permission through the Settings application.
+         <p>Protection level: signature|privileged|development|appop -->
     <permission android:name="android.permission.PACKAGE_USAGE_STATS"
         android:protectionLevel="signature|privileged|development|appop" />
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
@@ -3815,14 +3821,14 @@
 
     <!-- Permission an application must hold in order to use
          {@link android.provider.Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS}.
-         This is a normal permission: an app requesting it will always be granted the
-         permission, without the user needing to approve or see it. -->
+         <p>Protection level: normal -->
     <permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"
         android:label="@string/permlab_requestIgnoreBatteryOptimizations"
         android:description="@string/permdesc_requestIgnoreBatteryOptimizations"
         android:protectionLevel="normal" />
 
-    <!-- Allows an application to collect battery statistics -->
+    <!-- Allows an application to collect battery statistics
+         <p>Protection level: signature|privileged|development -->
     <permission android:name="android.permission.BATTERY_STATS"
         android:protectionLevel="signature|privileged|development" />
 
@@ -3852,7 +3858,8 @@
         android:protectionLevel="signature" />
 
     <!-- Must be required by a {@link android.widget.RemoteViewsService},
-         to ensure that only the system can bind to it. -->
+         to ensure that only the system can bind to it.
+         <p>Protection level: signature|privileged -->
     <permission android:name="android.permission.BIND_REMOTEVIEWS"
         android:protectionLevel="signature|privileged" />
 
@@ -3894,7 +3901,8 @@
          to the path in the provider where global search queries are
          performed.  This permission can not be held by regular applications;
          it is used by applications to protect themselves from everyone else
-         besides global search. -->
+         besides global search.
+         <p>Protection level: signature|privileged -->
     <permission android:name="android.permission.GLOBAL_SEARCH"
         android:protectionLevel="signature|privileged" />
 
@@ -4433,7 +4441,8 @@
     <permission android:name="android.permission.MODIFY_THEME_OVERLAY"
                 android:protectionLevel="signature" />
 
-    <!-- Allows an instant app to create foreground services. -->
+    <!-- Allows an instant app to create foreground services.
+         <p>Protection level: signature|development|instant|appop -->
     <permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"
         android:protectionLevel="signature|development|instant|appop" />
 
@@ -4503,7 +4512,8 @@
     <permission android:name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE"
         android:protectionLevel="signature|privileged" />
 
-    <!-- A subclass of {@link android.service.carrier.CarrierMessagingClientService} must be protected with this permission. -->
+    <!-- A subclass of {@link android.service.carrier.CarrierMessagingClientService} must be protected with this permission.
+           <p>Protection level: signature -->
     <permission android:name="android.permission.BIND_CARRIER_MESSAGING_CLIENT_SERVICE"
         android:protectionLevel="signature" />
 
@@ -4535,13 +4545,15 @@
     <permission android:name="android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS"
         android:protectionLevel="signature" />
 
-    <!-- Allows financial apps to read filtered sms messages. -->
+    <!-- Allows financial apps to read filtered sms messages.
+         Protection level: signature|appop  -->
     <permission android:name="android.permission.SMS_FINANCIAL_TRANSACTIONS"
         android:protectionLevel="signature|appop" />
 
     <!-- Required for apps targeting {@link android.os.Build.VERSION_CODES#Q} that want to use
          {@link android.app.Notification.Builder#setFullScreenIntent notification full screen
-         intents}.  -->
+         intents}.
+         <p>Protection level: normal -->
     <permission android:name="android.permission.USE_FULL_SCREEN_INTENT"
                 android:protectionLevel="normal" />
 
@@ -4981,6 +4993,7 @@
         <service
                 android:name="com.android.server.autofill.AutofillCompatAccessibilityService"
                 android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
+                android:visibleToInstantApps="true"
                 android:exported="true">
             <meta-data
                     android:name="android.accessibilityservice"
diff --git a/core/res/res/layout/notification_template_material_media.xml b/core/res/res/layout/notification_template_material_media.xml
index 13fef67..575295b 100644
--- a/core/res/res/layout/notification_template_material_media.xml
+++ b/core/res/res/layout/notification_template_material_media.xml
@@ -15,7 +15,7 @@
   ~ limitations under the License
   -->
 
-<FrameLayout
+<com.android.internal.widget.MediaNotificationView
     android:id="@+id/status_bar_latest_event_content"
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
@@ -24,8 +24,8 @@
     android:tag="media"
     >
     <ImageView android:id="@+id/right_icon"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_width="0dp"
+        android:layout_height="0dp"
         android:adjustViewBounds="true"
         android:layout_gravity="top|end"
         android:scaleType="centerCrop"
@@ -91,4 +91,4 @@
             android:layout_alignParentBottom="true"
         />
     </LinearLayout>
-</FrameLayout>
+</com.android.internal.widget.MediaNotificationView>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 7cfcaf4..bbf1736 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -595,7 +595,7 @@
   </string-array>
     <string name="face_icon_content_description" msgid="4024817159806482191">"Icona facial"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"llegir la configuració de sincronització"</string>
-    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permet que l\'aplicació llegeixi la configuració de sincronització d\'un compte. Per exemple, això pot determinar que l\'aplicació Persones estigui sincronitzada amb un compte."</string>
+    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Permet que l\'aplicació llegeixi la configuració de sincronització d\'un compte. Per exemple, això pot determinar que l\'aplicació Contactes estigui sincronitzada amb un compte."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"activar o desactivar la sincronització"</string>
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Permet que una aplicació modifiqui la configuració de sincronització d\'un compte. Per exemple, aquesta acció es pot fer servir per activar la sincronització de l\'aplicació Persones amb un compte."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"llegir les estadístiques de sincronització"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 5316d13..114d801 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -429,7 +429,7 @@
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Diese App kann jederzeit Audio über das Mikrofon aufnehmen."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"Befehle an die SIM senden"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Ermöglicht der App das Senden von Befehlen an die SIM-Karte. Dies ist äußerst risikoreich."</string>
-    <string name="permlab_activityRecognition" msgid="3634590230567608356">"körperlichen Aktivitäten erkennen"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"Körperliche Aktivitäten erkennen"</string>
     <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Diese App kann deine körperliche Aktivität erkennen."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"Bilder und Videos aufnehmen"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Diese App kann mit der Kamera jederzeit Bilder und Videos aufnehmen."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 18bba90..b3eed4a 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1985,7 +1985,7 @@
     <string name="harmful_app_warning_uninstall" msgid="4837672735619532931">"DESINSTALAR"</string>
     <string name="harmful_app_warning_open_anyway" msgid="596432803680914321">"ABRIR IGUALMENTE"</string>
     <string name="harmful_app_warning_title" msgid="8982527462829423432">"Detectouse unha aplicación daniña"</string>
-    <string name="slices_permission_request" msgid="8484943441501672932">"A aplicación <xliff:g id="APP_0">%1$s</xliff:g> quere mostrar partes de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
+    <string name="slices_permission_request" msgid="8484943441501672932">"<xliff:g id="APP_0">%1$s</xliff:g> quere mostrar fragmentos de aplicación de <xliff:g id="APP_2">%2$s</xliff:g>"</string>
     <string name="screenshot_edit" msgid="7867478911006447565">"Editar"</string>
     <string name="volume_dialog_ringer_guidance_vibrate" msgid="8902050240801159042">"As chamadas e as notificacións vibrarán"</string>
     <string name="volume_dialog_ringer_guidance_silent" msgid="2128975224280276122">"As chamadas e as notificacións estarán silenciadas"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index cb4886a..7165df9 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1614,7 +1614,7 @@
     <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"Ներկառուցված էկրան"</string>
     <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"HDMI էկրան"</string>
     <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Վերածածկ #<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> կմվ"</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> կմչ"</string>
     <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", անվտանգ"</string>
     <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"Մոռացել եմ սխեման"</string>
     <string name="kg_wrong_pattern" msgid="1850806070801358830">"Սխալ սխեմա"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a90acfa..054a456 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1712,7 +1712,7 @@
     <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"Gdy skrót jest włączony, jednoczesne naciśnięcie przez trzy sekundy obu klawiszy sterowania głośnością uruchomi funkcję ułatwień dostępu.\n\nBieżąca funkcja ułatwień dostępu:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nFunkcję możesz zmienić, wybierając Ustawienia &gt; Ułatwienia dostępu."</string>
     <string name="disable_accessibility_shortcut" msgid="627625354248453445">"Wyłącz skrót"</string>
     <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"Użyj skrótu"</string>
-    <string name="color_inversion_feature_name" msgid="4231186527799958644">"Inwersja kolorów"</string>
+    <string name="color_inversion_feature_name" msgid="4231186527799958644">"Odwrócenie kolorów"</string>
     <string name="color_correction_feature_name" msgid="6779391426096954933">"Korekcja kolorów"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"Skrót ułatwień dostępu wyłączył usługę <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"Skrót ułatwień dostępu wyłączył usługę <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index f2eb9d4..78c4290 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -521,7 +521,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Cho phép ứng dụng này sửa đổi bộ sưu tập ảnh của bạn."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"đọc vị trí từ bộ sưu tập phương tiện"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Cho phép ứng dụng này đọc vị trí từ bộ sưu tập phương tiện của bạn."</string>
-    <string name="biometric_dialog_default_title" msgid="881952973720613213">"Hãy xác minh đó là bạn"</string>
+    <string name="biometric_dialog_default_title" msgid="881952973720613213">"Xác minh danh tính của bạn"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Không có phần cứng sinh trắc học"</string>
     <string name="biometric_error_user_canceled" msgid="2260175018114348727">"Đã hủy xác thực"</string>
     <string name="biometric_not_recognized" msgid="5770511773560736082">"Không nhận dạng được"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 9ac4582..884772e 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -551,11 +551,11 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"指紋圖示"</string>
-    <string name="permlab_manageFace" msgid="7262837876352591553">"管理臉容解鎖硬件"</string>
+    <string name="permlab_manageFace" msgid="7262837876352591553">"管理臉孔解鎖硬件"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"允許應用程式調用方法,以加入和刪除可用的臉孔範本。"</string>
-    <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"使用臉容解鎖硬件"</string>
-    <string name="permdesc_useFaceAuthentication" msgid="4712947955047607722">"允許應用程式使用臉容解鎖硬件來驗證"</string>
-    <string name="face_recalibrate_notification_name" msgid="1913676850645544352">"臉容解鎖"</string>
+    <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"使用臉孔解鎖硬件"</string>
+    <string name="permdesc_useFaceAuthentication" msgid="4712947955047607722">"允許應用程式使用臉孔解鎖硬件來驗證"</string>
+    <string name="face_recalibrate_notification_name" msgid="1913676850645544352">"臉孔解鎖"</string>
     <string name="face_recalibrate_notification_title" msgid="4087620069451499365">"重新註冊臉孔"</string>
     <string name="face_recalibrate_notification_content" msgid="5530308842361499835">"如要提高識別能力,請重新註冊您的臉孔"</string>
     <string name="face_acquired_insufficient" msgid="2767330364802375742">"無法擷取準確的臉容資料。請再試一次。"</string>
@@ -581,15 +581,15 @@
   <string-array name="face_acquired_vendor">
   </string-array>
     <string name="face_error_hw_not_available" msgid="396883585636963908">"無法驗證臉孔,硬件無法使用。"</string>
-    <string name="face_error_timeout" msgid="981512090365729465">"請再次嘗試「臉容解鎖」。"</string>
+    <string name="face_error_timeout" msgid="981512090365729465">"請再次嘗試「臉孔解鎖」。"</string>
     <string name="face_error_no_space" msgid="2712120617457553825">"無法儲存新的臉容資料,請先刪除舊資料。"</string>
     <string name="face_error_canceled" msgid="283945501061931023">"臉孔操作已取消。"</string>
-    <string name="face_error_user_canceled" msgid="5317030072349668946">"使用者已取消「臉容解鎖」。"</string>
+    <string name="face_error_user_canceled" msgid="5317030072349668946">"使用者已取消「臉孔解鎖」。"</string>
     <string name="face_error_lockout" msgid="3407426963155388504">"嘗試次數過多,請稍後再試。"</string>
-    <string name="face_error_lockout_permanent" msgid="4723594314443097159">"嘗試次數過多,「臉容解鎖」已停用。"</string>
+    <string name="face_error_lockout_permanent" msgid="4723594314443097159">"嘗試次數過多,「臉孔解鎖」已停用。"</string>
     <string name="face_error_unable_to_process" msgid="4940944939691171539">"無法驗證臉孔。請再試一次。"</string>
-    <string name="face_error_not_enrolled" msgid="4016937174832839540">"您尚未設定「臉容解鎖」。"</string>
-    <string name="face_error_hw_not_present" msgid="8302690289757559738">"此裝置不支援「臉容解鎖」。"</string>
+    <string name="face_error_not_enrolled" msgid="4016937174832839540">"您尚未設定「臉孔解鎖」。"</string>
+    <string name="face_error_hw_not_present" msgid="8302690289757559738">"此裝置不支援「臉孔解鎖」。"</string>
     <string name="face_name_template" msgid="7004562145809595384">"臉孔 <xliff:g id="FACEID">%d</xliff:g>"</string>
   <string-array name="face_error_vendor">
   </string-array>
@@ -818,7 +818,7 @@
     <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"再試一次"</string>
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"再試一次"</string>
     <string name="lockscreen_storage_locked" msgid="9167551160010625200">"解鎖即可使用所有功能和資料"</string>
-    <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超過臉容解鎖嘗試次數上限"</string>
+    <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超過臉孔解鎖嘗試次數上限"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"找不到 SIM 卡"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板電腦中沒有 SIM 卡。"</string>
     <string name="lockscreen_missing_sim_message" product="tv" msgid="1943633865476989599">"電視沒有 SIM 卡。"</string>
@@ -888,7 +888,7 @@
     <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>
-    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"臉容解鎖。"</string>
+    <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"臉孔解鎖。"</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"PIN 解鎖。"</string>
     <string name="keyguard_accessibility_sim_pin_unlock" msgid="9149698847116962307">"SIM 卡 PIN 碼解鎖。"</string>
     <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"SIM 卡 PUK 解鎖。"</string>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 77fca8f..be6cdcf 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1315,7 +1315,11 @@
          it will yield the baseIntent to any activity that it launches in the same task. This
          continues until an activity is encountered which has this attribute set to false. False
          is the default. This attribute set to true also permits activity's use of the
-         TaskDescription to change labels, colors and icons in the recent task list. -->
+         TaskDescription to change labels, colors and icons in the recent task list.
+
+         <p>NOTE: Setting this flag to <code>true</code> will not change the affinity of the task,
+         which is used for intent resolution during activity launch. The task's root activity will
+         always define its affinity. -->
     <attr name="relinquishTaskIdentity" format="boolean" />
 
     <!-- Indicate that it is okay for this activity be resumed while the previous
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5ea7f5b..3b12753 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1115,6 +1115,22 @@
          regularly selected color mode will be used if this value is negative. -->
     <integer name="config_accessibilityColorMode">-1</integer>
 
+    <!-- The following two arrays specify which color space to use for display composition when a
+         certain color mode is active.
+         Composition color spaces are defined in android.view.Display.COLOR_MODE_xxx, and color
+         modes are defined in ColorDisplayManager.COLOR_MODE_xxx and
+         ColorDisplayManager.VENDOR_COLOR_MODE_xxx.
+         The color space COLOR_MODE_DEFAULT (0) lets the system select the most appropriate
+         composition color space for currently displayed content. Other values (e.g.,
+         COLOR_MODE_SRGB) override system selection; these other color spaces must be supported by
+         the device for for display composition.
+         If a color mode does not have a corresponding color space specified in this array, the
+         currently set composition color space will not be modified.-->
+    <integer-array name="config_displayCompositionColorModes">
+    </integer-array>
+    <integer-array name="config_displayCompositionColorSpaces">
+    </integer-array>
+
     <!-- Indicate whether to allow the device to suspend when the screen is off
          due to the proximity sensor.  This resource should only be set to true
          if the sensor HAL correctly handles the proximity sensor as a wake-up source.
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 039bc4d..6653879 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -279,7 +279,7 @@
     <dimen name="notification_expand_button_padding_top">1dp</dimen>
 
     <!-- Height of a small notification in the status bar -->
-    <dimen name="notification_min_height">92dp</dimen>
+    <dimen name="notification_min_height">106dp</dimen>
 
     <!-- The width of the big icons in notifications. -->
     <dimen name="notification_large_icon_width">64dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c4dbde8..d91bbd0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3196,6 +3196,8 @@
   <java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficientsNative" />
   <java-symbol type="array" name="config_availableColorModes" />
   <java-symbol type="integer" name="config_accessibilityColorMode" />
+  <java-symbol type="array" name="config_displayCompositionColorModes" />
+  <java-symbol type="array" name="config_displayCompositionColorSpaces" />
   <java-symbol type="bool" name="config_displayWhiteBalanceAvailable" />
   <java-symbol type="bool" name="config_displayWhiteBalanceEnabledDefault" />
   <java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureMin" />
@@ -3800,6 +3802,7 @@
   <java-symbol type="string" name="config_displayLightSensorType" />
 
   <java-symbol type="drawable" name="iconfactory_adaptive_icon_drawable_wrapper"/>
+  <java-symbol type="dimen" name="notification_min_height" />
   <java-symbol type="dimen" name="resolver_icon_size"/>
   <java-symbol type="dimen" name="resolver_badge_size"/>
   <java-symbol type="dimen" name="resolver_button_bar_spacing"/>
diff --git a/core/tests/coretests/res/values/styles.xml b/core/tests/coretests/res/values/styles.xml
index dbc4626..0bf4b92 100644
--- a/core/tests/coretests/res/values/styles.xml
+++ b/core/tests/coretests/res/values/styles.xml
@@ -39,4 +39,7 @@
         <item name="android:colorBackground">@null</item>
         <item name="android:windowBackgroundFallback">#0000FF</item>
     </style>
+    <style name="ViewDefaultBackground">
+        <item name="android:background">#00000000</item>
+    </style>
 </resources>
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index d2b18cb..51da0c8 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -416,7 +416,8 @@
                 IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1,
                 boolean b2, boolean b3, Configuration configuration,
                 CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1,
-                AutofillOptions ao, ContentCaptureOptions co) throws RemoteException {
+                AutofillOptions ao, ContentCaptureOptions co, long[] disableCompatChanges)
+                throws RemoteException {
         }
 
         @Override
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteTokenizerTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteTokenizerTest.java
new file mode 100644
index 0000000..a9d1482
--- /dev/null
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteTokenizerTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database.sqlite;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class SQLiteTokenizerTest {
+    private List<String> getTokens(String sql) {
+        return SQLiteTokenizer.tokenize(sql, SQLiteTokenizer.OPTION_NONE);
+    }
+
+    private void checkTokens(String sql, String spaceSeparatedExpectedTokens) {
+        final List<String> expected = spaceSeparatedExpectedTokens == null
+                ? new ArrayList<>()
+                : Arrays.asList(spaceSeparatedExpectedTokens.split(" +"));
+
+        assertEquals(expected, getTokens(sql));
+    }
+
+    private void assertInvalidSql(String sql, String message) {
+        try {
+            getTokens(sql);
+            fail("Didn't throw InvalidSqlException");
+        } catch (IllegalArgumentException e) {
+            assertTrue("Expected " + e.getMessage() + " to contain " + message,
+                    e.getMessage().contains(message));
+        }
+    }
+
+    @Test
+    public void testWhitespaces() {
+        checkTokens("  select  \t\r\n a\n\n  ", "select a");
+        checkTokens("a b", "a b");
+    }
+
+    @Test
+    public void testComment() {
+        checkTokens("--\n", null);
+        checkTokens("a--\n", "a");
+        checkTokens("a--abcdef\n", "a");
+        checkTokens("a--abcdef\nx", "a x");
+        checkTokens("a--\nx", "a x");
+        assertInvalidSql("a--abcdef", "Unterminated comment");
+        assertInvalidSql("a--abcdef\ndef--", "Unterminated comment");
+
+        checkTokens("/**/", null);
+        assertInvalidSql("/*", "Unterminated comment");
+        assertInvalidSql("/*/", "Unterminated comment");
+        assertInvalidSql("/*\n* /*a", "Unterminated comment");
+        checkTokens("a/**/", "a");
+        checkTokens("/**/b", "b");
+        checkTokens("a/**/b", "a b");
+        checkTokens("a/* -- \n* /* **/b", "a b");
+    }
+
+    @Test
+    public void testStrings() {
+        assertInvalidSql("'", "Unterminated quote");
+        assertInvalidSql("a'", "Unterminated quote");
+        assertInvalidSql("a'''", "Unterminated quote");
+        assertInvalidSql("a''' ", "Unterminated quote");
+        checkTokens("''", null);
+        checkTokens("''''", null);
+        checkTokens("a''''b", "a b");
+        checkTokens("a' '' 'b", "a b");
+        checkTokens("'abc'", null);
+        checkTokens("'abc\ndef'", null);
+        checkTokens("a'abc\ndef'", "a");
+        checkTokens("'abc\ndef'b", "b");
+        checkTokens("a'abc\ndef'b", "a b");
+        checkTokens("a'''abc\nd''ef'''b", "a b");
+    }
+
+    @Test
+    public void testDoubleQuotes() {
+        assertInvalidSql("\"", "Unterminated quote");
+        assertInvalidSql("a\"", "Unterminated quote");
+        assertInvalidSql("a\"\"\"", "Unterminated quote");
+        assertInvalidSql("a\"\"\" ", "Unterminated quote");
+        checkTokens("\"\"", "");
+        checkTokens("\"\"\"\"", "\"");
+        checkTokens("a\"\"\"\"b", "a \" b");
+        checkTokens("a\"\t\"\"\t\"b", "a  \t\"\t  b");
+        checkTokens("\"abc\"", "abc");
+        checkTokens("\"abc\ndef\"", "abc\ndef");
+        checkTokens("a\"abc\ndef\"", "a abc\ndef");
+        checkTokens("\"abc\ndef\"b", "abc\ndef b");
+        checkTokens("a\"abc\ndef\"b", "a abc\ndef b");
+        checkTokens("a\"\"\"abc\nd\"\"ef\"\"\"b", "a \"abc\nd\"ef\" b");
+    }
+
+    @Test
+    public void testBackQuotes() {
+        assertInvalidSql("`", "Unterminated quote");
+        assertInvalidSql("a`", "Unterminated quote");
+        assertInvalidSql("a```", "Unterminated quote");
+        assertInvalidSql("a``` ", "Unterminated quote");
+        checkTokens("``", "");
+        checkTokens("````", "`");
+        checkTokens("a````b", "a ` b");
+        checkTokens("a`\t``\t`b", "a  \t`\t  b");
+        checkTokens("`abc`", "abc");
+        checkTokens("`abc\ndef`", "abc\ndef");
+        checkTokens("a`abc\ndef`", "a abc\ndef");
+        checkTokens("`abc\ndef`b", "abc\ndef b");
+        checkTokens("a`abc\ndef`b", "a abc\ndef b");
+        checkTokens("a```abc\nd``ef```b", "a `abc\nd`ef` b");
+    }
+
+    @Test
+    public void testBrackets() {
+        assertInvalidSql("[", "Unterminated quote");
+        assertInvalidSql("a[", "Unterminated quote");
+        assertInvalidSql("a[ ", "Unterminated quote");
+        assertInvalidSql("a[[ ", "Unterminated quote");
+        checkTokens("[]", "");
+        checkTokens("[[]", "[");
+        checkTokens("a[[]b", "a [ b");
+        checkTokens("a[\t[\t]b", "a  \t[\t  b");
+        checkTokens("[abc]", "abc");
+        checkTokens("[abc\ndef]", "abc\ndef");
+        checkTokens("a[abc\ndef]", "a abc\ndef");
+        checkTokens("[abc\ndef]b", "abc\ndef b");
+        checkTokens("a[abc\ndef]b", "a abc\ndef b");
+        checkTokens("a[[abc\nd[ef[]b", "a [abc\nd[ef[ b");
+    }
+
+    @Test
+    public void testSemicolons() {
+        assertInvalidSql(";", "Semicolon is not allowed");
+        assertInvalidSql("  ;", "Semicolon is not allowed");
+        assertInvalidSql(";  ", "Semicolon is not allowed");
+        assertInvalidSql("-;-", "Semicolon is not allowed");
+        checkTokens("--;\n", null);
+        checkTokens("/*;*/", null);
+        checkTokens("';'", null);
+        checkTokens("[;]", ";");
+        checkTokens("`;`", ";");
+    }
+
+    @Test
+    public void testTokens() {
+        checkTokens("a,abc,a00b,_1,_123,abcdef", "a abc a00b _1 _123 abcdef");
+        checkTokens("a--\nabc/**/a00b''_1'''ABC'''`_123`abc[d]\"e\"f",
+                "a abc a00b _1 _123 abc d e f");
+    }
+}
diff --git a/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
new file mode 100644
index 0000000..b605520
--- /dev/null
+++ b/core/tests/coretests/src/android/text/format/TimeMigrationUtilsTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text.format;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TimeMigrationUtilsTest {
+
+    private static final int ONE_DAY_IN_SECONDS = 24 * 60 * 60;
+
+    private Locale mDefaultLocale;
+    private TimeZone mDefaultTimeZone;
+
+    @Before
+    public void setUp() {
+        mDefaultLocale = Locale.getDefault();
+        mDefaultTimeZone = TimeZone.getDefault();
+    }
+
+    @After
+    public void tearDown() {
+        Locale.setDefault(mDefaultLocale);
+        TimeZone.setDefault(mDefaultTimeZone);
+    }
+
+    @Test
+    public void formatMillisWithFixedFormat_fixes2038Issue() {
+        Locale.setDefault(Locale.UK);
+        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+
+        // The following cannot be represented properly using Time because they are outside of the
+        // supported range.
+        long y2038Issue1 = (((long) Integer.MIN_VALUE) - ONE_DAY_IN_SECONDS) * 1000L;
+        assertEquals(
+                "1901-12-12 20:45:52", TimeMigrationUtils.formatMillisWithFixedFormat(y2038Issue1));
+        long y2038Issue2 = (((long) Integer.MAX_VALUE) + ONE_DAY_IN_SECONDS) * 1000L;
+        assertEquals(
+                "2038-01-20 03:14:07", TimeMigrationUtils.formatMillisWithFixedFormat(y2038Issue2));
+    }
+
+    /**
+     * Compares TimeMigrationUtils.formatSimpleDateTime() with the code it is replacing.
+     */
+    @Test
+    public void formatMillisAsDateTime_matchesOldBehavior() {
+        // A selection of interesting locales.
+        Locale[] locales = new Locale[] {
+                Locale.US,
+                Locale.UK,
+                Locale.FRANCE,
+                Locale.JAPAN,
+                Locale.CHINA,
+                // Android supports RTL locales like arabic and arabic with latin numbers.
+                Locale.forLanguageTag("ar-AE"),
+                Locale.forLanguageTag("ar-AE-u-nu-latn"),
+        };
+        // A selection of interesting time zones.
+        String[] timeZoneIds = new String[] {
+                "UTC", "Europe/London", "America/New_York", "America/Los_Angeles", "Asia/Shanghai",
+        };
+        // Some arbitrary times when the two formatters should agree.
+        long[] timesMillis = new long[] {
+                System.currentTimeMillis(),
+                0,
+                // The Time class only works in 32-bit range, the replacement works beyond that. To
+                // avoid messing around with offsets and complicating the test, below there are a
+                // day after / before the known limits.
+                (Integer.MIN_VALUE + ONE_DAY_IN_SECONDS) * 1000L,
+                (Integer.MAX_VALUE - ONE_DAY_IN_SECONDS) * 1000L,
+        };
+
+        for (Locale locale : locales) {
+            Locale.setDefault(locale);
+            for (String timeZoneId : timeZoneIds) {
+                TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
+                TimeZone.setDefault(timeZone);
+                for (long timeMillis : timesMillis) {
+                    Time time = new Time();
+                    time.set(timeMillis);
+                    String oldResult = time.format("%Y-%m-%d %H:%M:%S");
+                    String newResult = TimeMigrationUtils.formatMillisWithFixedFormat(timeMillis);
+                    assertEquals(
+                            "locale=" + locale + ", timeZoneId=" + timeZoneId
+                                    + ", timeMillis=" + timeMillis,
+                            oldResult, newResult);
+                }
+            }
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/view/WindowInfoTest.java b/core/tests/coretests/src/android/view/WindowInfoTest.java
index 037a0d9..05e8bd8 100644
--- a/core/tests/coretests/src/android/view/WindowInfoTest.java
+++ b/core/tests/coretests/src/android/view/WindowInfoTest.java
@@ -91,7 +91,7 @@
         assertFalse(w.focused);
         assertFalse(w.inPictureInPicture);
         assertFalse(w.hasFlagWatchOutsideTouch);
-        assertTrue(w.boundsInScreen.isEmpty());
+        assertTrue(w.regionInScreen.isEmpty());
     }
 
     @SmallTest
@@ -114,7 +114,7 @@
         equality &= w1.childTokens.equals(w2.childTokens);
         equality &= w1.parentToken == w2.parentToken;
         equality &= w1.activityToken == w2.activityToken;
-        equality &= w1.boundsInScreen.equals(w2.boundsInScreen);
+        equality &= w1.regionInScreen.equals(w2.regionInScreen);
         return equality;
     }
 
@@ -132,6 +132,6 @@
         windowInfo.focused = true;
         windowInfo.inPictureInPicture = true;
         windowInfo.hasFlagWatchOutsideTouch = true;
-        windowInfo.boundsInScreen.set(0, 0, 1080, 1080);
+        windowInfo.regionInScreen.set(0, 0, 1080, 1080);
     }
 }
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index 683d16b..adaae5c 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -21,6 +21,7 @@
 import android.content.pm.ParceledListSlice;
 import android.graphics.Region;
 import android.os.Bundle;
+import android.os.IBinder;
 
 import java.util.List;
 
@@ -134,4 +135,8 @@
     public boolean isFingerprintGestureDetectionAvailable() {
         return false;
     }
+
+    public IBinder getOverlayWindowToken(int displayId) {
+        return null;
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
index aadfcbc..abee1da2 100644
--- a/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
+++ b/core/tests/coretests/src/com/android/internal/accessibility/AccessibilityShortcutControllerTest.java
@@ -71,7 +71,7 @@
 import com.android.internal.accessibility.AccessibilityShortcutController.FrameworkObjectProvider;
 import com.android.internal.util.test.FakeSettingsProvider;
 
-import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -136,6 +136,7 @@
 
         mContentResolver = new MockContentResolver(mContext);
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        FakeSettingsProvider.clearSettingsProvider();
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
 
         when(mAccessibilityManagerService.getInstalledAccessibilityServiceList(anyInt()))
@@ -193,8 +194,9 @@
         when(mTextToSpeech.getVoice()).thenReturn(mVoice);
     }
 
-    @After
-    public void tearDown() {
+    @AfterClass
+    public static void cleanUpSettingsProvider() {
+        FakeSettingsProvider.clearSettingsProvider();
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
index f66717e..62e4efe 100644
--- a/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
@@ -76,4 +76,13 @@
         expectedBitmap.getPixels(expPixels, 0, w, 0, 0, w, h);
         assertThat(Arrays.toString(expPixels)).isEqualTo(Arrays.toString(resPixels));
     }
+
+    @Test
+    public void setBackgroundWithNoWindow() {
+        PhoneWindow phoneWindow = new PhoneWindow(mContext);
+        // Set a theme that defines a non-null value for android:background
+        mContext.setTheme(R.style.ViewDefaultBackground);
+        DecorView decorView = (DecorView) phoneWindow.getDecorView();
+        assertThat(decorView.getBackground()).isNotNull();
+    }
 }
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index ae7fe6c..0e635c7 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -63,7 +63,7 @@
  * <h3>Creating a RenderNode</h3>
  * <pre class="prettyprint">
  *     RenderNode renderNode = new RenderNode("myRenderNode");
- *     renderNode.setLeftTopRightBottom(0, 0, 50, 50); // Set the size to 50x50
+ *     renderNode.setPosition(0, 0, 50, 50); // Set the size to 50x50
  *     RecordingCanvas canvas = renderNode.beginRecording();
  *     try {
  *         // Draw with the canvas
@@ -104,7 +104,7 @@
  * <pre class="prettyprint">
  *     private void createDisplayList() {
  *         mRenderNode = new RenderNode("MyRenderNode");
- *         mRenderNode.setLeftTopRightBottom(0, 0, width, height);
+ *         mRenderNode.setPosition(0, 0, width, height);
  *         RecordingCanvas canvas = mRenderNode.beginRecording();
  *         try {
  *             for (Bitmap b : mBitmaps) {
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 4755cb8..f7c8337 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -74,7 +74,7 @@
 const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
 const char* AssetManager::VENDOR_OVERLAY_DIR = "/vendor/overlay";
 const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
-const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
+const char* AssetManager::SYSTEM_EXT_OVERLAY_DIR = "/system_ext/overlay";
 const char* AssetManager::ODM_OVERLAY_DIR = "/odm/overlay";
 const char* AssetManager::OEM_OVERLAY_DIR = "/oem/overlay";
 const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
@@ -575,7 +575,7 @@
                         mZipSet.setZipResourceTableAsset(ap.path, ass);
                 }
             }
-            
+
             if (nextEntryIdx == 0 && ass != NULL) {
                 // If this is the first resource table in the asset
                 // manager, then we are going to cache it so that we
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index 66fba26b..ce0985b 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -61,7 +61,7 @@
     static const char* IDMAP_BIN;
     static const char* VENDOR_OVERLAY_DIR;
     static const char* PRODUCT_OVERLAY_DIR;
-    static const char* PRODUCT_SERVICES_OVERLAY_DIR;
+    static const char* SYSTEM_EXT_OVERLAY_DIR;
     static const char* ODM_OVERLAY_DIR;
     static const char* OEM_OVERLAY_DIR;
     /*
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 7269bca..16ec877 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -29,7 +29,6 @@
 #include "SkPaint.h"
 #include "SkPath.h"
 #include "SkRect.h"
-#include "SkTDArray.h"
 #include "SkTemplates.h"
 
 #include <vector>
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 6ea6af8..f01b1bf 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -778,6 +778,13 @@
     mCanvas->drawDrawable(drawable.get());
 }
 
+void SkiaCanvas::drawPicture(const SkPicture& picture) {
+    // TODO: Change to mCanvas->drawPicture()? SkCanvas::drawPicture seems to be
+    // where the logic is for playback vs. ref picture. Using picture.playback here
+    // to stay behavior-identical for now, but should revisit this at some point.
+    picture.playback(mCanvas);
+}
+
 // ----------------------------------------------------------------------------
 // Canvas draw operations: View System
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index 05a6d0dd..799a891 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -46,8 +46,6 @@
 
     virtual ~SkiaCanvas();
 
-    virtual SkCanvas* asSkCanvas() override { return mCanvas; }
-
     virtual void resetRecording(int width, int height,
                                 uirenderer::RenderNode* renderNode) override {
         LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas");
@@ -155,9 +153,11 @@
     virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
     virtual void callDrawGLFunction(Functor* functor,
                                     uirenderer::GlFunctorLifecycleListener* listener) override;
+    virtual void drawPicture(const SkPicture& picture) override;
 
 protected:
     SkiaCanvas();
+    SkCanvas* asSkCanvas() { return mCanvas; }
     void reset(SkCanvas* skiaCanvas);
     void drawDrawable(SkDrawable* drawable) { mCanvas->drawDrawable(drawable); }
 
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index ac8db21..ee4fa1d6 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -131,20 +131,6 @@
      */
     static void setCompatibilityVersion(int apiLevel);
 
-    /**
-     *  Provides a Skia SkCanvas interface that acts as a proxy to this Canvas.
-     *  It is useful for testing and clients (e.g. Picture/Movie) that expect to
-     *  draw their contents into an SkCanvas.
-     *
-     *  The SkCanvas returned is *only* valid until another Canvas call is made
-     *  that would change state (e.g. matrix or clip). Clients of asSkCanvas()
-     *  are responsible for *not* persisting this pointer.
-     *
-     *  Further, the returned SkCanvas should NOT be unref'd and is valid until
-     *  this canvas is destroyed or a new bitmap is set.
-     */
-    virtual SkCanvas* asSkCanvas() = 0;
-
     virtual void setBitmap(const SkBitmap& bitmap) = 0;
 
     virtual bool isOpaque() = 0;
@@ -264,6 +250,7 @@
                                const SkPaint* paint) = 0;
 
     virtual double drawAnimatedImage(AnimatedImageDrawable* imgDrawable) = 0;
+    virtual void drawPicture(const SkPicture& picture) = 0;
 
     /**
      * Specifies if the positions passed to ::drawText are absolute or relative
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 550c27d..d97c5ed 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -145,7 +145,8 @@
 
     if (surface) {
         mNativeSurface = new ReliableSurface{std::move(surface)};
-        mNativeSurface->setDequeueTimeout(500_ms);
+        // TODO: Fix error handling & re-shorten timeout
+        mNativeSurface->setDequeueTimeout(4000_ms);
     } else {
         mNativeSurface = nullptr;
     }
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index e50428b..40fbdff 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -16,6 +16,8 @@
 
 #include "RenderProxy.h"
 
+#include <gui/Surface.h>
+
 #include "DeferredLayerUpdater.h"
 #include "DisplayList.h"
 #include "Properties.h"
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index a0f08cb..c3eb6ed 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -19,7 +19,6 @@
 
 #include <SkBitmap.h>
 #include <cutils/compiler.h>
-#include <gui/Surface.h>
 #include <utils/Functor.h>
 
 #include "../FrameMetricsObserver.h"
@@ -30,6 +29,7 @@
 
 namespace android {
 class GraphicBuffer;
+class Surface;
 
 namespace uirenderer {
 
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 5fa860a..5717bb3 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -17,6 +17,7 @@
 
 #include <system/graphics.h>
 #include <system/window.h>
+#include <ui/BufferQueueDefs.h>
 #include <vulkan/vulkan.h>
 
 #include <SkRefCnt.h>
diff --git a/libs/hwui/tests/unit/SkiaCanvasTests.cpp b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
index f6178af..2ed1b25 100644
--- a/libs/hwui/tests/unit/SkiaCanvasTests.cpp
+++ b/libs/hwui/tests/unit/SkiaCanvasTests.cpp
@@ -78,7 +78,7 @@
     sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
 
     // Playback to a software sRGB canvas.  The result should be fully red.
-    canvas.asSkCanvas()->drawPicture(picture);
+    canvas.drawPicture(*picture);
     ASSERT_EQ(0xFF0000FF, *skBitmap.getAddr32(0, 0));
 }
 
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index f5330b4..1cc246b 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -191,19 +191,6 @@
     public static final String MODE_CHANGED_ACTION = "android.location.MODE_CHANGED";
 
     /**
-     * Broadcast intent action when {@link android.provider.Settings.Secure#LOCATION_MODE} is
-     * about to be changed through Settings app or Quick Settings.
-     * For use with the {@link android.provider.Settings.Secure#LOCATION_MODE} API.
-     * If you're interacting with {@link #isProviderEnabled(String)}, use
-     * {@link #PROVIDERS_CHANGED_ACTION} instead.
-     *
-     * @deprecated Do not use.
-     * @hide
-     */
-    @Deprecated
-    public static final String MODE_CHANGING_ACTION = "com.android.settings.location.MODE_CHANGING";
-
-    /**
      * Broadcast intent action indicating that a high power location requests
      * has either started or stopped being active.  The current state of
      * active location requests should be read from AppOpsManager using
@@ -216,17 +203,10 @@
 
     /**
      * Broadcast intent action for Settings app to inject a footer at the bottom of location
-     * settings.
+     * settings. This is for use only by apps that are included in the system image.
      *
-     * <p>This broadcast is used for two things:
-     * <ol>
-     *     <li>For receivers to inject a footer with provided text. This is for use only by apps
-     *         that are included in the system image. </li>
-     *     <li>For receivers to know their footer is injected under location settings.</li>
-     * </ol>
-     *
-     * <p>To inject a footer to location settings, you must declare a broadcast receiver of
-     * {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} in the manifest as so:
+     * <p>To inject a footer to location settings, you must declare a broadcast receiver for
+     * this action in the manifest:
      * <pre>
      *     &lt;receiver android:name="com.example.android.footer.MyFooterInjector"&gt;
      *         &lt;intent-filter&gt;
@@ -238,10 +218,8 @@
      *     &lt;/receiver&gt;
      * </pre>
      *
-     * <p>On entering location settings, Settings app will send a
-     * {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast to receivers whose footer is successfully
-     * injected. On leaving location settings, the footer becomes not visible to users. Settings app
-     * will send a {@link #SETTINGS_FOOTER_REMOVED_ACTION} broadcast to those receivers.
+     * <p>This broadcast receiver will never actually be invoked. See also
+     * {#METADATA_SETTINGS_FOOTER_STRING}.
      *
      * @hide
      */
@@ -249,16 +227,6 @@
             "com.android.settings.location.DISPLAYED_FOOTER";
 
     /**
-     * Broadcast intent action when location settings footer is not visible to users.
-     *
-     * <p>See {@link #SETTINGS_FOOTER_DISPLAYED_ACTION} for more detail on how to use.
-     *
-     * @hide
-     */
-    public static final String SETTINGS_FOOTER_REMOVED_ACTION =
-            "com.android.settings.location.REMOVED_FOOTER";
-
-    /**
      * Metadata name for {@link LocationManager#SETTINGS_FOOTER_DISPLAYED_ACTION} broadcast
      * receivers to specify a string resource id as location settings footer text. This is for use
      * only by apps that are included in the system image.
diff --git a/media/Android.bp b/media/Android.bp
index 4f9671f..29064ad 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -33,6 +33,8 @@
         "framework_media_annotation",
         "android_system_stubs_current",
     ],
+
+    plugins: ["java_api_finder"],
 }
 
 filegroup {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 353e58e..7906fa3 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -246,7 +246,7 @@
  *         via {@link #setOnBufferingUpdateListener(OnBufferingUpdateListener)}.
  *         This callback allows applications to keep track of the buffering status
  *         while streaming audio/video.</li>
- *         <li>Calling {@link #start()} has not effect
+ *         <li>Calling {@link #start()} has no effect
  *         on a MediaPlayer object that is already in the <em>Started</em> state.</li>
  *         </ul>
  *         </li>
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index bc3de74..bf7da23 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -720,7 +720,7 @@
 
     /**
      * Sets the width and height of the video to be captured.  Must be called
-     * after setVideoSource(). Call this after setOutFormat() but before
+     * after setVideoSource(). Call this after setOutputFormat() but before
      * prepare().
      *
      * @param width the width of the video to be captured
@@ -733,7 +733,7 @@
 
     /**
      * Sets the frame rate of the video to be captured.  Must be called
-     * after setVideoSource(). Call this after setOutFormat() but before
+     * after setVideoSource(). Call this after setOutputFormat() but before
      * prepare().
      *
      * @param rate the number of frames per second of video to capture
@@ -748,7 +748,7 @@
 
     /**
      * Sets the maximum duration (in ms) of the recording session.
-     * Call this after setOutFormat() but before prepare().
+     * Call this after setOutputFormat() but before prepare().
      * After recording reaches the specified duration, a notification
      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
@@ -769,7 +769,7 @@
 
     /**
      * Sets the maximum filesize (in bytes) of the recording session.
-     * Call this after setOutFormat() but before prepare().
+     * Call this after setOutputFormat() but before prepare().
      * After recording reaches the specified filesize, a notification
      * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
      * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index f13a64c..5dcbb05 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -23,6 +23,9 @@
 import android.os.Parcelable;
 import android.text.TextUtils;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -53,6 +56,8 @@
     final String mDescription;
     @Nullable
     final String mClientPackageName;
+    @NonNull
+    final List<String> mSupportedCategories;
     @Nullable
     final Bundle mExtras;
 
@@ -62,6 +67,7 @@
         mName = builder.mName;
         mDescription = builder.mDescription;
         mClientPackageName = builder.mClientPackageName;
+        mSupportedCategories = builder.mSupportedCategories;
         mExtras = builder.mExtras;
     }
 
@@ -71,6 +77,7 @@
         mName = in.readString();
         mDescription = in.readString();
         mClientPackageName = in.readString();
+        mSupportedCategories = in.createStringArrayList();
         mExtras = in.readBundle();
     }
 
@@ -103,13 +110,14 @@
                 && Objects.equals(mName, other.mName)
                 && Objects.equals(mDescription, other.mDescription)
                 && Objects.equals(mClientPackageName, other.mClientPackageName)
+                && Objects.equals(mSupportedCategories, other.mSupportedCategories)
                 //TODO: This will be evaluated as false in most cases. Try not to.
                 && Objects.equals(mExtras, other.mExtras);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mId, mName, mDescription);
+        return Objects.hash(mId, mName, mDescription, mSupportedCategories);
     }
 
     @NonNull
@@ -146,11 +154,38 @@
         return mClientPackageName;
     }
 
+    /**
+     * Gets the supported categories of the route.
+     */
+    @NonNull
+    public List<String> getSupportedCategories() {
+        return mSupportedCategories;
+    }
+
     @Nullable
     public Bundle getExtras() {
         return mExtras;
     }
 
+    //TODO: Move this if we re-define control category / selector things.
+    /**
+     * Returns true if the route supports at least one of the specified control categories
+     *
+     * @param controlCategories the list of control categories to consider
+     * @return true if the route supports at least one category
+     */
+    public boolean supportsControlCategory(@NonNull Collection<String> controlCategories) {
+        Objects.requireNonNull(controlCategories, "control categories must not be null");
+        for (String controlCategory : controlCategories) {
+            for (String supportedCategory : getSupportedCategories()) {
+                if (TextUtils.equals(controlCategory, supportedCategory)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -163,6 +198,7 @@
         dest.writeString(mName);
         dest.writeString(mDescription);
         dest.writeString(mClientPackageName);
+        dest.writeStringList(mSupportedCategories);
         dest.writeBundle(mExtras);
     }
 
@@ -187,6 +223,7 @@
         String mName;
         String mDescription;
         String mClientPackageName;
+        List<String> mSupportedCategories;
         Bundle mExtras;
 
         public Builder(@NonNull String id, @NonNull String name) {
@@ -198,6 +235,7 @@
             }
             setId(id);
             setName(name);
+            mSupportedCategories = new ArrayList<>();
         }
 
         public Builder(@NonNull MediaRoute2Info routeInfo) {
@@ -212,6 +250,7 @@
             setName(routeInfo.mName);
             mDescription = routeInfo.mDescription;
             setClientPackageName(routeInfo.mClientPackageName);
+            setSupportedCategories(routeInfo.mSupportedCategories);
             if (routeInfo.mExtras != null) {
                 mExtras = new Bundle(routeInfo.mExtras);
             }
@@ -273,6 +312,39 @@
         }
 
         /**
+         * Sets the supported categories of the route.
+         */
+        @NonNull
+        public Builder setSupportedCategories(@NonNull Collection<String> categories) {
+            mSupportedCategories = new ArrayList<>();
+            return addSupportedCategories(categories);
+        }
+
+        /**
+         * Adds supported categories for the route.
+         */
+        @NonNull
+        public Builder addSupportedCategories(@NonNull Collection<String> categories) {
+            Objects.requireNonNull(categories, "categories must not be null");
+            for (String category: categories) {
+                addSupportedCategory(category);
+            }
+            return this;
+        }
+
+        /**
+         * Add a supported category for the route.
+         */
+        @NonNull
+        public Builder addSupportedCategory(@NonNull String category) {
+            if (TextUtils.isEmpty(category)) {
+                throw new IllegalArgumentException("category must not be null or empty");
+            }
+            mSupportedCategories.add(category);
+            return this;
+        }
+
+        /**
          * Sets a bundle of extras for the route.
          */
         @NonNull
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 5fc37a5..85105e0 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -38,6 +38,8 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Executor;
 
@@ -66,6 +68,8 @@
     List<MediaRoute2ProviderInfo> mProviders = Collections.emptyList();
     @NonNull
     List<MediaRoute2Info> mRoutes = Collections.emptyList();
+    @NonNull
+    ConcurrentMap<String, List<String>> mControlCategoryMap = new ConcurrentHashMap<>();
 
     /**
      * Gets an instance of media router manager that controls media route of other applications.
@@ -160,6 +164,8 @@
         return -1;
     }
 
+    //TODO: Use cache not to create array. For now, it's unclear when to purge the cache.
+    //Do this when we finalize how to set control categories.
     /**
      * Gets available routes for an application.
      *
@@ -167,8 +173,17 @@
      */
     @NonNull
     public List<MediaRoute2Info> getAvailableRoutes(@NonNull String packageName) {
-        //TODO: filter irrelevant routes.
-        return Collections.unmodifiableList(mRoutes);
+        List<String> controlCategories = mControlCategoryMap.get(packageName);
+        if (controlCategories == null) {
+            return Collections.emptyList();
+        }
+        List<MediaRoute2Info> routes = new ArrayList<>();
+        for (MediaRoute2Info route : mRoutes) {
+            if (route.supportsControlCategory(controlCategories)) {
+                routes.add(route);
+            }
+        }
+        return routes;
     }
 
     /**
@@ -310,11 +325,8 @@
         }
     }
 
-    void notifyControlCategoriesChanged(String packageName, List<String> categories) {
-        for (CallbackRecord record : mCallbacks) {
-            record.mExecutor.execute(
-                    () -> record.mCallback.onControlCategoriesChanged(packageName, categories));
-        }
+    void updateControlCategories(String packageName, List<String> categories) {
+        mControlCategoryMap.put(packageName, categories);
     }
 
     /**
@@ -346,15 +358,6 @@
         public void onRouteSelected(@NonNull String packageName, @Nullable MediaRoute2Info route) {}
 
         /**
-         * Called when the control categories of an application is changed.
-         *
-         * @param packageName the package name of the app that changed control categories
-         * @param categories the changed categories
-         */
-        public void onControlCategoriesChanged(@NonNull String packageName,
-                @NonNull List<String> categories) {}
-
-        /**
          * Called when the list of routes are changed.
          * A client may refresh available routes for each application.
          */
@@ -389,7 +392,7 @@
 
         @Override
         public void notifyControlCategoriesChanged(String packageName, List<String> categories) {
-            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyControlCategoriesChanged,
+            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::updateControlCategories,
                     MediaRouter2Manager.this, packageName, categories));
         }
 
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index 1e9a194..357bb5e5 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -122,7 +122,7 @@
  *  - AMEDIA_ERROR_INVALID_PARAMETER
  *  AMEDIA_ERROR_UNKNOWN
  */
-static media_status_t AMIDI_API AMIDI_getDeviceInfo(const AMidiDevice *device,
+static media_status_t AMIDI_getDeviceInfo(const AMidiDevice *device,
         AMidiDeviceInfo *outDeviceInfoPtr) {
     if (device == nullptr) {
         return AMEDIA_ERROR_INVALID_PARAMETER;
@@ -142,7 +142,7 @@
     return AMEDIA_OK;
 }
 
-media_status_t AMIDI_API AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceObj,
+media_status_t AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceObj,
         AMidiDevice** devicePtrPtr)
 {
     if (j_midiDeviceObj == nullptr) {
@@ -188,7 +188,7 @@
     return AMEDIA_OK;
 }
 
-media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *device)
+media_status_t AMidiDevice_release(const AMidiDevice *device)
 {
     if (device == nullptr || device->midiDeviceObj == nullptr) {
         return AMEDIA_ERROR_INVALID_PARAMETER;
@@ -217,21 +217,21 @@
     return AMEDIA_OK;
 }
 
-int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) {
+int32_t AMidiDevice_getType(const AMidiDevice *device) {
     if (device == nullptr) {
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
     return device->deviceInfo.type;
 }
 
-ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) {
+ssize_t AMidiDevice_getNumInputPorts(const AMidiDevice *device) {
     if (device == nullptr) {
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
     return device->deviceInfo.inputPortCount;
 }
 
-ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) {
+ssize_t AMidiDevice_getNumOutputPorts(const AMidiDevice *device) {
     if (device == nullptr) {
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
@@ -291,7 +291,7 @@
 /*
  * Output (receiving) API
  */
-media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
+media_status_t AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
         AMidiOutputPort **outOutputPortPtr) {
     return AMIDI_openPort(device, portNumber, PORTTYPE_OUTPUT, (AMIDI_Port**)outOutputPortPtr);
 }
@@ -350,7 +350,7 @@
     AMIDI_Port *mPort;
 };
 
-ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
+ssize_t AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
          uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *timestampPtr) {
 
     if (outputPort == nullptr || buffer == nullptr) {
@@ -361,19 +361,19 @@
            numBytesReceivedPtr, timestampPtr);
 }
 
-void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) {
+void AMidiOutputPort_close(const AMidiOutputPort *outputPort) {
     AMIDI_closePort((AMIDI_Port*)outputPort);
 }
 
 /*
  * Input (sending) API
  */
-media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
+media_status_t AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
         AMidiInputPort **outInputPortPtr) {
     return AMIDI_openPort(device, portNumber, PORTTYPE_INPUT, (AMIDI_Port**)outInputPortPtr);
 }
 
-void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) {
+void AMidiInputPort_close(const AMidiInputPort *inputPort) {
     AMIDI_closePort((AMIDI_Port*)inputPort);
 }
 
@@ -386,12 +386,12 @@
     return numBytes + AMIDI_PACKET_OVERHEAD;
 }
 
-ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
+ssize_t AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
                             size_t numBytes) {
     return AMidiInputPort_sendWithTimestamp(inputPort, buffer, numBytes, 0);
 }
 
-ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
+ssize_t AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
         const uint8_t *data, size_t numBytes, int64_t timestamp) {
     if (inputPort == nullptr || data == nullptr) {
         return AMEDIA_ERROR_INVALID_PARAMETER;
@@ -423,7 +423,7 @@
     return numSent;
 }
 
-media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) {
+media_status_t AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) {
     if (inputPort == nullptr) {
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
diff --git a/media/native/midi/include/amidi/AMidi.h b/media/native/midi/include/amidi/AMidi.h
index cbe410f..76dec0f 100644
--- a/media/native/midi/include/amidi/AMidi.h
+++ b/media/native/midi/include/amidi/AMidi.h
@@ -41,8 +41,6 @@
 typedef struct AMidiInputPort AMidiInputPort;
 typedef struct AMidiOutputPort AMidiOutputPort;
 
-#define AMIDI_API __attribute__((visibility("default")))
-
 /*
  * Message Op Codes. Used to parse MIDI data packets
  */
@@ -61,6 +59,8 @@
     AMIDI_DEVICE_TYPE_BLUETOOTH = 3 /* A MIDI device connected via BlueTooth */
 };
 
+#if __ANDROID_API__ >= 29
+
 /*
  * Device API
  */
@@ -78,7 +78,7 @@
  *    is null or already connected to a native AMidiDevice
   *  @see AMEDIA_ERROR_UNKNOWN - an unknown error occurred.
  */
-media_status_t AMIDI_API AMidiDevice_fromJava(
+media_status_t AMidiDevice_fromJava(
         JNIEnv *env, jobject midiDeviceObj, AMidiDevice **outDevicePtrPtr) __INTRODUCED_IN(29);
 
 /**
@@ -93,7 +93,7 @@
  *  @see AMEDIA_ERROR_INVALID_OBJECT - the JNI interface initialization to the associated java MidiDevice failed.
  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
  */
-media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *midiDevice) __INTRODUCED_IN(29);
+media_status_t AMidiDevice_release(const AMidiDevice *midiDevice) __INTRODUCED_IN(29);
 
 /**
  * Gets the MIDI device type.
@@ -108,7 +108,7 @@
  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
  *  @see AMEDIA_ERROR_UNKNOWN - Unknown error.
  */
-int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN(29);
+int32_t AMidiDevice_getType(const AMidiDevice *device) __INTRODUCED_IN(29);
 
 /**
  * Gets the number of input (sending) ports available on the specified MIDI device.
@@ -120,7 +120,7 @@
  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
  */
-ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
+ssize_t AMidiDevice_getNumInputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
 
 /**
  * Gets the number of output (receiving) ports available on the specified MIDI device.
@@ -132,7 +132,7 @@
  *  @see AMEDIA_ERROR_INVALID_PARAMETER - the device parameter is NULL.
  *  @see AMEDIA_ERROR_UNKNOWN - couldn't retrieve the device info.
  */
-ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
+ssize_t AMidiDevice_getNumOutputPorts(const AMidiDevice *device) __INTRODUCED_IN(29);
 
 /*
  * API for receiving data from the Output port of a device.
@@ -150,7 +150,7 @@
  * @return AMEDIA_OK, or a negative error code:
  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
  */
-media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
+media_status_t AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
                              AMidiOutputPort **outOutputPortPtr) __INTRODUCED_IN(29);
 
 /**
@@ -158,7 +158,7 @@
  *
  * @param outputPort    The native API port identifier of the port.
  */
-void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTRODUCED_IN(29);
+void AMidiOutputPort_close(const AMidiOutputPort *outputPort) __INTRODUCED_IN(29);
 
 /**
  * Receives the next pending MIDI message. To retrieve all pending messages, the client should
@@ -178,7 +178,7 @@
  * @return the number of messages received (either 0 or 1), or a negative error code:
  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
  */
-ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
+ssize_t AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
          uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *outTimestampPtr) __INTRODUCED_IN(29);
 
 /*
@@ -197,7 +197,7 @@
  * @return AMEDIA_OK, or a negative error code:
  *  @see AMEDIA_ERROR_UNKNOWN - Unknown Error.
  */
-media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
+media_status_t AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
                             AMidiInputPort **outInputPortPtr) __INTRODUCED_IN(29);
 
 /**
@@ -210,7 +210,7 @@
  * @return The number of bytes sent, which could be less than specified or a negative error code:
  * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL.
  */
-ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
+ssize_t AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
                    size_t numBytes) __INTRODUCED_IN(29);
 
 /**
@@ -224,7 +224,7 @@
  * @return The number of bytes sent, which could be less than specified or a negative error code:
  * @see AMEDIA_ERROR_INVALID_PARAMETER - The specified port was NULL, the specified buffer was NULL.
  */
-ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
+ssize_t AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
         const uint8_t *buffer, size_t numBytes, int64_t timestamp) __INTRODUCED_IN(29);
 
 /**
@@ -238,14 +238,16 @@
  * @see AMEDIA_ERROR_UNSUPPORTED - The FLUSH command couldn't
  * be sent.
  */
-media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
+media_status_t AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
 
 /**
  * Closes the input port.
  *
  * @param inputPort Identifies the input (sending) port to close.
  */
-void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
+void AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
+
+#endif /* __ANDROID_API__ >= 29 */
 
 #ifdef __cplusplus
 }
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 2cdc6a8..1267aa8 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -32,19 +32,35 @@
     public static final String ROUTE_NAME1 = "Sample Route 1";
     public static final String ROUTE_ID2 = "route_id2";
     public static final String ROUTE_NAME2 = "Sample Route 2";
+
+    public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category";
+    public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route";
+
     public static final String ACTION_REMOVE_ROUTE =
             "com.android.mediarouteprovider.action_remove_route";
 
+    public static final String CATEGORY_SAMPLE =
+            "com.android.mediarouteprovider.CATEGORY_SAMPLE";
+    public static final String CATEGORY_SPECIAL =
+            "com.android.mediarouteprovider.CATEGORY_SPECIAL";
+
     Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
 
     private void initializeRoutes() {
         MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
+                .addSupportedCategory(CATEGORY_SAMPLE)
                 .build();
         MediaRoute2Info route2 = new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2)
+                .addSupportedCategory(CATEGORY_SAMPLE)
                 .build();
-
+        MediaRoute2Info routeSpecial =
+                new MediaRoute2Info.Builder(ROUTE_ID_SPECIAL_CATEGORY, ROUTE_NAME_SPECIAL_CATEGORY)
+                        .addSupportedCategory(CATEGORY_SAMPLE)
+                        .addSupportedCategory(CATEGORY_SPECIAL)
+                        .build();
         mRoutes.put(route1.getId(), route1);
         mRoutes.put(route2.getId(), route2);
+        mRoutes.put(routeSpecial.getId(), routeSpecial);
     }
 
     @Override
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index 03b43e2..4282a5bc 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -58,9 +58,18 @@
     public static final String ROUTE_NAME1 = "Sample Route 1";
     public static final String ROUTE_ID2 = "route_id2";
     public static final String ROUTE_NAME2 = "Sample Route 2";
+
+    public static final String ROUTE_ID_SPECIAL_CATEGORY = "route_special_category";
+    public static final String ROUTE_NAME_SPECIAL_CATEGORY = "Special Category Route";
+
     public static final String ACTION_REMOVE_ROUTE =
             "com.android.mediarouteprovider.action_remove_route";
 
+    public static final String CATEGORY_SAMPLE =
+            "com.android.mediarouteprovider.CATEGORY_SAMPLE";
+    public static final String CATEGORY_SPECIAL =
+            "com.android.mediarouteprovider.CATEGORY_SPECIAL";
+
     private static final int TIMEOUT_MS = 5000;
 
     private Context mContext;
@@ -69,12 +78,13 @@
     private Executor mExecutor;
     private String mPackageName;
 
-    private static final List<String> TEST_CONTROL_CATEGORIES = new ArrayList();
-    private static final String CONTROL_CATEGORY_1 = "android.media.mediarouter.MEDIA1";
-    private static final String CONTROL_CATEGORY_2 = "android.media.mediarouter.MEDIA2";
+    private static final List<String> CONTROL_CATEGORIES_ALL = new ArrayList();
+    private static final List<String> CONTROL_CATEGORIES_SPECIAL = new ArrayList();
     static {
-        TEST_CONTROL_CATEGORIES.add(CONTROL_CATEGORY_1);
-        TEST_CONTROL_CATEGORIES.add(CONTROL_CATEGORY_2);
+        CONTROL_CATEGORIES_ALL.add(CATEGORY_SAMPLE);
+        CONTROL_CATEGORIES_ALL.add(CATEGORY_SPECIAL);
+
+        CONTROL_CATEGORIES_SPECIAL.add(CATEGORY_SPECIAL);
     }
 
     @Before
@@ -125,7 +135,7 @@
         // (Control requests shouldn't be used in this way.)
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 (Runnable) () -> {
-                    mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, mockRouterCallback);
+                    mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, mockRouterCallback);
                     mRouter.sendControlRequest(
                             new MediaRoute2Info.Builder(ROUTE_ID2, ROUTE_NAME2).build(),
                             new Intent(ACTION_REMOVE_ROUTE));
@@ -138,8 +148,11 @@
         mManager.removeCallback(mockCallback);
     }
 
+    /**
+     * Tests if we get proper routes for application that has special control category.
+     */
     @Test
-    public void controlCategoryTest() throws Exception {
+    public void testControlCategory() throws Exception {
         MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
         mManager.addCallback(mExecutor, mockCallback);
 
@@ -147,12 +160,19 @@
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> {
-                    mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, mockRouterCallback);
+                    mRouter.addCallback(CONTROL_CATEGORIES_SPECIAL,
+                            mExecutor, mockRouterCallback);
                     mRouter.removeCallback(mockRouterCallback);
                 }
         );
-        verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
-                .onControlCategoriesChanged(mPackageName, TEST_CONTROL_CATEGORIES);
+        verify(mockCallback, timeout(TIMEOUT_MS))
+                .onRouteListChanged(argThat(routes -> routes.size() > 0));
+
+        Map<String, MediaRoute2Info> routes =
+                createRouteMap(mManager.getAvailableRoutes(mPackageName));
+
+        Assert.assertEquals(1, routes.size());
+        Assert.assertNotNull(routes.get(ROUTE_ID_SPECIAL_CATEGORY));
 
         mManager.removeCallback(mockCallback);
     }
@@ -164,7 +184,7 @@
         MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> {
-                    mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, mockRouterCallback);
+                    mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, mockRouterCallback);
                 }
         );
 
@@ -197,10 +217,10 @@
         mManager.removeCallback(managerCallback);
     }
 
-    @Test
     /**
      * Tests selecting and unselecting routes of a single provider.
      */
+    @Test
     public void testSingleProviderSelect() {
         MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
         MediaRouter2.Callback routerCallback = mock(MediaRouter2.Callback.class);
@@ -208,7 +228,7 @@
         mManager.addCallback(mExecutor, managerCallback);
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
                 () -> {
-                    mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, routerCallback);
+                    mRouter.addCallback(CONTROL_CATEGORIES_ALL, mExecutor, routerCallback);
                 }
         );
         verify(managerCallback, timeout(TIMEOUT_MS))
@@ -218,7 +238,8 @@
                 createRouteMap(mManager.getAvailableRoutes(mPackageName));
 
         mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
-        verify(managerCallback, timeout(TIMEOUT_MS))
+        verify(managerCallback, timeout(TIMEOUT_MS)
+        )
                 .onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID1, routeInfo.getId())
                         && TextUtils.equals(routeInfo.getClientPackageName(), mPackageName)));
 
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index 7592bd2..fb422af 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -114,10 +114,10 @@
     <!-- Car notification shade-->
     <dimen name="notification_shade_handle_bar_height">10dp</dimen>
     <dimen name="notification_shade_handle_bar_radius">20dp</dimen>
-    <dimen name="notification_shade_handle_bar_margin_start">500dp</dimen>
-    <dimen name="notification_shade_handle_bar_margin_end">500dp</dimen>
+    <dimen name="notification_shade_handle_bar_margin_start">200dp</dimen>
+    <dimen name="notification_shade_handle_bar_margin_end">200dp</dimen>
     <dimen name="notification_shade_handle_bar_margin_top">20dp</dimen>
     <dimen name="notification_shade_handle_bar_margin_bottom">10dp</dimen>
-    <dimen name="notification_shade_list_padding_bottom">0dp</dimen>
+    <dimen name="notification_shade_list_padding_bottom">50dp</dimen>
 
 </resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index fc5e791..c0dcbbc 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -70,13 +70,9 @@
                 R.styleable.CarNavigationButton_unselectedAlpha, mUnselectedAlpha);
         mSelectedIconResourceId = typedArray.getResourceId(
                 R.styleable.CarNavigationButton_selectedIcon, mIconResourceId);
+        mIconResourceId = typedArray.getResourceId(
+                R.styleable.CarNavigationButton_icon, 0);
         typedArray.recycle();
-
-        // ImageView attrs
-        TypedArray a = context.obtainStyledAttributes(
-                attrs, com.android.internal.R.styleable.ImageView);
-        mIconResourceId = a.getResourceId(com.android.internal.R.styleable.ImageView_src, 0);
-        a.recycle();
     }
 
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index a452bae..b1f9797 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -1073,9 +1073,10 @@
             // shade is visible to the user. When the notification shade is completely open then
             // alpha value will be 1.
             float alpha = (float) height / mNotificationView.getHeight();
-            Drawable background = mNotificationView.getBackground();
+            Drawable background = mNotificationView.getBackground().mutate();
 
             background.setAlpha((int) (alpha * 255));
+            mNotificationView.setBackground(background);
         }
     }
 
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 5ad9b01..3d9a78e 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -76,7 +76,7 @@
     <item msgid="3422726142222090896">"avrcp16"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_titles">
-    <item msgid="7065842274271279580">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="7065842274271279580">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="7539690996561263909">"SBC"</item>
     <item msgid="686685526567131661">"AAC"</item>
     <item msgid="5254942598247222737">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item>
@@ -86,7 +86,7 @@
     <item msgid="3304843301758635896">"वैकल्पिक कोडेक अक्षम करें"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_summaries">
-    <item msgid="5062108632402595000">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="5062108632402595000">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="6898329690939802290">"SBC"</item>
     <item msgid="6839647709301342559">"AAC"</item>
     <item msgid="7848030269621918608">"<xliff:g id="QUALCOMM">Qualcomm®</xliff:g> <xliff:g id="APTX">aptX™</xliff:g> ऑडियो"</item>
@@ -96,38 +96,38 @@
     <item msgid="741805482892725657">"वैकल्पिक कोडेक अक्षम करें"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_sample_rate_titles">
-    <item msgid="3093023430402746802">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="3093023430402746802">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="8895532488906185219">"44.1 kHz"</item>
     <item msgid="2909915718994807056">"48.0 kHz"</item>
     <item msgid="3347287377354164611">"88.2 kHz"</item>
     <item msgid="1234212100239985373">"96.0 kHz"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_sample_rate_summaries">
-    <item msgid="3214516120190965356">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="3214516120190965356">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="4482862757811638365">"44.1 kHz"</item>
     <item msgid="354495328188724404">"48.0 kHz"</item>
     <item msgid="7329816882213695083">"88.2 kHz"</item>
     <item msgid="6967397666254430476">"96.0 kHz"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_bits_per_sample_titles">
-    <item msgid="2684127272582591429">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="2684127272582591429">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="5618929009984956469">"16 बिट/नमूना"</item>
     <item msgid="3412640499234627248">"24 बिट/नमूना"</item>
     <item msgid="121583001492929387">"32 बिट/नमूना"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_bits_per_sample_summaries">
-    <item msgid="1081159789834584363">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="1081159789834584363">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="4726688794884191540">"16 बिट/नमूना"</item>
     <item msgid="305344756485516870">"24 बिट/नमूना"</item>
     <item msgid="244568657919675099">"32 बिट/नमूना"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_channel_mode_titles">
-    <item msgid="5226878858503393706">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="5226878858503393706">"सिस्टम से चुने जाने का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="4106832974775067314">"मोनो"</item>
     <item msgid="5571632958424639155">"स्टीरियो"</item>
   </string-array>
   <string-array name="bluetooth_a2dp_codec_channel_mode_summaries">
-    <item msgid="4118561796005528173">"सिस्टम चयन का उपयोग करें (डिफ़ॉल्ट)"</item>
+    <item msgid="4118561796005528173">"सिस्टम चुनाव का उपयोग करें (डिफ़ॉल्ट)"</item>
     <item msgid="8900559293912978337">"मोनो"</item>
     <item msgid="8883739882299884241">"स्टीरियो"</item>
   </string-array>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 5d512a8..238eba5 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -361,7 +361,7 @@
     <string name="runningservices_settings_summary" msgid="854608995821032748">"इस समय चल रही सेवाओं को देखें और नियंत्रित करें"</string>
     <string name="select_webview_provider_title" msgid="4628592979751918907">"वेबव्यू लागू करें"</string>
     <string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"वेबव्यू सेट करें"</string>
-    <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"यह चयन अब मान्य नहीं है. पुनः प्रयास करें."</string>
+    <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"यह चुनाव अब मान्य नहीं है. दोबारा कोशिश करें."</string>
     <string name="convert_to_file_encryption" msgid="3060156730651061223">"फ़ाइल आधारित सुरक्षित करने के तरीके में बदलें"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"रूपांतरित करें..."</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"फ़ाइल पहले से एन्क्रिप्ट की हुई है"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index fd45cb0..f1934c3 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -248,7 +248,7 @@
     <string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string>
     <string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string>
     <string name="wifi_scan_throttling_summary" msgid="4461922728822495763">"ब्याट्रीको खपत कम गरी नेटवर्कको कार्यसम्पादनमा सुधार गर्दछ"</string>
-    <string name="wifi_metered_label" msgid="4514924227256839725">"मिटर गरिएको जडान भनी चिन्ह लगाइएको"</string>
+    <string name="wifi_metered_label" msgid="4514924227256839725">"सशुल्क वाइफाइ"</string>
     <string name="wifi_unmetered_label" msgid="6124098729457992931">"मिटर नगरिएको"</string>
     <string name="select_logd_size_title" msgid="7433137108348553508">"लगर बफर आकारहरू"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
index 9a41f1d..9672fea 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -663,7 +663,8 @@
         final SpannableStringBuilder sb = new SpannableStringBuilder(textView.getText());
         removeExistingRestrictedSpans(sb);
         if (disabled) {
-            final int disabledColor = context.getColor(R.color.disabled_text_color);
+            final int disabledColor = Utils.getDisabled(context,
+                    textView.getCurrentTextColor());
             sb.setSpan(new ForegroundColorSpan(disabledColor), 0, sb.length(),
                     Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
             textView.setCompoundDrawables(null, null, getRestrictedPadlock(context), null);
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index d32e85f..14f233d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -35,8 +35,6 @@
 
 public class Utils {
 
-    private static final String CURRENT_MODE_KEY = "CURRENT_MODE";
-    private static final String NEW_MODE_KEY = "NEW_MODE";
     @VisibleForTesting
     static final String STORAGE_MANAGER_ENABLED_PROPERTY =
             "ro.storage_manager.enabled";
@@ -56,24 +54,11 @@
 
     public static void updateLocationEnabled(Context context, boolean enabled, int userId,
             int source) {
-        LocationManager locationManager = context.getSystemService(LocationManager.class);
-
         Settings.Secure.putIntForUser(
                 context.getContentResolver(), Settings.Secure.LOCATION_CHANGER, source,
                 userId);
 
-        Intent intent = new Intent(LocationManager.MODE_CHANGING_ACTION);
-        final int oldMode = locationManager.isLocationEnabled()
-                ? Settings.Secure.LOCATION_MODE_ON
-                : Settings.Secure.LOCATION_MODE_OFF;
-        final int newMode = enabled
-                ? Settings.Secure.LOCATION_MODE_ON
-                : Settings.Secure.LOCATION_MODE_OFF;
-        intent.putExtra(CURRENT_MODE_KEY, oldMode);
-        intent.putExtra(NEW_MODE_KEY, newMode);
-        context.sendBroadcastAsUser(
-                intent, UserHandle.of(userId), android.Manifest.permission.WRITE_SECURE_SETTINGS);
-
+        LocationManager locationManager = context.getSystemService(LocationManager.class);
         locationManager.setLocationEnabledForUser(enabled, UserHandle.of(userId));
     }
 
@@ -218,6 +203,13 @@
         return list.getDefaultColor();
     }
 
+    /**
+     * This method computes disabled color from normal color
+     *
+     * @param context
+     * @param inputColor normal color.
+     * @return disabled color.
+     */
     @ColorInt
     public static int getDisabled(Context context, int inputColor) {
         return applyAlphaAttr(context, android.R.attr.disabledAlpha, inputColor);
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/ColorUtil.java b/packages/SettingsLib/src/com/android/settingslib/utils/ColorUtil.java
new file mode 100644
index 0000000..c54b471
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/ColorUtil.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.utils;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+
+/** Utility class for getting color attribute **/
+public class ColorUtil {
+
+    /**
+     * Returns android:disabledAlpha value in context
+     */
+    public static float getDisabledAlpha(Context context) {
+        final TypedArray ta = context.obtainStyledAttributes(
+                new int[]{android.R.attr.disabledAlpha});
+        final float alpha = ta.getFloat(0, 0);
+        ta.recycle();
+        return alpha;
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
index 4d76e44..fc69b1a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/UtilsTest.java
@@ -15,17 +15,13 @@
  */
 package com.android.settingslib;
 
-import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
-
 import static com.android.settingslib.Utils.STORAGE_MANAGER_ENABLED_PROPERTY;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
@@ -45,7 +41,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentMatcher;
-import org.mockito.ArgumentMatchers;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
@@ -85,15 +80,11 @@
     }
 
     @Test
-    public void testUpdateLocationEnabled_sendBroadcast() {
+    public void testUpdateLocationEnabled() {
         int currentUserId = ActivityManager.getCurrentUser();
         Utils.updateLocationEnabled(mContext, true, currentUserId,
                 Settings.Secure.LOCATION_CHANGER_QUICK_SETTINGS);
 
-        verify(mContext).sendBroadcastAsUser(
-            argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
-            ArgumentMatchers.eq(UserHandle.of(currentUserId)),
-            ArgumentMatchers.eq(WRITE_SECURE_SETTINGS));
         assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.LOCATION_CHANGER, Settings.Secure.LOCATION_CHANGER_UNKNOWN))
                 .isEqualTo(Settings.Secure.LOCATION_CHANGER_QUICK_SETTINGS);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 9d398b5..b11df48 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -16,7 +16,6 @@
 
 package com.android.providers.settings;
 
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.backup.BackupAgentHelper;
 import android.app.backup.BackupDataInput;
@@ -41,6 +40,7 @@
 import android.util.BackupUtils;
 import android.util.Log;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.LockPatternUtils;
 
 import java.io.BufferedOutputStream;
@@ -586,15 +586,15 @@
         final String[] whitelist;
         Map<String, Validator> validators = null;
         if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
-            whitelist = concat(Settings.Secure.SETTINGS_TO_BACKUP,
+            whitelist = ArrayUtils.concatElements(String.class, Settings.Secure.SETTINGS_TO_BACKUP,
                     Settings.Secure.LEGACY_RESTORE_SETTINGS);
             validators = Settings.Secure.VALIDATORS;
         } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
-            whitelist = concat(Settings.System.SETTINGS_TO_BACKUP,
+            whitelist = ArrayUtils.concatElements(String.class, Settings.System.SETTINGS_TO_BACKUP,
                     Settings.System.LEGACY_RESTORE_SETTINGS);
             validators = Settings.System.VALIDATORS;
         } else if (contentUri.equals(Settings.Global.CONTENT_URI)) {
-            whitelist = concat(Settings.Global.SETTINGS_TO_BACKUP,
+            whitelist = ArrayUtils.concatElements(String.class, Settings.Global.SETTINGS_TO_BACKUP,
                     Settings.Global.LEGACY_RESTORE_SETTINGS);
             validators = Settings.Global.VALIDATORS;
         } else {
@@ -672,18 +672,6 @@
         return (validator != null) && validator.validate(value);
     }
 
-    private final String[] concat(String[] first, @Nullable String[] second) {
-        if (second == null || second.length == 0) {
-            return first;
-        }
-        final int firstLen = first.length;
-        final int secondLen = second.length;
-        String[] both = new String[firstLen + secondLen];
-        System.arraycopy(first, 0, both, 0, firstLen);
-        System.arraycopy(second, 0, both, firstLen, secondLen);
-        return both;
-    }
-
     /**
      * Restores the owner info enabled and other settings in LockSettings.
      *
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index ea87870..c9bb83c 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -50,7 +50,6 @@
 import android.os.BugreportManager.BugreportCallback;
 import android.os.BugreportManager.BugreportCallback.BugreportErrorCode;
 import android.os.BugreportParams;
-import android.os.BugreportParams.BugreportMode;
 import android.os.Bundle;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -354,7 +353,7 @@
         private final int mId;
         private final BugreportInfo mInfo;
 
-        BugreportCallbackImpl(String name, int id, @BugreportMode int bugreportType) {
+        BugreportCallbackImpl(String name, int id) {
             mId = id;
             // pid not used in this workflow, so setting default = 0
             mInfo = new BugreportInfo(mContext, mId, 0 /* pid */, name,
@@ -363,8 +362,6 @@
 
         @Override
         public void onProgress(float progress) {
-            // TODO: Make dumpstate call onProgress at 0% progress to trigger the
-            // progress notification instantly.
             checkProgressUpdated(mInfo, (int) progress);
         }
 
@@ -544,21 +541,21 @@
 
     private void startBugreportAPI(Intent intent) {
         mUsingBugreportApi = true;
-        String currentTimeStamp = new SimpleDateFormat("yyyy-MM-dd-HH-mm").format(
+        String bugreportName = "bugreport-" + new SimpleDateFormat("yyyy-MM-dd-HH-mm").format(
                 new Date());
 
         // TODO(b/126862297): Make file naming same as dumpstate triggered bugreports
         ParcelFileDescriptor bugreportFd = createReadWriteFile(BUGREPORT_DIR,
-                "bugreport-" + currentTimeStamp + ".zip");
+                bugreportName + ".zip");
         if (bugreportFd == null) {
             Log.e(TAG, "Bugreport parcel file descriptor is null.");
             return;
         }
+        int bugreportType = intent.getIntExtra(EXTRA_BUGREPORT_TYPE,
+                BugreportParams.BUGREPORT_MODE_INTERACTIVE);
 
-        // TODO(b/126862297): Screenshot file is not needed for INTERACTIVE_BUGREPORTS
-        // Add logic to pass screenshot file only for specific bugreports.
         ParcelFileDescriptor screenshotFd = createReadWriteFile(BUGREPORT_DIR,
-                "screenshot-" + currentTimeStamp + ".png");
+                bugreportName + ".png");
         if (screenshotFd == null) {
             Log.e(TAG, "Screenshot parcel file descriptor is null.");
             // TODO(b/123617758): Delete bugreport file created above
@@ -572,16 +569,13 @@
         // Dumpstate increments PROPERTY_LAST_ID, may be racy if multiple calls
         // to dumpstate are made simultaneously.
         final int id = SystemProperties.getInt(PROPERTY_LAST_ID, 0) + 1;
-        int bugreportType = intent.getIntExtra(EXTRA_BUGREPORT_TYPE,
-                BugreportParams.BUGREPORT_MODE_INTERACTIVE);
         Log.i(TAG, "bugreport type = " + bugreportType
                 + " bugreport file fd: " + bugreportFd
                 + " screenshot file fd: " + screenshotFd);
 
-        BugreportCallbackImpl bugreportCallback = new BugreportCallbackImpl("bugreport-"
-                + currentTimeStamp, id, bugreportType);
+        BugreportCallbackImpl bugreportCallback = new BugreportCallbackImpl(bugreportName, id);
         try {
-            mBugreportManager.startBugreport(bugreportFd, null,
+            mBugreportManager.startBugreport(bugreportFd, screenshotFd,
                     new BugreportParams(bugreportType), executor, bugreportCallback);
             mBugreportInfos.put(bugreportCallback.mInfo.id, bugreportCallback.mInfo);
         } catch (RuntimeException e) {
@@ -963,14 +957,20 @@
             return;
         }
         final int max = -1; // this is to log metrics for dumpstate duration.
-        final File screenshotFile = new File(BUGREPORT_DIR, info.name + ".png");
-        // TODO(b/126862297): Screenshot file is not needed for INTERACTIVE_BUGREPORTS
-        // Add logic to null check screenshot file only for specific bugreports.
+        File screenshotFile = new File(BUGREPORT_DIR, info.name + ".png");
         if (screenshotFile == null) {
             // Should never happen, an id always has a file linked to it.
             Log.wtf(TAG, "Missing file " + screenshotFile.getPath() + " does not exist.");
             return;
         }
+        // If the screenshot file did not get populated implies this type of bugreport does not
+        // need the screenshot file; setting the file to null so that empty file doesnt get shared
+        if (screenshotFile.length() == 0) {
+            if (screenshotFile.delete()) {
+                Log.d(TAG, "screenshot file deleted successfully.");
+            }
+            screenshotFile = null;
+        }
         onBugreportFinished(id, bugreportFile, screenshotFile, info.title, info.description, max);
     }
 
@@ -2195,7 +2195,7 @@
             max = CAPPED_MAX;
         }
 
-        if (newPercentage > oldPercentage) {
+        if (progress == 0 || newPercentage > oldPercentage) {
             updateProgressInfo(info, progress, max);
         }
     }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
index 28d5402..52ec1f0 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java
@@ -30,7 +30,7 @@
  */
 @ProvidesInterface(version = FalsingManager.VERSION)
 public interface FalsingManager {
-    int VERSION = 1;
+    int VERSION = 2;
 
     void onSucccessfulUnlock();
 
@@ -103,4 +103,6 @@
     void onTouchEvent(MotionEvent ev, int width, int height);
 
     void dump(PrintWriter pw);
+
+    void cleanup();
 }
diff --git a/packages/SystemUI/res/layout/biometric_dialog.xml b/packages/SystemUI/res/layout/biometric_dialog.xml
index c560d7e..e687cdf 100644
--- a/packages/SystemUI/res/layout/biometric_dialog.xml
+++ b/packages/SystemUI/res/layout/biometric_dialog.xml
@@ -55,7 +55,8 @@
                     android:id="@+id/left_space"
                     android:layout_weight="1"
                     android:layout_width="0dp"
-                    android:layout_height="match_parent"/>
+                    android:layout_height="match_parent"
+                    android:contentDescription="@string/biometric_dialog_empty_space_description"/>
 
                     <LinearLayout
                         android:id="@+id/dialog"
@@ -177,7 +178,8 @@
                     android:id="@+id/right_space"
                     android:layout_weight="1"
                     android:layout_width="0dp"
-                    android:layout_height="match_parent" />
+                    android:layout_height="match_parent"
+                    android:contentDescription="@string/biometric_dialog_empty_space_description"/>
 
             </LinearLayout>
 
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 7fc2066..21c2c6b 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -46,6 +46,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:gravity="center"
+                android:paddingStart="@dimen/keyguard_indication_text_padding"
+                android:paddingEnd="@dimen/keyguard_indication_text_padding"
                 android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
                 android:visibility="gone" />
 
@@ -54,6 +56,8 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:gravity="center"
+                android:paddingStart="@dimen/keyguard_indication_text_padding"
+                android:paddingEnd="@dimen/keyguard_indication_text_padding"
                 android:textAppearance="@style/TextAppearance.Keyguard.BottomArea"
                 android:accessibilityLiveRegion="polite" />
 
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 82252ba..dc661dd 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -401,7 +401,7 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
     <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string>
-    <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organization"</string>
+    <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organisation"</string>
     <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
     <string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index ca9e29a..9903cc0 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -401,7 +401,7 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
     <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string>
-    <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organization"</string>
+    <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organisation"</string>
     <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
     <string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 82252ba..dc661dd 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -401,7 +401,7 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
     <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string>
-    <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organization"</string>
+    <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organisation"</string>
     <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
     <string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 82252ba..dc661dd 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -401,7 +401,7 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
     <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string>
-    <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organization"</string>
+    <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organisation"</string>
     <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
     <string name="voice_hint" msgid="8939888732119726665">"Swipe from icon for voice assist"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index b25f2fc..75a76ae 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -376,7 +376,7 @@
     <string name="quick_settings_night_secondary_label_until_sunrise" msgid="4453017157391574402">"Jusqu\'à l\'aube"</string>
     <string name="quick_settings_night_secondary_label_on_at" msgid="6256314040368487637">"À partir de <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_secondary_label_until" msgid="2749196569462600150">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
-    <string name="quick_settings_ui_mode_night_label" msgid="3419947801072692538">"Thème foncé"</string>
+    <string name="quick_settings_ui_mode_night_label" msgid="3419947801072692538">"Thème sombre"</string>
     <string name="quick_settings_ui_mode_night_label_battery_saver" msgid="7438725724589758362">"Thème foncé\nÉconomiseur de batterie"</string>
     <string name="quick_settings_nfc_label" msgid="9012153754816969325">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="6883274004315134333">"La technologie NFC est désactivée"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 1a914e0..3268ed0 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -894,10 +894,10 @@
     <string name="mobile_data_disable_message" msgid="4756541658791493506">"Non terás acceso aos datos nin a Internet a través de <xliff:g id="CARRIER">%s</xliff:g>. Internet só estará dispoñible mediante a wifi."</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6078110473451946831">"o teu operador"</string>
     <string name="touch_filtered_warning" msgid="8671693809204767551">"Dado que unha aplicación se superpón sobre unha solicitude de permiso, a configuración non pode verificar a túa resposta."</string>
-    <string name="slice_permission_title" msgid="7465009437851044444">"Queres permitir que a aplicación <xliff:g id="APP_0">%1$s</xliff:g> mostre partes de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
+    <string name="slice_permission_title" msgid="7465009437851044444">"Queres permitir que <xliff:g id="APP_0">%1$s</xliff:g> mostre fragmentos de aplicación de <xliff:g id="APP_2">%2$s</xliff:g>?"</string>
     <string name="slice_permission_text_1" msgid="3514586565609596523">"- Pode ler información da aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
     <string name="slice_permission_text_2" msgid="3146758297471143723">"- Pode levar a cabo accións dentro da aplicación <xliff:g id="APP">%1$s</xliff:g>"</string>
-    <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permitir que a aplicación <xliff:g id="APP">%1$s</xliff:g> mostre partes de calquera aplicación"</string>
+    <string name="slice_permission_checkbox" msgid="7986504458640562900">"Permitir que <xliff:g id="APP">%1$s</xliff:g> mostre fragmentos de calquera aplicación"</string>
     <string name="slice_permission_allow" msgid="2340244901366722709">"Permitir"</string>
     <string name="slice_permission_deny" msgid="7683681514008048807">"Denegar"</string>
     <string name="auto_saver_title" msgid="1217959994732964228">"Tocar para programar a función Aforro de batería"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 08816c7..83a7aaa 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -614,7 +614,7 @@
     <string name="remove_from_settings_prompt" msgid="6069085993355887748">"Të hiqet Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit nga Cilësimet dhe të ndërpritet përdorimi i të gjitha funksioneve të tij?"</string>
     <string name="activity_not_found" msgid="348423244327799974">"Aplikacioni nuk është instaluar në pajisjen tënde."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Trego sekondat e orës"</string>
-    <string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te jeta e baterisë."</string>
+    <string name="clock_seconds_desc" msgid="6282693067130470675">"Trego sekondat e orës në shiritin e statusit. Mund të ndikojë te kohëzgjatja e baterisë."</string>
     <string name="qs_rearrange" msgid="8060918697551068765">"Risistemo Cilësimet e shpejta"</string>
     <string name="show_brightness" msgid="6613930842805942519">"Shfaq ndriçimin te Cilësimet e shpejta"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentale"</string>
diff --git a/packages/SystemUI/res/values/attrs_car.xml b/packages/SystemUI/res/values/attrs_car.xml
index ced26c9..49b87f3 100644
--- a/packages/SystemUI/res/values/attrs_car.xml
+++ b/packages/SystemUI/res/values/attrs_car.xml
@@ -62,6 +62,8 @@
         <attr name="unselectedAlpha" />
         <!-- icon to be rendered when in selected state -->
         <attr name="selectedIcon" />
+        <!-- icon to be rendered (drawable) -->
+        <attr name="icon"/>
     </declare-styleable>
 
     <!-- Custom attributes to configure hvac values -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 7c24130..861187f 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -154,12 +154,8 @@
     <!-- The number of milliseconds before the heads up notification accepts touches. -->
     <integer name="touch_acceptance_delay">700</integer>
 
-    <!-- The number of milliseconds before the ambient notification auto-dismisses. This will
-         override the default pulse length. -->
-    <integer name="heads_up_notification_decay_dozing">10000</integer>
-
     <!-- The number of milliseconds to extend ambient pulse by when prompted (e.g. on touch) -->
-    <integer name="ambient_notification_extension_time">6000</integer>
+    <integer name="ambient_notification_extension_time">10000</integer>
 
     <!-- In multi-window, determines whether the stack where recents lives should grow from
          the smallest position when being launched. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f4970d0..be815e1 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -112,7 +112,7 @@
     <dimen name="status_bar_connected_device_bt_indicator_size">17dp</dimen>
 
     <!-- Height of a small notification in the status bar-->
-    <dimen name="notification_min_height">106dp</dimen>
+    <dimen name="notification_min_height">@*android:dimen/notification_min_height</dimen>
 
     <!-- Increased height of a small notification in the status bar -->
     <dimen name="notification_min_height_increased">146dp</dimen>
@@ -183,6 +183,9 @@
     <!-- The padding on the bottom of the notifications on the keyguard -->
     <dimen name="keyguard_indication_bottom_padding">12sp</dimen>
 
+    <!-- The padding at start and end of indication text shown on AOD -->
+    <dimen name="keyguard_indication_text_padding">16dp</dimen>
+
     <!-- Shadows under the clock, date and other keyguard text fields -->
     <dimen name="keyguard_shadow_radius">5</dimen>
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index 53403aa..a7e3c59 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -171,15 +171,21 @@
         PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener,
                 allowMultiple, mLooper, cls, this);
         p.loadAll();
-        mPluginMap.put(listener, p);
+        synchronized (this) {
+            mPluginMap.put(listener, p);
+        }
         startListening();
     }
 
     public void removePluginListener(PluginListener<?> listener) {
-        if (!mPluginMap.containsKey(listener)) return;
-        mPluginMap.remove(listener).destroy();
-        if (mPluginMap.size() == 0) {
-            stopListening();
+        synchronized (this) {
+            if (!mPluginMap.containsKey(listener)) {
+                return;
+            }
+            mPluginMap.remove(listener).destroy();
+            if (mPluginMap.size() == 0) {
+                stopListening();
+            }
         }
     }
 
@@ -208,8 +214,10 @@
     @Override
     public void onReceive(Context context, Intent intent) {
         if (Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())) {
-            for (PluginInstanceManager manager : mPluginMap.values()) {
-                manager.loadAll();
+            synchronized (this) {
+                for (PluginInstanceManager manager : mPluginMap.values()) {
+                    manager.loadAll();
+                }
             }
         } else if (DISABLE_PLUGIN.equals(intent.getAction())) {
             Uri uri = intent.getData();
@@ -274,13 +282,15 @@
                     getPluginEnabler().setEnabled(componentName);
                 }
             }
-            if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
-                for (PluginInstanceManager manager : mPluginMap.values()) {
-                    manager.onPackageChange(pkg);
-                }
-            } else {
-                for (PluginInstanceManager manager : mPluginMap.values()) {
-                    manager.onPackageRemoved(pkg);
+            synchronized (this) {
+                if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+                    for (PluginInstanceManager manager : mPluginMap.values()) {
+                        manager.onPackageChange(pkg);
+                    }
+                } else {
+                    for (PluginInstanceManager manager : mPluginMap.values()) {
+                        manager.onPackageRemoved(pkg);
+                    }
                 }
             }
         }
@@ -322,9 +332,11 @@
     }
 
     public <T> boolean dependsOn(Plugin p, Class<T> cls) {
-        for (int i = 0; i < mPluginMap.size(); i++) {
-            if (mPluginMap.valueAt(i).dependsOn(p, cls)) {
-                return true;
+        synchronized (this) {
+            for (int i = 0; i < mPluginMap.size(); i++) {
+                if (mPluginMap.valueAt(i).dependsOn(p, cls)) {
+                    return true;
+                }
             }
         }
         return false;
@@ -335,10 +347,12 @@
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println(String.format("  plugin map (%d):", mPluginMap.size()));
-        for (PluginListener listener: mPluginMap.keySet()) {
-            pw.println(String.format("    %s -> %s",
-                    listener, mPluginMap.get(listener)));
+        synchronized (this) {
+            pw.println(String.format("  plugin map (%d):", mPluginMap.size()));
+            for (PluginListener listener : mPluginMap.keySet()) {
+                pw.println(String.format("    %s -> %s",
+                        listener, mPluginMap.get(listener)));
+            }
         }
     }
 
@@ -418,8 +432,10 @@
                 // We couldn't find any plugins involved in this crash, just to be safe
                 // disable all the plugins, so we can be sure that SysUI is running as
                 // best as possible.
-                for (PluginInstanceManager manager : mPluginMap.values()) {
-                    disabledAny |= manager.disableAll();
+                synchronized (this) {
+                    for (PluginInstanceManager manager : mPluginMap.values()) {
+                        disabledAny |= manager.disableAll();
+                    }
                 }
             }
             if (disabledAny) {
@@ -433,9 +449,11 @@
         private boolean checkStack(Throwable throwable) {
             if (throwable == null) return false;
             boolean disabledAny = false;
-            for (StackTraceElement element : throwable.getStackTrace()) {
-                for (PluginInstanceManager manager : mPluginMap.values()) {
-                    disabledAny |= manager.checkAndDisable(element.getClassName());
+            synchronized (this) {
+                for (StackTraceElement element : throwable.getStackTrace()) {
+                    for (PluginInstanceManager manager : mPluginMap.values()) {
+                        disabledAny |= manager.checkAndDisable(element.getClassName());
+                    }
                 }
             }
             return disabledAny | checkStack(throwable.getCause());
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 98a8110..98b7e24 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -38,6 +38,7 @@
     public int windowingMode;
     public int systemUiVisibility;
     public float scale;
+    public long snapshotId;
 
     public ThumbnailData() {
         thumbnail = null;
@@ -49,6 +50,7 @@
         isTranslucent = false;
         windowingMode = WINDOWING_MODE_UNDEFINED;
         systemUiVisibility = 0;
+        snapshotId = 0;
     }
 
     public ThumbnailData(TaskSnapshot snapshot) {
@@ -61,5 +63,6 @@
         isTranslucent = snapshot.isTranslucent();
         windowingMode = snapshot.getWindowingMode();
         systemUiVisibility = snapshot.getSystemUiVisibility();
+        snapshotId = snapshot.getId();
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 2483192..5097216 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -584,6 +584,9 @@
         @Override
         public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues,
                 TransitionValues endValues) {
+            if (!sceneRoot.isShown()) {
+                return null;
+            }
             final float cutoff = mCutoff;
             final int startVisibility = View.INVISIBLE;
             final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY);
@@ -596,6 +599,9 @@
         @Override
         public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues,
                 TransitionValues endValues) {
+            if (!sceneRoot.isShown()) {
+                return null;
+            }
             final float cutoff = 1f - mCutoff;
             final int startVisibility = View.VISIBLE;
             final int endVisibility = (int) endValues.values.get(PROPNAME_VISIBILITY);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index c7c648c..4ad262f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -513,7 +513,7 @@
                 case SimPuk:
                     // Shortcut for SIM PIN/PUK to go to directly to user's security screen or home
                     SecurityMode securityMode = mSecurityModel.getSecurityMode(targetUserId);
-                    if (securityMode == SecurityMode.None || mLockPatternUtils.isLockScreenDisabled(
+                    if (securityMode == SecurityMode.None && mLockPatternUtils.isLockScreenDisabled(
                             KeyguardUpdateMonitor.getCurrentUser())) {
                         finish = true;
                         eventSubtype = BOUNCER_DISMISS_SIM;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index e219e24..af4e61b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -89,6 +89,7 @@
     private final HashMap<View, PendingIntent> mClickActions;
     private final ActivityStarter mActivityStarter;
     private final ConfigurationController mConfigurationController;
+    private final LayoutTransition mLayoutTransition;
     private Uri mKeyguardSliceUri;
     @VisibleForTesting
     TextView mTitle;
@@ -126,16 +127,16 @@
         mActivityStarter = activityStarter;
         mConfigurationController = configurationController;
 
-        LayoutTransition transition = new LayoutTransition();
-        transition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2);
-        transition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION);
-        transition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 2);
-        transition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
-        transition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
-        transition.setInterpolator(LayoutTransition.APPEARING, Interpolators.FAST_OUT_SLOW_IN);
-        transition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT);
-        transition.setAnimateParentHierarchy(false);
-        setLayoutTransition(transition);
+        mLayoutTransition = new LayoutTransition();
+        mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2);
+        mLayoutTransition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION);
+        mLayoutTransition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 2);
+        mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
+        mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
+        mLayoutTransition.setInterpolator(LayoutTransition.APPEARING,
+                Interpolators.FAST_OUT_SLOW_IN);
+        mLayoutTransition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT);
+        mLayoutTransition.setAnimateParentHierarchy(false);
     }
 
     @Override
@@ -174,6 +175,12 @@
         mConfigurationController.removeCallback(this);
     }
 
+    @Override
+    public void onVisibilityAggregated(boolean isVisible) {
+        super.onVisibilityAggregated(isVisible);
+        setLayoutTransition(isVisible ? mLayoutTransition : null);
+    }
+
     /**
      * Returns whether the current visible slice has a title/header.
      */
@@ -419,6 +426,7 @@
          * their desired positions.
          */
         private final Animation.AnimationListener mKeepAwakeListener;
+        private LayoutTransition mLayoutTransition;
         private float mDarkAmount;
 
         public Row(Context context) {
@@ -440,33 +448,41 @@
 
         @Override
         protected void onFinishInflate() {
-            LayoutTransition transition = new LayoutTransition();
-            transition.setDuration(DEFAULT_ANIM_DURATION);
+            mLayoutTransition = new LayoutTransition();
+            mLayoutTransition.setDuration(DEFAULT_ANIM_DURATION);
 
             PropertyValuesHolder left = PropertyValuesHolder.ofInt("left", 0, 1);
             PropertyValuesHolder right = PropertyValuesHolder.ofInt("right", 0, 1);
             ObjectAnimator changeAnimator = ObjectAnimator.ofPropertyValuesHolder((Object) null,
                     left, right);
-            transition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeAnimator);
-            transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeAnimator);
-            transition.setInterpolator(LayoutTransition.CHANGE_APPEARING,
+            mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeAnimator);
+            mLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeAnimator);
+            mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_APPEARING,
                     Interpolators.ACCELERATE_DECELERATE);
-            transition.setInterpolator(LayoutTransition.CHANGE_DISAPPEARING,
+            mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_DISAPPEARING,
                     Interpolators.ACCELERATE_DECELERATE);
-            transition.setStartDelay(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION);
-            transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, DEFAULT_ANIM_DURATION);
+            mLayoutTransition.setStartDelay(LayoutTransition.CHANGE_APPEARING,
+                    DEFAULT_ANIM_DURATION);
+            mLayoutTransition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING,
+                    DEFAULT_ANIM_DURATION);
 
             ObjectAnimator appearAnimator = ObjectAnimator.ofFloat(null, "alpha", 0f, 1f);
-            transition.setAnimator(LayoutTransition.APPEARING, appearAnimator);
-            transition.setInterpolator(LayoutTransition.APPEARING, Interpolators.ALPHA_IN);
+            mLayoutTransition.setAnimator(LayoutTransition.APPEARING, appearAnimator);
+            mLayoutTransition.setInterpolator(LayoutTransition.APPEARING, Interpolators.ALPHA_IN);
 
             ObjectAnimator disappearAnimator = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);
-            transition.setInterpolator(LayoutTransition.DISAPPEARING, Interpolators.ALPHA_OUT);
-            transition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 4);
-            transition.setAnimator(LayoutTransition.DISAPPEARING, disappearAnimator);
+            mLayoutTransition.setInterpolator(LayoutTransition.DISAPPEARING,
+                    Interpolators.ALPHA_OUT);
+            mLayoutTransition.setDuration(LayoutTransition.DISAPPEARING, DEFAULT_ANIM_DURATION / 4);
+            mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, disappearAnimator);
 
-            transition.setAnimateParentHierarchy(false);
-            setLayoutTransition(transition);
+            mLayoutTransition.setAnimateParentHierarchy(false);
+        }
+
+        @Override
+        public void onVisibilityAggregated(boolean isVisible) {
+            super.onVisibilityAggregated(isVisible);
+            setLayoutTransition(isVisible ? mLayoutTransition : null);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2eb93d3..fd618b0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -377,14 +377,15 @@
         }
     };
 
-    private boolean mFaceSettingEnabledForUser;
+    private SparseBooleanArray mFaceSettingEnabledForUser = new SparseBooleanArray();
     private BiometricManager mBiometricManager;
     private IBiometricEnabledOnKeyguardCallback mBiometricEnabledCallback =
             new IBiometricEnabledOnKeyguardCallback.Stub() {
         @Override
-        public void onChanged(BiometricSourceType type, boolean enabled) throws RemoteException {
+        public void onChanged(BiometricSourceType type, boolean enabled, int userId)
+                throws RemoteException {
             if (type == BiometricSourceType.FACE) {
-                mFaceSettingEnabledForUser = enabled;
+                mFaceSettingEnabledForUser.put(userId, enabled);
                 updateFaceListeningState();
             }
         }
@@ -1711,7 +1712,7 @@
         // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware.
         return (mBouncer || mAuthInterruptActive || awakeKeyguard || shouldListenForFaceAssistant())
                 && !mSwitchingUser && !isFaceDisabled(user) && becauseCannotSkipBouncer
-                && !mKeyguardGoingAway && mFaceSettingEnabledForUser && !mLockIconPressed
+                && !mKeyguardGoingAway && mFaceSettingEnabledForUser.get(user) && !mLockIconPressed
                 && strongAuthAllowsScanning && mIsPrimaryUser
                 && !mSecureCameraLaunched;
     }
@@ -1783,13 +1784,14 @@
     }
 
     /**
-     * If face hardware is available and user has enrolled. Not considering encryption or
-     * lockdown state.
+     * If face hardware is available, user has enrolled and enabled auth via setting.
+     * Not considering encryption or lock down state.
      */
     public boolean isUnlockWithFacePossible(int userId) {
         return mFaceManager != null && mFaceManager.isHardwareDetected()
                 && !isFaceDisabled(userId)
-                && mFaceManager.hasEnrolledTemplates(userId);
+                && mFaceManager.hasEnrolledTemplates(userId)
+                && mFaceSettingEnabledForUser.get(userId);
     }
 
     private void stopListeningForFingerprint() {
@@ -2657,7 +2659,7 @@
             pw.println("    possible=" + isUnlockWithFacePossible(userId));
             pw.println("    strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
             pw.println("    trustManaged=" + getUserTrustIsManaged(userId));
-            pw.println("    enabledByUser=" + mFaceSettingEnabledForUser);
+            pw.println("    enabledByUser=" + mFaceSettingEnabledForUser.get(userId));
             pw.println("    mSecureCameraLaunched=" + mSecureCameraLaunched);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/SystemBars.java b/packages/SystemUI/src/com/android/systemui/SystemBars.java
index 4285af0..c4c0fd6 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemBars.java
@@ -46,6 +46,13 @@
         }
     }
 
+    @Override
+    public void onBootCompleted() {
+        if (mStatusBar != null) {
+            mStatusBar.onBootCompleted();
+        }
+    }
+
     private void createStatusBarFromConfig() {
         if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
         final String clsName = mContext.getString(R.string.config_statusBarComponent);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
index 0041b0c..ea175ed 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java
@@ -239,4 +239,8 @@
     public void dump(PrintWriter pw) {
 
     }
+
+    @Override
+    public void cleanup() {
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index 67dfdca..fba0d50 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -168,6 +168,7 @@
                     .append("enabled=").append(isEnabled() ? 1 : 0)
                     .append(" mScreenOn=").append(mScreenOn ? 1 : 0)
                     .append(" mState=").append(StatusBarState.toShortString(mState))
+                    .append(" mShowingAod=").append(mShowingAod ? 1 : 0)
                     .toString()
             );
         }
@@ -550,6 +551,14 @@
         pw.println();
     }
 
+    @Override
+    public void cleanup() {
+        mSensorManager.unregisterListener(mSensorEventListener);
+        mContext.getContentResolver().unregisterContentObserver(mSettingsObserver);
+        Dependency.get(StatusBarStateController.class).removeCallback(mStatusBarStateListener);
+        KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mKeyguardUpdateCallback);
+    }
+
     public Uri reportRejectedTouch() {
         if (mDataCollector.isEnabled()) {
             return mDataCollector.reportRejectedTouch();
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index 3cc8ec9a..128cc61 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -65,6 +65,7 @@
             public void onPluginConnected(FalsingPlugin plugin, Context context) {
                 FalsingManager pluginFalsingManager = plugin.getFalsingManager(context);
                 if (pluginFalsingManager != null) {
+                    mInternalFalsingManager.cleanup();
                     mInternalFalsingManager = pluginFalsingManager;
                 }
             }
@@ -91,7 +92,11 @@
     @VisibleForTesting
     public void setupFalsingManager(Context context) {
         boolean brightlineEnabled = DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, false);
+                DeviceConfig.NAMESPACE_SYSTEMUI, BRIGHTLINE_FALSING_MANAGER_ENABLED, true);
+
+        if (mInternalFalsingManager != null) {
+            mInternalFalsingManager.cleanup();
+        }
         if (!brightlineEnabled) {
             mInternalFalsingManager = new FalsingManagerImpl(context);
         } else {
@@ -290,4 +295,9 @@
     public void dump(PrintWriter pw) {
         mInternalFalsingManager.dump(pw);
     }
+
+    @Override
+    public void cleanup() {
+        mInternalFalsingManager.cleanup();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index 00f35aa..cee01a4 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -324,6 +324,11 @@
     public void dump(PrintWriter printWriter) {
     }
 
+    @Override
+    public void cleanup() {
+        unregisterSensors();
+    }
+
     static void logDebug(String msg) {
         logDebug(msg, null);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
index 730907e..cc66454 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DiagonalClassifier.java
@@ -16,9 +16,13 @@
 
 package com.android.systemui.classifier.brightline;
 
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE;
 import static com.android.systemui.classifier.Classifier.LEFT_AFFORDANCE;
 import static com.android.systemui.classifier.Classifier.RIGHT_AFFORDANCE;
 
+import android.provider.DeviceConfig;
+
 /**
  * False on swipes that are too close to 45 degrees.
  *
@@ -35,8 +39,20 @@
     private static final float ONE_HUNDRED_EIGHTY_DEG = (float) (Math.PI);
     private static final float THREE_HUNDRED_SIXTY_DEG = (float) (2 * Math.PI);
 
+    private final float mHorizontalAngleRange;
+    private final float mVerticalAngleRange;
+
     DiagonalClassifier(FalsingDataProvider dataProvider) {
         super(dataProvider);
+
+        mHorizontalAngleRange = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_DIAGONAL_HORIZONTAL_ANGLE_RANGE,
+                HORIZONTAL_ANGLE_RANGE);
+        mVerticalAngleRange = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_DIAGONAL_VERTICAL_ANGLE_RANGE,
+                VERTICAL_ANGLE_RANGE);
     }
 
     @Override
@@ -52,11 +68,11 @@
             return false;
         }
 
-        float minAngle = DIAGONAL - HORIZONTAL_ANGLE_RANGE;
-        float maxAngle = DIAGONAL + HORIZONTAL_ANGLE_RANGE;
+        float minAngle = DIAGONAL - mHorizontalAngleRange;
+        float maxAngle = DIAGONAL + mHorizontalAngleRange;
         if (isVertical()) {
-            minAngle = DIAGONAL - VERTICAL_ANGLE_RANGE;
-            maxAngle = DIAGONAL + VERTICAL_ANGLE_RANGE;
+            minAngle = DIAGONAL - mVerticalAngleRange;
+            maxAngle = DIAGONAL + mVerticalAngleRange;
         }
 
         return angleBetween(angle, minAngle, maxAngle)
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
index 005ee12..a6a617d 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
@@ -16,6 +16,14 @@
 
 package com.android.systemui.classifier.brightline;
 
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN;
+
+import android.provider.DeviceConfig;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 
@@ -31,12 +39,13 @@
     private static final float HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
     private static final float VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
     private static final float VELOCITY_TO_DISTANCE = 80f;
-    private static final float SCREEN_FRACTION_MIN_DISTANCE = 0.8f;
+    private static final float SCREEN_FRACTION_MAX_DISTANCE = 0.8f;
 
     private final float mVerticalFlingThresholdPx;
     private final float mHorizontalFlingThresholdPx;
     private final float mVerticalSwipeThresholdPx;
     private final float mHorizontalSwipeThresholdPx;
+    private final float mVelocityToDistanceMultiplier;
 
     private boolean mDistanceDirty;
     private DistanceVectors mCachedDistance;
@@ -44,18 +53,48 @@
     DistanceClassifier(FalsingDataProvider dataProvider) {
         super(dataProvider);
 
+        mVelocityToDistanceMultiplier = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_DISTANCE_VELOCITY_TO_DISTANCE,
+                VELOCITY_TO_DISTANCE);
+
+        float horizontalFlingThresholdIn = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_FLING_THRESHOLD_IN,
+                HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN);
+
+        float verticalFlingThresholdIn = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_DISTANCE_VERTICAL_FLING_THRESHOLD_IN,
+                VERTICAL_FLING_THRESHOLD_DISTANCE_IN);
+
+        float horizontalSwipeThresholdIn = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_DISTANCE_HORIZONTAL_SWIPE_THRESHOLD_IN,
+                HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN);
+
+        float verticalSwipeThresholdIn = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_DISTANCE_VERTICAL_SWIPE_THRESHOLD_IN,
+                VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN);
+
+        float screenFractionMaxDistance = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_DISTANCE_SCREEN_FRACTION_MAX_DISTANCE,
+                SCREEN_FRACTION_MAX_DISTANCE);
+
         mHorizontalFlingThresholdPx = Math
-                .min(getWidthPixels() * SCREEN_FRACTION_MIN_DISTANCE,
-                        HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN * getXdpi());
+                .min(getWidthPixels() * screenFractionMaxDistance,
+                        horizontalFlingThresholdIn * getXdpi());
         mVerticalFlingThresholdPx = Math
-                .min(getHeightPixels() * SCREEN_FRACTION_MIN_DISTANCE,
-                        VERTICAL_FLING_THRESHOLD_DISTANCE_IN * getYdpi());
+                .min(getHeightPixels() * screenFractionMaxDistance,
+                        verticalFlingThresholdIn * getYdpi());
         mHorizontalSwipeThresholdPx = Math
-                .min(getWidthPixels() * SCREEN_FRACTION_MIN_DISTANCE,
-                        HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN * getXdpi());
+                .min(getWidthPixels() * screenFractionMaxDistance,
+                        horizontalSwipeThresholdIn * getXdpi());
         mVerticalSwipeThresholdPx = Math
-                .min(getHeightPixels() * SCREEN_FRACTION_MIN_DISTANCE,
-                        VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN * getYdpi());
+                .min(getHeightPixels() * screenFractionMaxDistance,
+                        verticalSwipeThresholdIn * getYdpi());
         mDistanceDirty = true;
     }
 
@@ -139,18 +178,18 @@
         }
 
         boolean getPassedFlingThreshold() {
-            float dX = this.mDx + this.mVx * VELOCITY_TO_DISTANCE;
-            float dY = this.mDy + this.mVy * VELOCITY_TO_DISTANCE;
+            float dX = this.mDx + this.mVx * mVelocityToDistanceMultiplier;
+            float dY = this.mDy + this.mVy * mVelocityToDistanceMultiplier;
 
             if (isHorizontal()) {
                 logDebug("Horizontal swipe and fling distance: " + this.mDx + ", "
-                        + this.mVx * VELOCITY_TO_DISTANCE);
+                        + this.mVx * mVelocityToDistanceMultiplier);
                 logDebug("Threshold: " + mHorizontalFlingThresholdPx);
                 return Math.abs(dX) >= mHorizontalFlingThresholdPx;
             }
 
             logDebug("Vertical swipe and fling distance: " + this.mDy + ", "
-                    + this.mVy * VELOCITY_TO_DISTANCE);
+                    + this.mVy * mVelocityToDistanceMultiplier);
             logDebug("Threshold: " + mVerticalFlingThresholdPx);
             return Math.abs(dY) >= mVerticalFlingThresholdPx;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
index 94a8ac85..2644bf9 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ProximityClassifier.java
@@ -16,10 +16,12 @@
 
 package com.android.systemui.classifier.brightline;
 
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD;
 import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
 
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
+import android.provider.DeviceConfig;
 import android.view.MotionEvent;
 
 
@@ -31,8 +33,9 @@
  */
 class ProximityClassifier extends FalsingClassifier {
 
-    private static final double PERCENT_COVERED_THRESHOLD = 0.1;
+    private static final float PERCENT_COVERED_THRESHOLD = 0.1f;
     private final DistanceClassifier mDistanceClassifier;
+    private final float mPercentCoveredThreshold;
 
     private boolean mNear;
     private long mGestureStartTimeNs;
@@ -44,6 +47,11 @@
             FalsingDataProvider dataProvider) {
         super(dataProvider);
         this.mDistanceClassifier = distanceClassifier;
+
+        mPercentCoveredThreshold = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_PROXIMITY_PERCENT_COVERED_THRESHOLD,
+                PERCENT_COVERED_THRESHOLD);
     }
 
     @Override
@@ -107,7 +115,7 @@
 
         logInfo("Percent of gesture in proximity: " + mPercentNear);
 
-        if (mPercentNear > PERCENT_COVERED_THRESHOLD) {
+        if (mPercentNear > mPercentCoveredThreshold) {
             return !mDistanceClassifier.isLongSwipe();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
index a62574f..c58b7db 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
@@ -16,7 +16,13 @@
 
 package com.android.systemui.classifier.brightline;
 
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_X_PRIMARY_DEVIANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE;
+
 import android.graphics.Point;
+import android.provider.DeviceConfig;
 import android.view.MotionEvent;
 
 import java.util.ArrayList;
@@ -37,8 +43,34 @@
     private static final float MAX_X_SECONDARY_DEVIANCE = .3f;
     private static final float MAX_Y_SECONDARY_DEVIANCE = .3f;
 
+    private final float mMaxXPrimaryDeviance;
+    private final float mMaxYPrimaryDeviance;
+    private final float mMaxXSecondaryDeviance;
+    private final float mMaxYSecondaryDeviance;
+
     ZigZagClassifier(FalsingDataProvider dataProvider) {
         super(dataProvider);
+
+        mMaxXPrimaryDeviance = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_ZIGZAG_X_PRIMARY_DEVIANCE,
+                MAX_X_PRIMARY_DEVIANCE);
+
+        mMaxYPrimaryDeviance = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_ZIGZAG_Y_PRIMARY_DEVIANCE,
+                MAX_Y_PRIMARY_DEVIANCE);
+
+        mMaxXSecondaryDeviance = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_ZIGZAG_X_SECONDARY_DEVIANCE,
+                MAX_X_SECONDARY_DEVIANCE);
+
+        mMaxYSecondaryDeviance = DeviceConfig.getFloat(
+                DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_ZIGZAG_Y_SECONDARY_DEVIANCE,
+                MAX_Y_SECONDARY_DEVIANCE);
+
     }
 
     @Override
@@ -98,11 +130,11 @@
         float maxXDeviance;
         float maxYDeviance;
         if (actualDx > actualDy) {
-            maxXDeviance = MAX_X_PRIMARY_DEVIANCE * totalDistanceIn * getXdpi();
-            maxYDeviance = MAX_Y_SECONDARY_DEVIANCE * totalDistanceIn * getYdpi();
+            maxXDeviance = mMaxXPrimaryDeviance * totalDistanceIn * getXdpi();
+            maxYDeviance = mMaxYSecondaryDeviance * totalDistanceIn * getYdpi();
         } else {
-            maxXDeviance = MAX_X_SECONDARY_DEVIANCE * totalDistanceIn * getXdpi();
-            maxYDeviance = MAX_Y_PRIMARY_DEVIANCE * totalDistanceIn * getYdpi();
+            maxXDeviance = mMaxXSecondaryDeviance * totalDistanceIn * getXdpi();
+            maxYDeviance = mMaxYPrimaryDeviance * totalDistanceIn * getYdpi();
         }
 
         logDebug("Straightness Deviance: (" + devianceX + "," + devianceY + ") vs "
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 0e93f42..d3e8b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -77,7 +77,7 @@
     protected void extractWallpaperColors() {
         super.extractWallpaperColors();
         // mTonal is final but this method will be invoked by the base class during its ctor.
-        if (mTonal == null) {
+        if (mTonal == null || mNeutralColorsLock == null) {
             return;
         }
         mTonal.applyFallback(mLockColors == null ? mSystemColors : mLockColors, mNeutralColorsLock);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 537c09e..1bc7e63 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -30,6 +30,7 @@
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.AsyncSensorManager;
 import com.android.systemui.util.wakelock.DelayedWakeLock;
@@ -70,7 +71,7 @@
                 new DozeScreenState(wrappedService, handler, params, wakeLock),
                 createDozeScreenBrightness(context, wrappedService, sensorManager, host, params,
                         handler),
-                new DozeWallpaperState(context),
+                new DozeWallpaperState(context, getBiometricUnlockController(dozeService)),
                 new DozeDockHandler(context, machine, host, config, handler, dockManager),
                 new DozeAuthRemover(dozeService)
         });
@@ -108,4 +109,10 @@
         final SystemUIApplication app = (SystemUIApplication) appCandidate;
         return app.getComponent(DozeHost.class);
     }
+
+    public static BiometricUnlockController getBiometricUnlockController(DozeService service) {
+        Application appCandidate = service.getApplication();
+        final SystemUIApplication app = (SystemUIApplication) appCandidate;
+        return app.getComponent(BiometricUnlockController.class);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 3c9d4a9..ae6dac5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -50,9 +50,23 @@
      */
     void onSlpiTap(float x, float y);
 
+    /**
+     * Artificially dim down the the display by changing scrim opacities.
+     * @param scrimOpacity opacity from 0 to 1.
+     */
     default void setAodDimmingScrim(float scrimOpacity) {}
+
+    /**
+     * Sets the actual display brightness.
+     * @param value from 0 to 255.
+     */
     void setDozeScreenBrightness(int value);
 
+    /**
+     * Makes scrims black and changes animation durations.
+     */
+    default void prepareForGentleWakeUp() {}
+
     void onIgnoreTouchWhilePulsing(boolean ignore);
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 5be097c..38ee2fe 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -82,7 +82,10 @@
         boolean messagePending = mHandler.hasCallbacks(mApplyPendingScreenState);
         boolean pulseEnding = oldState  == DozeMachine.State.DOZE_PULSE_DONE
                 && newState == DozeMachine.State.DOZE_AOD;
-        if (messagePending || oldState == DozeMachine.State.INITIALIZED || pulseEnding) {
+        boolean turningOn = (oldState == DozeMachine.State.DOZE_AOD_PAUSED
+                || oldState  == DozeMachine.State.DOZE) && newState == DozeMachine.State.DOZE_AOD;
+        boolean justInitialized = oldState == DozeMachine.State.INITIALIZED;
+        if (messagePending || justInitialized || pulseEnding || turningOn) {
             // During initialization, we hide the navigation bar. That is however only applied after
             // a traversal; setting the screen state here is immediate however, so it can happen
             // that the screen turns on again before the navigation bar is hidden. To work around
@@ -91,7 +94,7 @@
 
             // Delay screen state transitions even longer while animations are running.
             boolean shouldDelayTransition = newState == DozeMachine.State.DOZE_AOD
-                    && mParameters.shouldControlScreenOff();
+                    && mParameters.shouldControlScreenOff() && !turningOn;
 
             if (shouldDelayTransition) {
                 mWakeLock.setAcquired(true);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index cf04b7f..f6a921d 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -43,6 +43,7 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.R;
 import com.android.systemui.plugins.SensorManagerPlugin;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.AlarmTimeout;
@@ -198,7 +199,10 @@
         updateListening();
     }
 
-    private void updateListening() {
+    /**
+     * Registers/unregisters sensors based on internal state.
+     */
+    public void updateListening() {
         boolean anyListening = false;
         for (TriggerSensor s : mSensors) {
             // We don't want to be listening while we're PAUSED (prox sensor is covered)
@@ -231,7 +235,7 @@
 
     public void onUserSwitched() {
         for (TriggerSensor s : mSensors) {
-            s.updateListener();
+            s.updateListening();
         }
     }
 
@@ -246,7 +250,7 @@
                 return;
             }
             for (TriggerSensor s : mSensors) {
-                s.updateListener();
+                s.updateListening();
             }
         }
     };
@@ -287,12 +291,21 @@
         long mLastNear;
         final AlarmTimeout mCooldownTimer;
         final AlwaysOnDisplayPolicy mPolicy;
-
+        final Sensor mSensor;
 
         public ProxSensor(AlwaysOnDisplayPolicy policy) {
             mPolicy = policy;
             mCooldownTimer = new AlarmTimeout(mAlarmManager, this::updateRegistered,
                     "prox_cooldown", mHandler);
+
+            // The default prox sensor can be noisy, so let's use a prox gated brightness sensor
+            // if available.
+            Sensor sensor = DozeSensors.findSensorWithType(mSensorManager,
+                    mContext.getString(R.string.doze_brightness_sensor_type));
+            if (sensor == null) {
+                sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+            }
+            mSensor = sensor;
         }
 
         void setRequested(boolean requested) {
@@ -356,8 +369,9 @@
 
         @Override
         public String toString() {
-            return String.format("{registered=%s, requested=%s, coolingDown=%s, currentlyFar=%s}",
-                    mRegistered, mRequested, mCooldownTimer.isScheduled(), mCurrentlyFar);
+            return String.format("{registered=%s, requested=%s, coolingDown=%s, currentlyFar=%s,"
+                    + " sensor=%s}", mRegistered, mRequested, mCooldownTimer.isScheduled(),
+                    mCurrentlyFar, mSensor);
         }
     }
 
@@ -409,22 +423,22 @@
         public void setListening(boolean listen) {
             if (mRequested == listen) return;
             mRequested = listen;
-            updateListener();
+            updateListening();
         }
 
         public void setDisabled(boolean disabled) {
             if (mDisabled == disabled) return;
             mDisabled = disabled;
-            updateListener();
+            updateListening();
         }
 
         public void ignoreSetting(boolean ignored) {
             if (mIgnoresSetting == ignored) return;
             mIgnoresSetting = ignored;
-            updateListener();
+            updateListening();
         }
 
-        public void updateListener() {
+        public void updateListening() {
             if (!mConfigured || mSensor == null) return;
             if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
                     && !mRegistered) {
@@ -480,7 +494,7 @@
                 mCallback.onSensorPulse(mPulseReason, mSensorPerformsProxCheck, screenX, screenY,
                         event.values);
                 if (!mRegistered) {
-                    updateListener();  // reregister, this sensor only fires once
+                    updateListening();  // reregister, this sensor only fires once
                 }
             }));
         }
@@ -541,7 +555,7 @@
         }
 
         @Override
-        public void updateListener() {
+        public void updateListening() {
             if (!mConfigured) return;
             AsyncSensorManager asyncSensorManager = (AsyncSensorManager) mSensorManager;
             if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 97b08d5..8ef01e8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -201,7 +201,7 @@
             // Let's prepare the display to wake-up by drawing black.
             // This will cover the hardware wake-up sequence, where the display
             // becomes black for a few frames.
-            mDozeHost.setAodDimmingScrim(255f);
+            mDozeHost.setAodDimmingScrim(1f);
         }
         mMachine.wakeUp();
     }
@@ -314,6 +314,9 @@
                 break;
             case DOZE_PULSE_DONE:
                 mDozeSensors.requestTemporaryDisable();
+                // A pulse will temporarily disable sensors that require a touch screen.
+                // Let's make sure that they are re-enabled when the pulse is over.
+                mDozeSensors.updateListening();
                 break;
             case FINISH:
                 mBroadcastReceiver.unregister(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 51e96d2..1f33af8 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.doze;
 
+import static com.android.systemui.doze.DozeMachine.State.DOZE;
 import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
 
 import android.app.AlarmManager;
@@ -116,7 +117,7 @@
     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
         switch (newState) {
             case DOZE_AOD:
-                if (oldState == DOZE_AOD_PAUSED) {
+                if (oldState == DOZE_AOD_PAUSED || oldState == DOZE) {
                     // Whenever turning on the display, it's necessary to push a new frame.
                     // The display buffers will be empty and need to be filled.
                     mHost.dozeTimeTick();
@@ -130,6 +131,7 @@
                 break;
             case DOZE:
             case DOZE_AOD_PAUSED:
+                mHost.prepareForGentleWakeUp();
                 unscheduleTimeTick();
                 break;
             case DOZE_REQUEST_PULSE:
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
index 1b3cd88..35c8b74 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeWallpaperState.java
@@ -24,6 +24,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import java.io.PrintWriter;
@@ -38,18 +39,22 @@
 
     private final IWallpaperManager mWallpaperManagerService;
     private final DozeParameters mDozeParameters;
+    private final BiometricUnlockController mBiometricUnlockController;
     private boolean mIsAmbientMode;
 
-    public DozeWallpaperState(Context context) {
+    public DozeWallpaperState(Context context,
+            BiometricUnlockController biometricUnlockController) {
         this(IWallpaperManager.Stub.asInterface(
                 ServiceManager.getService(Context.WALLPAPER_SERVICE)),
+                biometricUnlockController,
                 DozeParameters.getInstance(context));
     }
 
     @VisibleForTesting
     DozeWallpaperState(IWallpaperManager wallpaperManagerService,
-            DozeParameters parameters) {
+            BiometricUnlockController biometricUnlockController, DozeParameters parameters) {
         mWallpaperManagerService = wallpaperManagerService;
+        mBiometricUnlockController = biometricUnlockController;
         mDozeParameters = parameters;
     }
 
@@ -76,7 +81,9 @@
         } else {
             boolean wakingUpFromPulse = oldState == DozeMachine.State.DOZE_PULSING
                     && newState == DozeMachine.State.FINISH;
-            animated = !mDozeParameters.getDisplayNeedsBlanking() || wakingUpFromPulse;
+            boolean fastDisplay = !mDozeParameters.getDisplayNeedsBlanking();
+            animated = (fastDisplay && !mBiometricUnlockController.unlockedByWakeAndUnlock())
+                    || wakingUpFromPulse;
         }
 
         if (isAmbientMode != mIsAmbientMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 5136682..48f32cf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -52,6 +52,7 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
@@ -62,7 +63,6 @@
 import com.android.systemui.util.wakelock.WakeLock;
 
 import java.util.Date;
-import java.util.HashSet;
 import java.util.Locale;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
@@ -128,6 +128,7 @@
     private CharSequence mMediaTitle;
     private CharSequence mMediaArtist;
     protected boolean mDozing;
+    private int mStatusBarState;
     private boolean mMediaIsVisible;
 
     /**
@@ -231,7 +232,11 @@
     protected boolean needsMediaLocked() {
         boolean keepWhenAwake = mKeyguardBypassController != null
                 && mKeyguardBypassController.getBypassEnabled() && mDozeParameters.getAlwaysOn();
-        return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenAwake);
+        // Show header if music is playing and the status bar is in the shade state. This way, an
+        // animation isn't necessary when pressing power and transitioning to AOD.
+        boolean keepWhenShade = mStatusBarState == StatusBarState.SHADE && mMediaIsVisible;
+        return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenAwake
+                || keepWhenShade);
     }
 
     protected void addMediaLocked(ListBuilder listBuilder) {
@@ -458,7 +463,7 @@
         synchronized (this) {
             boolean nextVisible = NotificationMediaManager.isPlayingState(state);
             mHandler.removeCallbacksAndMessages(mMediaToken);
-            if (mMediaIsVisible && !nextVisible) {
+            if (mMediaIsVisible && !nextVisible && mStatusBarState != StatusBarState.SHADE) {
                 // We need to delay this event for a few millis when stopping to avoid jank in the
                 // animation. The media app might not send its update when buffering, and the slice
                 // would end up without a header for 0.5 second.
@@ -515,5 +520,14 @@
 
     @Override
     public void onStateChanged(int newState) {
+        final boolean notify;
+        synchronized (this) {
+            boolean needsMedia = needsMediaLocked();
+            mStatusBarState = newState;
+            notify = needsMedia != needsMediaLocked();
+        }
+        if (notify) {
+            notifyChange();
+        }
     }
 }
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 46d53e4..14459d6 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -414,6 +414,7 @@
             if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null &&
                     pinnedStackInfo.taskIds.length > 0) {
                 Intent intent = new Intent(mContext, PipMenuActivity.class);
+                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                 intent.putExtra(EXTRA_CONTROLLER_MESSENGER, mMessenger);
                 intent.putExtra(EXTRA_ACTIONS, resolveMenuActions());
                 if (stackBounds != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 6a3816c..f7e5bcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -64,7 +64,6 @@
     private var mVisibilityAnimator: ObjectAnimator? = null
     private var mVisibilityAmount = 0.0f
     private var mLinearVisibilityAmount = 0.0f
-    private var mWakingUp = false
     private val mEntrySetToClearWhenFinished = mutableSetOf<NotificationEntry>()
     private val mDozeParameters: DozeParameters
     private var pulseExpanding: Boolean = false
@@ -73,6 +72,25 @@
 
     var fullyAwake: Boolean = false
 
+    var wakingUp = false
+        set(value) {
+            field = value
+            willWakeUp = false
+            if (value) {
+                if (mNotificationsVisible && !mNotificationsVisibleForExpansion
+                        && !bypassController.bypassEnabled) {
+                    // We're waking up while pulsing, let's make sure the animation looks nice
+                    mStackScroller.wakeUpFromPulse();
+                }
+                if (bypassController.bypassEnabled && !mNotificationsVisible) {
+                    // Let's make sure our huns become visible once we are waking up in case
+                    // they were blocked by the proximity sensor
+                    updateNotificationVisibility(animate = shouldAnimateVisibility(),
+                            increaseSpeed = false)
+                }
+            }
+        }
+
     var willWakeUp = false
         set(value) {
             if (!value || mDozeAmount != 0.0f) {
@@ -112,7 +130,7 @@
             var canShow = pulsing
             if (bypassController.bypassEnabled) {
                 // We also allow pulsing on the lock screen!
-                canShow = canShow || (mWakingUp || willWakeUp || fullyAwake)
+                canShow = canShow || (wakingUp || willWakeUp || fullyAwake)
                         && statusBarStateController.state == StatusBarState.KEYGUARD
             }
             return canShow
@@ -160,7 +178,7 @@
         wakeUpListeners.add(listener);
     }
 
-    fun removeFullyHiddenChangedListener(listener: WakeUpListener) {
+    fun removeListener(listener: WakeUpListener) {
         wakeUpListeners.remove(listener);
     }
 
@@ -169,7 +187,7 @@
         var visible = mNotificationsVisibleForExpansion || mHeadsUpManagerPhone.hasNotifications()
         visible = visible && canShowPulsingHuns
 
-        if (!visible && mNotificationsVisible && (mWakingUp || willWakeUp) && mDozeAmount != 0.0f) {
+        if (!visible && mNotificationsVisible && (wakingUp || willWakeUp) && mDozeAmount != 0.0f) {
             // let's not make notifications invisible while waking up, otherwise the animation
             // is strange
             return;
@@ -307,16 +325,6 @@
         return if (bypassController.bypassEnabled) 0.0f else overflow
     }
 
-    fun setWakingUp(wakingUp: Boolean) {
-        willWakeUp = false
-        mWakingUp = wakingUp
-        if (wakingUp && mNotificationsVisible && !mNotificationsVisibleForExpansion
-                && !bypassController.bypassEnabled) {
-            // We're waking up while pulsing, let's make sure the animation looks nice
-            mStackScroller.wakeUpFromPulse();
-        }
-    }
-
     override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) {
         var animate = shouldAnimateVisibility()
         if (!isHeadsUp) {
@@ -325,7 +333,7 @@
                     // if we animate, we see the shelf briefly visible. Instead we fully animate
                     // the notification and its background out
                     animate = false
-                } else if (!mWakingUp && !willWakeUp){
+                } else if (!wakingUp && !willWakeUp){
                     // TODO: look that this is done properly and not by anyone else
                     entry.setHeadsUpAnimatingAway(true)
                     mEntrySetToClearWhenFinished.add(entry)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index bec9520..04cbb13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -2549,13 +2549,21 @@
             }
             return;
         }
-        int minTopPosition = 0;
+        int minTopPosition;
         NotificationSection lastSection = getLastVisibleSection();
         boolean onKeyguard = mStatusBarState == StatusBarState.KEYGUARD;
         if (!onKeyguard) {
             minTopPosition = (int) (mTopPadding + mStackTranslation);
         } else if (lastSection == null) {
             minTopPosition = mTopPadding;
+        } else {
+            // The first sections could be empty while there could still be elements in later
+            // sections. The position of these first few sections is determined by the position of
+            // the first visible section.
+            NotificationSection firstVisibleSection = getFirstVisibleSection();
+            firstVisibleSection.updateBounds(0 /* minTopPosition*/, 0 /* minBottomPosition */,
+                    false /* shiftPulsingWithFirst */);
+            minTopPosition = firstVisibleSection.getBounds().top;
         }
         boolean shiftPulsingWithFirst = mHeadsUpManager.getAllEntries().count() <= 1
                 && (mAmbientState.isDozing()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index cc1170f..b444fa5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -83,6 +83,11 @@
         bindContents();
     }
 
+    @Override
+    public boolean isTransparent() {
+        return true;
+    }
+
     /** Must be called whenever the UI mode changes (i.e. when we enter night mode). */
     void onUiModeChanged() {
         updateBackgroundColors();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 01e2b28..7655056 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -159,15 +159,13 @@
         float drawStart = !ambientState.isOnKeyguard() ? ambientState.getTopPadding()
                 + ambientState.getStackTranslation() + ambientState.getExpandAnimationTopChange()
                 : 0;
-        float previousNotificationEnd = 0;
-        float previousNotificationStart = 0;
+        float clipStart = 0;
         int childCount = algorithmState.visibleChildren.size();
         for (int i = 0; i < childCount; i++) {
             ExpandableView child = algorithmState.visibleChildren.get(i);
             ExpandableViewState state = child.getViewState();
             if (!child.mustStayOnScreen() || state.headsUpIsVisible) {
-                previousNotificationEnd = Math.max(drawStart, previousNotificationEnd);
-                previousNotificationStart = Math.max(drawStart, previousNotificationStart);
+                clipStart = Math.max(drawStart, clipStart);
             }
             float newYTranslation = state.yTranslation;
             float newHeight = state.height;
@@ -175,10 +173,10 @@
             boolean isHeadsUp = (child instanceof ExpandableNotificationRow)
                     && ((ExpandableNotificationRow) child).isPinned();
             if (mClipNotificationScrollToTop
-                    && !state.inShelf && newYTranslation < previousNotificationEnd
-                    && (!isHeadsUp || ambientState.isShadeExpanded())) {
+                    && (!state.inShelf || isHeadsUp)
+                    && newYTranslation < clipStart) {
                 // The previous view is overlapping on top, clip!
-                float overlapAmount = previousNotificationEnd - newYTranslation;
+                float overlapAmount = clipStart - newYTranslation;
                 state.clipTopAmount = (int) overlapAmount;
             } else {
                 state.clipTopAmount = 0;
@@ -187,8 +185,7 @@
             if (!child.isTransparent()) {
                 // Only update the previous values if we are not transparent,
                 // otherwise we would clip to a transparent view.
-                previousNotificationEnd = newNotificationEnd;
-                previousNotificationStart = newYTranslation;
+                clipStart = Math.max(clipStart, isHeadsUp ? newYTranslation : newNotificationEnd);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index ea25ca8..94cd2cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -141,6 +141,7 @@
     private BiometricSourceType mPendingAuthenticatedBioSourceType = null;
     private boolean mPendingShowBouncer;
     private boolean mHasScreenTurnedOnSinceAuthenticating;
+    private boolean mFadedAwayAfterWakeAndUnlock;
 
     private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
 
@@ -368,6 +369,7 @@
     @Override
     public void onStartedGoingToSleep(int why) {
         resetMode();
+        mFadedAwayAfterWakeAndUnlock = false;
         mPendingAuthenticatedUserId = -1;
         mPendingAuthenticatedBioSourceType = null;
     }
@@ -467,8 +469,11 @@
         }
         if (mStatusBarKeyguardViewManager.isShowing()) {
             if (mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing() && unlockingAllowed) {
-                return bypass && !mKeyguardBypassController.canPlaySubtleWindowAnimations()
-                        ? MODE_UNLOCK_COLLAPSING : MODE_UNLOCK_FADING;
+                if (bypass && mKeyguardBypassController.canPlaySubtleWindowAnimations()) {
+                    return MODE_UNLOCK_FADING;
+                } else {
+                    return MODE_DISMISS_BOUNCER;
+                }
             } else if (unlockingAllowed) {
                 return bypass ? MODE_UNLOCK_FADING : MODE_NONE;
             } else {
@@ -510,6 +515,9 @@
     }
 
     public void finishKeyguardFadingAway() {
+        if (isWakeAndUnlock()) {
+            mFadedAwayAfterWakeAndUnlock = true;
+        }
         resetMode();
     }
 
@@ -560,6 +568,14 @@
     }
 
     /**
+     * Successful authentication with fingerprint, face, or iris that wakes up the device.
+     * This will return {@code true} even after the keyguard fades away.
+     */
+    public boolean unlockedByWakeAndUnlock() {
+        return  isWakeAndUnlock() || mFadedAwayAfterWakeAndUnlock;
+    }
+
+    /**
      * Successful authentication with fingerprint, face, or iris when the screen was either
      * on or off.
      */
@@ -568,6 +584,13 @@
     }
 
     /**
+     * Successful authentication with fingerprint, face, or iris when the lockscreen fades away
+     */
+    public boolean isUnlockFading() {
+        return mMode == MODE_UNLOCK_FADING;
+    }
+
+    /**
      * Translates biometric source type for logging purpose.
      */
     private int toSubtype(BiometricSourceType biometricSourceType) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 46dd5e6..f53c4e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -35,6 +35,7 @@
 import com.android.systemui.statusbar.HeadsUpStatusBarView;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
@@ -48,7 +49,7 @@
  * Controls the appearance of heads up notifications in the icon area and the header itself.
  */
 public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
-        DarkIconDispatcher.DarkReceiver {
+        DarkIconDispatcher.DarkReceiver, NotificationWakeUpCoordinator.WakeUpListener {
     public static final int CONTENT_FADE_DURATION = 110;
     public static final int CONTENT_FADE_DELAY = 100;
     private final NotificationIconAreaController mNotificationIconAreaController;
@@ -67,6 +68,7 @@
     private final KeyguardBypassController mBypassController;
     private final StatusBarStateController mStatusBarStateController;
     private final CommandQueue mCommandQueue;
+    private final NotificationWakeUpCoordinator mWakeUpCoordinator;
     @VisibleForTesting
     float mExpandedHeight;
     @VisibleForTesting
@@ -95,9 +97,10 @@
             HeadsUpManagerPhone headsUpManager,
             View statusbarView,
             SysuiStatusBarStateController statusBarStateController,
-            KeyguardBypassController keyguardBypassController) {
+            KeyguardBypassController keyguardBypassController,
+            NotificationWakeUpCoordinator wakeUpCoordinator) {
         this(notificationIconAreaController, headsUpManager, statusBarStateController,
-                keyguardBypassController,
+                keyguardBypassController, wakeUpCoordinator,
                 statusbarView.findViewById(R.id.heads_up_status_bar_view),
                 statusbarView.findViewById(R.id.notification_stack_scroller),
                 statusbarView.findViewById(R.id.notification_panel),
@@ -112,6 +115,7 @@
             HeadsUpManagerPhone headsUpManager,
             StatusBarStateController stateController,
             KeyguardBypassController bypassController,
+            NotificationWakeUpCoordinator wakeUpCoordinator,
             HeadsUpStatusBarView headsUpStatusBarView,
             NotificationStackScrollLayout stackScroller,
             NotificationPanelView panelView,
@@ -153,6 +157,8 @@
         });
         mBypassController = bypassController;
         mStatusBarStateController = stateController;
+        mWakeUpCoordinator = wakeUpCoordinator;
+        wakeUpCoordinator.addListener(this);
         mCommandQueue = getComponent(headsUpStatusBarView.getContext(), CommandQueue.class);
         mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
     }
@@ -161,6 +167,7 @@
     public void destroy() {
         mHeadsUpManager.removeListener(this);
         mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null);
+        mWakeUpCoordinator.removeListener(this);
         mPanelView.removeTrackingHeadsUpListener(mSetTrackingHeadsUp);
         mPanelView.removeVerticalTranslationListener(mUpdatePanelTranslation);
         mPanelView.setHeadsUpAppearanceController(null);
@@ -289,6 +296,11 @@
                     updateParentClipping(true /* shouldClip */);
                 });
             }
+            // Show the status bar icons when the view gets shown / hidden
+            if (mStatusBarStateController.getState() != StatusBarState.SHADE) {
+                mCommandQueue.recomputeDisableFlags(
+                        mHeadsUpStatusBarView.getContext().getDisplayId(), false);
+            }
         }
     }
 
@@ -362,10 +374,12 @@
      * @return if the heads up status bar view should be shown
      */
     public boolean shouldBeVisible() {
-        boolean canShow = !mIsExpanded;
+        boolean notificationsShown = !mWakeUpCoordinator.getNotificationsFullyHidden();
+        boolean canShow = !mIsExpanded && notificationsShown;
         if (mBypassController.getBypassEnabled() &&
                 (mStatusBarStateController.getState() == StatusBarState.KEYGUARD
-                        || mKeyguardMonitor.isKeyguardGoingAway())) {
+                        || mKeyguardMonitor.isKeyguardGoingAway())
+                && notificationsShown) {
             canShow = true;
         }
         return canShow && mHeadsUpManager.hasPinnedHeadsUp();
@@ -377,15 +391,6 @@
         updateHeader(entry);
     }
 
-    @Override
-    public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
-        if (mStatusBarStateController.getState() != StatusBarState.SHADE) {
-            // Show the status bar icons when the pinned mode changes
-            mCommandQueue.recomputeDisableFlags(
-                    mHeadsUpStatusBarView.getContext().getDisplayId(), false);
-        }
-    }
-
     public void setAppearFraction(float expandedHeight, float appearFraction) {
         boolean changed = expandedHeight != mExpandedHeight;
         mExpandedHeight = expandedHeight;
@@ -451,4 +456,9 @@
             mAppearFraction = oldController.mAppearFraction;
         }
     }
+
+    @Override
+    public void onFullyHiddenChanged(boolean isFullyHidden) {
+        updateTopEntry();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index cbaf85c..a7e7f08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -72,8 +72,6 @@
     private NotificationGroupManager mGroupManager;
     private VisualStabilityManager mVisualStabilityManager;
     private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
-    @VisibleForTesting
-    int mAutoDismissNotificationDecayDozing;
     private boolean mReleaseOnExpandFinish;
 
     private int mStatusBarHeight;
@@ -120,8 +118,6 @@
             KeyguardBypassController bypassController) {
         super(context);
         Resources resources = mContext.getResources();
-        mAutoDismissNotificationDecayDozing = resources.getInteger(
-                R.integer.heads_up_notification_decay_dozing);
         mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
         mAutoHeadsUpNotificationDecay = resources.getInteger(
                 R.integer.auto_heads_up_notification_decay);
@@ -367,12 +363,15 @@
     }
 
     public Region calculateTouchableRegion() {
-        if (!hasPinnedHeadsUp()) {
+        NotificationEntry topEntry = getTopEntry();
+        // This call could be made in an inconsistent state while the pinnedMode hasn't been
+        // updated yet, but callbacks leading out of the headsUp manager, querying it. Let's
+        // therefore also check if the topEntry is null.
+        if (!hasPinnedHeadsUp() || topEntry == null) {
             mTouchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
             updateRegionForNotch(mTouchableRegion);
 
         } else {
-            NotificationEntry topEntry = getTopEntry();
             if (topEntry.isChildInGroup()) {
                 final NotificationEntry groupSummary =
                         mGroupManager.getGroupSummary(topEntry.notification);
@@ -612,9 +611,7 @@
         }
 
         private int getDecayDuration() {
-            if (mStatusBarStateController.isDozing()) {
-                return mAutoDismissNotificationDecayDozing;
-            } else if (isAutoHeadsUp()) {
+            if (isAutoHeadsUp()) {
                 return getRecommendedHeadsUpTimeoutMs(mAutoHeadsUpNotificationDecay);
             } else {
                 return getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index c88b22b..0aec2b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -167,4 +167,8 @@
         pw.print("  qSExpanded: "); pw.println(qSExpanded)
         pw.print("  bouncerShowing: "); pw.println(bouncerShowing)
     }
+
+    companion object {
+        const val BYPASS_PANEL_FADE_DURATION = 67
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 49afae7..b13af8b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -102,6 +102,7 @@
     private boolean mWakeAndUnlockRunning;
     private boolean mKeyguardShowing;
     private boolean mShowingLaunchAffordance;
+    private boolean mKeyguardJustShown;
     private boolean mUpdatePending;
 
     private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
@@ -115,6 +116,9 @@
                         mBlockUpdates = false;
                         force = true;
                     }
+                    if (!wasShowing && mKeyguardShowing) {
+                        mKeyguardJustShown = true;
+                    }
                     update(force);
                 }
 
@@ -213,7 +217,7 @@
         mConfigurationController.removeCallback(this);
         mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
         mKeyguardMonitor.removeCallback(mKeyguardMonitorCallback);
-        mWakeUpCoordinator.removeFullyHiddenChangedListener(this);
+        mWakeUpCoordinator.removeListener(this);
         mUnlockMethodCache.removeListener(this);
         if (mDockManager != null) {
             mDockManager.removeListener(mDockEventListener);
@@ -273,8 +277,10 @@
 
         int state = getState();
         int lastState = mLastState;
+        boolean keyguardJustShown = mKeyguardJustShown;
         mIsFaceUnlockState = state == STATE_SCANNING_FACE;
         mLastState = state;
+        mKeyguardJustShown = false;
 
         boolean shouldUpdate = lastState != state || mForceUpdate;
         if (mBlockUpdates && canBlockUpdates()) {
@@ -283,7 +289,7 @@
         if (shouldUpdate) {
             mForceUpdate = false;
             @LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(lastState,
-                    state, mPulsing, mDozing);
+                    state, mPulsing, mDozing, keyguardJustShown);
             boolean isAnim = lockAnimIndex != -1;
             int iconRes = isAnim ? getThemedAnimationResId(lockAnimIndex) : getIconForState(state);
 
@@ -412,7 +418,7 @@
     }
 
     private static int getAnimationIndexForTransition(int oldState, int newState, boolean pulsing,
-            boolean dozing) {
+            boolean dozing, boolean keyguardJustShown) {
 
         // Never animate when screen is off
         if (dozing && !pulsing) {
@@ -423,7 +429,7 @@
             return ERROR;
         } else if (oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN) {
             return UNLOCK;
-        } else if (oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED) {
+        } else if (oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED && !keyguardJustShown) {
             return LOCK;
         } else if (newState == STATE_SCANNING_FACE) {
             return SCANNING;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 64fef55..1df9411 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -32,8 +32,6 @@
 import static com.android.systemui.shared.system.QuickStepContract.ACTION_ENABLE_GESTURE_NAV_RESULT;
 import static com.android.systemui.shared.system.QuickStepContract.EXTRA_RESULT_INTENT;
 
-import android.app.Notification;
-import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
@@ -42,7 +40,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.om.IOverlayManager;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.ApkAssets;
 import android.os.PatternMatcher;
@@ -52,16 +49,13 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
-import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseBooleanArray;
 
 import com.android.systemui.Dumpable;
-import com.android.systemui.R;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.util.NotificationChannels;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -80,11 +74,6 @@
     private static final String TAG = NavigationModeController.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    private static final int SYSTEM_APP_MASK =
-            ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
-    static final String SHARED_PREFERENCES_NAME = "navigation_mode_controller_preferences";
-    static final String PREFS_SWITCHED_FROM_GESTURE_NAV_KEY = "switched_from_gesture_nav";
-
     public interface ModeChangedListener {
         void onNavigationModeChanged(int mode);
     }
@@ -100,8 +89,6 @@
     private int mMode = NAV_BAR_MODE_3BUTTON;
     private ArrayList<ModeChangedListener> mListeners = new ArrayList<>();
 
-    private String mLastDefaultLauncher;
-
     private BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -112,18 +99,6 @@
                     }
                     updateCurrentInteractionMode(true /* notify */);
                     break;
-                case ACTION_PREFERRED_ACTIVITY_CHANGED:
-                    if (DEBUG) {
-                        Log.d(TAG, "ACTION_PREFERRED_ACTIVITY_CHANGED");
-                    }
-                    final String launcher = getDefaultLauncherPackageName(mCurrentUserContext);
-                    // Check if it is a default launcher change
-                    if (!TextUtils.equals(mLastDefaultLauncher, launcher)) {
-                        switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
-                        showNotificationIfDefaultLauncherSupportsGestureNav();
-                        mLastDefaultLauncher = launcher;
-                    }
-                    break;
             }
         }
     };
@@ -159,7 +134,6 @@
 
                     // Update the nav mode for the current user
                     updateCurrentInteractionMode(true /* notify */);
-                    switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
 
                     // When switching users, defer enabling the gestural nav overlay until the user
                     // is all set up
@@ -190,11 +164,7 @@
         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null,
                 null);
 
-        // We are only interested in launcher changes, so keeping track of the current default.
-        mLastDefaultLauncher = getDefaultLauncherPackageName(mContext);
-
         updateCurrentInteractionMode(false /* notify */);
-        switchFromGestureNavModeIfNotSupportedByDefaultLauncher();
 
         // Check if we need to defer enabling gestural nav
         deferGesturalNavOverlayIfNecessary();
@@ -216,21 +186,13 @@
             // Already in gesture mode
             return true;
         }
-        final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext);
-        if (supported == null || supported) {
-            Log.d(TAG, "Switching system navigation to full-gesture mode:"
-                    + " defaultLauncher="
-                    + getDefaultLauncherPackageName(mCurrentUserContext)
-                    + " contextUser="
-                    + mCurrentUserContext.getUserId());
 
-            setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT);
-            return true;
-        } else {
-            Log.e(TAG, "Gesture nav is not supported for defaultLauncher="
-                    + getDefaultLauncherPackageName(mCurrentUserContext));
-            return false;
-        }
+        Log.d(TAG, "Switching system navigation to full-gesture mode:"
+                + " contextUser="
+                + mCurrentUserContext.getUserId());
+
+        setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT);
+        return true;
     }
 
     private boolean enableGestureNav(Intent intent) {
@@ -430,100 +392,6 @@
         });
     }
 
-    private void switchFromGestureNavModeIfNotSupportedByDefaultLauncher() {
-        if (getCurrentInteractionMode(mCurrentUserContext) != NAV_BAR_MODE_GESTURAL) {
-            return;
-        }
-        final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext);
-        if (supported == null || supported) {
-            return;
-        }
-
-        Log.d(TAG, "Switching system navigation to 3-button mode:"
-                + " defaultLauncher=" + getDefaultLauncherPackageName(mCurrentUserContext)
-                + " contextUser=" + mCurrentUserContext.getUserId());
-
-        setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT);
-        showNotification(mCurrentUserContext, R.string.notification_content_system_nav_changed);
-        mCurrentUserContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
-                .edit().putBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, true).apply();
-    }
-
-    private void showNotificationIfDefaultLauncherSupportsGestureNav() {
-        boolean previouslySwitchedFromGestureNav = mCurrentUserContext
-                .getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
-                .getBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false);
-        if (!previouslySwitchedFromGestureNav) {
-            return;
-        }
-        if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL) {
-            return;
-        }
-        final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext);
-        if (supported == null || !supported) {
-            return;
-        }
-
-        showNotification(mCurrentUserContext, R.string.notification_content_gesture_nav_available);
-        mCurrentUserContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
-                .edit().putBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false).apply();
-    }
-
-    /**
-     * Returns null if there is no default launcher set for the current user. Returns true if the
-     * current default launcher supports Gesture Navigation. Returns false otherwise.
-     */
-    private Boolean isGestureNavSupportedByDefaultLauncher(Context context) {
-        final String defaultLauncherPackageName = getDefaultLauncherPackageName(context);
-        if (DEBUG) {
-            Log.d(TAG, "isGestureNavSupportedByDefaultLauncher:"
-                    + " defaultLauncher=" + defaultLauncherPackageName
-                    + " contextUser=" + context.getUserId());
-        }
-        if (defaultLauncherPackageName == null) {
-            return null;
-        }
-        if (isSystemApp(context, defaultLauncherPackageName)) {
-            return true;
-        }
-        return false;
-    }
-
-    private String getDefaultLauncherPackageName(Context context) {
-        final ComponentName cn = context.getPackageManager().getHomeActivities(new ArrayList<>());
-        if (cn == null) {
-            return null;
-        }
-        return cn.getPackageName();
-    }
-
-    /** Returns true if the app for the given package name is a system app for this device */
-    private boolean isSystemApp(Context context, String packageName) {
-        try {
-            ApplicationInfo ai = context.getPackageManager().getApplicationInfo(packageName,
-                    PackageManager.GET_META_DATA);
-            return ai != null && ((ai.flags & SYSTEM_APP_MASK) != 0);
-        } catch (PackageManager.NameNotFoundException e) {
-            return false;
-        }
-    }
-
-    private void showNotification(Context context, int resId) {
-        final CharSequence message = context.getResources().getString(resId);
-        if (DEBUG) {
-            Log.d(TAG, "showNotification: message=" + message);
-        }
-
-        final Notification.Builder builder =
-                new Notification.Builder(mContext, NotificationChannels.ALERTS)
-                        .setContentText(message)
-                        .setStyle(new Notification.BigTextStyle())
-                        .setSmallIcon(R.drawable.ic_info)
-                        .setAutoCancel(true)
-                        .setContentIntent(PendingIntent.getActivity(context, 0, new Intent(), 0));
-        context.getSystemService(NotificationManager.class).notify(TAG, 0, builder.build());
-    }
-
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NavigationModeController:");
@@ -536,12 +404,6 @@
         }
         pw.println("  defaultOverlays=" + defaultOverlays);
         dumpAssetPaths(mCurrentUserContext);
-
-        pw.println("  defaultLauncher=" + mLastDefaultLauncher);
-        boolean previouslySwitchedFromGestureNav = mCurrentUserContext
-                .getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
-                .getBoolean(PREFS_SWITCHED_FROM_GESTURE_NAV_KEY, false);
-        pw.println("  previouslySwitchedFromGestureNav=" + previouslySwitchedFromGestureNav);
     }
 
     private void dumpAssetPaths(Context context) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 0bbfbef..195870b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -464,7 +464,7 @@
         if (!sbn.isGroup() || sbn.getNotification().isGroupSummary()) {
             return false;
         }
-        if (!mHeadsUpManager.isAlerting(entry.key)) {
+        if (mHeadsUpManager != null && !mHeadsUpManager.isAlerting(entry.key)) {
             return false;
         }
         return (sbn.getNotification().fullScreenIntent != null
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 d2159ca..21de8a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -4,7 +4,6 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
-import android.provider.Settings;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -32,7 +31,6 @@
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.tuner.TunerService;
 
 import java.util.ArrayList;
 import java.util.Objects;
@@ -58,7 +56,6 @@
     private final KeyguardBypassController mBypassController;
     private final DozeParameters mDozeParameters;
 
-    private boolean mShowSilentOnLockscreen = true;
     private int mIconSize;
     private int mIconHPadding;
     private int mIconTint = Color.WHITE;
@@ -101,11 +98,6 @@
 
         initializeNotificationAreaViews(context);
         reloadAodColor();
-
-        TunerService tunerService = Dependency.get(TunerService.class);
-        tunerService.addTunable((key, newValue) -> {
-            mShowSilentOnLockscreen = "1".equals(newValue);
-        }, Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS);
     }
 
     protected View inflateIconArea(LayoutInflater inflater) {
@@ -238,7 +230,7 @@
     }
 
     protected boolean shouldShowNotificationIcon(NotificationEntry entry,
-            boolean showAmbient, boolean showLowPriority, boolean hideDismissed,
+            boolean showAmbient, boolean hideDismissed,
             boolean hideRepliedMessages, boolean hideCurrentMedia, boolean hideCenteredIcon,
             boolean hidePulsing, boolean onlyShowCenteredIcon) {
 
@@ -257,9 +249,6 @@
         if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) {
             return false;
         }
-        if (!showLowPriority && !entry.isHighPriority()) {
-            return false;
-        }
         if (!entry.isTopLevelChild()) {
             return false;
         }
@@ -297,7 +286,6 @@
     private void updateShelfIcons() {
         updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
                 true /* showAmbient */,
-                true /* showLowPriority */,
                 false /* hideDismissed */,
                 false /* hideRepliedMessages */,
                 false /* hideCurrentMedia */,
@@ -309,7 +297,6 @@
     public void updateStatusBarIcons() {
         updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
                 false /* showAmbient */,
-                true /* showLowPriority */,
                 true /* hideDismissed */,
                 true /* hideRepliedMessages */,
                 false /* hideCurrentMedia */,
@@ -321,7 +308,6 @@
     private void updateCenterIcon() {
         updateIconsForLayout(entry -> entry.centeredIcon, mCenteredIcon,
                 false /* showAmbient */,
-                true /* showLowPriority */,
                 false /* hideDismissed */,
                 false /* hideRepliedMessages */,
                 false /* hideCurrentMedia */,
@@ -333,7 +319,6 @@
     public void updateAodNotificationIcons() {
         updateIconsForLayout(entry -> entry.aodIcon, mAodIcons,
                 false /* showAmbient */,
-                mShowSilentOnLockscreen /* showLowPriority */,
                 true /* hideDismissed */,
                 true /* hideRepliedMessages */,
                 true /* hideCurrentMedia */,
@@ -353,7 +338,7 @@
      * @param hidePulsing should pulsing notifications be hidden
      */
     private void updateIconsForLayout(Function<NotificationEntry, StatusBarIconView> function,
-            NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority,
+            NotificationIconContainer hostLayout, boolean showAmbient,
             boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia,
             boolean hideCenteredIcon, boolean hidePulsing, boolean onlyShowCenteredIcon) {
         ArrayList<StatusBarIconView> toShow = new ArrayList<>(
@@ -364,7 +349,7 @@
             View view = mNotificationScrollLayout.getChildAt(i);
             if (view instanceof ExpandableNotificationRow) {
                 NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry();
-                if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed,
+                if (shouldShowNotificationIcon(ent, showAmbient, hideDismissed,
                         hideRepliedMessages, hideCurrentMedia, hideCenteredIcon, hidePulsing,
                         onlyShowCenteredIcon)) {
                     StatusBarIconView iconView = function.apply(ent);
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 971a7ee..901afab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -454,6 +454,11 @@
         mPulseExpansionHandler.setUp(mNotificationStackScroller, this, mShadeController);
         mWakeUpCoordinator.addListener(new NotificationWakeUpCoordinator.WakeUpListener() {
             @Override
+            public void onFullyHiddenChanged(boolean isFullyHidden) {
+                updateKeyguardStatusBarForHeadsUp();
+            }
+
+            @Override
             public void onPulseExpansionChanged(boolean expandingChanged) {
                 if (mKeyguardBypassController.getBypassEnabled()) {
                     // Position the notifications while dragging down while pulsing
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 3f38c04..1aec5e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -487,6 +487,20 @@
     }
 
     /**
+     * Set front scrim to black, cancelling animations, in order to prepare to fade them
+     * away once the display turns on.
+     */
+    public void prepareForGentleWakeUp() {
+        if (mState == ScrimState.AOD && mDozeParameters.getAlwaysOn()) {
+            mCurrentInFrontAlpha = 1f;
+            mAnimateChange = false;
+            updateScrims();
+            mAnimateChange = true;
+            mAnimationDuration = ANIMATION_DURATION_LONG;
+        }
+    }
+
+    /**
      * If the lock screen sensor is active.
      */
     public void setWakeLockScreenSensorActive(boolean active) {
@@ -932,6 +946,12 @@
         }
     }
 
+    public void setUnlockIsFading(boolean unlockFading) {
+        for (ScrimState state : ScrimState.values()) {
+            state.setUnlockIsFading(unlockFading);
+        }
+    }
+
     public void setLaunchingAffordanceWithPreview(boolean launchingAffordanceWithPreview) {
         for (ScrimState state : ScrimState.values()) {
             state.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index d152ecd..763e0d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -147,7 +147,9 @@
         public void prepare(ScrimState previousState) {
             mCurrentBehindAlpha = 0;
             mCurrentInFrontAlpha = 0;
-            mAnimationDuration = StatusBar.FADE_KEYGUARD_DURATION;
+            mAnimationDuration = mUnlockIsFading
+                    ? KeyguardBypassController.BYPASS_PANEL_FADE_DURATION
+                    : StatusBar.FADE_KEYGUARD_DURATION;
             mAnimateChange = !mLaunchingAffordanceWithPreview;
 
             if (previousState == ScrimState.AOD) {
@@ -198,6 +200,7 @@
     boolean mHasBackdrop;
     boolean mLaunchingAffordanceWithPreview;
     boolean mWakeLockScreenSensorActive;
+    boolean mUnlockIsFading;
 
     ScrimState(int index) {
         mIndex = index;
@@ -285,4 +288,8 @@
     public void setWakeLockScreenSensorActive(boolean active) {
         mWakeLockScreenSensorActive = active;
     }
+
+    public void setUnlockIsFading(boolean unlockIsFading) {
+        mUnlockIsFading = unlockIsFading;
+    }
 }
\ No newline at end of file
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 40ebe58..9f1ec4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -855,7 +855,8 @@
                     }
                     mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                             mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow,
-                            mStatusBarStateController, mKeyguardBypassController);
+                            mStatusBarStateController, mKeyguardBypassController,
+                            mWakeUpCoordinator);
                     mHeadsUpAppearanceController.readFrom(oldController);
                     mStatusBarWindow.setStatusBarView(mStatusBarView);
                     updateAreThereNotifications();
@@ -1229,6 +1230,7 @@
                 mDozeScrimController, keyguardViewMediator,
                 mScrimController, this, UnlockMethodCache.getInstance(mContext),
                 new Handler(), mKeyguardUpdateMonitor, mKeyguardBypassController);
+        putComponent(BiometricUnlockController.class, mBiometricUnlockController);
         mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
                 getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
                 mStatusBarWindow.findViewById(R.id.lock_icon_container), mStackScroller,
@@ -3839,6 +3841,7 @@
 
     public void notifyBiometricAuthModeChanged() {
         updateDozing();
+        mScrimController.setUnlockIsFading(mBiometricUnlockController.isUnlockFading());
         updateScrimController();
         mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock(),
                 mBiometricUnlockController.isBiometricUnlock());
@@ -3850,7 +3853,8 @@
 
         // We don't want to end up in KEYGUARD state when we're unlocking with
         // fingerprint from doze. We should cross fade directly from black.
-        boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock();
+        boolean unlocking = mBiometricUnlockController.isWakeAndUnlock()
+                || mKeyguardMonitor.isKeyguardFadingAway();
 
         // Do not animate the scrim expansion when triggered by the fingerprint sensor.
         mScrimController.setExpansionAffectsAlpha(
@@ -3875,9 +3879,9 @@
         } else if (isPulsing()) {
             mScrimController.transitionTo(ScrimState.PULSING,
                     mDozeScrimController.getScrimCallback());
-        } else if (mDozing && !wakeAndUnlocking) {
+        } else if (mDozing && !unlocking) {
             mScrimController.transitionTo(ScrimState.AOD);
-        } else if (mIsKeyguard && !wakeAndUnlocking) {
+        } else if (mIsKeyguard && !unlocking) {
             mScrimController.transitionTo(ScrimState.KEYGUARD);
         } else if (mBubbleController.isStackExpanded()) {
             mScrimController.transitionTo(ScrimState.BUBBLE_EXPANDED);
@@ -4118,6 +4122,11 @@
             mScrimController.setAodFrontScrimAlpha(scrimOpacity);
         }
 
+        @Override
+        public void prepareForGentleWakeUp() {
+            mScrimController.prepareForGentleWakeUp();
+        }
+
         private void dispatchTap(View view, float x, float y) {
             long now = SystemClock.elapsedRealtime();
             dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN);
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 65be708..5ce1329 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -85,7 +85,6 @@
     // make everything a bit slower to bridge a gap until the user is unlocked and home screen has
     // dranw its first frame.
     private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000;
-    private static final long BYPASS_PANEL_FADE_DURATION = 67;
 
     private static String TAG = "StatusBarKeyguardViewManager";
 
@@ -270,7 +269,7 @@
         boolean keyguardWithoutQs = mStatusBarStateController.getState() == StatusBarState.KEYGUARD
                 && !mNotificationPanelView.isQsExpanded();
         boolean lockVisible = (mBouncer.isShowing() || keyguardWithoutQs)
-                && !mBouncer.isAnimatingAway();
+                && !mBouncer.isAnimatingAway() && !mKeyguardMonitor.isKeyguardFadingAway();
 
         if (mLastLockVisible != lockVisible) {
             mLastLockVisible = lockVisible;
@@ -279,8 +278,14 @@
                         AppearAnimationUtils.DEFAULT_APPEAR_DURATION /* duration */,
                         0 /* delay */);
             } else {
+                final long duration;
+                if (needsBypassFading()) {
+                    duration = KeyguardBypassController.BYPASS_PANEL_FADE_DURATION;
+                } else {
+                    duration = AppearAnimationUtils.DEFAULT_APPEAR_DURATION / 2;
+                }
                 CrossFadeHelper.fadeOut(mLockIconContainer,
-                        AppearAnimationUtils.DEFAULT_APPEAR_DURATION / 2 /* duration */,
+                        duration /* duration */,
                         0 /* delay */, null /* runnable */);
             }
         }
@@ -567,7 +572,7 @@
                 if (needsBypassFading()) {
                     ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView,
                             mNotificationContainer,
-                            BYPASS_PANEL_FADE_DURATION,
+                            KeyguardBypassController.BYPASS_PANEL_FADE_DURATION,
                                     () -> {
                         mStatusBar.hideKeyguard();
                         onKeyguardFadedAway();
@@ -583,7 +588,7 @@
                     if (needsBypassFading()) {
                         ViewGroupFadeHelper.fadeOutAllChildrenExcept(mNotificationPanelView,
                                 mNotificationContainer,
-                                BYPASS_PANEL_FADE_DURATION,
+                                KeyguardBypassController.BYPASS_PANEL_FADE_DURATION,
                                 () -> {
                                     mStatusBar.hideKeyguard();
                                 });
@@ -602,6 +607,7 @@
                     mBiometricUnlockController.finishKeyguardFadingAway();
                 }
             }
+            updateLockIcon();
             updateStates();
             mStatusBarWindowController.setKeyguardShowing(false);
             mViewMediatorCallback.keyguardGone();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index f36c56f..a71fcdb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -107,6 +107,9 @@
         mListeners.remove(listener);
     }
 
+    /**
+     * If there are faces enrolled and user enabled face auth on keyguard.
+     */
     public boolean isUnlockingWithFacePossible() {
         return mIsUnlockingWithFacePossible;
     }
@@ -119,15 +122,16 @@
                 || (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked);
         boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
         boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
-        boolean hasEnrolledFaces = mKeyguardUpdateMonitor.isUnlockWithFacePossible(user);
-        boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer ||
-                trustManaged != mTrustManaged || mIsUnlockingWithFacePossible != hasEnrolledFaces;
+        boolean isUnlockingWithFacePossible = mKeyguardUpdateMonitor.isUnlockWithFacePossible(user);
+        boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer
+                || trustManaged != mTrustManaged
+                || mIsUnlockingWithFacePossible != isUnlockingWithFacePossible;
         if (changed || updateAlways) {
             mSecure = secure;
             mCanSkipBouncer = canSkipBouncer;
             mTrusted = trusted;
             mTrustManaged = trustManaged;
-            mIsUnlockingWithFacePossible = hasEnrolledFaces;
+            mIsUnlockingWithFacePossible = isUnlockingWithFacePossible;
             notifyListeners();
         }
         Trace.endSection();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index bdc6341..db6177a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -103,7 +103,8 @@
         when(context.getPackageManager()).thenReturn(mPackageManager);
         doAnswer(invocation -> {
             IBiometricEnabledOnKeyguardCallback callback = invocation.getArgument(0);
-            callback.onChanged(BiometricSourceType.FACE, true /* enabled */);
+            callback.onChanged(BiometricSourceType.FACE, true /* enabled */,
+                    KeyguardUpdateMonitor.getCurrentUser());
             return null;
         }).when(mBiometricManager).registerEnabledOnKeyguardCallback(any());
         when(mFaceManager.isHardwareDetected()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
index 329ef1c..7ea6493 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
@@ -56,6 +56,9 @@
         mHandler = new Handler(mTestableLooper.getLooper());
         mDefaultConfigValue = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
                 BRIGHTLINE_FALSING_MANAGER_ENABLED, false);
+        // In case it runs on a device where it's been set to true, set it to false by hand.
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+                BRIGHTLINE_FALSING_MANAGER_ENABLED, "false", false);
     }
 
     @After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index 2d6ae26..2ed0970 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.withSettings;
 
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.utils.hardware.FakeSensorManager;
 
 import org.mockito.Answers;
 import org.mockito.MockSettings;
@@ -39,6 +40,7 @@
         when(params.getPickupPerformsProxCheck()).thenReturn(true);
         when(params.getPolicy()).thenReturn(mock(AlwaysOnDisplayPolicy.class));
         when(params.doubleTapReportsTouchCoordinates()).thenReturn(false);
+        when(params.getDisplayNeedsBlanking()).thenReturn(false);
 
         doneHolder[0] = true;
         return params;
@@ -52,11 +54,17 @@
         when(config.pickupGestureEnabled(anyInt())).thenReturn(false);
         when(config.pulseOnNotificationEnabled(anyInt())).thenReturn(true);
         when(config.alwaysOnEnabled(anyInt())).thenReturn(false);
+        when(config.enabled(anyInt())).thenReturn(true);
+        when(config.getWakeLockScreenDebounce()).thenReturn(0L);
 
         when(config.doubleTapSensorType()).thenReturn(null);
         when(config.tapSensorType()).thenReturn(null);
         when(config.longPressSensorType()).thenReturn(null);
 
+        when(config.tapGestureEnabled(anyInt())).thenReturn(true);
+        when(config.tapSensorAvailable()).thenReturn(true);
+        when(config.tapSensorType()).thenReturn(FakeSensorManager.TAP_SENSOR_TYPE);
+
         when(config.dozePickupSensorAvailable()).thenReturn(false);
         when(config.wakeScreenGestureAvailable()).thenReturn(false);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 6979fd8..eb8ef09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -19,6 +19,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -27,18 +28,17 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AlarmManager;
-import android.app.Instrumentation;
+import android.hardware.Sensor;
 import android.hardware.display.AmbientDisplayConfiguration;
 import android.os.Handler;
 import android.os.Looper;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 
-import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dock.DockManagerFake;
+import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.wakelock.WakeLock;
 import com.android.systemui.util.wakelock.WakeLockFake;
@@ -46,14 +46,12 @@
 
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @SmallTest
-@Ignore("failing")
 @RunWith(AndroidTestingRunner.class)
-@RunWithLooper
+@RunWithLooper(setAsMainLooper = true)
 public class DozeTriggersTest extends SysuiTestCase {
     private DozeTriggers mTriggers;
     private DozeMachine mMachine;
@@ -61,10 +59,10 @@
     private AmbientDisplayConfiguration mConfig;
     private DozeParameters mParameters;
     private FakeSensorManager mSensors;
+    private Sensor mTapSensor;
     private WakeLock mWakeLock;
-    private Instrumentation mInstrumentation;
     private AlarmManager mAlarmManager;
-    private DockManagerFake mDockManagerFake;
+    private DockManager mDockManagerFake;
 
     @BeforeClass
     public static void setupSuite() {
@@ -74,15 +72,15 @@
 
     @Before
     public void setUp() throws Exception {
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mMachine = mock(DozeMachine.class);
         mAlarmManager = mock(AlarmManager.class);
-        mHost = new DozeHostFake();
+        mHost = spy(new DozeHostFake());
         mConfig = DozeConfigurationUtil.createMockConfig();
         mParameters = DozeConfigurationUtil.createMockParameters();
-        mSensors = new FakeSensorManager(mContext);
+        mSensors = spy(new FakeSensorManager(mContext));
+        mTapSensor = mSensors.getFakeTapSensor().getSensor();
         mWakeLock = new WakeLockFake();
-        mDockManagerFake = spy(new DockManagerFake());
+        mDockManagerFake = mock(DockManager.class);
 
         mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, mConfig, mParameters,
                 mSensors, Handler.createAsync(Looper.myLooper()), mWakeLock, true,
@@ -95,29 +93,45 @@
 
         mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
         mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
+        clearInvocations(mMachine);
 
         mHost.callback.onNotificationAlerted();
-
         mSensors.getMockProximitySensor().sendProximityResult(false); /* Near */
 
         verify(mMachine, never()).requestState(any());
         verify(mMachine, never()).requestPulse(anyInt());
 
         mHost.callback.onNotificationAlerted();
-
         mSensors.getMockProximitySensor().sendProximityResult(true); /* Far */
 
         verify(mMachine).requestPulse(anyInt());
     }
 
     @Test
+    public void testTransitionTo_disablesAndEnablesTouchSensors() {
+        when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+
+        mTriggers.transitionTo(DozeMachine.State.INITIALIZED, DozeMachine.State.DOZE);
+        verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor));
+
+        clearInvocations(mSensors);
+        mTriggers.transitionTo(DozeMachine.State.DOZE,
+                DozeMachine.State.DOZE_REQUEST_PULSE);
+        mTriggers.transitionTo(DozeMachine.State.DOZE_REQUEST_PULSE,
+                DozeMachine.State.DOZE_PULSING);
+        verify(mSensors).cancelTriggerSensor(any(), eq(mTapSensor));
+
+        clearInvocations(mSensors);
+        mTriggers.transitionTo(DozeMachine.State.DOZE_PULSING, DozeMachine.State.DOZE_PULSE_DONE);
+        verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor));
+    }
+
+    @Test
     public void testDockEventListener_registerAndUnregister() {
         mTriggers.transitionTo(DozeMachine.State.UNINITIALIZED, DozeMachine.State.INITIALIZED);
-
         verify(mDockManagerFake).addListener(any());
 
         mTriggers.transitionTo(DozeMachine.State.DOZE, DozeMachine.State.FINISH);
-
         verify(mDockManagerFake).removeListener(any());
     }
 
@@ -128,7 +142,6 @@
         mTriggers.onSensor(DozeLog.REASON_SENSOR_DOUBLE_TAP,
                 false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
                 null /* rawValues */);
-
         verify(mMachine, never()).wakeUp();
     }
 
@@ -142,7 +155,7 @@
                 false /* sensorPerformedProxCheck */, 50 /* screenX */, 50 /* screenY */,
                 null /* rawValues */);
 
-        verify(mHost).setAodDimmingScrim(eq(255));
+        verify(mHost).setAodDimmingScrim(eq(1f));
         verify(mMachine).wakeUp();
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
index 87ae85f..f07edf3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeWallpaperStateTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -29,6 +30,7 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.DozeParameters;
 
 import org.junit.Before;
@@ -44,12 +46,14 @@
 
     private DozeWallpaperState mDozeWallpaperState;
     @Mock IWallpaperManager mIWallpaperManager;
+    @Mock BiometricUnlockController mBiometricUnlockController;
     @Mock DozeParameters mDozeParameters;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mDozeParameters);
+        mDozeWallpaperState = new DozeWallpaperState(mIWallpaperManager, mBiometricUnlockController,
+                mDozeParameters);
     }
 
     @Test
@@ -102,6 +106,20 @@
     }
 
     @Test
+    public void testDoesNotAnimate_whenWakeAndUnlock() throws RemoteException {
+        // Pre-conditions
+        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
+        when(mBiometricUnlockController.unlockedByWakeAndUnlock()).thenReturn(true);
+
+        mDozeWallpaperState.transitionTo(DozeMachine.State.UNINITIALIZED,
+                DozeMachine.State.DOZE_AOD);
+        clearInvocations(mIWallpaperManager);
+
+        mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE_AOD, DozeMachine.State.FINISH);
+        verify(mIWallpaperManager).setInAmbientMode(eq(false), eq(0L));
+    }
+
+    @Test
     public void testTransitionTo_requestPulseIsAmbientMode() throws RemoteException {
         mDozeWallpaperState.transitionTo(DozeMachine.State.DOZE,
                 DozeMachine.State.DOZE_REQUEST_PULSE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index 893f3d1..9576cb2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -48,6 +48,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.ZenModeController;
@@ -197,6 +198,7 @@
 
     @Test
     public void onMetadataChanged_updatesSlice() {
+        mProvider.onStateChanged(StatusBarState.KEYGUARD);
         mProvider.onDozingChanged(true);
         reset(mContentResolver);
         mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING);
@@ -210,6 +212,7 @@
 
     @Test
     public void onDozingChanged_updatesSliceIfMedia() {
+        mProvider.onStateChanged(StatusBarState.KEYGUARD);
         mProvider.onMetadataOrStateChanged(mock(MediaMetadata.class), PlaybackState.STATE_PLAYING);
         reset(mContentResolver);
         // Show media when dozing
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index 5c1f473..881cc39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -64,7 +64,7 @@
     protected static final int TEST_AUTO_DISMISS_TIME = 500;
     // Number of notifications to use in tests requiring multiple notifications
     private static final int TEST_NUM_NOTIFICATIONS = 4;
-    protected static final int TEST_TIMEOUT_TIME = 10000;
+    protected static final int TEST_TIMEOUT_TIME = 15000;
     protected final Runnable TEST_TIMEOUT_RUNNABLE = () -> mTimedOut = true;
 
     private AlertingNotificationManager mAlertingNotificationManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index a99dc7f..7d9920d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -192,6 +194,34 @@
     }
 
     @Test
+    public void onBiometricAuthenticated_whenBypassOnBouncer_dismissBouncer() {
+        reset(mKeyguardBypassController);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+        when(mKeyguardBypassController.onBiometricAuthenticated(any())).thenReturn(true);
+        when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true);
+        mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+                BiometricSourceType.FACE);
+
+        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_DISMISS_BOUNCER);
+    }
+
+    @Test
+    public void onBiometricAuthenticated_whenBypassOnBouncer_respectsCanPlaySubtleAnim() {
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+        when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true);
+        mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+                BiometricSourceType.FACE);
+
+        verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_UNLOCK_FADING);
+    }
+
+    @Test
     public void onBiometricAuthenticated_whenFaceAndPulsing_dontDismissKeyguard() {
         reset(mUpdateMonitor);
         reset(mStatusBarKeyguardViewManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index b45707e..a38094d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -35,6 +35,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.HeadsUpStatusBarView;
 import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 
@@ -59,6 +60,7 @@
     private View mOperatorNameView;
     private StatusBarStateController mStatusbarStateController;
     private KeyguardBypassController mBypassController;
+    private NotificationWakeUpCoordinator mWakeUpCoordinator;
 
     @Before
     public void setUp() throws Exception {
@@ -72,11 +74,13 @@
         mOperatorNameView = new View(mContext);
         mStatusbarStateController = mock(StatusBarStateController.class);
         mBypassController = mock(KeyguardBypassController.class);
+        mWakeUpCoordinator = mock(NotificationWakeUpCoordinator.class);
         mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                 mock(NotificationIconAreaController.class),
                 mHeadsUpManager,
                 mStatusbarStateController,
                 mBypassController,
+                mWakeUpCoordinator,
                 mHeadsUpStatusBarView,
                 mStackScroller,
                 mPanelView,
@@ -153,6 +157,7 @@
                 mHeadsUpManager,
                 mStatusbarStateController,
                 mBypassController,
+                mWakeUpCoordinator,
                 mHeadsUpStatusBarView,
                 mStackScroller,
                 mPanelView,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index f8b9e68..48934da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -70,7 +70,6 @@
             setUp(statusBarWindowView, groupManager, bar, vsManager);
             mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
             mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
-            mAutoDismissNotificationDecayDozing = TEST_AUTO_DISMISS_TIME;
         }
     }
 
@@ -134,13 +133,11 @@
 
     @Test
     public void testExtendHeadsUp() {
-        when(mStatusBarStateController.isDozing()).thenReturn(true);
         mHeadsUpManager.showNotification(mEntry);
         Runnable pastNormalTimeRunnable =
                 () -> mLivesPastNormalTime = mHeadsUpManager.isAlerting(mEntry.key);
         mTestHandler.postDelayed(pastNormalTimeRunnable,
-                mHeadsUpManager.mAutoDismissNotificationDecayDozing +
-                        mHeadsUpManager.mExtensionTime / 2);
+                TEST_AUTO_DISMISS_TIME + mHeadsUpManager.mExtensionTime / 2);
         mTestHandler.postDelayed(TEST_TIMEOUT_RUNNABLE, TEST_TIMEOUT_TIME);
 
         mHeadsUpManager.extendHeadsUp();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
index a4ae166..29b8ab60 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/hardware/FakeSensorManager.java
@@ -40,18 +40,23 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
+import javax.annotation.Nullable;
+
 /**
  * Rudimentary fake for SensorManager
  *
- * Currently only supports the proximity sensor.
+ * Currently only supports proximity, light and tap sensors.
  *
  * Note that this class ignores the "Handler" argument, so the test is responsible for calling the
  * listener on the right thread.
  */
 public class FakeSensorManager extends SensorManager {
 
+    public static final String TAP_SENSOR_TYPE = "tapSensorType";
+
     private final MockProximitySensor mMockProximitySensor;
     private final FakeGenericSensor mFakeLightSensor;
+    private final FakeGenericSensor mFakeTapSensor;
     private final FakeGenericSensor[] mSensors;
 
     public FakeSensorManager(Context context) throws Exception {
@@ -59,12 +64,13 @@
                 .getDefaultSensor(Sensor.TYPE_PROXIMITY);
         if (proxSensor == null) {
             // No prox? Let's create a fake one!
-            proxSensor = createSensor(Sensor.TYPE_PROXIMITY);
+            proxSensor = createSensor(Sensor.TYPE_PROXIMITY, null);
         }
 
         mSensors = new FakeGenericSensor[]{
                 mMockProximitySensor = new MockProximitySensor(proxSensor),
-                mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT)),
+                mFakeLightSensor = new FakeGenericSensor(createSensor(Sensor.TYPE_LIGHT, null)),
+                mFakeTapSensor = new FakeGenericSensor(createSensor(99, TAP_SENSOR_TYPE))
         };
     }
 
@@ -76,6 +82,10 @@
         return mFakeLightSensor;
     }
 
+    public FakeGenericSensor getFakeTapSensor() {
+        return mFakeTapSensor;
+    }
+
     @Override
     public Sensor getDefaultSensor(int type) {
         Sensor s = super.getDefaultSensor(type);
@@ -160,13 +170,13 @@
 
     @Override
     protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
-        return false;
+        return true;
     }
 
     @Override
     protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
             boolean disable) {
-        return false;
+        return true;
     }
 
     @Override
@@ -185,12 +195,15 @@
         return false;
     }
 
-    private Sensor createSensor(int type) throws Exception {
+    private Sensor createSensor(int type, @Nullable String stringType) throws Exception {
         Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor();
         constr.setAccessible(true);
         Sensor sensor = constr.newInstance();
 
         setSensorType(sensor, type);
+        if (stringType != null) {
+            setSensorField(sensor, "mStringType", stringType);
+        }
         setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type);
         setSensorField(sensor, "mVendor", "Mock Vendor");
         setSensorField(sensor, "mVersion", 1);
diff --git a/proto/src/task_snapshot.proto b/proto/src/task_snapshot.proto
index 381d983..821db86 100644
--- a/proto/src/task_snapshot.proto
+++ b/proto/src/task_snapshot.proto
@@ -33,4 +33,5 @@
      bool is_translucent = 9;
      string top_activity_component = 10;
      float scale = 11;
- }
\ No newline at end of file
+     int64 id = 12;
+ }
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 1873de5..2db7f0e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -17,7 +17,6 @@
 package com.android.server.accessibility;
 
 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
-import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
@@ -37,6 +36,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.graphics.Region;
+import android.hardware.display.DisplayManager;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
@@ -49,6 +49,7 @@
 import android.os.SystemClock;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.KeyEvent;
 import android.view.MagnificationSpec;
 import android.view.View;
@@ -91,6 +92,7 @@
     private final WindowManagerInternal mWindowManagerService;
     private final GlobalActionPerformer mGlobalActionPerformer;
     private final AccessibilityWindowManager mA11yWindowManager;
+    private final DisplayManager mDisplayManager;
     private final PowerManager mPowerManager;
 
     // Handler for scheduling method invocations on the main thread.
@@ -149,7 +151,7 @@
     // types as message types allowing us to remove messages per event type.
     public Handler mEventDispatchHandler;
 
-    final IBinder mOverlayWindowToken = new Binder();
+    final SparseArray<IBinder> mOverlayWindowTokens = new SparseArray();
 
 
     public interface SystemSupport {
@@ -222,6 +224,7 @@
         mSystemSupport = systemSupport;
         mInvocationHandler = new InvocationHandler(mainHandler.getLooper());
         mA11yWindowManager = a11yWindowManager;
+        mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mEventDispatchHandler = new Handler(mainHandler.getLooper()) {
             @Override
@@ -928,24 +931,73 @@
     }
 
     public void onAdded() {
+        final Display[] displays = mDisplayManager.getDisplays();
+        for (int i = 0; i < displays.length; i++) {
+            final int displayId = displays[i].getDisplayId();
+            onDisplayAdded(displayId);
+        }
+    }
+
+    /**
+     * Called whenever a logical display has been added to the system. Add a window token for adding
+     * an accessibility overlay.
+     *
+     * @param displayId The id of the logical display that was added.
+     */
+    public void onDisplayAdded(int displayId) {
         final long identity = Binder.clearCallingIdentity();
         try {
-            mWindowManagerService.addWindowToken(mOverlayWindowToken,
-                    TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY);
+            final IBinder overlayWindowToken = new Binder();
+            mWindowManagerService.addWindowToken(overlayWindowToken, TYPE_ACCESSIBILITY_OVERLAY,
+                    displayId);
+            synchronized (mLock) {
+                mOverlayWindowTokens.put(displayId, overlayWindowToken);
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
     public void onRemoved() {
+        final Display[] displays = mDisplayManager.getDisplays();
+        for (int i = 0; i < displays.length; i++) {
+            final int displayId = displays[i].getDisplayId();
+            onDisplayRemoved(displayId);
+        }
+    }
+
+    /**
+     * Called whenever a logical display has been removed from the system. Remove a window token for
+     * removing an accessibility overlay.
+     *
+     * @param displayId The id of the logical display that was added.
+     */
+    public void onDisplayRemoved(int displayId) {
         final long identity = Binder.clearCallingIdentity();
         try {
-            mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY);
+            mWindowManagerService.removeWindowToken(mOverlayWindowTokens.get(displayId), true,
+                    displayId);
+            synchronized (mLock) {
+                mOverlayWindowTokens.remove(displayId);
+            }
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
     }
 
+    /**
+     * Gets overlay window token by the display Id.
+     *
+     * @param displayId The id of the logical display that was added.
+     * @return window token.
+     */
+    @Override
+    public IBinder getOverlayWindowToken(int displayId) {
+        synchronized (mLock) {
+            return mOverlayWindowTokens.get(displayId);
+        }
+    }
+
     public void resetLocked() {
         mSystemSupport.getKeyEventDispatcher().flush(this);
         try {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 47f137c..a220451 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -579,10 +579,11 @@
             // Make sure clients receiving this event will be able to get the
             // current state of the windows as the window manager may be delaying
             // the computation for performance reasons.
+            // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
             if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
                     && mA11yWindowManager.isTrackingWindowsLocked()) {
                 WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
-                wm.computeWindowsForAccessibility();
+                wm.computeWindowsForAccessibility(Display.DEFAULT_DISPLAY);
             }
             synchronized (mLock) {
                 notifyAccessibilityServicesDelayedLocked(event, false);
@@ -2550,6 +2551,13 @@
                     mInputFilter.onDisplayChanged();
                 }
                 UserState userState = getCurrentUserStateLocked();
+                if (displayId != Display.DEFAULT_DISPLAY) {
+                    final List<AccessibilityServiceConnection> services = userState.mBoundServices;
+                    for (int i = 0; i < services.size(); i++) {
+                        AccessibilityServiceConnection boundClient = services.get(i);
+                        boundClient.onDisplayAdded(displayId);
+                    }
+                }
                 updateMagnificationLocked(userState);
             }
         }
@@ -2566,6 +2574,14 @@
                 if (mInputFilter != null) {
                     mInputFilter.onDisplayChanged();
                 }
+                UserState userState = getCurrentUserStateLocked();
+                if (displayId != Display.DEFAULT_DISPLAY) {
+                    final List<AccessibilityServiceConnection> services = userState.mBoundServices;
+                    for (int i = 0; i < services.size(); i++) {
+                        AccessibilityServiceConnection boundClient = services.get(i);
+                        boundClient.onDisplayRemoved(displayId);
+                    }
+                }
             }
             if (mMagnificationController != null) {
                 mMagnificationController.onDisplayRemoved(displayId);
@@ -2601,8 +2617,6 @@
         public final RemoteCallbackList<IAccessibilityManagerClient> mUserClients =
                 new RemoteCallbackList<>();
 
-        public final SparseArray<IBinder> mWindowTokens = new SparseArray<>();
-
         // Transient state.
 
         public final ArrayList<AccessibilityServiceConnection> mBoundServices = new ArrayList<>();
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 547f7d3..02306c0 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -31,6 +31,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Slog;
+import android.view.Display;
 
 import com.android.server.accessibility.AccessibilityManagerService.UserState;
 import com.android.server.wm.WindowManagerInternal;
@@ -196,7 +197,7 @@
             return;
         }
         try {
-            serviceInterface.init(this, mId, mOverlayWindowToken);
+            serviceInterface.init(this, mId, mOverlayWindowTokens.get(Display.DEFAULT_DISPLAY));
         } catch (RemoteException re) {
             Slog.w(LOG_TAG, "Error while setting connection for service: "
                     + serviceInterface, re);
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 8415272..c129291 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -23,7 +23,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Binder;
 import android.os.Handler;
@@ -34,6 +33,7 @@
 import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.IWindow;
 import android.view.WindowInfo;
 import android.view.WindowManager;
@@ -277,7 +277,7 @@
         } else if (!oldWindow.activityToken.equals(newWindow.activityToken)) {
             return true;
         }
-        if (!oldWindow.boundsInScreen.equals(newWindow.boundsInScreen)) {
+        if (!oldWindow.regionInScreen.equals(newWindow.regionInScreen)) {
             return true;
         }
         if (oldWindow.childTokens != null && newWindow.childTokens != null
@@ -312,7 +312,9 @@
                 // In some cases, onWindowsForAccessibilityChanged will be called immediately in
                 // setWindowsForAccessibilityCallback. We'll lost windows if flag is false.
                 mTrackingWindows = true;
-                mWindowManagerInternal.setWindowsForAccessibilityCallback(this);
+                // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
+                mWindowManagerInternal.setWindowsForAccessibilityCallback(Display.DEFAULT_DISPLAY,
+                        this);
             }
         }
     }
@@ -323,7 +325,9 @@
     public void stopTrackingWindows() {
         synchronized (mLock) {
             if (mTrackingWindows) {
-                mWindowManagerInternal.setWindowsForAccessibilityCallback(null);
+                // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
+                mWindowManagerInternal.setWindowsForAccessibilityCallback(Display.DEFAULT_DISPLAY,
+                        null);
                 mTrackingWindows = false;
                 clearWindowsLocked();
             }
@@ -522,7 +526,8 @@
                 }
             }
         }
-        mWindowManagerInternal.computeWindowsForAccessibility();
+        // TODO [Multi-Display] : using correct display Id to replace DEFAULT_DISPLAY
+        mWindowManagerInternal.computeWindowsForAccessibility(Display.DEFAULT_DISPLAY);
         return windowId;
     }
 
@@ -755,20 +760,20 @@
         boolean windowInteractiveRegionChanged = false;
 
         final int windowCount = mWindows.size();
-        final Rect currentWindowBounds = new Rect();
+        final Region currentWindowRegions = new Region();
         for (int i = windowCount - 1; i >= 0; i--) {
             AccessibilityWindowInfo currentWindow = mWindows.get(i);
             if (windowInteractiveRegion == null) {
                 if (currentWindow.getId() == windowId) {
-                    currentWindow.getBoundsInScreen(currentWindowBounds);
-                    outRegion.set(currentWindowBounds);
+                    currentWindow.getRegionInScreen(currentWindowRegions);
+                    outRegion.set(currentWindowRegions);
                     windowInteractiveRegion = outRegion;
                     continue;
                 }
             } else if (currentWindow.getType()
                     != AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY) {
-                currentWindow.getBoundsInScreen(currentWindowBounds);
-                if (windowInteractiveRegion.op(currentWindowBounds, Region.Op.DIFFERENCE)) {
+                currentWindow.getRegionInScreen(currentWindowRegions);
+                if (windowInteractiveRegion.op(currentWindowRegions, Region.Op.DIFFERENCE)) {
                     windowInteractiveRegionChanged = true;
                 }
             }
@@ -1115,7 +1120,7 @@
         reportedWindow.setType(getTypeForWindowManagerWindowType(window.type));
         reportedWindow.setLayer(window.layer);
         reportedWindow.setFocused(window.focused);
-        reportedWindow.setBoundsInScreen(window.boundsInScreen);
+        reportedWindow.setRegionInScreen(window.regionInScreen);
         reportedWindow.setTitle(window.title);
         reportedWindow.setAnchorId(window.accessibilityIdOfAnchor);
         reportedWindow.setPictureInPicture(window.inPictureInPicture);
diff --git a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
index 285bd09..2698b72 100644
--- a/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/UiAutomationManager.java
@@ -27,6 +27,7 @@
 import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
 import android.util.Slog;
+import android.view.Display;
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.util.DumpUtils;
@@ -246,7 +247,8 @@
                     // another thread.
                     if (serviceInterface != null) {
                         service.linkToDeath(this, 0);
-                        serviceInterface.init(this, mId, mOverlayWindowToken);
+                        serviceInterface.init(this, mId,
+                                mOverlayWindowTokens.get(Display.DEFAULT_DISPLAY));
                     }
                 } catch (RemoteException re) {
                     Slog.w(LOG_TAG, "Error initialized connection", re);
diff --git a/services/art-profile b/services/art-profile
index a9d5982..cbc4627 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -16071,7 +16071,7 @@
 PLcom/android/server/wm/DisplayPolicy;->offsetInputMethodWindowLw(Lcom/android/server/wm/WindowState;Lcom/android/server/wm/DisplayFrames;)V
 HSPLcom/android/server/wm/DisplayPolicy;->onConfigurationChanged()V
 PLcom/android/server/wm/DisplayPolicy;->onPowerKeyDown(Z)V
-HSPLcom/android/server/wm/DisplayPolicy;->prepareAddWindowLw(Lcom/android/server/wm/WindowState;Landroid/view/WindowManager$LayoutParams;)I
+HSPLcom/android/server/wm/DisplayPolicy;->validateAddingWindowLw(Landroid/view/WindowManager$LayoutParams;)I
 HSPLcom/android/server/wm/DisplayPolicy;->removeWindowLw(Lcom/android/server/wm/WindowState;)V
 HSPLcom/android/server/wm/DisplayPolicy;->requestTransientBars(Lcom/android/server/wm/WindowState;)V
 HSPLcom/android/server/wm/DisplayPolicy;->resetSystemUiVisibilityLw()V
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index aada967..1e1e07d 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -769,6 +769,19 @@
     }
 
     /**
+     * Updates the last fill response when a dataset is shown.
+     */
+    void logDatasetShown(int sessionId, @Nullable Bundle clientState) {
+        synchronized (mLock) {
+            if (isValidEventLocked("logDatasetShown", sessionId)) {
+                mEventHistory.addEvent(
+                        new Event(Event.TYPE_DATASETS_SHOWN, null, clientState, null, null, null,
+                                null, null, null, null, null));
+            }
+        }
+    }
+
+    /**
      * Updates the last fill response when an autofill context is committed.
      */
     @GuardedBy("mLock")
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 988db6a..46c2a85 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2497,6 +2497,8 @@
                 mService.getServicePackageName(), mComponentName,
                 serviceLabel, serviceIcon, this, id, mCompatMode);
 
+        mService.logDatasetShown(id, mClientState);
+
         synchronized (mLock) {
             if (mUiShownTime == 0) {
                 // Log first time UI is shown.
diff --git a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
index e68263a..813fc8d 100644
--- a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
+++ b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
@@ -64,12 +64,13 @@
             return;
         }
 
+        mWidth = MeasureSpec.getSize(widthMeasureSpec);
         calculateDimensions();
         setMeasuredDimension(mWidth, mHeight);
     }
 
     private void calculateDimensions() {
-        if (mWidth != -1) return;
+        if (mHeight != -1) return;
 
         final TypedValue typedValue = new TypedValue();
         final Point point = new Point();
@@ -81,7 +82,6 @@
         final int childHeight = child.getMeasuredHeight();
         final int maxHeight = (int) typedValue.getFraction(point.y, point.y);
 
-        mWidth = point.x;
         mHeight = Math.min(childHeight, maxHeight);
         if (sDebug) {
             Slog.d(TAG, "calculateDimensions(): maxHeight=" + maxHeight
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 8df25b5..d5a7c81 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -194,6 +194,11 @@
         }
     }
 
+    boolean isAbleToServeUser(int userId) {
+        return getServiceUsers().get(UserHandle.USER_SYSTEM) != null
+                && getServiceUsers().get(userId) != null;
+    }
+
     /**
      *  Returns a lst of users currently unlocked that have a
      *  {@link UserBackupManagerService} registered.
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 53bbac4..f4b6645 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -202,11 +202,10 @@
         }
     }
 
-    // A user is ready for a backup if it's unlocked and is not suppressed by a device
-    // admin (device owner or profile owner).
+    // This method should not perform any I/O (e.g. do not call isBackupActivatedForUser),
+    // it's used in multiple places where I/O waits would cause system lock-ups.
     private boolean isUserReadyForBackup(int userId) {
-        return mService != null && mService.getServiceUsers().get(userId) != null
-                && isBackupActivatedForUser(userId);
+        return mService != null && mService.isAbleToServeUser(userId);
     }
 
     /**
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index 18ee7a4..18c38dc 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -128,7 +128,7 @@
 
     private static final String TAG = "PFTBT";
 
-    private UserBackupManagerService backupManagerService;
+    private UserBackupManagerService mUserBackupManagerService;
     private final Object mCancelLock = new Object();
 
     ArrayList<PackageInfo> mPackages;
@@ -159,7 +159,7 @@
             @Nullable IBackupManagerMonitor monitor, @Nullable OnTaskFinishedListener listener,
             boolean userInitiated) {
         super(observer);
-        this.backupManagerService = backupManagerService;
+        this.mUserBackupManagerService = backupManagerService;
         mTransportClient = transportClient;
         mUpdateSchedule = updateSchedule;
         mLatch = latch;
@@ -252,16 +252,16 @@
     }
 
     private void registerTask() {
-        synchronized (backupManagerService.getCurrentOpLock()) {
+        synchronized (mUserBackupManagerService.getCurrentOpLock()) {
             Slog.d(TAG, "backupmanager pftbt token=" + Integer.toHexString(mCurrentOpToken));
-            backupManagerService.getCurrentOperations().put(
+            mUserBackupManagerService.getCurrentOperations().put(
                     mCurrentOpToken,
                     new Operation(OP_PENDING, this, OP_TYPE_BACKUP));
         }
     }
 
     public void unregisterTask() {
-        backupManagerService.removeOperation(mCurrentOpToken);
+        mUserBackupManagerService.removeOperation(mCurrentOpToken);
     }
 
     @Override
@@ -288,7 +288,7 @@
 
             mCancelAll = true;
             if (mIsDoingBackup) {
-                backupManagerService.handleCancel(mBackupRunnerOpToken, cancelAll);
+                mUserBackupManagerService.handleCancel(mBackupRunnerOpToken, cancelAll);
                 try {
                     // If we're running a backup we should be connected to a transport
                     IBackupTransport transport =
@@ -320,16 +320,17 @@
         int backupRunStatus = BackupManager.SUCCESS;
 
         try {
-            if (!backupManagerService.isEnabled() || !backupManagerService.isSetupComplete()) {
+            if (!mUserBackupManagerService.isEnabled()
+                    || !mUserBackupManagerService.isSetupComplete()) {
                 // Backups are globally disabled, so don't proceed.
                 if (DEBUG) {
-                    Slog.i(TAG, "full backup requested but enabled=" + backupManagerService
+                    Slog.i(TAG, "full backup requested but enabled=" + mUserBackupManagerService
                             .isEnabled()
-                            + " setupComplete=" + backupManagerService.isSetupComplete()
+                            + " setupComplete=" + mUserBackupManagerService.isSetupComplete()
                             + "; ignoring");
                 }
                 int monitoringEvent;
-                if (backupManagerService.isSetupComplete()) {
+                if (mUserBackupManagerService.isSetupComplete()) {
                     monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED;
                 } else {
                     monitoringEvent = BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED;
@@ -532,7 +533,8 @@
                 // Roll this package to the end of the backup queue if we're
                 // in a queue-driven mode (regardless of success/failure)
                 if (mUpdateSchedule) {
-                    backupManagerService.enqueueFullBackup(packageName, System.currentTimeMillis());
+                    mUserBackupManagerService.enqueueFullBackup(
+                            packageName, System.currentTimeMillis());
                 }
 
                 if (backupPackageStatus == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
@@ -549,7 +551,8 @@
                     // from the preflight pass.  If we got as far as preflight, we now need
                     // to tear down the target process.
                     if (mBackupRunner != null) {
-                        backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+                        mUserBackupManagerService.tearDownAgentAndKill(
+                                currentPackage.applicationInfo);
                     }
                     // ... and continue looping.
                 } else if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
@@ -561,7 +564,7 @@
                         EventLog.writeEvent(EventLogTags.FULL_BACKUP_QUOTA_EXCEEDED,
                                 packageName);
                     }
-                    backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+                    mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
                     // Do nothing, clean up, and continue looping.
                 } else if (backupPackageStatus == BackupTransport.AGENT_ERROR) {
                     BackupObserverUtils
@@ -569,7 +572,7 @@
                                     BackupManager.ERROR_AGENT_FAILURE);
                     Slog.w(TAG, "Application failure for package: " + packageName);
                     EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
-                    backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+                    mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
                     // Do nothing, clean up, and continue looping.
                 } else if (backupPackageStatus == BackupManager.ERROR_BACKUP_CANCELLED) {
                     BackupObserverUtils
@@ -578,7 +581,7 @@
                     Slog.w(TAG, "Backup cancelled. package=" + packageName +
                             ", cancelAll=" + mCancelAll);
                     EventLog.writeEvent(EventLogTags.FULL_BACKUP_CANCELLED, packageName);
-                    backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+                    mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
                     // Do nothing, clean up, and continue looping.
                 } else if (backupPackageStatus != BackupTransport.TRANSPORT_OK) {
                     BackupObserverUtils
@@ -588,7 +591,7 @@
                     EventLog.writeEvent(EventLogTags.FULL_BACKUP_TRANSPORT_FAILURE);
                     // Abort entire backup pass.
                     backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
-                    backupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+                    mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
                     return;
                 } else {
                     // Success!
@@ -596,14 +599,14 @@
                             .sendBackupOnPackageResult(mBackupObserver, packageName,
                                     BackupManager.SUCCESS);
                     EventLog.writeEvent(EventLogTags.FULL_BACKUP_SUCCESS, packageName);
-                    backupManagerService.logBackupComplete(packageName);
+                    mUserBackupManagerService.logBackupComplete(packageName);
                 }
                 cleanUpPipes(transportPipes);
                 cleanUpPipes(enginePipes);
                 if (currentPackage.applicationInfo != null) {
                     Slog.i(TAG, "Unbinding agent in " + packageName);
                     try {
-                        backupManagerService.getActivityManager().unbindBackupAgent(
+                        mUserBackupManagerService.getActivityManager().unbindBackupAgent(
                                 currentPackage.applicationInfo);
                     } catch (RemoteException e) { /* can't happen; activity manager is local */ }
                 }
@@ -639,8 +642,8 @@
                 mJob.finishBackupPass(mUserId);
             }
 
-            synchronized (backupManagerService.getQueueLock()) {
-                backupManagerService.setRunningFullBackupTask(null);
+            synchronized (mUserBackupManagerService.getQueueLock()) {
+                mUserBackupManagerService.setRunningFullBackupTask(null);
             }
 
             mListener.onFinished("PFTBT.run()");
@@ -650,11 +653,11 @@
             // Now that we're actually done with schedule-driven work, reschedule
             // the next pass based on the new queue state.
             if (mUpdateSchedule) {
-                backupManagerService.scheduleNextFullBackupJob(backoff);
+                mUserBackupManagerService.scheduleNextFullBackupJob(backoff);
             }
 
             Slog.i(TAG, "Full data backup pass finished.");
-            backupManagerService.getWakelock().release();
+            mUserBackupManagerService.getWakelock().release();
         }
     }
 
@@ -709,13 +712,13 @@
             long fullBackupAgentTimeoutMillis =
                     mAgentTimeoutParameters.getFullBackupAgentTimeoutMillis();
             try {
-                backupManagerService.prepareOperationTimeout(
+                mUserBackupManagerService.prepareOperationTimeout(
                         mCurrentOpToken, fullBackupAgentTimeoutMillis, this, OP_TYPE_BACKUP_WAIT);
                 if (MORE_DEBUG) {
                     Slog.d(TAG, "Preflighting full payload of " + pkg.packageName);
                 }
                 agent.doMeasureFullBackup(mQuota, mCurrentOpToken,
-                        backupManagerService.getBackupManagerBinder(), mTransportFlags);
+                        mUserBackupManagerService.getBackupManagerBinder(), mTransportFlags);
 
                 // Now wait to get our result back.  If this backstop timeout is reached without
                 // the latch being thrown, flow will continue as though a result or "normal"
@@ -765,7 +768,7 @@
             }
             mResult.set(result);
             mLatch.countDown();
-            backupManagerService.removeOperation(mCurrentOpToken);
+            mUserBackupManagerService.removeOperation(mCurrentOpToken);
         }
 
         @Override
@@ -775,7 +778,7 @@
             }
             mResult.set(BackupTransport.AGENT_ERROR);
             mLatch.countDown();
-            backupManagerService.removeOperation(mCurrentOpToken);
+            mUserBackupManagerService.removeOperation(mCurrentOpToken);
         }
 
         @Override
@@ -812,7 +815,7 @@
             mOutput = ParcelFileDescriptor.dup(output.getFileDescriptor());
             mTarget = target;
             mCurrentOpToken = currentOpToken;
-            mEphemeralToken = backupManagerService.generateRandomIntegerToken();
+            mEphemeralToken = mUserBackupManagerService.generateRandomIntegerToken();
             mPreflight = new SinglePackageBackupPreflight(
                     transportClient, quota, mEphemeralToken, transportFlags);
             mPreflightLatch = new CountDownLatch(1);
@@ -825,23 +828,32 @@
         }
 
         void registerTask() {
-            synchronized (backupManagerService.getCurrentOpLock()) {
-                backupManagerService.getCurrentOperations().put(
+            synchronized (mUserBackupManagerService.getCurrentOpLock()) {
+                mUserBackupManagerService.getCurrentOperations().put(
                         mCurrentOpToken, new Operation(OP_PENDING, this, OP_TYPE_BACKUP_WAIT));
             }
         }
 
         void unregisterTask() {
-            synchronized (backupManagerService.getCurrentOpLock()) {
-                backupManagerService.getCurrentOperations().remove(mCurrentOpToken);
+            synchronized (mUserBackupManagerService.getCurrentOpLock()) {
+                mUserBackupManagerService.getCurrentOperations().remove(mCurrentOpToken);
             }
         }
 
         @Override
         public void run() {
             FileOutputStream out = new FileOutputStream(mOutput.getFileDescriptor());
-            mEngine = new FullBackupEngine(backupManagerService, out, mPreflight, mTarget, false,
-                    this, mQuota, mCurrentOpToken, mTransportFlags);
+            mEngine =
+                    new FullBackupEngine(
+                            mUserBackupManagerService,
+                            out,
+                            mPreflight,
+                            mTarget,
+                            false,
+                            this,
+                            mQuota,
+                            mCurrentOpToken,
+                            mTransportFlags);
             try {
                 try {
                     if (!mIsCancelled) {
@@ -928,13 +940,13 @@
                     mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
             mIsCancelled = true;
             // Cancel tasks spun off by this task.
-            backupManagerService.handleCancel(mEphemeralToken, cancelAll);
-            backupManagerService.tearDownAgentAndKill(mTarget.applicationInfo);
+            mUserBackupManagerService.handleCancel(mEphemeralToken, cancelAll);
+            mUserBackupManagerService.tearDownAgentAndKill(mTarget.applicationInfo);
             // Free up everyone waiting on this task and its children.
             mPreflightLatch.countDown();
             mBackupLatch.countDown();
             // We are done with this operation.
-            backupManagerService.removeOperation(mCurrentOpToken);
+            mUserBackupManagerService.removeOperation(mCurrentOpToken);
         }
     }
 }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 188d654..208b638 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1185,7 +1185,8 @@
         if (isBluetoothDisallowed) {
             return;
         }
-        if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) {
+        final boolean isSafeMode = mContext.getPackageManager().isSafeMode();
+        if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) {
             if (DBG) {
                 Slog.d(TAG, "Auto-enabling Bluetooth.");
             }
diff --git a/services/core/java/com/android/server/BluetoothService.java b/services/core/java/com/android/server/BluetoothService.java
index 5c5b477..112cf08 100644
--- a/services/core/java/com/android/server/BluetoothService.java
+++ b/services/core/java/com/android/server/BluetoothService.java
@@ -18,8 +18,7 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
-
-import com.android.internal.os.RoSystemProperties;
+import android.os.UserManager;
 
 class BluetoothService extends SystemService {
     private BluetoothManagerService mBluetoothManagerService;
@@ -47,7 +46,7 @@
             publishBinderService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE,
                     mBluetoothManagerService);
         } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY &&
-                !RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER) {
+                !UserManager.isHeadlessSystemUserMode()) {
             initialize();
         }
     }
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 9dead16..aeb3e7f 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -41,7 +41,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
@@ -582,11 +582,9 @@
         }
 
         int numFound = 0, numArgs = searchArgs.size();
-        Time time = new Time();
         out.append("\n");
         for (EntryFile entry : mAllFiles.contents) {
-            time.set(entry.timestampMillis);
-            String date = time.format("%Y-%m-%d %H:%M:%S");
+            String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis);
             boolean match = true;
             for (int i = 0; i < numArgs && match; i++) {
                 String arg = searchArgs.get(i);
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 930cf9e..5089ee0 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -42,7 +42,6 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
 import android.content.res.Resources;
@@ -121,6 +120,7 @@
 import com.android.server.location.MockProvider;
 import com.android.server.location.PassiveProvider;
 import com.android.server.location.RemoteListenerHelper;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import java.io.ByteArrayOutputStream;
 import java.io.FileDescriptor;
@@ -282,12 +282,12 @@
 
         // Let the package manager query which are the default location
         // providers as they get certain permissions granted by default.
-        PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
-        packageManagerInternal.setLocationPackagesProvider(
+        PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
+                PermissionManagerServiceInternal.class);
+        permissionManagerInternal.setLocationPackagesProvider(
                 userId -> mContext.getResources().getStringArray(
                         com.android.internal.R.array.config_locationProviderPackageNames));
-        packageManagerInternal.setLocationExtraPackagesProvider(
+        permissionManagerInternal.setLocationExtraPackagesProvider(
                 userId -> mContext.getResources().getStringArray(
                       com.android.internal.R.array.config_locationExtraPackageNames));
 
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index 80d7ac9..df5005e 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -26,7 +26,6 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.database.ContentObserver;
 import android.location.LocationManager;
 import android.net.INetworkRecommendationProvider;
@@ -54,15 +53,14 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.IntArray;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.TransferPipe;
-import com.android.internal.telephony.SmsApplication;
 import com.android.internal.util.DumpUtils;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -294,7 +292,7 @@
                     String useOpenWifiPackage = Global.getString(mContext.getContentResolver(),
                             Global.USE_OPEN_WIFI_PACKAGE);
                     if (!TextUtils.isEmpty(useOpenWifiPackage)) {
-                        LocalServices.getService(PackageManagerInternal.class)
+                        LocalServices.getService(PermissionManagerServiceInternal.class)
                                 .grantDefaultPermissionsToDefaultUseOpenWifiApp(useOpenWifiPackage,
                                         userId);
                     }
@@ -306,17 +304,14 @@
                 false /*notifyForDescendants*/,
                 mUseOpenWifiPackageObserver);
         // Set a callback for the package manager to query the use open wifi app.
-        LocalServices.getService(PackageManagerInternal.class).setUseOpenWifiAppPackagesProvider(
-                new PackageManagerInternal.PackagesProvider() {
-                    @Override
-                    public String[] getPackages(int userId) {
-                        String useOpenWifiPackage = Global.getString(mContext.getContentResolver(),
-                                Global.USE_OPEN_WIFI_PACKAGE);
-                        if (!TextUtils.isEmpty(useOpenWifiPackage)) {
-                            return new String[]{useOpenWifiPackage};
-                        }
-                        return null;
+        LocalServices.getService(PermissionManagerServiceInternal.class)
+                .setUseOpenWifiAppPackagesProvider((userId) -> {
+                    String useOpenWifiPackage = Global.getString(mContext.getContentResolver(),
+                            Global.USE_OPEN_WIFI_PACKAGE);
+                    if (!TextUtils.isEmpty(useOpenWifiPackage)) {
+                        return new String[]{useOpenWifiPackage};
                     }
+                    return null;
                 });
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 54fc739..268e813 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -347,6 +347,7 @@
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerServiceDumpProcessesProto.UidObserverRegistrationProto;
 import com.android.server.appop.AppOpsService;
+import com.android.server.compat.CompatConfig;
 import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.firewall.IntentFirewall;
 import com.android.server.job.JobSchedulerInternal;
@@ -2398,7 +2399,7 @@
         final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */);
         mProcessList.init(this, activeUids);
         mLowMemDetector = null;
-        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
+        mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, handlerThread);
 
         mIntentFirewall = hasHandlerThread
                 ? new IntentFirewall(new IntentFirewallInterface(), mHandler) : null;
@@ -5029,6 +5030,7 @@
             bindApplicationTimeMillis = SystemClock.elapsedRealtime();
             mAtmInternal.preBindApplication(app.getWindowProcessController());
             final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
+            long[] disabledCompatChanges = CompatConfig.get().getDisabledChanges(app.info);
             if (app.isolatedEntryPoint != null) {
                 // This is an isolated process which should just call an entry point instead of
                 // being bound to an application.
@@ -5044,7 +5046,8 @@
                         new Configuration(app.getWindowProcessController().getConfiguration()),
                         app.compat, getCommonServicesLocked(app.isolated),
                         mCoreSettingsObserver.getCoreSettingsLocked(),
-                        buildSerial, autofillOptions, contentCaptureOptions);
+                        buildSerial, autofillOptions, contentCaptureOptions,
+                        disabledCompatChanges);
             } else {
                 thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                         null, null, null, testMode,
@@ -5053,7 +5056,8 @@
                         new Configuration(app.getWindowProcessController().getConfiguration()),
                         app.compat, getCommonServicesLocked(app.isolated),
                         mCoreSettingsObserver.getCoreSettingsLocked(),
-                        buildSerial, autofillOptions, contentCaptureOptions);
+                        buildSerial, autofillOptions, contentCaptureOptions,
+                        disabledCompatChanges);
             }
             if (profilerInfo != null) {
                 profilerInfo.closeFd();
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index f7512f9..33070dc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -89,6 +89,7 @@
 import com.android.internal.util.HexDump;
 import com.android.internal.util.MemInfoReader;
 import com.android.internal.util.Preconditions;
+import com.android.server.compat.CompatConfig;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -290,6 +291,8 @@
                     return runNoHomeScreen(pw);
                 case "wait-for-broadcast-idle":
                     return runWaitForBroadcastIdle(pw);
+                case "compat":
+                    return runCompat(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -2874,6 +2877,50 @@
         return 0;
     }
 
+    private int runCompat(PrintWriter pw) {
+        final CompatConfig config = CompatConfig.get();
+        String toggleValue = getNextArgRequired();
+        long changeId;
+        String changeIdString = getNextArgRequired();
+        try {
+            changeId = Long.parseLong(changeIdString);
+        } catch (NumberFormatException e) {
+            changeId = config.lookupChangeId(changeIdString);
+        }
+        if (changeId == -1) {
+            pw.println("Unknown or invalid change: '" + changeIdString + "'.");
+        }
+        String packageName = getNextArgRequired();
+        switch(toggleValue) {
+            case "enable":
+                if (!config.addOverride(changeId, packageName, true)) {
+                    pw.println("Warning! Change " + changeId + " is not known yet. Enabling it"
+                            + " could have no effect.");
+                }
+                pw.println("Enabled change " + changeId + " for " + packageName + ".");
+                return 0;
+            case "disable":
+                if (!config.addOverride(changeId, packageName, false)) {
+                    pw.println("Warning! Change " + changeId + " is not known yet. Disabling it"
+                            + " could have no effect.");
+                }
+                pw.println("Disabled change " + changeId + " for " + packageName + ".");
+                return 0;
+            case "reset":
+                if (config.removeOverride(changeId, packageName)) {
+                    pw.println("Reset change " + changeId + " for " + packageName
+                            + " to default value.");
+                } else {
+                    pw.println("No override exists for changeId " + changeId + ".");
+                }
+                return 0;
+            default:
+                pw.println("Invalid toggle value: '" + toggleValue + "'.");
+        }
+        return -1;
+    }
+
+
     private Resources getResources(PrintWriter pw) throws RemoteException {
         // system resources does not contain all the device configuration, construct it manually.
         Configuration config = mInterface.getConfiguration();
@@ -3181,6 +3228,8 @@
             pw.println("      without restarting any processes.");
             pw.println("  write");
             pw.println("      Write all pending state to storage.");
+            pw.println("  compat enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
+            pw.println("      Toggles a change either by id or by name for <PACKAGE_NAME>.");
             pw.println();
             Intent.printIntentArgsHelp(pw, "");
         }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index a2613d8..770cb3d 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -162,6 +162,21 @@
     private final ProcessList mProcessList;
 
     OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids) {
+        this(service, processList, activeUids, createAdjusterThread());
+    }
+
+    private static ServiceThread createAdjusterThread() {
+        // The process group is usually critical to the response time of foreground app, so the
+        // setter should apply it as soon as possible.
+        final ServiceThread adjusterThread =
+                new ServiceThread(TAG, TOP_APP_PRIORITY_BOOST, false /* allowIo */);
+        adjusterThread.start();
+        Process.setThreadGroupAndCpuset(adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP);
+        return adjusterThread;
+    }
+
+    OomAdjuster(ActivityManagerService service, ProcessList processList, ActiveUids activeUids,
+            ServiceThread adjusterThread) {
         mService = service;
         mProcessList = processList;
         mActiveUids = activeUids;
@@ -170,12 +185,6 @@
         mConstants = mService.mConstants;
         mAppCompact = new AppCompactor(mService);
 
-        // The process group is usually critical to the response time of foreground app, so the
-        // setter should apply it as soon as possible.
-        final ServiceThread adjusterThread = new ServiceThread(TAG, TOP_APP_PRIORITY_BOOST,
-                false /* allowIo */);
-        adjusterThread.start();
-        Process.setThreadGroupAndCpuset(adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP);
         mProcessGroupHandler = new Handler(adjusterThread.getLooper(), msg -> {
             final int pid = msg.arg1;
             final int group = msg.arg2;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 2fe5bbe..3007016 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -198,6 +198,7 @@
         }
     };
 
+    @GuardedBy("this")
     @VisibleForTesting
     final SparseArray<UidState> mUidStates = new SparseArray<>();
 
@@ -1187,7 +1188,7 @@
         }
     }
 
-    private void pruneOp(Op op, int uid, String packageName) {
+    private void pruneOpLocked(Op op, int uid, String packageName) {
         if (!op.hasAnyTime()) {
             Ops ops = getOpsRawLocked(uid, packageName, false /* isPrivileged */, false /* edit */);
             if (ops != null) {
@@ -1396,7 +1397,7 @@
                     if (mode == AppOpsManager.opToDefaultMode(op.op)) {
                         // If going into the default mode, prune this op
                         // if there is nothing else interesting in it.
-                        pruneOp(op, uid, packageName);
+                        pruneOpLocked(op, uid, packageName);
                     }
                     scheduleFastWriteLocked();
                 }
@@ -2979,23 +2980,25 @@
                 out.startTag(null, "app-ops");
                 out.attribute(null, "v", String.valueOf(CURRENT_VERSION));
 
-                final int uidStateCount = mUidStates.size();
-                for (int i = 0; i < uidStateCount; i++) {
-                    UidState uidState = mUidStates.valueAt(i);
-                    if (uidState.opModes != null && uidState.opModes.size() > 0) {
-                        out.startTag(null, "uid");
-                        out.attribute(null, "n", Integer.toString(uidState.uid));
-                        SparseIntArray uidOpModes = uidState.opModes;
-                        final int opCount = uidOpModes.size();
-                        for (int j = 0; j < opCount; j++) {
-                            final int op = uidOpModes.keyAt(j);
-                            final int mode = uidOpModes.valueAt(j);
-                            out.startTag(null, "op");
-                            out.attribute(null, "n", Integer.toString(op));
-                            out.attribute(null, "m", Integer.toString(mode));
-                            out.endTag(null, "op");
+                synchronized (this) {
+                    final int uidStateCount = mUidStates.size();
+                    for (int i = 0; i < uidStateCount; i++) {
+                        UidState uidState = mUidStates.valueAt(i);
+                        if (uidState.opModes != null && uidState.opModes.size() > 0) {
+                            out.startTag(null, "uid");
+                            out.attribute(null, "n", Integer.toString(uidState.uid));
+                            SparseIntArray uidOpModes = uidState.opModes;
+                            final int opCount = uidOpModes.size();
+                            for (int j = 0; j < opCount; j++) {
+                                final int op = uidOpModes.keyAt(j);
+                                final int mode = uidOpModes.valueAt(j);
+                                out.startTag(null, "op");
+                                out.attribute(null, "n", Integer.toString(op));
+                                out.attribute(null, "m", Integer.toString(mode));
+                                out.endTag(null, "op");
+                            }
+                            out.endTag(null, "uid");
                         }
-                        out.endTag(null, "uid");
                     }
                 }
 
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index df6f73b..bd3cd54 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -521,8 +521,8 @@
             List<EnabledOnKeyguardCallback> callbacks = mEnabledOnKeyguardCallbacks;
             for (int i = 0; i < callbacks.size(); i++) {
                 callbacks.get(i).notify(BiometricSourceType.FACE,
-                        mFaceEnabledOnKeyguard.getOrDefault(userId,
-                                DEFAULT_KEYGUARD_ENABLED));
+                        mFaceEnabledOnKeyguard.getOrDefault(userId, DEFAULT_KEYGUARD_ENABLED),
+                        userId);
             }
         }
     }
@@ -540,9 +540,9 @@
             }
         }
 
-        void notify(BiometricSourceType sourceType, boolean enabled) {
+        void notify(BiometricSourceType sourceType, boolean enabled, int userId) {
             try {
-                mCallback.onChanged(sourceType, enabled);
+                mCallback.onChanged(sourceType, enabled, userId);
             } catch (DeadObjectException e) {
                 Slog.w(TAG, "Death while invoking notify", e);
                 mEnabledOnKeyguardCallbacks.remove(this);
@@ -796,7 +796,8 @@
             mEnabledOnKeyguardCallbacks.add(new EnabledOnKeyguardCallback(callback));
             try {
                 callback.onChanged(BiometricSourceType.FACE,
-                        mSettingObserver.getFaceEnabledOnKeyguard());
+                        mSettingObserver.getFaceEnabledOnKeyguard(),
+                        UserHandle.getCallingUserId());
             } catch (RemoteException e) {
                 Slog.w(TAG, "Remote exception", e);
             }
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index f08423e..20eb618 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -665,8 +665,12 @@
         mMetricsLogger.count(getConstants().tagHalDied(), 1);
         mHALDeathCount++;
         mCurrentUserId = UserHandle.USER_NULL;
-        handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
-                0 /*vendorCode */);
+
+        // All client lifecycle must be managed on the handler.
+        mHandler.post(() -> {
+            handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
+                    0 /*vendorCode */);
+        });
 
         StatsLog.write(StatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED, statsModality(),
                 BiometricsProtoEnums.ISSUE_HAL_DEATH);
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index bb3b9be..2a866f3 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -106,6 +106,12 @@
      * @return {@code true} if the change should be enabled for the package.
      */
     boolean isEnabled(ApplicationInfo app) {
+        if (app.isSystemApp()) {
+            // All changes are enabled for system apps, and we do not support overrides.
+            // Compatibility issues for system apps should be addressed in the app itself when
+            // the compatibility change is made.
+            return true;
+        }
         if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) {
             return mPackageOverrides.get(app.packageName);
         }
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index fea5d83..bcf1d80 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -128,20 +128,24 @@
      * <p>Note, package overrides are not persistent and will be lost on system or runtime restart.
      *
      * @param changeId The ID of the change to be overridden. Note, this call will succeed even if
-     *                 this change is not known; it will only have any affect if any code in the
+     *                 this change is not known; it will only have any effect if any code in the
      *                 platform is gated on the ID given.
      * @param packageName The app package name to override the change for.
      * @param enabled If the change should be enabled or disabled.
+     * @return {@code true} if the change existed before adding the override.
      */
-    public void addOverride(long changeId, String packageName, boolean enabled) {
+    public boolean addOverride(long changeId, String packageName, boolean enabled) {
+        boolean alreadyKnown = true;
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
             if (c == null) {
+                alreadyKnown = false;
                 c = new CompatChange(changeId);
                 addChange(c);
             }
             c.addPackageOverride(packageName, enabled);
         }
+        return alreadyKnown;
     }
 
     /**
@@ -151,14 +155,18 @@
      *
      * @param changeId The ID of the change that was overridden.
      * @param packageName The app package name that was overridden.
+     * @return {@code true} if an override existed;
      */
-    public void removeOverride(long changeId, String packageName) {
+    public boolean removeOverride(long changeId, String packageName) {
+        boolean overrideExists = false;
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
             if (c != null) {
+                overrideExists = true;
                 c.removePackageOverride(packageName);
             }
         }
+        return overrideExists;
     }
 
 }
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 7824a0a..3e1817b 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -40,7 +40,6 @@
 import android.content.SyncRequest;
 import android.content.SyncStatusInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.content.pm.ProviderInfo;
 import android.database.IContentObserver;
 import android.database.sqlite.SQLiteException;
@@ -71,6 +70,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -280,15 +280,11 @@
 
         // Let the package manager query for the sync adapters for a given authority
         // as we grant default permissions to sync adapters for specific authorities.
-        PackageManagerInternal packageManagerInternal = LocalServices.getService(
-                PackageManagerInternal.class);
-        packageManagerInternal.setSyncAdapterPackagesprovider(
-                new PackageManagerInternal.SyncAdapterPackagesProvider() {
-                    @Override
-                    public String[] getPackages(String authority, int userId) {
-                        return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
-                    }
-                });
+        final PermissionManagerServiceInternal permissionManagerInternal =
+                LocalServices.getService(PermissionManagerServiceInternal.class);
+        permissionManagerInternal.setSyncAdapterPackagesProvider((authority, userId) -> {
+            return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
+        });
 
         final IntentFilter packageFilter = new IntentFilter();
         packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 64a05c9..f6c49ed 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -86,7 +86,7 @@
 import android.os.UserManager;
 import android.os.WorkSource;
 import android.provider.Settings;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Pair;
@@ -1993,9 +1993,7 @@
         if (time == 0) {
             return "N/A";
         }
-        Time tobj = new Time();
-        tobj.set(time);
-        return tobj.format("%Y-%m-%d %H:%M:%S");
+        return TimeMigrationUtils.formatMillisWithFixedFormat(time);
     }
 
     private final static Comparator<SyncOperation> sOpDumpComparator = (op1, op2) -> {
@@ -2561,9 +2559,7 @@
                     accountKey = "Unknown";
                 }
                 final long elapsedTime = item.elapsedTime;
-                final Time time = new Time();
                 final long eventTime = item.eventTime;
-                time.set(eventTime);
 
                 final String key = authorityName + "/" + accountKey;
                 final Long lastEventTime = lastTimeMap.get(key);
@@ -2628,9 +2624,7 @@
                     authorityName = "Unknown";
                     accountKey = "Unknown";
                 }
-                final Time time = new Time();
                 final long eventTime = item.eventTime;
-                time.set(eventTime);
 
                 pw.printf("  #%-3d: %s %8s ",
                         i + 1,
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 2e5aafe..7fb5b19 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -63,6 +63,8 @@
 import android.provider.Settings.System;
 import android.util.MathUtils;
 import android.util.Slog;
+import android.util.SparseIntArray;
+import android.view.Display;
 import android.view.SurfaceControl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AnimationUtils;
@@ -171,6 +173,11 @@
 
     private NightDisplayAutoMode mNightDisplayAutoMode;
 
+    /**
+     * Map of color modes -> display composition colorspace
+     */
+    private SparseIntArray mColorModeCompositionColorSpaces = null;
+
     public ColorDisplayService(Context context) {
         super(context);
         mHandler = new TintHandler(DisplayThread.get().getLooper());
@@ -267,6 +274,30 @@
         return Secure.getIntForUser(cr, Secure.USER_SETUP_COMPLETE, 0, userHandle) == 1;
     }
 
+    private void setUpDisplayCompositionColorSpaces(Resources res) {
+        mColorModeCompositionColorSpaces = null;
+
+        final int[] colorModes = res.getIntArray(R.array.config_displayCompositionColorModes);
+        if (colorModes == null) {
+            return;
+        }
+
+        final int[] compSpaces = res.getIntArray(R.array.config_displayCompositionColorSpaces);
+        if (compSpaces == null) {
+            return;
+        }
+
+        if (colorModes.length != compSpaces.length) {
+            Slog.e(TAG, "Number of composition color spaces doesn't match specified color modes");
+            return;
+        }
+
+        mColorModeCompositionColorSpaces = new SparseIntArray(colorModes.length);
+        for (int i = 0; i < colorModes.length; i++) {
+            mColorModeCompositionColorSpaces.put(colorModes[i], compSpaces[i]);
+        }
+    }
+
     private void setUp() {
         Slog.d(TAG, "setUp: currentUser=" + mCurrentUser);
 
@@ -359,6 +390,8 @@
         onAccessibilityInversionChanged();
         onAccessibilityDaltonizerChanged();
 
+        setUpDisplayCompositionColorSpaces(getContext().getResources());
+
         // Set the color mode, if valid, and immediately apply the updated tint matrix based on the
         // existing activated state. This ensures consistency of tint across the color mode change.
         onDisplayColorModeChanged(getColorModeInternal());
@@ -450,6 +483,14 @@
         }
     }
 
+    private int getCompositionColorSpace(int mode) {
+        if (mColorModeCompositionColorSpaces == null) {
+            return Display.COLOR_MODE_INVALID;
+        }
+
+        return mColorModeCompositionColorSpaces.get(mode, Display.COLOR_MODE_INVALID);
+    }
+
     private void onDisplayColorModeChanged(int mode) {
         if (mode == NOT_SET) {
             return;
@@ -470,7 +511,8 @@
         // DisplayTransformManager.needsLinearColorMatrix(), therefore it is dependent
         // on the state of DisplayTransformManager.
         final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
-        dtm.setColorMode(mode, mNightDisplayTintController.getMatrix());
+        dtm.setColorMode(mode, mNightDisplayTintController.getMatrix(),
+                getCompositionColorSpace(mode));
 
         if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) {
             updateDisplayWhiteBalanceStatus();
diff --git a/services/core/java/com/android/server/display/color/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
index 5ff45a9..d5706a5 100644
--- a/services/core/java/com/android/server/display/color/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
@@ -26,6 +26,7 @@
 import android.os.SystemProperties;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -77,6 +78,8 @@
     @VisibleForTesting
     static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation";
     @VisibleForTesting
+    static final String PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE = "persist.sys.sf.color_mode";
+    @VisibleForTesting
     static final String PERSISTENT_PROPERTY_DISPLAY_COLOR = "persist.sys.sf.native_mode";
 
     private static final float COLOR_SATURATION_NATURAL = 1.0f;
@@ -251,23 +254,24 @@
     /**
      * Sets color mode and updates night display transform values.
      */
-    public boolean setColorMode(int colorMode, float[] nightDisplayMatrix) {
+    public boolean setColorMode(int colorMode, float[] nightDisplayMatrix,
+            int compositionColorMode) {
         if (colorMode == ColorDisplayManager.COLOR_MODE_NATURAL) {
             applySaturation(COLOR_SATURATION_NATURAL);
-            setDisplayColor(DISPLAY_COLOR_MANAGED);
+            setDisplayColor(DISPLAY_COLOR_MANAGED, compositionColorMode);
         } else if (colorMode == ColorDisplayManager.COLOR_MODE_BOOSTED) {
             applySaturation(COLOR_SATURATION_BOOSTED);
-            setDisplayColor(DISPLAY_COLOR_MANAGED);
+            setDisplayColor(DISPLAY_COLOR_MANAGED, compositionColorMode);
         } else if (colorMode == ColorDisplayManager.COLOR_MODE_SATURATED) {
             applySaturation(COLOR_SATURATION_NATURAL);
-            setDisplayColor(DISPLAY_COLOR_UNMANAGED);
+            setDisplayColor(DISPLAY_COLOR_UNMANAGED, compositionColorMode);
         } else if (colorMode == ColorDisplayManager.COLOR_MODE_AUTOMATIC) {
             applySaturation(COLOR_SATURATION_NATURAL);
-            setDisplayColor(DISPLAY_COLOR_ENHANCED);
+            setDisplayColor(DISPLAY_COLOR_ENHANCED, compositionColorMode);
         } else if (colorMode >= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MIN
                 && colorMode <= ColorDisplayManager.VENDOR_COLOR_MODE_RANGE_MAX) {
             applySaturation(COLOR_SATURATION_NATURAL);
-            setDisplayColor(colorMode);
+            setDisplayColor(colorMode, compositionColorMode);
         }
 
         setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, nightDisplayMatrix);
@@ -323,13 +327,21 @@
     /**
      * Toggles native mode on/off in SurfaceFlinger.
      */
-    private void setDisplayColor(int color) {
+    private void setDisplayColor(int color, int compositionColorMode) {
         SystemProperties.set(PERSISTENT_PROPERTY_DISPLAY_COLOR, Integer.toString(color));
+        if (compositionColorMode != Display.COLOR_MODE_INVALID) {
+            SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE,
+                Integer.toString(compositionColorMode));
+        }
+
         final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
         if (flinger != null) {
             final Parcel data = Parcel.obtain();
             data.writeInterfaceToken("android.ui.ISurfaceComposer");
             data.writeInt(color);
+            if (compositionColorMode != Display.COLOR_MODE_INVALID) {
+                data.writeInt(compositionColorMode);
+            }
             try {
                 flinger.transact(SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR, data, null, 0);
             } catch (RemoteException ex) {
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index d73c253..6f2b334 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -28,7 +28,7 @@
 import android.net.Uri;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.text.format.Time;
+import android.text.format.TimeMigrationUtils;
 import android.util.ArraySet;
 import android.util.Pair;
 import android.util.Slog;
@@ -1660,17 +1660,13 @@
         if (numFailures != 0) {
             pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);
         }
-        final Time t = new Time();
-        final String format = "%Y-%m-%d %H:%M:%S";
         if (mLastSuccessfulRunTime != 0) {
             pw.print(prefix); pw.print("Last successful run: ");
-            t.set(mLastSuccessfulRunTime);
-            pw.println(t.format(format));
+            pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastSuccessfulRunTime));
         }
         if (mLastFailedRunTime != 0) {
             pw.print(prefix); pw.print("Last failed run: ");
-            t.set(mLastFailedRunTime);
-            pw.println(t.format(format));
+            pw.println(TimeMigrationUtils.formatMillisWithFixedFormat(mLastFailedRunTime));
         }
     }
 
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index f0e431e..84ae7c7 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java