Merge "Use embedded native libs for NetworkStack.apk." into qt-dev
diff --git a/api/current.txt b/api/current.txt
index 8b24826..54fb459 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -143,6 +143,7 @@
     field public static final String SET_WALLPAPER_HINTS = "android.permission.SET_WALLPAPER_HINTS";
     field public static final String SIGNAL_PERSISTENT_PROCESSES = "android.permission.SIGNAL_PERSISTENT_PROCESSES";
     field public static final String SMS_FINANCIAL_TRANSACTIONS = "android.permission.SMS_FINANCIAL_TRANSACTIONS";
+    field public static final String START_VIEW_PERMISSION_USAGE = "android.permission.START_VIEW_PERMISSION_USAGE";
     field public static final String STATUS_BAR = "android.permission.STATUS_BAR";
     field public static final String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
     field public static final String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
@@ -10326,6 +10327,7 @@
     field public static final String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED";
     field public static final String ACTION_VIEW = "android.intent.action.VIEW";
     field public static final String ACTION_VIEW_LOCUS = "android.intent.action.VIEW_LOCUS";
+    field @RequiresPermission(android.Manifest.permission.START_VIEW_PERMISSION_USAGE) public static final String ACTION_VIEW_PERMISSION_USAGE = "android.intent.action.VIEW_PERMISSION_USAGE";
     field public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
     field @Deprecated public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
     field public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index b9a4b52..f53ac1b 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -298,6 +298,7 @@
         VehicleMapServicePacketFailureReported vms_packet_failure_reported = 202;
         CarPowerStateChanged car_power_state_changed = 203;
         GarageModeInfo garage_mode_info = 204;
+        TestAtomReported test_atom_reported = 205 [(log_from_module) = "cts"];
     }
 
     // Pulled events will start at field 10000.
@@ -3342,6 +3343,23 @@
     optional int32 user_id = 8;
 }
 
+/* Test atom, is not logged anywhere */
+message TestAtomReported {
+    repeated AttributionNode attribution_node = 1;
+    optional int32 int_field = 2;
+    optional int64 long_field = 3;
+    optional float float_field = 4;
+    optional string string_field = 5;
+    optional bool boolean_field = 6;
+    enum State {
+        UNKNOWN = 0;
+        OFF = 1;
+        ON = 2;
+    }
+    optional State state = 7;
+    optional TrainExperimentIds bytes_field = 8 [(android.os.statsd.log_mode) = MODE_BYTES];
+}
+
 /** Represents USB port overheat event. */
 message UsbPortOverheatEvent {
     /* Temperature of USB port at USB plug event, in 1/10ths of degree C. */
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b4c6d94..789351e 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8832,8 +8832,8 @@
              * <p>Setting this flag is optional; it defaults to false.</p>
              */
             @NonNull
-            public BubbleMetadata.Builder setSuppressNotification(boolean shouldSupressNotif) {
-                setFlag(FLAG_SUPPRESS_NOTIFICATION, shouldSupressNotif);
+            public BubbleMetadata.Builder setSuppressNotification(boolean shouldSuppressNotif) {
+                setFlag(FLAG_SUPPRESS_NOTIFICATION, shouldSuppressNotif);
                 return this;
             }
 
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 8046776..2c5860a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -825,7 +825,9 @@
      * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
      *         clause (excluding the ORDER BY itself). Passing null will use the
      *         default sort order, which may be unordered.
-     * @return A Cursor object, which is positioned before the first entry, or null
+     * @return A Cursor object, which is positioned before the first entry. May return
+     *         <code>null</code> if the underlying content provider returns <code>null</code>,
+     *         or if it crashes.
      * @see Cursor
      */
     public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
@@ -865,7 +867,9 @@
      * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
      * If the operation is canceled, then {@link OperationCanceledException} will be thrown
      * when the query is executed.
-     * @return A Cursor object, which is positioned before the first entry, or null
+     * @return A Cursor object, which is positioned before the first entry. May return
+     *         <code>null</code> if the underlying content provider returns <code>null</code>,
+     *         or if it crashes.
      * @see Cursor
      */
     public final @Nullable Cursor query(@RequiresPermission.Read @NonNull Uri uri,
@@ -902,7 +906,9 @@
      * @param cancellationSignal A signal to cancel the operation in progress, or null if none.
      * If the operation is canceled, then {@link OperationCanceledException} will be thrown
      * when the query is executed.
-     * @return A Cursor object, which is positioned before the first entry, or null
+     * @return A Cursor object, which is positioned before the first entry. May return
+     *         <code>null</code> if the underlying content provider returns <code>null</code>,
+     *         or if it crashes.
      * @see Cursor
      */
     @Override
@@ -1799,7 +1805,8 @@
      * @param url The URL of the table to insert into.
      * @param values The initial values for the newly inserted row. The key is the column name for
      *               the field. Passing an empty ContentValues will create an empty row.
-     * @return the URL of the newly created row.
+     * @return the URL of the newly created row. May return <code>null</code> if the underlying
+     *         content provider returns <code>null</code>, or if it crashes.
      */
     @Override
     public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 50d1785..9e5fcfb 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1881,6 +1881,31 @@
             "android.intent.action.REVIEW_PERMISSIONS";
 
     /**
+     * Activity action: Launch UI to show information about the usage
+     * of a given permission. This action would be handled by apps that
+     * want to show details about how and why given permission is being
+     * used.
+     * <p>
+     * <strong>Important:</strong>You must protect the activity that handles
+     * this action with the {@link android.Manifest.permission#START_VIEW_PERMISSION_USAGE
+     *  START_VIEW_PERMISSION_USAGE} permission to ensure that only the
+     * system can launch this activity. The system will not launch
+     * activities that are not properly protected.
+     *
+     * <p>
+     * Input: {@code android.intent.extra.PERMISSION_NAME} specifies the permission
+     * for which the launched UI would be targeted.
+     * </p>
+     * <p>
+     * Output: Nothing.
+     * </p>
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    @RequiresPermission(android.Manifest.permission.START_VIEW_PERMISSION_USAGE)
+    public static final String ACTION_VIEW_PERMISSION_USAGE =
+            "android.intent.action.VIEW_PERMISSION_USAGE";
+
+    /**
      * Activity action: Launch UI to manage a default app.
      * <p>
      * Input: {@link #EXTRA_ROLE_NAME} specifies the role of the default app which will be managed
diff --git a/core/java/android/util/MemoryIntArray.java b/core/java/android/util/MemoryIntArray.java
index 74fea3f..80b1607 100644
--- a/core/java/android/util/MemoryIntArray.java
+++ b/core/java/android/util/MemoryIntArray.java
@@ -20,9 +20,8 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 
-import dalvik.system.CloseGuard;
-
 import libcore.io.IoUtils;
+import dalvik.system.CloseGuard;
 
 import java.io.Closeable;
 import java.io.IOException;
@@ -57,7 +56,7 @@
 
     private final boolean mIsOwner;
     private final long mMemoryAddr;
-    private ParcelFileDescriptor mFd;
+    private int mFd = -1;
 
     /**
      * Creates a new instance.
@@ -72,8 +71,8 @@
         }
         mIsOwner = true;
         final String name = UUID.randomUUID().toString();
-        mFd = ParcelFileDescriptor.adoptFd(nativeCreate(name, size));
-        mMemoryAddr = nativeOpen(mFd.getFd(), mIsOwner);
+        mFd = nativeCreate(name, size);
+        mMemoryAddr = nativeOpen(mFd, mIsOwner);
         mCloseGuard.open("close");
     }
 
@@ -83,8 +82,8 @@
         if (pfd == null) {
             throw new IOException("No backing file descriptor");
         }
-        mFd = ParcelFileDescriptor.adoptFd(pfd.detachFd());
-        mMemoryAddr = nativeOpen(mFd.getFd(), mIsOwner);
+        mFd = pfd.detachFd();
+        mMemoryAddr = nativeOpen(mFd, mIsOwner);
         mCloseGuard.open("close");
     }
 
@@ -106,7 +105,7 @@
     public int get(int index) throws IOException {
         enforceNotClosed();
         enforceValidIndex(index);
-        return nativeGet(mFd.getFd(), mMemoryAddr, index);
+        return nativeGet(mFd, mMemoryAddr, index);
     }
 
     /**
@@ -122,7 +121,7 @@
         enforceNotClosed();
         enforceWritable();
         enforceValidIndex(index);
-        nativeSet(mFd.getFd(), mMemoryAddr, index, value);
+        nativeSet(mFd, mMemoryAddr, index, value);
     }
 
     /**
@@ -132,7 +131,7 @@
      */
     public int size() throws IOException {
         enforceNotClosed();
-        return nativeSize(mFd.getFd());
+        return nativeSize(mFd);
     }
 
     /**
@@ -143,9 +142,8 @@
     @Override
     public void close() throws IOException {
         if (!isClosed()) {
-            nativeClose(mFd.getFd(), mMemoryAddr, mIsOwner);
-            mFd.close();
-            mFd = null;
+            nativeClose(mFd, mMemoryAddr, mIsOwner);
+            mFd = -1;
             mCloseGuard.close();
         }
     }
@@ -154,7 +152,7 @@
      * @return Whether this array is closed and shouldn't be used.
      */
     public boolean isClosed() {
-        return mFd == null;
+        return mFd == -1;
     }
 
     @Override
@@ -177,8 +175,13 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
-        // Don't let writing to a parcel to close our fd - plz
-        parcel.writeParcelable(mFd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        ParcelFileDescriptor pfd = ParcelFileDescriptor.adoptFd(mFd);
+        try {
+            // Don't let writing to a parcel to close our fd - plz
+            parcel.writeParcelable(pfd, flags & ~Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        } finally {
+            pfd.detachFd();
+        }
     }
 
     @Override
@@ -192,13 +195,13 @@
         if (getClass() != obj.getClass()) {
             return false;
         }
-
-        return false;
+        MemoryIntArray other = (MemoryIntArray) obj;
+        return mFd == other.mFd;
     }
 
     @Override
     public int hashCode() {
-        return mFd.hashCode();
+        return mFd;
     }
 
     private void enforceNotClosed() {
diff --git a/core/jni/android_util_MemoryIntArray.cpp b/core/jni/android_util_MemoryIntArray.cpp
index b68f9ec..2dfbe3e 100644
--- a/core/jni/android_util_MemoryIntArray.cpp
+++ b/core/jni/android_util_MemoryIntArray.cpp
@@ -142,6 +142,8 @@
         jniThrowException(env, "java/io/IOException", "ashmem unpinning failed");
         return;
     }
+
+    close(fd);
 }
 
 static jint android_util_MemoryIntArray_get(JNIEnv* env, jobject clazz,
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 57b7704..b634bb2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4213,6 +4213,15 @@
         android:description="@string/permdesc_bindCarrierServices"
         android:protectionLevel="signature|privileged" />
 
+    <!--
+        Allows the holder to start the permission usage screen for an app.
+        <p>Protection level: signature|installer
+    -->
+    <permission android:name="android.permission.START_VIEW_PERMISSION_USAGE"
+        android:label="@string/permlab_startViewPermissionUsage"
+        android:description="@string/permdesc_startViewPermissionUsage"
+        android:protectionLevel="signature|installer" />
+
     <!-- Allows an application to query whether DO_NOT_ASK_CREDENTIALS_ON_BOOT
          flag is set.
          @hide -->
diff --git a/core/res/res/layout/media_route_chooser_dialog.xml b/core/res/res/layout/media_route_chooser_dialog.xml
index d1c6267..cd1c74f 100644
--- a/core/res/res/layout/media_route_chooser_dialog.xml
+++ b/core/res/res/layout/media_route_chooser_dialog.xml
@@ -40,7 +40,7 @@
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:layout_gravity="center"
-                  android:paddingLeft="16dp"
+                  android:paddingStart="16dp"
                   android:text="@string/media_route_chooser_searching" />
     </LinearLayout>
 
diff --git a/core/res/res/layout/media_route_list_item.xml b/core/res/res/layout/media_route_list_item.xml
index bdca433..e8460db 100644
--- a/core/res/res/layout/media_route_list_item.xml
+++ b/core/res/res/layout/media_route_list_item.xml
@@ -34,6 +34,7 @@
                   android:layout_height="wrap_content"
                   android:singleLine="true"
                   android:ellipsize="marquee"
+                  android:textAlignment="viewStart"
                   android:textAppearance="?android:attr/textAppearanceMedium"
                   android:duplicateParentState="true" />
 
@@ -42,6 +43,7 @@
                   android:layout_height="wrap_content"
                   android:singleLine="true"
                   android:ellipsize="marquee"
+                  android:textAlignment="viewStart"
                   android:textAppearance="?android:attr/textAppearanceSmall"
                   android:duplicateParentState="true" />
     </LinearLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3ac0af7..0daebd7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1110,6 +1110,11 @@
         -->
     </integer-array>
 
+    <!-- Color mode to use when accessibility transforms are enabled. This color mode must be
+         supported by the device, but not necessarily appear in config_availableColorModes. The
+         regularly selected color mode will be used if this value is negative. -->
+    <integer name="config_accessibilityColorMode">-1</integer>
+
     <!-- 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.
@@ -3297,6 +3302,10 @@
          {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
     <bool name="config_navBarNeedsScrim">true</bool>
 
+    <!-- Controls whether seamless rotation should be allowed even though the navbar can move
+         (which normally prevents seamless rotation). -->
+    <bool name="config_allowSeamlessRotationDespiteNavBarMoving">false</bool>
+
     <!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows.
          These values are in DPs and will be converted to pixel sizes internally. -->
     <string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">16x16</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5652c85..0cf9500 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1726,6 +1726,11 @@
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_access_notification_policy">Allows the app to read and write Do Not Disturb configuration.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_startViewPermissionUsage">start view permission usage</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_startViewPermissionUsage">Allows the holder to start the permission usage for an app. Should never be needed for normal apps.</string>
+
     <!-- Policy administration -->
 
     <!-- Title of policy access to limiting the user's password choices -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 77988de..1ef2eb4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2875,6 +2875,7 @@
   <java-symbol type="bool" name="config_navBarTapThrough" />
   <java-symbol type="bool" name="config_navBarAlwaysShowOnSideEdgeGesture" />
   <java-symbol type="bool" name="config_navBarNeedsScrim" />
+  <java-symbol type="bool" name="config_allowSeamlessRotationDespiteNavBarMoving" />
   <java-symbol type="dimen" name="config_backGestureInset" />
   <java-symbol type="color" name="system_bar_background_semi_transparent" />
 
@@ -3186,6 +3187,7 @@
   <java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficients" />
   <java-symbol type="array" name="config_nightDisplayColorTemperatureCoefficientsNative" />
   <java-symbol type="array" name="config_availableColorModes" />
+  <java-symbol type="integer" name="config_accessibilityColorMode" />
   <java-symbol type="bool" name="config_displayWhiteBalanceAvailable" />
   <java-symbol type="bool" name="config_displayWhiteBalanceEnabledDefault" />
   <java-symbol type="integer" name="config_displayWhiteBalanceColorTemperatureMin" />
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
index 343c07a..9ef73e9 100644
--- a/core/tests/utiltests/Android.mk
+++ b/core/tests/utiltests/Android.mk
@@ -18,6 +18,7 @@
     androidx.test.rules \
     frameworks-base-testutils \
     mockito-target-minus-junit4 \
+    androidx.test.ext.junit
 
 LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
 
diff --git a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
index 4b14284..57ee2d5 100644
--- a/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
+++ b/core/tests/utiltests/jni/android_util_MemoryIntArrayTest.cpp
@@ -21,6 +21,36 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 
+jint android_util_MemoryIntArrayTest_createAshmem(__attribute__((unused)) JNIEnv* env,
+        __attribute__((unused)) jobject clazz,
+        jstring name, jint size)
+{
+
+    if (name == NULL) {
+        return -1;
+    }
+
+    if (size < 0) {
+        return -1;
+    }
+
+    const char* nameStr = env->GetStringUTFChars(name, NULL);
+    const int ashmemSize = sizeof(std::atomic_int) * size;
+    int fd = ashmem_create_region(nameStr, ashmemSize);
+    env->ReleaseStringUTFChars(name, nameStr);
+
+    if (fd < 0) {
+        return -1;
+    }
+
+    int setProtResult = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
+    if (setProtResult < 0) {
+        return -1;
+    }
+
+    return fd;
+}
+
 void android_util_MemoryIntArrayTest_setAshmemSize(__attribute__((unused)) JNIEnv* env,
         __attribute__((unused)) jobject clazz, jint fd, jint size)
 {
diff --git a/core/tests/utiltests/jni/registration.cpp b/core/tests/utiltests/jni/registration.cpp
index d4fc2fb..0c84d98 100644
--- a/core/tests/utiltests/jni/registration.cpp
+++ b/core/tests/utiltests/jni/registration.cpp
@@ -16,14 +16,25 @@
 
 #include <jni.h>
 
+extern jint android_util_MemoryIntArrayTest_createAshmem(JNIEnv* env,
+        jobject clazz, jstring name, jint size);
 extern void android_util_MemoryIntArrayTest_setAshmemSize(JNIEnv* env,
        jobject clazz, jint fd, jint size);
 
 extern "C" {
+    JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
+            JNIEnv * env, jobject obj, jstring name, jint size);
     JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
             JNIEnv * env, jobject obj, jint fd, jint size);
 };
 
+JNIEXPORT jint JNICALL Java_android_util_MemoryIntArrayTest_nativeCreateAshmem(
+        __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
+        jstring name, jint size)
+{
+    return android_util_MemoryIntArrayTest_createAshmem(env, obj, name, size);
+}
+
 JNIEXPORT void JNICALL Java_android_util_MemoryIntArrayTest_nativeSetAshmemSize(
         __attribute__((unused)) JNIEnv * env,__attribute__((unused)) jobject obj,
         jint fd, jint size)
diff --git a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
index 2daefe7..1966e12 100644
--- a/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
+++ b/core/tests/utiltests/src/android/util/MemoryIntArrayTest.java
@@ -23,9 +23,8 @@
 import static org.junit.Assert.fail;
 
 import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
 
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 
 import libcore.io.IoUtils;
 
@@ -36,6 +35,8 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 @RunWith(AndroidJUnit4.class)
 public class MemoryIntArrayTest {
     static {
@@ -255,11 +256,13 @@
                 // Create a MemoryIntArray to muck with
                 MemoryIntArray array = new MemoryIntArray(1);
 
-                // Grab the internal ashmem fd.
-                Field fdField = MemoryIntArray.class.getDeclaredField("mFd");
-                fdField.setAccessible(true);
-                int fd = ((ParcelFileDescriptor)fdField.get(array)).getFd();
-                assertTrue("fd must be valid", fd != -1);
+                // Create the fd to stuff in the MemoryIntArray
+                final int fd = nativeCreateAshmem("foo", 1);
+
+                // Replace the fd with our ahsmem region
+                Field fdFiled = MemoryIntArray.class.getDeclaredField("mFd");
+                fdFiled.setAccessible(true);
+                fdFiled.set(array, fd);
 
                 CountDownLatch countDownLatch = new CountDownLatch(2);
 
@@ -294,9 +297,10 @@
         }
 
         if (!success) {
-            fail("MemoryIntArray should catch ashmem size changing under it");
+            fail("MemoryIntArray should catch ahshmem size changing under it");
         }
     }
 
+    private native int nativeCreateAshmem(String name, int size);
     private native void nativeSetAshmemSize(int fd, int size);
 }
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
index 4e8a3a3..195d4fe 100644
--- a/packages/CarSystemUI/AndroidManifest.xml
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -19,6 +19,6 @@
         package="com.android.systemui"
         android:sharedUserId="android.uid.systemui"
         coreApp="true">
-
-
+    <!-- This permission is required to monitor car power state. -->
+    <uses-permission android:name="android.car.permission.CAR_POWER" />
 </manifest>
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 febf8b8..f5dab01 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -25,6 +25,7 @@
 import android.car.Car;
 import android.car.drivingstate.CarDrivingStateEvent;
 import android.car.drivingstate.CarUxRestrictionsManager;
+import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
 import android.content.Context;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
@@ -121,12 +122,17 @@
     private boolean mDeviceIsProvisioned = true;
     private HvacController mHvacController;
     private DrivingStateHelper mDrivingStateHelper;
-    private static FlingAnimationUtils sFlingAnimationUtils;
+    private PowerManagerHelper mPowerManagerHelper;
+    private FlingAnimationUtils mFlingAnimationUtils;
     private SwitchToGuestTimer mSwitchToGuestTimer;
+    private NotificationDataManager mNotificationDataManager;
+    private NotificationClickHandlerFactory mNotificationClickHandlerFactory;
 
     // The container for the notifications.
     private CarNotificationView mNotificationView;
     private RecyclerView mNotificationList;
+    // The controller for the notification view.
+    private NotificationViewController mNotificationViewController;
     // The state of if the notification list is currently showing the bottom.
     private boolean mNotificationListAtBottom;
     // Was the notification list at the bottom when the user first touched the screen
@@ -156,6 +162,20 @@
     // If notification shade is being swiped vertically to close.
     private boolean mIsSwipingVerticallyToClose;
 
+    private final CarPowerStateListener mCarPowerStateListener =
+            (int state) -> {
+                // When the car powers on, clear all notifications and mute/unread states.
+                Log.d(TAG, "New car power state: " + state);
+                if (state == CarPowerStateListener.ON) {
+                    if (mNotificationClickHandlerFactory != null) {
+                        mNotificationClickHandlerFactory.clearAllNotifications();
+                    }
+                    if (mNotificationDataManager != null) {
+                        mNotificationDataManager.clearAll();
+                    }
+                }
+            };
+
     @Override
     public void start() {
         // get the provisioned state before calling the parent class since it's that flow that
@@ -172,7 +192,7 @@
                 R.integer.notification_settle_open_percentage);
         mSettleClosePercentage = mContext.getResources().getInteger(
                 R.integer.notification_settle_close_percentage);
-        sFlingAnimationUtils = new FlingAnimationUtils(mContext,
+        mFlingAnimationUtils = new FlingAnimationUtils(mContext,
                 FLING_ANIMATION_MAX_TIME, FLING_SPEED_UP_FACTOR);
 
         createBatteryController();
@@ -204,6 +224,9 @@
         mDrivingStateHelper = new DrivingStateHelper(mContext, this::onDrivingStateChanged);
         mDrivingStateHelper.connectToCarService();
 
+        mPowerManagerHelper = new PowerManagerHelper(mContext, mCarPowerStateListener);
+        mPowerManagerHelper.connectToCarService();
+
         mSwitchToGuestTimer = new SwitchToGuestTimer(mContext);
     }
 
@@ -308,7 +331,6 @@
         }
     }
 
-
     @Override
     protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
         super.makeStatusBarView(result);
@@ -407,7 +429,7 @@
                 }
         );
 
-        NotificationClickHandlerFactory clickHandlerFactory = new NotificationClickHandlerFactory(
+        mNotificationClickHandlerFactory = new NotificationClickHandlerFactory(
                 mBarService,
                 launchResult -> {
                     if (launchResult == ActivityManager.START_TASK_TO_FRONT
@@ -422,26 +444,27 @@
         CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper =
                 new CarUxRestrictionManagerWrapper();
         carUxRestrictionManagerWrapper.setCarUxRestrictionsManager(carUxRestrictionsManager);
-        NotificationDataManager notificationDataManager = new NotificationDataManager();
 
-        notificationDataManager.setOnUnseenCountUpdateListener(
+        mNotificationDataManager = new NotificationDataManager();
+        mNotificationDataManager.setOnUnseenCountUpdateListener(
                 () -> {
                     // TODO: Update Notification Icon based on unseen count
                     Log.d(TAG, "unseen count: " +
-                            notificationDataManager.getUnseenNotificationCount());
+                            mNotificationDataManager.getUnseenNotificationCount());
                 });
 
         CarHeadsUpNotificationManager carHeadsUpNotificationManager =
-                new CarSystemUIHeadsUpNotificationManager(mContext, clickHandlerFactory,
-                        notificationDataManager);
+                new CarSystemUIHeadsUpNotificationManager(mContext,
+                        mNotificationClickHandlerFactory, mNotificationDataManager);
+        mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager);
 
         carNotificationListener.registerAsSystemService(mContext, carUxRestrictionManagerWrapper,
-                carHeadsUpNotificationManager, notificationDataManager);
+                carHeadsUpNotificationManager, mNotificationDataManager);
 
         mNotificationView = mStatusBarWindow.findViewById(R.id.notification_view);
         View glassPane = mStatusBarWindow.findViewById(R.id.glass_pane);
-        mNotificationView.setClickHandlerFactory(clickHandlerFactory);
-        mNotificationView.setNotificationDataManager(notificationDataManager);
+        mNotificationView.setClickHandlerFactory(mNotificationClickHandlerFactory);
+        mNotificationView.setNotificationDataManager(mNotificationDataManager);
 
         // The glass pane is used to view touch events before passed to the notification list.
         // This allows us to initialize gesture listeners and detect when to close the notifications
@@ -523,12 +546,12 @@
             }
         });
 
-        NotificationViewController mNotificationViewController = new NotificationViewController(
+        mNotificationViewController = new NotificationViewController(
                 mNotificationView,
                 PreprocessingManager.getInstance(mContext),
                 carNotificationListener,
                 carUxRestrictionManagerWrapper,
-                notificationDataManager);
+                mNotificationDataManager);
         mNotificationViewController.enable();
     }
 
@@ -630,16 +653,18 @@
                     mStatusBarWindowController.setPanelVisible(false);
                     mNotificationView.setVisibility(View.INVISIBLE);
                     mNotificationList.setClipBounds(null);
+                    mNotificationViewController.setIsInForeground(false);
                     // let the status bar know that the panel is closed
                     setPanelExpanded(false);
                 } else {
+                    mNotificationViewController.setIsInForeground(true);
                     // let the status bar know that the panel is open
                     mNotificationView.setVisibleNotificationsAsSeen();
                     setPanelExpanded(true);
                 }
             }
         });
-        sFlingAnimationUtils.apply(animator, from, to, Math.abs(velocity));
+        mFlingAnimationUtils.apply(animator, from, to, Math.abs(velocity));
         animator.start();
     }
 
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
new file mode 100644
index 0000000..8de1439
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car;
+
+import android.annotation.NonNull;
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.hardware.power.CarPowerManager;
+import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.util.Log;
+
+/**
+ * Helper class for connecting to the {@link CarPowerManager} and listening for power state changes.
+ */
+public class PowerManagerHelper {
+    public static final String TAG = "PowerManagerHelper";
+
+    private final Context mContext;
+    private final CarPowerStateListener mCarPowerStateListener;
+
+    private Car mCar;
+    private CarPowerManager mCarPowerManager;
+
+    private final ServiceConnection mCarConnectionListener =
+            new ServiceConnection() {
+                public void onServiceConnected(ComponentName name, IBinder service) {
+                    Log.d(TAG, "Car Service connected");
+                    try {
+                        mCarPowerManager = (CarPowerManager) mCar.getCarManager(Car.POWER_SERVICE);
+                        if (mCarPowerManager != null) {
+                            mCarPowerManager.setListener(mCarPowerStateListener);
+                        } else {
+                            Log.e(TAG, "CarPowerManager service not available");
+                        }
+                    } catch (CarNotConnectedException e) {
+                        Log.e(TAG, "Car not connected", e);
+                    }
+                }
+
+                @Override
+                public void onServiceDisconnected(ComponentName name) {
+                    destroyCarPowerManager();
+                }
+            };
+
+    PowerManagerHelper(Context context, @NonNull CarPowerStateListener listener) {
+        mContext = context;
+        mCarPowerStateListener = listener;
+    }
+
+    /**
+     * Connect to Car service.
+     */
+    void connectToCarService() {
+        mCar = Car.createCar(mContext, mCarConnectionListener);
+        if (mCar != null) {
+            mCar.connect();
+        }
+    }
+
+    /**
+     * Disconnects from Car service.
+     */
+    void disconnectFromCarService() {
+        if (mCar != null) {
+            mCar.disconnect();
+        }
+    }
+
+    private void destroyCarPowerManager() {
+        if (mCarPowerManager != null) {
+            mCarPowerManager.clearListener();
+        }
+    }
+}
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index 9c8efe6..64718da 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -108,6 +108,8 @@
     defaults: ["NetworkStackAppCommon"],
     certificate: "platform",
     manifest: "AndroidManifest_InProcess.xml",
+    // InProcessNetworkStack is a replacement for NetworkStack
+    overrides: ["NetworkStack"],
 }
 
 // Updatable network stack packaged as an application
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index dc74c04..266b1b0 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -372,10 +372,6 @@
     private boolean mMulticastFiltering;
     private long mStartTimeMillis;
 
-    /* This must match the definition in KeepaliveTracker.KeepaliveInfo */
-    private static final int TYPE_NATT = 1;
-    private static final int TYPE_TCP = 2;
-
     /**
      * Reading the snapshot is an asynchronous operation initiated by invoking
      * Callback.startReadPacketFilter() and completed when the WiFi Service responds with an
@@ -705,7 +701,7 @@
      * keepalive offload.
      */
     public void addKeepalivePacketFilter(int slot, @NonNull TcpKeepalivePacketDataParcelable pkt) {
-        sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, TYPE_TCP, pkt);
+        sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0 /* Unused */, pkt);
     }
 
     /**
@@ -714,7 +710,7 @@
      */
     public void addNattKeepalivePacketFilter(int slot,
             @NonNull NattKeepalivePacketDataParcelable pkt) {
-        sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, TYPE_NATT, pkt);
+        sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF, slot, 0 /* Unused */ , pkt);
     }
 
     /**
@@ -1626,13 +1622,12 @@
 
                 case CMD_ADD_KEEPALIVE_PACKET_FILTER_TO_APF: {
                     final int slot = msg.arg1;
-                    final int type = msg.arg2;
 
                     if (mApfFilter != null) {
-                        if (type == TYPE_NATT) {
+                        if (msg.obj instanceof NattKeepalivePacketDataParcelable) {
                             mApfFilter.addNattKeepalivePacketFilter(slot,
                                     (NattKeepalivePacketDataParcelable) msg.obj);
-                        } else {
+                        } else if (msg.obj instanceof TcpKeepalivePacketDataParcelable) {
                             mApfFilter.addTcpKeepalivePacketFilter(slot,
                                     (TcpKeepalivePacketDataParcelable) msg.obj);
                         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
index cb0b7c2..98eb573 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
@@ -286,8 +286,7 @@
 
     /** Returns the state representing empty mobile signal with the given number of levels. */
     public static int getEmptyState(int numLevels) {
-        // TODO empty state == 0 state. does there need to be a new drawable for this?
-        return getState(0, numLevels, false);
+        return getState(0, numLevels, true);
     }
 
     /** Returns the state representing carrier change with the given number of levels. */
diff --git a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
index b8e1251..6fd8749 100644
--- a/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
+++ b/packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java
@@ -18,11 +18,11 @@
 
 import android.app.AppOpsManager;
 import android.content.Context;
+import android.content.PermissionChecker;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.drawable.Drawable;
-import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.text.format.DateUtils;
@@ -48,10 +48,15 @@
     private static final long RECENT_TIME_INTERVAL_MILLIS = DateUtils.DAY_IN_MILLIS;
 
     @VisibleForTesting
-    static final int[] LOCATION_OPS = new int[] {
+    static final int[] LOCATION_REQUEST_OPS = new int[]{
             AppOpsManager.OP_MONITOR_LOCATION,
             AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION,
     };
+    @VisibleForTesting
+    static final int[] LOCATION_PERMISSION_OPS = new int[]{
+            AppOpsManager.OP_FINE_LOCATION,
+            AppOpsManager.OP_COARSE_LOCATION,
+    };
 
     private final PackageManager mPackageManager;
     private final Context mContext;
@@ -67,11 +72,13 @@
      * Fills a list of applications which queried location recently within specified time.
      * Apps are sorted by recency. Apps with more recent location requests are in the front.
      */
-    public List<Request> getAppList() {
+    public List<Request> getAppList(boolean showSystemApps) {
+        // Retrieve a location usage list from AppOps
+        PackageManager pm = mContext.getPackageManager();
         // Retrieve a location usage list from AppOps
         AppOpsManager aoManager =
                 (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
-        List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_OPS);
+        List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_REQUEST_OPS);
 
         final int appOpsCount = appOps != null ? appOps.size() : 0;
 
@@ -83,26 +90,58 @@
 
         for (int i = 0; i < appOpsCount; ++i) {
             AppOpsManager.PackageOps ops = appOps.get(i);
-            // Don't show the Android System in the list - it's not actionable for the user.
-            // Also don't show apps belonging to background users except managed users.
             String packageName = ops.getPackageName();
             int uid = ops.getUid();
-            int userId = UserHandle.getUserId(uid);
-            boolean isAndroidOs =
-                    (uid == Process.SYSTEM_UID) && ANDROID_SYSTEM_PACKAGE_NAME.equals(packageName);
-            if (isAndroidOs || !profiles.contains(new UserHandle(userId))) {
+            final UserHandle user = UserHandle.getUserHandleForUid(uid);
+
+            // Don't show apps belonging to background users except managed users.
+            if (!profiles.contains(user)) {
                 continue;
             }
-            Request request = getRequestFromOps(now, ops);
-            if (request != null) {
-                requests.add(request);
+
+            // Don't show apps that do not have user sensitive location permissions
+            boolean showApp = true;
+            if (!showSystemApps) {
+                for (int op : LOCATION_PERMISSION_OPS) {
+                    final String permission = AppOpsManager.opToPermission(op);
+                    final int permissionFlags = pm.getPermissionFlags(permission, packageName,
+                            user);
+                    if (PermissionChecker.checkPermission(mContext, permission, -1, uid,
+                            packageName)
+                            == PermissionChecker.PERMISSION_GRANTED) {
+                        if ((permissionFlags
+                                & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)
+                                == 0) {
+                            showApp = false;
+                            break;
+                        }
+                    } else {
+                        if ((permissionFlags
+                                & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) == 0) {
+                            showApp = false;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (showApp) {
+                Request request = getRequestFromOps(now, ops);
+                if (request != null) {
+                    requests.add(request);
+                }
             }
         }
         return requests;
     }
 
-    public List<Request> getAppListSorted() {
-        List<Request> requests = getAppList();
+    /**
+     * Gets a list of apps that requested for location recently, sorting by recency.
+     *
+     * @param showSystemApps whether includes system apps in the list.
+     * @return the list of apps that recently requested for location.
+     */
+    public List<Request> getAppListSorted(boolean showSystemApps) {
+        List<Request> requests = getAppList(showSystemApps);
         // Sort the list of Requests by recency. Most recent request first.
         Collections.sort(requests, Collections.reverseOrder(new Comparator<Request>() {
             @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 4d332b9..e28c612 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -180,7 +180,8 @@
     public static final int SECURITY_SAE = 5;
     public static final int SECURITY_EAP_SUITE_B = 6;
     public static final int SECURITY_PSK_SAE_TRANSITION = 7;
-    public static final int SECURITY_MAX_VAL = 8; // Has to be the last
+    public static final int SECURITY_OWE_TRANSITION = 8;
+    public static final int SECURITY_MAX_VAL = 9; // Has to be the last
 
     private static final int PSK_UNKNOWN = 0;
     private static final int PSK_WPA = 1;
@@ -869,6 +870,12 @@
                     return concise ? context.getString(R.string.wifi_security_short_sae) :
                             context.getString(R.string.wifi_security_sae);
                 }
+            case SECURITY_OWE_TRANSITION:
+                if (mConfig != null && getSecurity(mConfig) == SECURITY_OWE) {
+                    return concise ? context.getString(R.string.wifi_security_short_owe) :
+                            context.getString(R.string.wifi_security_owe);
+                }
+                return concise ? "" : context.getString(R.string.wifi_security_none);
             case SECURITY_OWE:
                 return concise ? context.getString(R.string.wifi_security_short_owe) :
                     context.getString(R.string.wifi_security_owe);
@@ -1179,7 +1186,8 @@
      * Can only be called for unsecured networks.
      */
     public void generateOpenNetworkConfig() {
-        if ((security != SECURITY_NONE) && (security != SECURITY_OWE)) {
+        if ((security != SECURITY_NONE) && (security != SECURITY_OWE)
+                && (security != SECURITY_OWE_TRANSITION)) {
             throw new IllegalStateException();
         }
         if (mConfig != null)
@@ -1187,7 +1195,7 @@
         mConfig = new WifiConfiguration();
         mConfig.SSID = AccessPoint.convertToQuotedString(ssid);
 
-        if (security == SECURITY_NONE) {
+        if (security == SECURITY_NONE || !getWifiManager().isEasyConnectSupported()) {
             mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
         } else {
             mConfig.allowedKeyManagement.set(KeyMgmt.OWE);
@@ -1229,6 +1237,9 @@
     private static final String sPskSuffix = "," + String.valueOf(SECURITY_PSK);
     private static final String sSaeSuffix = "," + String.valueOf(SECURITY_SAE);
     private static final String sPskSaeSuffix = "," + String.valueOf(SECURITY_PSK_SAE_TRANSITION);
+    private static final String sOweSuffix = "," + String.valueOf(SECURITY_OWE);
+    private static final String sOpenSuffix = "," + String.valueOf(SECURITY_NONE);
+    private static final String sOweTransSuffix = "," + String.valueOf(SECURITY_OWE_TRANSITION);
 
     private boolean isKeyEqual(String compareTo) {
         if (mKey == null) {
@@ -1240,7 +1251,15 @@
                 // Special handling for PSK-SAE transition mode. If the AP has advertised both,
                 // we compare the key with both PSK and SAE for a match.
                 return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')),
-                        compareTo.substring(0, mKey.lastIndexOf(',')));
+                        compareTo.substring(0, compareTo.lastIndexOf(',')));
+            }
+        }
+        if (compareTo.endsWith(sOpenSuffix) || compareTo.endsWith(sOweSuffix)) {
+            if (mKey.endsWith(sOweTransSuffix)) {
+                // Special handling for OWE/Open networks. If AP advertises OWE in transition mode
+                // and we have an Open network saved, allow this connection to be established.
+                return TextUtils.equals(mKey.substring(0, mKey.lastIndexOf(',')),
+                        compareTo.substring(0, compareTo.lastIndexOf(',')));
             }
         }
         return mKey.equals(compareTo);
@@ -1579,10 +1598,11 @@
             return SECURITY_EAP_SUITE_B;
         } else if (result.capabilities.contains("EAP")) {
             return SECURITY_EAP;
+        } else if (result.capabilities.contains("OWE_TRANSITION")) {
+            return SECURITY_OWE_TRANSITION;
         } else if (result.capabilities.contains("OWE")) {
             return SECURITY_OWE;
         }
-
         return SECURITY_NONE;
     }
 
@@ -1628,6 +1648,8 @@
             return "OWE";
         } else if (security == SECURITY_PSK_SAE_TRANSITION) {
             return "PSK+SAE";
+        } else if (security == SECURITY_OWE_TRANSITION) {
+            return "OWE_TRANSITION";
         }
         return "NONE";
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 6269a71..dae5464 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -201,7 +201,8 @@
             return;
         }
         if ((mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE)
-                && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE)) {
+                && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE)
+                && (mAccessPoint.getSecurity() != AccessPoint.SECURITY_OWE_TRANSITION)) {
             mFrictionSld.setState(STATE_SECURED);
         } else if (mAccessPoint.isMetered()) {
             mFrictionSld.setState(STATE_METERED);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
index 8bd5fd2..7a553fc 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java
@@ -16,8 +16,8 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
-
 import android.util.LongSparseLongArray;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -75,7 +75,8 @@
 
         long[] testRequestTime = {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO};
         List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime);
-        when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_OPS)).thenReturn(appOps);
+        when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_REQUEST_OPS)).thenReturn(
+                appOps);
         mockTestApplicationInfos(mTestUserId, TEST_PACKAGE_NAMES);
 
         mRecentLocationApps = new RecentLocationApps(mContext);
@@ -83,7 +84,7 @@
 
     @Test
     public void testGetAppList_shouldFilterRecentApps() {
-        List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList();
+        List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(true);
         // Only two of the apps have requested location within 15 min.
         assertThat(requests).hasSize(2);
         // Make sure apps are ordered by recency
@@ -107,11 +108,12 @@
                 {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO, ONE_MIN_AGO};
         List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime);
         appOps.add(androidSystemPackageOps);
-        when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_OPS)).thenReturn(appOps);
+        when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_REQUEST_OPS)).thenReturn(
+                appOps);
         mockTestApplicationInfos(
                 Process.SYSTEM_UID, RecentLocationApps.ANDROID_SYSTEM_PACKAGE_NAME);
 
-        List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList();
+        List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(true);
         // Android OS shouldn't show up in the list of apps.
         assertThat(requests).hasSize(2);
         // Make sure apps are ordered by recency
@@ -133,7 +135,7 @@
 
     private List<PackageOps> createTestPackageOpsList(String[] packageNameList, long[] time) {
         List<PackageOps> packageOpsList = new ArrayList<>();
-        for (int i = 0; i < packageNameList.length ; i++) {
+        for (int i = 0; i < packageNameList.length; i++) {
             PackageOps packageOps = createPackageOps(
                     packageNameList[i],
                     TEST_UID,
@@ -156,11 +158,11 @@
     private OpEntry createOpEntryWithTime(int op, long time, int duration) {
         final LongSparseLongArray accessTimes = new LongSparseLongArray();
         accessTimes.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
-            AppOpsManager.OP_FLAG_SELF), time);
+                AppOpsManager.OP_FLAG_SELF), time);
         final LongSparseLongArray durations = new LongSparseLongArray();
         durations.put(AppOpsManager.makeKey(AppOpsManager.UID_STATE_TOP,
-            AppOpsManager.OP_FLAG_SELF), duration);
+                AppOpsManager.OP_FLAG_SELF), duration);
         return new OpEntry(op, false, AppOpsManager.MODE_ALLOWED, accessTimes,
-            null /*rejectTimes*/, durations, null /* proxyUids */, null /* proxyPackages */);
+                null /*rejectTimes*/, durations, null /* proxyUids */, null /* proxyPackages */);
     }
 }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 715e1eb..dd72d57 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -225,7 +225,7 @@
     <bool name="def_charging_sounds_enabled">true</bool>
 
     <!-- Default for Settings.Secure.NOTIFICATION_BUBBLES -->
-    <bool name="def_notification_bubbles">true</bool>
+    <bool name="def_notification_bubbles">false</bool>
 
     <!-- Default for Settings.Secure.AWARE_ENABLED -->
     <bool name="def_aware_enabled">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 82592ce..6558c87a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3237,7 +3237,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 179;
+            private static final int SETTINGS_VERSION = 180;
 
             private final int mUserId;
 
@@ -4387,6 +4387,19 @@
                     currentVersion = 179;
                 }
 
+                if (currentVersion == 179) {
+                    // Version 178: Reset the default for Secure Settings: NOTIFICATION_BUBBLES
+                    // This is originally set in version 173, however, the default value changed
+                    // so this step is to ensure the value is updated to the correct defaulte
+                    final SettingsState secureSettings = getSecureSettingsLocked(userId);
+
+                    secureSettings.insertSettingLocked(Secure.NOTIFICATION_BUBBLES,
+                            getContext().getResources().getBoolean(
+                                    R.bool.def_notification_bubbles) ? "1" : "0", null,
+                                    true, SettingsState.SYSTEM_PACKAGE_NAME);
+
+                    currentVersion = 180;
+                }
 
                 // vXXX: Add new settings above this point.
 
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index c2495b5..9425941 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -58,6 +58,7 @@
         "androidx.arch.core_core-runtime",
         "androidx.lifecycle_lifecycle-extensions",
         "androidx.dynamicanimation_dynamicanimation",
+        "iconloader_base",
         "SystemUI-tags",
         "SystemUI-proto",
         "dagger2-2.19",
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
index 29376ce0..796123d 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
@@ -38,6 +38,7 @@
         android:clipChildren="false"
         android:clipToPadding="false"
         android:padding="0dp"
+        android:fitsSystemWindows="true"
         android:layout_gravity="center">
         <com.android.keyguard.KeyguardSecurityViewFlipper
             android:id="@+id/view_flipper"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 4cf5f85..a914930 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -69,7 +69,7 @@
         android:layout_height="match_parent"
         android:importantForAccessibility="no"
         sysui:ignoreRightInset="true"
-        />
+    />
 
     <LinearLayout
         android:id="@+id/lock_icon_container"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index fbb439a..6297423 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -252,6 +252,9 @@
     <!-- size at which Notification icons will be drawn on Ambient Display -->
     <dimen name="status_bar_icon_drawing_size_dark">@*android:dimen/notification_header_icon_size_ambient</dimen>
 
+    <!-- size of notification icons on AOD -->
+    <dimen name="dark_shelf_icon_size">16dp</dimen>
+
     <!-- opacity at which Notification icons will be drawn in the status bar -->
     <item type="dimen" name="status_bar_icon_drawing_alpha">90%</item>
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 6709804..577e3bb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -134,9 +134,4 @@
      * Sent when some system ui state changes.
      */
     void onSystemUiStateChanged(int stateFlags) = 16;
-
-    /**
-     * Sent when the scrim colors (based on wallpaper) change.
-     */
-    void onScrimColorsChanged(int color, int type) = 17;
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index d051def..0914fb8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -20,6 +20,7 @@
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.graphics.Rect;
 import android.metrics.LogMaker;
 import android.os.UserHandle;
 import android.util.AttributeSet;
@@ -139,7 +140,6 @@
             getSecurityView(mCurrentSecuritySelection).onResume(reason);
         }
         updateBiometricRetry();
-        updatePaddings();
     }
 
     @Override
@@ -180,7 +180,7 @@
                 }
                 int index = event.findPointerIndex(mActivePointerId);
                 int touchSlop = mViewConfiguration.getScaledTouchSlop();
-                if (mCurrentSecurityView != null
+                if (mCurrentSecurityView != null && index != -1
                         && mStartTouchY - event.getY(index) > touchSlop) {
                     mIsDragging = true;
                     return true;
@@ -319,17 +319,11 @@
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        updatePaddings();
-    }
-
-    private void updatePaddings() {
-        int bottomPadding = getRootWindowInsets().getSystemWindowInsets().bottom;
-        if (getPaddingBottom() == bottomPadding) {
-            return;
-        }
-        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottomPadding);
+    protected boolean fitSystemWindows(Rect insets) {
+        // Consume bottom insets because we're setting the padding locally (for IME and navbar.)
+        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), insets.bottom);
+        insets.bottom = 0;
+        return false;
     }
 
     private void showDialog(String title, String message) {
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index de10690..05665b5 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.colorextraction;
 
-import android.annotation.ColorInt;
-import android.annotation.IntDef;
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.Context;
@@ -36,13 +34,10 @@
 import com.android.internal.colorextraction.types.Tonal;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Dumpable;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 
 import javax.inject.Inject;
@@ -55,41 +50,23 @@
 public class SysuiColorExtractor extends ColorExtractor implements Dumpable,
         ConfigurationController.ConfigurationListener {
     private static final String TAG = "SysuiColorExtractor";
-
-    public static final int SCRIM_TYPE_REGULAR = 1;
-    public static final int SCRIM_TYPE_LIGHT = 2;
-    public static final int SCRIM_TYPE_DARK = 3;
-
-    @IntDef(prefix = {"SCRIM_TYPE_"}, value = {
-            SCRIM_TYPE_REGULAR,
-            SCRIM_TYPE_LIGHT,
-            SCRIM_TYPE_DARK
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ScrimType {
-    }
-
     private final Tonal mTonal;
-    private final OverviewProxyService mOverviewProxyService;
     private boolean mWallpaperVisible;
     private boolean mHasBackdrop;
     // Colors to return when the wallpaper isn't visible
     private final GradientColors mWpHiddenColors;
 
     @Inject
-    public SysuiColorExtractor(Context context, ConfigurationController configurationController,
-            OverviewProxyService overviewProxyService) {
-        this(context, new Tonal(context), configurationController, true, overviewProxyService);
+    public SysuiColorExtractor(Context context, ConfigurationController configurationController) {
+        this(context, new Tonal(context), configurationController, true);
     }
 
     @VisibleForTesting
     public SysuiColorExtractor(Context context, ExtractionType type,
-            ConfigurationController configurationController, boolean registerVisibility,
-            OverviewProxyService overviewProxyService) {
+            ConfigurationController configurationController, boolean registerVisibility) {
         super(context, type, false /* immediately */);
         mTonal = type instanceof Tonal ? (Tonal) type : new Tonal(context);
         mWpHiddenColors = new GradientColors();
-        mOverviewProxyService = overviewProxyService;
         configurationController.addCallback(this);
 
         WallpaperColors systemColors = getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
@@ -133,35 +110,17 @@
             return;
         }
 
+        super.onColorsChanged(colors, which);
+
         if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
             updateDefaultGradients(colors);
         }
-        super.onColorsChanged(colors, which);
     }
 
     @Override
     public void onUiModeChanged() {
         WallpaperColors systemColors = getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
         updateDefaultGradients(systemColors);
-        triggerColorsChanged(WallpaperManager.FLAG_SYSTEM);
-    }
-
-    @Override
-    protected void triggerColorsChanged(int which) {
-        super.triggerColorsChanged(which);
-
-        if (mWpHiddenColors != null && (which & WallpaperManager.FLAG_SYSTEM) != 0) {
-            @ColorInt int colorInt = mWpHiddenColors.getMainColor();
-            @ScrimType int scrimType;
-            if (colorInt == Tonal.MAIN_COLOR_LIGHT) {
-                scrimType = SCRIM_TYPE_LIGHT;
-            } else if (colorInt == Tonal.MAIN_COLOR_DARK) {
-                scrimType = SCRIM_TYPE_DARK;
-            } else {
-                scrimType = SCRIM_TYPE_REGULAR;
-            }
-            mOverviewProxyService.onScrimColorsChanged(colorInt, scrimType);
-        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index e87ff52..acc0197 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -25,6 +25,7 @@
 import android.app.Dialog;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
+import android.app.StatusBarManager;
 import android.app.WallpaperManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
@@ -38,7 +39,9 @@
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
+import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -75,6 +78,7 @@
 import com.android.internal.colorextraction.drawable.ScrimDrawable;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.util.EmergencyAffordanceManager;
@@ -1501,6 +1505,8 @@
 
         private final Context mContext;
         private final MyAdapter mAdapter;
+        private final IStatusBarService mStatusBarService;
+        private final IBinder mToken = new Binder();
         private MultiListLayout mGlobalActionsLayout;
         private Drawable mBackgroundDrawable;
         private final SysuiColorExtractor mColorExtractor;
@@ -1516,6 +1522,7 @@
             mContext = context;
             mAdapter = adapter;
             mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+            mStatusBarService = Dependency.get(IStatusBarService.class);
 
             // Window initialization
             Window window = getWindow();
@@ -1574,6 +1581,9 @@
                             mContext, true, RotationUtils.ROTATION_NONE);
                 }
 
+                // Disable rotation suggestions, if enabled
+                setRotationSuggestionsEnabled(false);
+
                 FrameLayout panelContainer = new FrameLayout(mContext);
                 FrameLayout.LayoutParams panelParams =
                         new FrameLayout.LayoutParams(
@@ -1732,11 +1742,24 @@
             }
         }
 
+        private void setRotationSuggestionsEnabled(boolean enabled) {
+            try {
+                final int userId = Binder.getCallingUserHandle().getIdentifier();
+                final int what = enabled
+                        ? StatusBarManager.DISABLE2_NONE
+                        : StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
+                mStatusBarService.disable2ForUser(what, mToken, mContext.getPackageName(), userId);
+            } catch (RemoteException ex) {
+                throw ex.rethrowFromSystemServer();
+            }
+        }
+
         private void resetOrientation() {
             if (mResetOrientationData != null) {
                 RotationPolicy.setRotationLockAtAngle(mContext, mResetOrientationData.locked,
                         mResetOrientationData.rotation);
             }
+            setRotationSuggestionsEnabled(true);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index c5591cf..78c7cd4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -31,7 +31,6 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 
-import android.annotation.ColorInt;
 import android.annotation.FloatRange;
 import android.app.ActivityTaskManager;
 import android.content.BroadcastReceiver;
@@ -60,7 +59,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.colorextraction.SysuiColorExtractor.ScrimType;
 import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
@@ -537,16 +535,6 @@
         dispatchNavButtonBounds();
     }
 
-    public void onScrimColorsChanged(@ColorInt int color, @ScrimType int type) {
-        if (mOverviewProxy != null) {
-            try {
-                mOverviewProxy.onScrimColorsChanged(color, type);
-            } catch (RemoteException e) {
-                Log.e(TAG_OPS, "Failed to call onScrimColorsChanged()", e);
-            }
-        }
-    }
-
     private void dispatchNavButtonBounds() {
         if (mOverviewProxy != null && mActiveNavBarRegion != null) {
             try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 2cca701..d202190 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -71,6 +71,7 @@
     private int mIconAppearTopPadding;
     private int mShelfAppearTranslation;
     private float mDarkShelfPadding;
+    private float mDarkShelfIconSize;
     private int mStatusBarHeight;
     private int mStatusBarPaddingStart;
     private AmbientState mAmbientState;
@@ -151,6 +152,7 @@
         mScrollFastThreshold = res.getDimensionPixelOffset(R.dimen.scroll_fast_threshold);
         mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf);
         mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
+        mDarkShelfIconSize = res.getDimensionPixelOffset(R.dimen.dark_shelf_icon_size);
         mGapHeight = res.getDimensionPixelSize(R.dimen.qs_notification_padding);
 
         if (!mShowNotificationShelf) {
@@ -705,12 +707,13 @@
         }
         notificationIconPosition += iconTopPadding;
         float shelfIconPosition = getTranslationY() + icon.getTop();
-        shelfIconPosition += (icon.getHeight() - icon.getIconScale() * mIconSize) / 2.0f;
+        float iconSize = mDark ? mDarkShelfIconSize : mIconSize;
+        shelfIconPosition += (icon.getHeight() - icon.getIconScale() * iconSize) / 2.0f;
         float iconYTranslation = NotificationUtils.interpolate(
                 notificationIconPosition - shelfIconPosition,
                 0,
                 transitionAmount);
-        float shelfIconSize = mIconSize * icon.getIconScale();
+        float shelfIconSize = iconSize * icon.getIconScale();
         float alpha = 1.0f;
         boolean noIcon = !row.isShowingIcon();
         if (noIcon) {
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 1074f3a..f93c5f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -29,6 +29,7 @@
 import android.graphics.drawable.Drawable;
 import android.hardware.biometrics.BiometricSourceType;
 import android.os.Handler;
+import android.os.Trace;
 import android.util.AttributeSet;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -89,6 +90,7 @@
     private float mDozeAmount;
     private int mIconRes;
     private boolean mWasPulsingOnThisFrame;
+    private boolean mWakeAndUnlockRunning;
 
     private final Runnable mDrawOffTimeout = () -> update(true /* forceUpdate */);
     private final DockManager.DockEventListener mDockEventListener =
@@ -255,9 +257,12 @@
                             if (getDrawable() == animation && state == getState()
                                     && doesAnimationLoop(iconAnimRes)) {
                                 animation.start();
+                            } else {
+                                Trace.endAsyncSection("LockIcon#Animation", state);
                             }
                         }
                     });
+                    Trace.beginAsyncSection("LockIcon#Animation", state);
                     animation.start();
                 }
             }
@@ -277,7 +282,8 @@
             mLastBouncerVisible = mBouncerVisible;
         }
 
-        boolean invisible = mDozing && (!mPulsing || mDocked);
+        boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
+        boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning;
         setVisibility(invisible ? INVISIBLE : VISIBLE);
         updateClickability();
     }
@@ -450,4 +456,23 @@
     public void onUnlockMethodStateChanged() {
         update();
     }
+
+    /**
+     * We need to hide the lock whenever there's a fingerprint unlock, otherwise you'll see the
+     * icon on top of the black front scrim.
+     */
+    public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
+        if (wakeAndUnlock) {
+            mWakeAndUnlockRunning = true;
+        }
+        update();
+    }
+
+    /**
+     * Triggered after the unlock animation is over and the user is looking at launcher.
+     */
+    public void onKeyguardFadedAway() {
+        mWakeAndUnlockRunning = false;
+        update();
+    }
 }
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 b4b4235..17f0d5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -538,6 +538,7 @@
             }
             if (mKeyguardMonitor.isKeyguardFadingAway()) {
                 mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+                mStatusBarWindow.onKeyguardFadedAway();
             }
         }
 
@@ -3798,6 +3799,7 @@
     public void notifyBiometricAuthModeChanged() {
         updateDozing();
         updateScrimController();
+        mStatusBarWindow.onBiometricAuthModeChanged(mBiometricUnlockController.isWakeAndUnlock());
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 9f538bb..0b83b69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -265,6 +265,21 @@
         mLockIcon.setPulsing(pulsing);
     }
 
+    /**
+     * Called when the biometric authentication mode changes.
+     * @param wakeAndUnlock If the type is {@link BiometricUnlockController#isWakeAndUnlock()}
+     */
+    public void onBiometricAuthModeChanged(boolean wakeAndUnlock) {
+        mLockIcon.onBiometricAuthModeChanged(wakeAndUnlock);
+    }
+
+    /**
+     * Called after finished unlocking and the status bar window is already collapsed.
+     */
+    public void onKeyguardFadedAway() {
+        mLockIcon.onKeyguardFadedAway();
+    }
+
     public void setStatusBarView(PhoneStatusBarView statusBarView) {
         mStatusBarView = statusBarView;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
index 3d3c295..67df60a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
@@ -34,14 +34,10 @@
 import com.android.internal.colorextraction.ColorExtractor;
 import com.android.internal.colorextraction.types.Tonal;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
-import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 
 /**
  * Tests color extraction generation.
@@ -57,13 +53,6 @@
             ColorExtractor.TYPE_NORMAL,
             ColorExtractor.TYPE_DARK,
             ColorExtractor.TYPE_EXTRA_DARK};
-    @Mock
-    private OverviewProxyService mOverviewProxyService;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-    }
 
     @Test
     public void getColors_usesGreyIfWallpaperNotVisible() {
@@ -129,8 +118,7 @@
         Tonal tonal = mock(Tonal.class);
         ConfigurationController configurationController = mock(ConfigurationController.class);
         SysuiColorExtractor sysuiColorExtractor = new SysuiColorExtractor(getContext(),
-                tonal, configurationController, false /* registerVisibility */,
-                mOverviewProxyService);
+                tonal, configurationController, false /* registerVisibility */);
         verify(configurationController).addCallback(eq(sysuiColorExtractor));
 
         reset(tonal);
@@ -145,7 +133,7 @@
                     outGradientColorsNormal.set(colors);
                     outGradientColorsDark.set(colors);
                     outGradientColorsExtraDark.set(colors);
-                }, mock(ConfigurationController.class), false, mOverviewProxyService);
+                }, mock(ConfigurationController.class), false);
     }
 
     private void simulateEvent(SysuiColorExtractor extractor) {
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
index 9694e76..f1d2e0b 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
@@ -37,6 +37,10 @@
      {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
     <bool name="config_navBarNeedsScrim">false</bool>
 
+    <!-- Controls whether seamless rotation should be allowed even though the navbar can move
+         (which normally prevents seamless rotation). -->
+    <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool>
+
     <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
          show. -->
     <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 7605ccb..e148468 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -270,7 +270,7 @@
                 return;
             }
             if (!userState.mCurrentAttentionCheck.mCallbackInternal.equals(callbackInternal)) {
-                Slog.e(LOG_TAG, "Cannot cancel a non-current request");
+                Slog.w(LOG_TAG, "Cannot cancel a non-current request");
                 return;
             }
             cancel(userState);
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 4437926..3de2537 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -209,6 +209,7 @@
                 case NOT_STARTED : return "NOT_STARTED";
                 case STARTING : return "STARTING";
                 case STARTED : return "STARTED";
+                case STOPPING : return "STOPPING";
             }
             throw new IllegalArgumentException("Unknown state");
         }
@@ -326,6 +327,8 @@
                 Log.d(TAG, "Starting keepalive " + mSlot + " on " + mNai.name());
                 switch (mType) {
                     case TYPE_NATT:
+                        mNai.asyncChannel.sendMessage(
+                                CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */, mPacket);
                         mNai.asyncChannel
                                 .sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket);
                         break;
@@ -336,9 +339,8 @@
                             handleStopKeepalive(mNai, mSlot, ERROR_INVALID_SOCKET);
                             return;
                         }
-                        mNai.asyncChannel
-                                .sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */,
-                                        mPacket);
+                        mNai.asyncChannel.sendMessage(
+                                CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */, mPacket);
                         // TODO: check result from apf and notify of failure as needed.
                         mNai.asyncChannel
                                 .sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket);
@@ -362,18 +364,30 @@
                     Log.e(TAG, "Cannot stop unowned keepalive " + mSlot + " on " + mNai.network);
                 }
             }
-            if (NOT_STARTED != mStartedState) {
-                mStartedState = STOPPING;
-                Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name());
-                if (mType == TYPE_NATT) {
-                    mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
-                } else if (mType == TYPE_TCP) {
-                    mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
-                    mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, mSlot);
-                    mTcpController.stopSocketMonitor(mSlot);
-                } else {
-                    Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
-                }
+            Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name() + ": " + reason);
+            switch (mStartedState) {
+                case NOT_STARTED:
+                    // Remove the reference of the keepalive that meet error before starting,
+                    // e.g. invalid parameter.
+                    cleanupStoppedKeepalive(mNai, mSlot);
+                    break;
+                case STOPPING:
+                    // Keepalive is already in stopping state, ignore.
+                    return;
+                default:
+                    mStartedState = STOPPING;
+                    switch (mType) {
+                        case TYPE_TCP:
+                            mTcpController.stopSocketMonitor(mSlot);
+                            // fall through
+                        case TYPE_NATT:
+                            mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
+                            mNai.asyncChannel.sendMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER,
+                                    mSlot);
+                            break;
+                        default:
+                            Log.wtf(TAG, "Stopping keepalive with unknown type: " + mType);
+                    }
             }
 
             // Close the duplicated fd that maintains the lifecycle of socket whenever
@@ -448,14 +462,18 @@
     }
 
     public void handleStopAllKeepalives(NetworkAgentInfo nai, int reason) {
-        HashMap <Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
+        final HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
         if (networkKeepalives != null) {
-            for (KeepaliveInfo ki : networkKeepalives.values()) {
+            final ArrayList<KeepaliveInfo> kalist = new ArrayList(networkKeepalives.values());
+            for (KeepaliveInfo ki : kalist) {
                 ki.stop(reason);
+                // Clean up keepalives since the network agent is disconnected and unable to pass
+                // back asynchronous result of stop().
+                cleanupStoppedKeepalive(nai, ki.mSlot);
             }
-            networkKeepalives.clear();
-            mKeepalives.remove(nai);
         }
+        // Clean up keepalives will be done as a result of calling ki.stop() after the slots are
+        // freed.
     }
 
     public void handleStopKeepalive(NetworkAgentInfo nai, int slot, int reason) {
@@ -471,8 +489,24 @@
             return;
         }
         ki.stop(reason);
+        // Clean up keepalives will be done as a result of calling ki.stop() after the slots are
+        // freed.
+    }
+
+    private void cleanupStoppedKeepalive(NetworkAgentInfo nai, int slot) {
+        String networkName = (nai == null) ? "(null)" : nai.name();
+        HashMap<Integer, KeepaliveInfo> networkKeepalives = mKeepalives.get(nai);
+        if (networkKeepalives == null) {
+            Log.e(TAG, "Attempt to remove keepalive on nonexistent network " + networkName);
+            return;
+        }
+        KeepaliveInfo ki = networkKeepalives.get(slot);
+        if (ki == null) {
+            Log.e(TAG, "Attempt to remove nonexistent keepalive " + slot + " on " + networkName);
+            return;
+        }
         networkKeepalives.remove(slot);
-        Log.d(TAG, "Stopped keepalive " + slot + " on " + networkName + ", "
+        Log.d(TAG, "Remove keepalive " + slot + " on " + networkName + ", "
                 + networkKeepalives.size() + " remains.");
         if (networkKeepalives.isEmpty()) {
             mKeepalives.remove(nai);
@@ -543,10 +577,11 @@
                 handleStopKeepalive(nai, slot, reason);
             }
         } else if (KeepaliveInfo.STOPPING == ki.mStartedState) {
-            // The message indicated result of stopping : don't call handleStopKeepalive.
+            // The message indicated result of stopping : clean up keepalive slots.
             Log.d(TAG, "Stopped keepalive " + slot + " on " + nai.name()
                     + " stopped: " + reason);
             ki.mStartedState = KeepaliveInfo.NOT_STARTED;
+            cleanupStoppedKeepalive(nai, slot);
         } else {
             Log.wtf(TAG, "Event " + message.what + "," + slot + "," + reason
                     + " for keepalive in wrong state: " + ki.toString());
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 7e79a12..d8b7c2e 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -3256,14 +3256,17 @@
                 }
             }
 
-            // On account add, check if there are any settings to be restored.
-            for (AccountAndUser aau : mRunningAccounts) {
-                if (!containsAccountAndUser(oldAccounts, aau.account, aau.userId)) {
-                    if (Log.isLoggable(TAG, Log.DEBUG)) {
-                        Log.d(TAG, "Account " + aau.account + " added, checking sync restore data");
+            if (syncTargets != null) {
+                // On account add, check if there are any settings to be restored.
+                for (AccountAndUser aau : mRunningAccounts) {
+                    if (!containsAccountAndUser(oldAccounts, aau.account, aau.userId)) {
+                        if (Log.isLoggable(TAG, Log.DEBUG)) {
+                            Log.d(TAG, "Account " + aau.account
+                                    + " added, checking sync restore data");
+                        }
+                        AccountSyncSettingsBackupHelper.accountAdded(mContext, syncTargets.userId);
+                        break;
                     }
-                    AccountSyncSettingsBackupHelper.accountAdded(mContext, syncTargets.userId);
-                    break;
                 }
             }
 
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 85fb1e0..ad81ca2 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -775,10 +775,10 @@
         final ContentResolver cr = getContext().getContentResolver();
         if (isAccessibilityEnabled()) {
             // There are restrictions on the available color modes combined with a11y transforms.
-            if (isColorModeAvailable(COLOR_MODE_SATURATED)) {
-                return COLOR_MODE_SATURATED;
-            } else if (isColorModeAvailable(COLOR_MODE_AUTOMATIC)) {
-                return COLOR_MODE_AUTOMATIC;
+            final int a11yColorMode = getContext().getResources().getInteger(
+                    R.integer.config_accessibilityColorMode);
+            if (a11yColorMode >= 0) {
+                return a11yColorMode;
             }
         }
 
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index 3262eb6..14f1196 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -75,6 +75,8 @@
      */
     private final AtomicBoolean mRequested;
 
+    private long mLastActedOnNextScreenDimming;
+
     /**
      * Monotonously increasing ID for the requests sent.
      */
@@ -150,6 +152,9 @@
     }
 
     public long updateUserActivity(long nextScreenDimming) {
+        if (nextScreenDimming == mLastActedOnNextScreenDimming) {
+            return nextScreenDimming;
+        }
         if (!mIsSettingEnabled) {
             return nextScreenDimming;
         }
@@ -190,13 +195,14 @@
         // afterwards if AttentionManager couldn't deliver it.
         mRequested.set(true);
         mRequestId++;
+        mLastActedOnNextScreenDimming = nextScreenDimming;
         mCallback = new AttentionCallbackInternalImpl(mRequestId);
+        Slog.v(TAG, "Checking user attention, ID: " + mRequestId);
         final boolean sent = mAttentionManager.checkAttention(getAttentionTimeout(), mCallback);
         if (!sent) {
             mRequested.set(false);
         }
 
-        Slog.v(TAG, "Checking user attention, ID: " + mRequestId);
         return whenToCheck;
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index b8504db..197a3cf 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -255,6 +255,7 @@
     private volatile boolean mNavigationBarCanMove;
     private volatile boolean mNavigationBarLetsThroughTaps;
     private volatile boolean mNavigationBarAlwaysShowOnSideGesture;
+    private volatile boolean mAllowSeamlessRotationDespiteNavBarMoving;
 
     // Written by vr manager thread, only read in this class.
     private volatile boolean mPersistentVrModeEnabled;
@@ -2726,6 +2727,8 @@
         mNavigationBarCanMove =
                 mDisplayContent.mBaseDisplayWidth != mDisplayContent.mBaseDisplayHeight
                         && res.getBoolean(R.bool.config_navBarCanMove);
+        mAllowSeamlessRotationDespiteNavBarMoving =
+                res.getBoolean(R.bool.config_allowSeamlessRotationDespiteNavBarMoving);
     }
 
     /**
@@ -3508,8 +3511,9 @@
         }
         // If the navigation bar can't change sides, then it will
         // jump when we change orientations and we don't rotate
-        // seamlessly.
-        if (!navigationBarCanMove()) {
+        // seamlessly - unless that is allowed, eg. with gesture
+        // navigation where the navbar is low-profile enough that this isn't very noticeable.
+        if (!navigationBarCanMove() && !mAllowSeamlessRotationDespiteNavBarMoving) {
             return false;
         }
 
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 204a1ea..fb3076b 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -59,6 +59,7 @@
 #include <android_view_PointerIcon.h>
 #include <android/graphics/GraphicsJNI.h>
 
+#include <nativehelper/ScopedLocalFrame.h>
 #include <nativehelper/ScopedLocalRef.h>
 #include <nativehelper/ScopedPrimitiveArray.h>
 #include <nativehelper/ScopedUtfChars.h>
@@ -723,6 +724,7 @@
     ATRACE_CALL();
 
     JNIEnv* env = jniEnv();
+    ScopedLocalFrame localFrame(env);
 
     jobject tokenObj = javaObjectForIBinder(env, token);
     jstring reasonObj = env->NewStringUTF(reason.c_str());
@@ -735,8 +737,6 @@
     } else {
         assert(newTimeout >= 0);
     }
-
-    env->DeleteLocalRef(reasonObj);
     return newTimeout;
 }
 
@@ -747,6 +747,7 @@
     ATRACE_CALL();
 
     JNIEnv* env = jniEnv();
+    ScopedLocalFrame localFrame(env);
 
     jobject tokenObj = javaObjectForIBinder(env, token);
     if (tokenObj) {
@@ -764,6 +765,7 @@
     ATRACE_CALL();
 
     JNIEnv* env = jniEnv();
+    ScopedLocalFrame localFrame(env);
 
     jobject oldTokenObj = javaObjectForIBinder(env, oldToken);
     jobject newTokenObj = javaObjectForIBinder(env, newToken);
@@ -1139,6 +1141,7 @@
     nsecs_t result = 0;
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
+        ScopedLocalFrame localFrame(env);
 
         // Token may be null
         jobject tokenObj = javaObjectForIBinder(env, token);
@@ -1173,6 +1176,7 @@
     bool result = false;
     if (policyFlags & POLICY_FLAG_TRUSTED) {
         JNIEnv* env = jniEnv();
+        ScopedLocalFrame localFrame(env);
 
         // Note: tokenObj may be null.
         jobject tokenObj = javaObjectForIBinder(env, token);
@@ -1224,6 +1228,7 @@
 void NativeInputManager::onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) {
     ATRACE_CALL();
     JNIEnv* env = jniEnv();
+    ScopedLocalFrame localFrame(env);
 
     jobject touchedTokenObj = javaObjectForIBinder(env, touchedToken);
     env->CallVoidMethod(mServiceObj, gServiceClassInfo.onPointerDownOutsideFocus, touchedTokenObj);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
index 8af4edd..18453aa 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsStorageTests.java
@@ -27,6 +27,7 @@
 import android.content.pm.UserInfo;
 import android.database.sqlite.SQLiteDatabase;
 import android.os.FileUtils;
+import android.os.SystemClock;
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.platform.test.annotations.Presubmit;
@@ -125,7 +126,7 @@
         List<Thread> threads = new ArrayList<>();
         for (int i = 0; i < 100; i++) {
             final int threadId = i;
-            threads.add(new Thread() {
+            threads.add(new Thread("testKeyValue_Concurrency_" + i) {
                 @Override
                 public void run() {
                     synchronized (monitor) {
@@ -134,17 +135,17 @@
                         } catch (InterruptedException e) {
                             return;
                         }
-                        mStorage.writeKeyValue("key", "1 from thread " + threadId, 0);
-                        mStorage.readKeyValue("key", "default", 0);
-                        mStorage.writeKeyValue("key", "2 from thread " + threadId, 0);
-                        mStorage.readKeyValue("key", "default", 0);
-                        mStorage.writeKeyValue("key", "3 from thread " + threadId, 0);
-                        mStorage.readKeyValue("key", "default", 0);
-                        mStorage.writeKeyValue("key", "4 from thread " + threadId, 0);
-                        mStorage.readKeyValue("key", "default", 0);
-                        mStorage.writeKeyValue("key", "5 from thread " + threadId, 0);
-                        mStorage.readKeyValue("key", "default", 0);
                     }
+                    mStorage.writeKeyValue("key", "1 from thread " + threadId, 0);
+                    mStorage.readKeyValue("key", "default", 0);
+                    mStorage.writeKeyValue("key", "2 from thread " + threadId, 0);
+                    mStorage.readKeyValue("key", "default", 0);
+                    mStorage.writeKeyValue("key", "3 from thread " + threadId, 0);
+                    mStorage.readKeyValue("key", "default", 0);
+                    mStorage.writeKeyValue("key", "4 from thread " + threadId, 0);
+                    mStorage.readKeyValue("key", "default", 0);
+                    mStorage.writeKeyValue("key", "5 from thread " + threadId, 0);
+                    mStorage.readKeyValue("key", "default", 0);
                 }
             });
             threads.get(i).start();
@@ -153,12 +154,7 @@
         synchronized (monitor) {
             monitor.notifyAll();
         }
-        for (int i = 0; i < threads.size(); i++) {
-            try {
-                threads.get(i).join();
-            } catch (InterruptedException e) {
-            }
-        }
+        joinAll(threads, 10000);
         assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
         mStorage.clearCache();
         assertEquals('5', mStorage.readKeyValue("key", "default", 0).charAt(0));
@@ -515,4 +511,29 @@
         }
         return captured[0];
     }
+
+    private static void joinAll(List<Thread> threads, long timeoutMillis) {
+        long deadline = SystemClock.uptimeMillis() + timeoutMillis;
+        for (Thread t : threads) {
+            try {
+                t.join(deadline - SystemClock.uptimeMillis());
+                if (t.isAlive()) {
+                    t.interrupt();
+                    throw new RuntimeException(
+                            "Joining " + t + " timed out. Stack: \n" + getStack(t));
+                }
+            } catch (InterruptedException e) {
+                throw new RuntimeException("Interrupted while joining " + t, e);
+            }
+        }
+    }
+
+    private static String getStack(Thread t) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(t.toString()).append('\n');
+        for (StackTraceElement ste : t.getStackTrace()) {
+            sb.append("\tat ").append(ste.toString()).append('\n');
+        }
+        return sb.toString();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index c30a7dd..a63f49b 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.atMost;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -182,10 +183,22 @@
     }
 
     @Test
+    public void testOnUserActivity_ignoresIfAlreadyDoneForThatNextScreenDimming() {
+        long when = registerAttention();
+        verify(mAttentionManagerInternal).checkAttention(anyLong(), any());
+        assertThat(when).isLessThan(mNextDimming);
+        clearInvocations(mAttentionManagerInternal);
+
+        long redundantWhen = mAttentionDetector.updateUserActivity(mNextDimming);
+        assertThat(redundantWhen).isEqualTo(mNextDimming);
+        verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
+    }
+
+    @Test
     public void testOnUserActivity_skipsIfAlreadyScheduled() {
         registerAttention();
         reset(mAttentionManagerInternal);
-        long when = mAttentionDetector.updateUserActivity(mNextDimming);
+        long when = mAttentionDetector.updateUserActivity(mNextDimming + 1);
         verify(mAttentionManagerInternal, never()).checkAttention(anyLong(), any());
         assertThat(when).isLessThan(mNextDimming);
     }
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 7786627..75e8fb5 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -1356,7 +1356,7 @@
     private void fetchCarrierPrivilegedAppsLocked() {
         TelephonyManager telephonyManager =
                 mContext.getSystemService(TelephonyManager.class);
-        mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivileges();
+        mCarrierPrivilegedApps = telephonyManager.getPackagesWithCarrierPrivilegesForAllPhones();
         mHaveCarrierPrivilegedApps = true;
         if (DEBUG) {
             Slog.d(TAG, "apps with carrier privilege " + mCarrierPrivilegedApps);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 328a0a7..dab1e6f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -7475,7 +7475,7 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null)
-                return telephony.checkCarrierPrivilegesForPackage(pkgName);
+                return telephony.checkCarrierPrivilegesForPackage(getSubId(), pkgName);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "checkCarrierPrivilegesForPackage RemoteException", ex);
         } catch (NullPointerException ex) {
@@ -7526,7 +7526,7 @@
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getPackagesWithCarrierPrivileges();
+                return telephony.getPackagesWithCarrierPrivileges(getPhoneId());
             }
         } catch (RemoteException ex) {
             Rlog.e(TAG, "getPackagesWithCarrierPrivileges RemoteException", ex);
@@ -7537,6 +7537,22 @@
     }
 
     /** @hide */
+    public List<String> getPackagesWithCarrierPrivilegesForAllPhones() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getPackagesWithCarrierPrivilegesForAllPhones();
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getPackagesWithCarrierPrivilegesForAllPhones RemoteException", ex);
+        } catch (NullPointerException ex) {
+            Rlog.e(TAG, "getPackagesWithCarrierPrivilegesForAllPhones NPE", ex);
+        }
+        return Collections.EMPTY_LIST;
+    }
+
+
+    /** @hide */
     @SystemApi
     @SuppressLint("Doclava125")
     public void dial(String number) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index e8ce2b4..68fd9ac 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1000,7 +1000,7 @@
     /**
      * Similar to above, but check for the package whose name is pkgName.
      */
-    int checkCarrierPrivilegesForPackage(String pkgName);
+    int checkCarrierPrivilegesForPackage(int subId, String pkgName);
 
     /**
      * Similar to above, but check across all phones.
@@ -1357,9 +1357,14 @@
             in PhoneAccountHandle phoneAccountHandle, boolean enabled);
 
     /**
-     * Returns a list of packages that have carrier privileges.
+     * Returns a list of packages that have carrier privileges for the specific phone.
      */
-    List<String> getPackagesWithCarrierPrivileges();
+    List<String> getPackagesWithCarrierPrivileges(int phoneId);
+
+     /**
+      * Returns a list of packages that have carrier privileges.
+      */
+    List<String> getPackagesWithCarrierPrivilegesForAllPhones();
 
     /**
      * Return the application ID for the app type.
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index fe13787..b0cc207 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -4342,8 +4342,9 @@
         }
 
         // Check that there is no port leaked after all keepalives and sockets are closed.
-        assertFalse(isUdpPortInUse(srcPort));
-        assertFalse(isUdpPortInUse(srcPort2));
+        // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
+        // assertFalse(isUdpPortInUse(srcPort));
+        // assertFalse(isUdpPortInUse(srcPort2));
 
         mWiFiNetworkAgent.disconnect();
         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
@@ -4471,7 +4472,8 @@
         assertEquals(anyIPv4, sa.getAddress());
 
         testPfd.close();
-        assertFalse(isUdpPortInUse(srcPort));
+        // TODO: enable this check after ensuring a valid free port. See b/129512753#comment7.
+        // assertFalse(isUdpPortInUse(srcPort));
 
         mWiFiNetworkAgent.disconnect();
         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 0b1108d..c0c0361 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -160,6 +160,11 @@
     public static final int KEY_MGMT_FT_SAE = 11;
     /**
      * @hide
+     * Security key management scheme: OWE in transition mode.
+     */
+    public static final int KEY_MGMT_OWE_TRANSITION = 12;
+    /**
+     * @hide
      * No cipher suite.
      */
     public static final int CIPHER_NONE = 0;