Merge "Move MediaStore.java inside APEX boundary."
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 278a786..661f32f 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -146,7 +146,8 @@
 
             final CountDownLatch latch = new CountDownLatch(1);
             registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId);
-            // Don't use this.startUserInBackground() since only waiting until ACTION_USER_STARTED.
+            // Don't use this.startUserInBackgroundAndWaitForUnlock() since only waiting until
+            // ACTION_USER_STARTED.
             mIam.startUserInBackground(userId);
             latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
 
@@ -156,6 +157,48 @@
         }
     }
 
+    /**
+     * Measures the time until ACTION_USER_STARTED is received.
+     */
+    @Test
+    public void startUser() throws Exception {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createUserNoFlags();
+            final CountDownLatch latch = new CountDownLatch(1);
+            registerBroadcastReceiver(Intent.ACTION_USER_STARTED, latch, userId);
+            mRunner.resumeTiming();
+
+            mIam.startUserInBackground(userId);
+            latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
+
+            mRunner.pauseTiming();
+            removeUser(userId);
+            mRunner.resumeTiming();
+        }
+    }
+
+    /**
+     * Measures the time until unlock listener is triggered and user is unlocked.
+     */
+    @Test
+    public void startAndUnlockUser() throws Exception {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int userId = createUserNoFlags();
+            mRunner.resumeTiming();
+
+            // Waits for UserState.mUnlockProgress.finish().
+            startUserInBackgroundAndWaitForUnlock(userId);
+
+            mRunner.pauseTiming();
+            removeUser(userId);
+            mRunner.resumeTiming();
+        }
+    }
+
+
+
     @Test
     public void switchUser() throws Exception {
         while (mRunner.keepRunning()) {
@@ -309,7 +352,7 @@
             final int userId = createManagedProfile();
             mRunner.resumeTiming();
 
-            startUserInBackground(userId);
+            startUserInBackgroundAndWaitForUnlock(userId);
 
             mRunner.pauseTiming();
             removeUser(userId);
@@ -326,11 +369,11 @@
             mRunner.pauseTiming();
             final int userId = createManagedProfile();
             // Start the profile initially, then stop it. Similar to setQuietModeEnabled.
-            startUserInBackground(userId);
+            startUserInBackgroundAndWaitForUnlock(userId);
             stopUser(userId, true);
             mRunner.resumeTiming();
 
-            startUserInBackground(userId);
+            startUserInBackgroundAndWaitForUnlock(userId);
 
             mRunner.pauseTiming();
             removeUser(userId);
@@ -352,7 +395,7 @@
             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
             mRunner.resumeTiming();
 
-            startUserInBackground(userId);
+            startUserInBackgroundAndWaitForUnlock(userId);
             startApp(userId, DUMMY_PACKAGE_NAME);
 
             mRunner.pauseTiming();
@@ -376,13 +419,13 @@
             final int userId = createManagedProfile();
             WindowManagerGlobal.getWindowManagerService().dismissKeyguard(null, null);
             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
-            startUserInBackground(userId);
+            startUserInBackgroundAndWaitForUnlock(userId);
             startApp(userId, DUMMY_PACKAGE_NAME);
             stopUser(userId, true);
             TimeUnit.SECONDS.sleep(1); // Brief cool-down before re-starting profile.
             mRunner.resumeTiming();
 
-            startUserInBackground(userId);
+            startUserInBackgroundAndWaitForUnlock(userId);
             startApp(userId, DUMMY_PACKAGE_NAME);
 
             mRunner.pauseTiming();
@@ -423,7 +466,7 @@
             mRunner.resumeTiming();
 
             final int userId = createManagedProfile();
-            startUserInBackground(userId);
+            startUserInBackgroundAndWaitForUnlock(userId);
             installPreexistingApp(userId, DUMMY_PACKAGE_NAME);
             startApp(userId, DUMMY_PACKAGE_NAME);
 
@@ -441,7 +484,7 @@
         while (mRunner.keepRunning()) {
             mRunner.pauseTiming();
             final int userId = createManagedProfile();
-            startUserInBackground(userId);
+            startUserInBackgroundAndWaitForUnlock(userId);
             mRunner.resumeTiming();
 
             stopUser(userId, true);
@@ -467,7 +510,7 @@
                 final int userId = createManagedProfile();
                 mRunner.resumeTiming();
 
-                startUserInBackground(userId);
+                startUserInBackgroundAndWaitForUnlock(userId);
 
                 mRunner.pauseTiming();
                 removeUser(userId);
@@ -490,7 +533,7 @@
                 final int userId = createManagedProfile();
                 mRunner.resumeTiming();
 
-                startUserInBackground(userId);
+                startUserInBackgroundAndWaitForUnlock(userId);
 
                 mRunner.pauseTiming();
                 removeUser(userId);
@@ -526,18 +569,19 @@
     }
 
     /**
-     * Start user in background and wait for it to unlock (equivalent to ACTION_USER_UNLOCKED).
-     * To start in foreground instead, see {@link #switchUser(int)}.
-     * This should always be used for profiles since profiles cannot be started in foreground.
+     * Start user in background and wait for it to unlock by waiting for
+     * UserState.mUnlockProgress.finish().
+     * <p> To start in foreground instead, see {@link #switchUser(int)}.
+     * <p> This should always be used for profiles since profiles cannot be started in foreground.
      */
-    private void startUserInBackground(int userId) {
+    private void startUserInBackgroundAndWaitForUnlock(int userId) {
         final ProgressWaiter waiter = new ProgressWaiter();
         try {
             mIam.startUserInBackgroundWithListener(userId, waiter);
             boolean success = waiter.waitForFinish(TIMEOUT_IN_SECOND);
             attestTrue("Failed to start user " + userId + " in background.", success);
         } catch (RemoteException e) {
-            Log.e(TAG, "startUserInBackground failed", e);
+            Log.e(TAG, "startUserInBackgroundAndWaitForUnlock failed", e);
         }
     }
 
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 182f02b..c5fd3f2 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -542,9 +542,9 @@
     private void informAllUidsLocked(Context context) throws RemoteException {
         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
         PackageManager pm = context.getPackageManager();
-        final List<UserInfo> users = um.getUsers(true);
+        final List<UserHandle> users = um.getUserHandles(true);
         if (DEBUG) {
-            Slog.d(TAG, "Iterating over " + users.size() + " profiles.");
+            Slog.d(TAG, "Iterating over " + users.size() + " userHandles.");
         }
 
         ParcelFileDescriptor[] fds;
@@ -571,11 +571,11 @@
                 ProtoOutputStream output = new ProtoOutputStream(fout);
                 int numRecords = 0;
                 // Add in all the apps for every user/profile.
-                for (UserInfo profile : users) {
+                for (UserHandle userHandle : users) {
                     List<PackageInfo> pi =
                             pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES
                                             | PackageManager.MATCH_ANY_USER,
-                                    profile.id);
+                                    userHandle.getIdentifier());
                     for (int j = 0; j < pi.size(); j++) {
                         if (pi.get(j).applicationInfo != null) {
                             String installer;
diff --git a/api/current.txt b/api/current.txt
index 90f5a5b..31857a2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30417,8 +30417,11 @@
     method public int getMaxMatchFilterLength();
     method public int getMaxServiceNameLength();
     method public int getMaxServiceSpecificInfoLength();
+    method public int getSupportedCipherSuites();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.Characteristics> CREATOR;
+    field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1; // 0x1
+    field public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_256 = 2; // 0x2
   }
 
   public class DiscoverySession implements java.lang.AutoCloseable {
diff --git a/api/system-current.txt b/api/system-current.txt
index fa7d949..8a147bb 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -15,6 +15,7 @@
     field public static final String ACCESS_SHARED_LIBRARIES = "android.permission.ACCESS_SHARED_LIBRARIES";
     field public static final String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS";
     field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER";
+    field public static final String ACCESS_TV_TUNER = "android.permission.ACCESS_TV_TUNER";
     field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
     field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
     field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
@@ -365,6 +366,7 @@
     field public static final String OPSTR_GPS = "android:gps";
     field public static final String OPSTR_INSTANT_APP_START_FOREGROUND = "android:instant_app_start_foreground";
     field public static final String OPSTR_LEGACY_STORAGE = "android:legacy_storage";
+    field public static final String OPSTR_MANAGE_EXTERNAL_STORAGE = "android:manage_external_storage";
     field public static final String OPSTR_MANAGE_IPSEC_TUNNELS = "android:manage_ipsec_tunnels";
     field public static final String OPSTR_MUTE_MICROPHONE = "android:mute_microphone";
     field public static final String OPSTR_NEIGHBORING_CELLS = "android:neighboring_cells";
@@ -2176,6 +2178,7 @@
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     field public static final int FLAG_REMOVED = 2; // 0x2
     field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
+    field public static final int PROTECTION_FLAG_COMPANION = 8388608; // 0x800000
     field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
     field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
     field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
@@ -4016,6 +4019,7 @@
     field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
     field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
     field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
+    field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int STREAM_ASSISTANT = 11; // 0xb
     field public static final int SUCCESS = 0; // 0x0
   }
 
@@ -4478,6 +4482,20 @@
 
 }
 
+package android.media.tv.tuner {
+
+  public abstract class FrontendSettings {
+    method public final int getFrequency();
+    method public abstract int getType();
+  }
+
+  public final class Tuner implements java.lang.AutoCloseable {
+    ctor public Tuner(@NonNull android.content.Context);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.FrontendSettings);
+  }
+
+}
+
 package android.metrics {
 
   public class LogMaker {
diff --git a/api/test-current.txt b/api/test-current.txt
index d5c7d89..e47bd91 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -813,6 +813,7 @@
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     field public static final int FLAG_REMOVED = 2; // 0x2
     field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
+    field public static final int PROTECTION_FLAG_COMPANION = 8388608; // 0x800000
     field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000
     field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000
     field public static final int PROTECTION_FLAG_INCIDENT_REPORT_APPROVER = 1048576; // 0x100000
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index a545fc5..4385964 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -435,6 +435,25 @@
     return eq;
 }
 
+bool subsetDimensions(const std::vector<Matcher>& dimension_a,
+                      const std::vector<Matcher>& dimension_b) {
+    if (dimension_a.size() > dimension_b.size()) {
+        return false;
+    }
+    for (size_t i = 0; i < dimension_a.size(); ++i) {
+        bool found = false;
+        for (size_t j = 0; j < dimension_b.size(); ++j) {
+            if (dimension_a[i] == dimension_b[j]) {
+                found = true;
+            }
+        }
+        if (!found) {
+            return false;
+        }
+    }
+    return true;
+}
+
 bool HasPositionANY(const FieldMatcher& matcher) {
     if (matcher.has_position() && matcher.position() == Position::ANY) {
         return true;
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index 0e033e0..6fc1e23 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -396,6 +396,10 @@
 
 bool equalDimensions(const std::vector<Matcher>& dimension_a,
                      const std::vector<Matcher>& dimension_b);
+
+// Returns true if dimension_a is a subset of dimension_b.
+bool subsetDimensions(const std::vector<Matcher>& dimension_a,
+                      const std::vector<Matcher>& dimension_b);
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp
index f1cad92..f4a59ed 100644
--- a/cmds/statsd/tests/FieldValue_test.cpp
+++ b/cmds/statsd/tests/FieldValue_test.cpp
@@ -480,6 +480,137 @@
     EXPECT_EQ(999, atom.num_results());
 }
 
+/*
+ * Test two Matchers is not a subset of one Matcher.
+ * Test one Matcher is subset of two Matchers.
+ */
+TEST(AtomMatcherTest, TestSubsetDimensions1) {
+    // Initialize first set of matchers
+    FieldMatcher matcher1;
+    matcher1.set_field(10);
+
+    FieldMatcher* child = matcher1.add_child();
+    child->set_field(1);
+    child->set_position(Position::ALL);
+    child->add_child()->set_field(1);
+    child->add_child()->set_field(2);
+
+    vector<Matcher> matchers1;
+    translateFieldMatcher(matcher1, &matchers1);
+    EXPECT_EQ(2, matchers1.size());
+
+    // Initialize second set of matchers
+    FieldMatcher matcher2;
+    matcher2.set_field(10);
+
+    child = matcher2.add_child();
+    child->set_field(1);
+    child->set_position(Position::ALL);
+    child->add_child()->set_field(1);
+
+    vector<Matcher> matchers2;
+    translateFieldMatcher(matcher2, &matchers2);
+    EXPECT_EQ(1, matchers2.size());
+
+    EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
+    EXPECT_TRUE(subsetDimensions(matchers2, matchers1));
+}
+/*
+ * Test not a subset with one matching Matcher, one non-matching Matcher.
+ */
+TEST(AtomMatcherTest, TestSubsetDimensions2) {
+    // Initialize first set of matchers
+    FieldMatcher matcher1;
+    matcher1.set_field(10);
+
+    FieldMatcher* child = matcher1.add_child();
+    child->set_field(1);
+
+    child = matcher1.add_child();
+    child->set_field(2);
+
+    vector<Matcher> matchers1;
+    translateFieldMatcher(matcher1, &matchers1);
+
+    // Initialize second set of matchers
+    FieldMatcher matcher2;
+    matcher2.set_field(10);
+
+    child = matcher2.add_child();
+    child->set_field(1);
+
+    child = matcher2.add_child();
+    child->set_field(3);
+
+    vector<Matcher> matchers2;
+    translateFieldMatcher(matcher2, &matchers2);
+
+    EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
+}
+
+/*
+ * Test not a subset if parent field is not equal.
+ */
+TEST(AtomMatcherTest, TestSubsetDimensions3) {
+    // Initialize first set of matchers
+    FieldMatcher matcher1;
+    matcher1.set_field(10);
+
+    FieldMatcher* child = matcher1.add_child();
+    child->set_field(1);
+
+    vector<Matcher> matchers1;
+    translateFieldMatcher(matcher1, &matchers1);
+
+    // Initialize second set of matchers
+    FieldMatcher matcher2;
+    matcher2.set_field(5);
+
+    child = matcher2.add_child();
+    child->set_field(1);
+
+    vector<Matcher> matchers2;
+    translateFieldMatcher(matcher2, &matchers2);
+
+    EXPECT_FALSE(subsetDimensions(matchers1, matchers2));
+}
+
+/*
+ * Test is subset with two matching Matchers.
+ */
+TEST(AtomMatcherTest, TestSubsetDimensions4) {
+    // Initialize first set of matchers
+    FieldMatcher matcher1;
+    matcher1.set_field(10);
+
+    FieldMatcher* child = matcher1.add_child();
+    child->set_field(1);
+
+    child = matcher1.add_child();
+    child->set_field(2);
+
+    vector<Matcher> matchers1;
+    translateFieldMatcher(matcher1, &matchers1);
+
+    // Initialize second set of matchers
+    FieldMatcher matcher2;
+    matcher2.set_field(10);
+
+    child = matcher2.add_child();
+    child->set_field(1);
+
+    child = matcher2.add_child();
+    child->set_field(2);
+
+    child = matcher2.add_child();
+    child->set_field(3);
+
+    vector<Matcher> matchers2;
+    translateFieldMatcher(matcher2, &matchers2);
+
+    EXPECT_TRUE(subsetDimensions(matchers1, matchers2));
+    EXPECT_FALSE(subsetDimensions(matchers2, matchers1));
+}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 4ce91a6..ce89754c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -846,10 +846,12 @@
     public static final int OP_ACCESS_MEDIA_LOCATION = 90;
     /** @hide Query all apps on device, regardless of declarations in the calling app manifest */
     public static final int OP_QUERY_ALL_PACKAGES = 91;
+    /** @hide Access all external storage */
+    public static final int OP_MANAGE_EXTERNAL_STORAGE = 92;
 
     /** @hide */
     @UnsupportedAppUsage
-    public static final int _NUM_OP = 92;
+    public static final int _NUM_OP = 93;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1135,6 +1137,10 @@
     public static final String OPSTR_READ_DEVICE_IDENTIFIERS = "android:read_device_identifiers";
     /** @hide Query all packages on device */
     public static final String OPSTR_QUERY_ALL_PACKAGES = "android:query_all_packages";
+    /** @hide Access all external storage */
+    @SystemApi
+    public static final String OPSTR_MANAGE_EXTERNAL_STORAGE =
+            "android:manage_external_storage";
 
 
     /** {@link #sAppOpsToNote} not initialized yet for this op */
@@ -1317,6 +1323,7 @@
             OP_READ_DEVICE_IDENTIFIERS,         // READ_DEVICE_IDENTIFIERS
             OP_ACCESS_MEDIA_LOCATION,           // ACCESS_MEDIA_LOCATION
             OP_QUERY_ALL_PACKAGES,              // QUERY_ALL_PACKAGES
+            OP_MANAGE_EXTERNAL_STORAGE,         // MANAGE_EXTERNAL_STORAGE
     };
 
     /**
@@ -1415,6 +1422,7 @@
             OPSTR_READ_DEVICE_IDENTIFIERS,
             OPSTR_ACCESS_MEDIA_LOCATION,
             OPSTR_QUERY_ALL_PACKAGES,
+            OPSTR_MANAGE_EXTERNAL_STORAGE,
     };
 
     /**
@@ -1514,6 +1522,7 @@
             "READ_DEVICE_IDENTIFIERS",
             "ACCESS_MEDIA_LOCATION",
             "QUERY_ALL_PACKAGES",
+            "MANAGE_EXTERNAL_STORAGE"
     };
 
     /**
@@ -1614,6 +1623,7 @@
             null, // no direct permission for OP_READ_DEVICE_IDENTIFIERS
             Manifest.permission.ACCESS_MEDIA_LOCATION,
             null, // no permission for OP_QUERY_ALL_PACKAGES
+            null, // no permission for OP_MANAGE_EXTERNAL_STORAGE
     };
 
     /**
@@ -1714,6 +1724,7 @@
             null, // READ_DEVICE_IDENTIFIERS
             null, // ACCESS_MEDIA_LOCATION
             null, // QUERY_ALL_PACKAGES
+            null, // MANAGE_EXTERNAL_STORAGE
     };
 
     /**
@@ -1813,6 +1824,7 @@
             false, // READ_DEVICE_IDENTIFIERS
             false, // ACCESS_MEDIA_LOCATION
             false, // QUERY_ALL_PACKAGES
+            false, // MANAGE_EXTERNAL_STORAGE
     };
 
     /**
@@ -1911,6 +1923,7 @@
             AppOpsManager.MODE_ERRORED, // READ_DEVICE_IDENTIFIERS
             AppOpsManager.MODE_ALLOWED, // ALLOW_MEDIA_LOCATION
             AppOpsManager.MODE_DEFAULT, // QUERY_ALL_PACKAGES
+            AppOpsManager.MODE_DEFAULT, // MANAGE_EXTERNAL_STORAGE
     };
 
     /**
@@ -2013,6 +2026,7 @@
             false, // READ_DEVICE_IDENTIFIERS
             false, // ACCESS_MEDIA_LOCATION
             false, // QUERY_ALL_PACKAGES
+            false, // MANAGE_EXTERNAL_STORAGE
     };
 
     /**
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index 958ebae..0e1f921 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -285,7 +285,7 @@
             time = 1571327470155L,
             codegenVersion = "1.0.9",
             sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
-            inputSignatures = "private final @android.annotation.IntRange(from=0L, to=91L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+            inputSignatures = "private final @android.annotation.IntRange(from=0L, to=92L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mNotingPackageName\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 89a1c6a..a0f089b 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -248,6 +248,17 @@
     @TestApi
     public static final int PROTECTION_FLAG_TELEPHONY = 0x400000;
 
+    /**
+     * Additional flag for {@link #protectionLevel}, corresponding
+     * to the <code>companion</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public static final int PROTECTION_FLAG_COMPANION = 0x800000;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = {
             PROTECTION_FLAG_PRIVILEGED,
@@ -270,6 +281,7 @@
             PROTECTION_FLAG_INCIDENT_REPORT_APPROVER,
             PROTECTION_FLAG_APP_PREDICTOR,
             PROTECTION_FLAG_TELEPHONY,
+            PROTECTION_FLAG_COMPANION,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProtectionFlags {}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 503d6db..7629e1b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3900,6 +3900,12 @@
         public static final String VOLUME_ACCESSIBILITY = "volume_a11y";
 
         /**
+         * @hide
+         * Volume index for virtual assistant.
+         */
+        public static final String VOLUME_ASSISTANT = "volume_assistant";
+
+        /**
          * Master volume (float in the range 0.0f to 1.0f).
          *
          * @hide
@@ -3977,7 +3983,7 @@
                 "" /*STREAM_SYSTEM_ENFORCED, no setting for this stream*/,
                 "" /*STREAM_DTMF, no setting for this stream*/,
                 "" /*STREAM_TTS, no setting for this stream*/,
-                VOLUME_ACCESSIBILITY
+                VOLUME_ACCESSIBILITY, VOLUME_ASSISTANT
             };
 
         /**
@@ -4524,6 +4530,7 @@
             PUBLIC_SETTINGS.add(VOLUME_ALARM);
             PUBLIC_SETTINGS.add(VOLUME_NOTIFICATION);
             PUBLIC_SETTINGS.add(VOLUME_BLUETOOTH_SCO);
+            PUBLIC_SETTINGS.add(VOLUME_ASSISTANT);
             PUBLIC_SETTINGS.add(RINGTONE);
             PUBLIC_SETTINGS.add(NOTIFICATION_SOUND);
             PUBLIC_SETTINGS.add(ALARM_ALERT);
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index f1d152b..00edb3a 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -45,4 +45,17 @@
      * {@param animationDuration} suggests the animation duration transitioning to PiP window.
      */
     void startAnimation(in Rect destinationBounds, in Rect sourceRectHint, int animationDuration);
+
+    /**
+     * Notifies the controller to reset on bounds animation, if there is any.
+     * This could happen when screen rotation is happening and we need to notify the WM to reset
+     * any running bounds animation on the pinned stack.
+     * {@param bounds} here is the final destination bounds.
+     */
+    void resetBoundsAnimation(in Rect bounds);
+
+    /**
+     * Reports the current default and movement bounds to controller.
+     */
+    void reportBounds(in Rect defaultBounds, in Rect movementBounds);
 }
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index bc80197..c7ec2cd 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -136,6 +136,13 @@
     }
 
     /**
+     * Returns the same array or an empty one if it's null.
+     */
+    public static @NonNull <T> T[] emptyIfNull(@Nullable T[] items, Class<T> kind) {
+        return items != null ? items : emptyArray(kind);
+    }
+
+    /**
      * Checks if given array is null or has zero elements.
      */
     public static boolean isEmpty(@Nullable Collection<?> array) {
@@ -751,6 +758,42 @@
         return result;
     }
 
+    /**
+     * Returns an array containing elements from the given one that match the given predicate.
+     */
+    public static @Nullable <T> T[] filter(@Nullable T[] items,
+            @NonNull IntFunction<T[]> arrayConstructor,
+            @NonNull java.util.function.Predicate<T> predicate) {
+        if (isEmpty(items)) {
+            return items;
+        }
+
+        int matchesCount = 0;
+        int size = size(items);
+        for (int i = 0; i < size; i++) {
+            if (predicate.test(items[i])) {
+                matchesCount++;
+            }
+        }
+        if (matchesCount == 0) {
+            return items;
+        }
+        if (matchesCount == items.length) {
+            return items;
+        }
+        if (matchesCount == 0) {
+            return null;
+        }
+        T[] result = arrayConstructor.apply(matchesCount);
+        int outIdx = 0;
+        for (int i = 0; i < size; i++) {
+            if (predicate.test(items[i])) {
+                result[outIdx++] = items[i];
+            }
+        }
+        return result;
+    }
+
     public static boolean startsWith(byte[] cur, byte[] val) {
         if (cur == null || val == null) return false;
         if (cur.length < val.length) return false;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ee86c162..3937066 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1629,6 +1629,14 @@
     <permission android:name="android.permission.NETWORK_SETTINGS"
         android:protectionLevel="signature|telephony" />
 
+    <!-- Allows holder to request bluetooth/wifi scan bypassing global "use location" setting and
+         location permissions.
+         <p>Not for use by third-party or privileged applications.
+         @hide
+    -->
+    <permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION"
+                android:protectionLevel="signature|companion" />
+
     <!-- Allows SetupWizard to call methods in Networking services
          <p>Not for use by any other third-party or privileged applications.
          @SystemApi
@@ -4715,6 +4723,12 @@
     <permission android:name="android.permission.PEEK_DROPBOX_DATA"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi Allows an application to access TV tuner HAL
+         <p>Not for use by third-party applications.
+         @hide -->
+    <permission android:name="android.permission.ACCESS_TV_TUNER"
+        android:protectionLevel="signature|privileged" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 166cde0..b17d473 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -298,6 +298,9 @@
         <!-- Additional flag from base permission type: this permission can be automatically
             granted to the system telephony apps -->
         <flag name="telephony" value="0x400000" />
+        <!-- Additional flag from base permission type: this permission can be automatically
+            granted to the system companion device manager service -->
+        <flag name="companion" value="0x800000" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 85406c7..32ec95a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3572,6 +3572,13 @@
         <item>android.ext.services</item>
     </string-array>
 
+    <!-- The package name for the system companion device manager service.
+         This service must be trusted, as it can be activated without explicit consent of the user.
+         Example: "com.android.companiondevicemanager"
+         See android.companion.CompanionDeviceManager.
+    -->
+    <string name="config_companionDeviceManagerPackage" translatable="false"></string>
+
     <!-- The package name for the default wellbeing app.
          This package must be trusted, as it has the permissions to control other applications
          on the device.
@@ -4272,4 +4279,7 @@
          value is left empty.  When this is non-empty then config_rawContactsLocalAccountName
          should also be non-empty.-->
     <string name="config_rawContactsLocalAccountType" translatable="false"></string>
+
+    <!-- Whether or not to use assistant stream volume separately from music volume -->
+    <bool name="config_useAssistantVolume">false</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1e59c37..d30c7bf 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -468,6 +468,7 @@
   <java-symbol type="string" name="config_deviceSpecificAudioService" />
   <java-symbol type="integer" name="config_num_physical_slots" />
   <java-symbol type="array" name="config_integrityRuleProviderPackages" />
+  <java-symbol type="bool" name="config_useAssistantVolume" />
 
   <java-symbol type="color" name="tab_indicator_text_v4" />
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c8a7ef5..34ed5b3 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -374,6 +374,10 @@
     public static final int STREAM_TTS = AudioSystem.STREAM_TTS;
     /** Used to identify the volume of audio streams for accessibility prompts */
     public static final int STREAM_ACCESSIBILITY = AudioSystem.STREAM_ACCESSIBILITY;
+    /** @hide Used to identify the volume of audio streams for virtual assistant */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+    public static final int STREAM_ASSISTANT = AudioSystem.STREAM_ASSISTANT;
 
     /** Number of audio streams */
     /**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 8e76fcf..e584add 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -80,6 +80,8 @@
     public static final int STREAM_TTS = 9;
     /** Used to identify the volume of audio streams for accessibility prompts */
     public static final int STREAM_ACCESSIBILITY = 10;
+    /** Used to identify the volume of audio streams for virtual assistant */
+    public static final int STREAM_ASSISTANT = 11;
     /**
      * @deprecated Use {@link #numStreamTypes() instead}
      */
@@ -92,7 +94,7 @@
     private static native int native_get_FCC_8();
 
     // Expose only the getter method publicly so we can change it in the future
-    private static final int NUM_STREAM_TYPES = 11;
+    private static final int NUM_STREAM_TYPES = 12;
     @UnsupportedAppUsage
     public static final int getNumStreamTypes() { return NUM_STREAM_TYPES; }
 
@@ -107,7 +109,8 @@
         "STREAM_SYSTEM_ENFORCED",
         "STREAM_DTMF",
         "STREAM_TTS",
-        "STREAM_ACCESSIBILITY"
+        "STREAM_ACCESSIBILITY",
+        "STREAM_ASSISTANT"
     };
 
     /*
@@ -1277,6 +1280,7 @@
         5, // STREAM_DTMF
         5, // STREAM_TTS
         5, // STREAM_ACCESSIBILITY
+        5, // STREAM_ASSISTANT
     };
 
     public static String streamToString(int stream) {
diff --git a/media/java/android/media/tv/tuner/FrontendSettings.java b/media/java/android/media/tv/tuner/FrontendSettings.java
index 3782cc6..531e210 100644
--- a/media/java/android/media/tv/tuner/FrontendSettings.java
+++ b/media/java/android/media/tv/tuner/FrontendSettings.java
@@ -16,15 +16,22 @@
 
 package android.media.tv.tuner;
 
+import android.annotation.SystemApi;
 import android.media.tv.tuner.TunerConstants.FrontendSettingsType;
 
 import java.util.List;
 
 /**
+ * Frontend settings for tune and scan operations.
  * @hide
  */
+@SystemApi
 public abstract class FrontendSettings {
-    protected int mFrequency;
+    private final int mFrequency;
+
+    FrontendSettings(int frequency) {
+        mFrequency = frequency;
+    }
 
     /**
      * Returns the frontend type.
@@ -32,7 +39,12 @@
     @FrontendSettingsType
     public abstract int getType();
 
-    public int getFrequency() {
+    /**
+     * Gets the frequency setting.
+     *
+     * @return the frequency in Hz.
+     */
+    public final int getFrequency() {
         return mFrequency;
     }
 
@@ -42,6 +54,7 @@
 
     /**
      * Frontend settings for analog.
+     * @hide
      */
     public static class FrontendAnalogSettings extends FrontendSettings {
         private int mAnalogType;
@@ -68,7 +81,7 @@
         }
 
         private FrontendAnalogSettings(int frequency, int analogType, int sifStandard) {
-            mFrequency = frequency;
+            super(frequency);
             mAnalogType = analogType;
             mSifStandard = sifStandard;
         }
@@ -118,10 +131,15 @@
 
     /**
      * Frontend settings for ATSC.
+     * @hide
      */
     public static class FrontendAtscSettings extends FrontendSettings {
         public int modulation;
 
+        FrontendAtscSettings(int frequency) {
+            super(frequency);
+        }
+
         @Override
         public int getType() {
             return TunerConstants.FRONTEND_TYPE_ATSC;
@@ -130,12 +148,17 @@
 
     /**
      * Frontend settings for ATSC-3.
+     * @hide
      */
     public static class FrontendAtsc3Settings extends FrontendSettings {
         public int bandwidth;
         public byte demodOutputFormat;
         public List<FrontendAtsc3PlpSettings> plpSettings;
 
+        FrontendAtsc3Settings(int frequency) {
+            super(frequency);
+        }
+
         @Override
         public int getType() {
             return TunerConstants.FRONTEND_TYPE_ATSC3;
@@ -144,6 +167,7 @@
 
     /**
      * Frontend settings for DVBS.
+     * @hide
      */
     public static class FrontendDvbsSettings extends FrontendSettings {
         public int modulation;
@@ -154,6 +178,10 @@
         public int inputStreamId;
         public byte standard;
 
+        FrontendDvbsSettings(int frequency) {
+            super(frequency);
+        }
+
         @Override
         public int getType() {
             return TunerConstants.FRONTEND_TYPE_DVBS;
@@ -162,6 +190,7 @@
 
     /**
      * Frontend settings for DVBC.
+     * @hide
      */
     public static class FrontendDvbcSettings extends FrontendSettings {
         public int modulation;
@@ -171,6 +200,10 @@
         public byte annex;
         public int spectralInversion;
 
+        FrontendDvbcSettings(int frequency) {
+            super(frequency);
+        }
+
         @Override
         public int getType() {
             return TunerConstants.FRONTEND_TYPE_DVBC;
@@ -179,6 +212,7 @@
 
     /**
      * Frontend settings for DVBT.
+     * @hide
      */
     public static class FrontendDvbtSettings extends FrontendSettings {
         public int transmissionMode;
@@ -195,6 +229,10 @@
         public byte plpId;
         public byte plpGroupId;
 
+        FrontendDvbtSettings(int frequency) {
+            super(frequency);
+        }
+
         @Override
         public int getType() {
             return TunerConstants.FRONTEND_TYPE_DVBT;
@@ -203,6 +241,7 @@
 
     /**
      * Frontend settings for ISDBS.
+     * @hide
      */
     public static class FrontendIsdbsSettings extends FrontendSettings {
         public int streamId;
@@ -212,6 +251,10 @@
         public int symbolRate;
         public int rolloff;
 
+        FrontendIsdbsSettings(int frequency) {
+            super(frequency);
+        }
+
         @Override
         public int getType() {
             return TunerConstants.FRONTEND_TYPE_ISDBS;
@@ -220,6 +263,7 @@
 
     /**
      * Frontend settings for ISDBS-3.
+     * @hide
      */
     public static class FrontendIsdbs3Settings extends FrontendSettings {
         public int streamId;
@@ -229,6 +273,10 @@
         public int symbolRate;
         public int rolloff;
 
+        FrontendIsdbs3Settings(int frequency) {
+            super(frequency);
+        }
+
         @Override
         public int getType() {
             return TunerConstants.FRONTEND_TYPE_ISDBS3;
@@ -237,6 +285,7 @@
 
     /**
      * Frontend settings for ISDBT.
+     * @hide
      */
     public static class FrontendIsdbtSettings extends FrontendSettings {
         public int modulation;
@@ -245,6 +294,10 @@
         public int guardInterval;
         public int serviceAreaId;
 
+        FrontendIsdbtSettings(int frequency) {
+            super(frequency);
+        }
+
         @Override
         public int getType() {
             return TunerConstants.FRONTEND_TYPE_ISDBT;
@@ -253,6 +306,7 @@
 
     /**
      * PLP settings for ATSC-3.
+     * @hide
      */
     public static class FrontendAtsc3PlpSettings {
         public byte plpId;
@@ -264,6 +318,7 @@
 
     /**
      * Code rate for DVBS.
+     * @hide
      */
     public static class FrontendDvbsCodeRate {
         public long fec;
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 4c93101..a4197441 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -18,6 +18,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.content.Context;
+import android.content.pm.PackageManager;
 import android.media.tv.tuner.TunerConstants.DemuxPidType;
 import android.os.Handler;
 import android.os.Looper;
@@ -26,14 +30,20 @@
 import java.util.List;
 
 /**
- * Tuner is used to interact with tuner devices.
+ * This class is used to interact with hardware tuners devices.
+ *
+ * <p> Each TvInputService Session should create one instance of this class.
+ *
+ * <p> This class controls the TIS interaction with Tuner HAL.
  *
  * @hide
  */
+@SystemApi
 public final class Tuner implements AutoCloseable  {
     private static final String TAG = "MediaTvTuner";
     private static final boolean DEBUG = false;
 
+    private static final String PERMISSION = android.Manifest.permission.ACCESS_TV_TUNER;
     private static final int MSG_ON_FRONTEND_EVENT = 1;
     private static final int MSG_ON_FILTER_EVENT = 2;
     private static final int MSG_ON_FILTER_STATUS = 3;
@@ -44,6 +54,8 @@
         nativeInit();
     }
 
+    private final Context mContext;
+
     private List<Integer> mFrontendIds;
     private Frontend mFrontend;
     private EventHandler mHandler;
@@ -51,12 +63,26 @@
     private List<Integer> mLnbIds;
     private Lnb mLnb;
 
-    public Tuner() {
+    /**
+     * Constructs a Tuner instance.
+     *
+     * @param context context of the caller.
+     */
+    public Tuner(@NonNull Context context) {
+        mContext = context;
         nativeSetup();
     }
 
+    private void checkPermission() {
+        if (mContext.checkCallingOrSelfPermission(PERMISSION)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Caller must have " + PERMISSION + " permission.");
+        }
+    }
+
     private long mNativeContext; // used by native jMediaTuner
 
+    /** @hide */
     @Override
     public void close() {}
 
@@ -92,6 +118,8 @@
 
     /**
      * Frontend Callback.
+     *
+     * @hide
      */
     public interface FrontendCallback {
 
@@ -103,6 +131,8 @@
 
     /**
      * LNB Callback.
+     *
+     * @hide
      */
     public interface LnbCallback {
         /**
@@ -113,6 +143,8 @@
 
     /**
      * Frontend Callback.
+     *
+     * @hide
      */
     public interface FilterCallback {
         /**
@@ -123,6 +155,8 @@
 
     /**
      * DVR Callback.
+     *
+     * @hide
      */
     public interface DvrCallback {
         /**
@@ -177,7 +211,7 @@
         }
     }
 
-    protected class Frontend {
+    private class Frontend {
         private int mId;
         private FrontendCallback mCallback;
 
@@ -210,9 +244,15 @@
     }
 
     /**
-     * Tunes the frontend to using the settings given.
+     * Tunes the frontend to the settings given.
+     *
+     * @return result status of tune operation.
+     * @throws SecurityException if the caller does not have appropriate permissions.
+     * TODO: add result constants or throw exceptions.
      */
+    @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     public int tune(@NonNull FrontendSettings settings) {
+        checkPermission();
         return nativeTune(settings.getType(), settings);
     }
 
@@ -238,7 +278,8 @@
         }
     }
 
-    protected class Filter {
+    /** @hide */
+    public class Filter {
         private long mNativeContext;
         private FilterCallback mCallback;
         int mId;
@@ -297,7 +338,8 @@
         return filter;
     }
 
-    protected class Lnb {
+    /** @hide */
+    public class Lnb {
         private int mId;
         private LnbCallback mCallback;
 
@@ -338,7 +380,8 @@
         }
     }
 
-    protected class Descrambler {
+    /** @hide */
+    public class Descrambler {
         private long mNativeContext;
 
         private native boolean nativeAddPid(int pidType, int pid, Filter filter);
@@ -362,7 +405,8 @@
     }
 
     // TODO: consider splitting Dvr to Playback and Recording
-    protected class Dvr {
+    /** @hide */
+    public class Dvr {
         private long mNativeContext;
         private DvrCallback mCallback;
 
diff --git a/packages/CompanionDeviceManager/Android.bp b/packages/CompanionDeviceManager/Android.bp
index a379bfc..1453ec3 100644
--- a/packages/CompanionDeviceManager/Android.bp
+++ b/packages/CompanionDeviceManager/Android.bp
@@ -15,5 +15,6 @@
 android_app {
     name: "CompanionDeviceManager",
     srcs: ["src/**/*.java"],
+
     platform_apis: true,
 }
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 42885e8..a9c6685 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -29,6 +29,7 @@
     <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
+    <uses-permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION"/>
 
     <application
         android:allowClearUserData="true"
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 19ff244..443811f 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -87,6 +87,7 @@
                     Settings.System.VOLUME_ACCESSIBILITY, // used internally, changing value will
                                                           // not change volume
                     Settings.System.VOLUME_ALARM, // deprecated since API 2?
+                    Settings.System.VOLUME_ASSISTANT, // candidate for backup?
                     Settings.System.VOLUME_BLUETOOTH_SCO, // deprecated since API 2?
                     Settings.System.VOLUME_MASTER, // candidate for backup?
                     Settings.System.VOLUME_MUSIC, // deprecated since API 2?
diff --git a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
index 75e260e..d1d9b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
@@ -20,11 +20,13 @@
 import android.content.res.Configuration;
 
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.wm.DisplayWindowController;
 
 import java.io.PrintWriter;
 
 public interface BasePipManager {
-    void initialize(Context context, BroadcastDispatcher broadcastDispatcher);
+    void initialize(Context context, BroadcastDispatcher broadcastDispatcher,
+            DisplayWindowController displayWindowController);
     void showPictureInPictureMenu();
     default void expandPip() {}
     default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index f10274a..8e34a90 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -16,8 +16,14 @@
 
 package com.android.systemui.pip;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
 
+import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Resources;
@@ -32,10 +38,9 @@
 import android.view.Gravity;
 import android.view.IPinnedStackController;
 import android.view.IWindowManager;
+import android.view.WindowContainerTransaction;
 import android.view.WindowManagerGlobal;
 
-import com.android.internal.policy.PipSnapAlgorithm;
-
 import java.io.PrintWriter;
 
 /**
@@ -154,6 +159,7 @@
      */
     public void onMinimizedStateChanged(boolean minimized) {
         mIsMinimized = minimized;
+        mSnapAlgorithm.setMinimized(minimized);
     }
 
     /**
@@ -199,6 +205,7 @@
         mReentrySnapFraction = INVALID_SNAP_FRACTION;
         mReentrySize = null;
         mLastPipComponentName = null;
+        mLastDestinationBounds.setEmpty();
     }
 
     public Rect getLastDestinationBounds() {
@@ -235,8 +242,9 @@
      */
     public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect bounds) {
         final Rect destinationBounds;
+        final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
         if (bounds == null) {
-            destinationBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
+            destinationBounds = new Rect(defaultBounds);
         } else {
             destinationBounds = new Rect(bounds);
         }
@@ -253,12 +261,85 @@
             mPinnedStackController.startAnimation(destinationBounds, sourceRectHint,
                     -1 /* animationDuration */);
             mLastDestinationBounds.set(destinationBounds);
+            mPinnedStackController.reportBounds(defaultBounds,
+                    getMovementBounds(defaultBounds));
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to start PiP animation from SysUI", e);
         }
     }
 
     /**
+     * Updates the display info, calculating and returning the new stack and movement bounds in the
+     * new orientation of the device if necessary.
+     *
+     * @return {@code true} if internal {@link DisplayInfo} is rotated, {@code false} otherwise.
+     */
+    public boolean onDisplayRotationChanged(Rect outBounds, int displayId, int fromRotation,
+            int toRotation, WindowContainerTransaction t) {
+        // Bail early if the event is not sent to current {@link #mDisplayInfo}
+        if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) {
+            return false;
+        }
+
+        // Bail early if the pinned stack is staled.
+        final ActivityManager.StackInfo pinnedStackInfo;
+        try {
+            pinnedStackInfo = ActivityTaskManager.getService()
+                    .getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+            if (pinnedStackInfo == null) return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get StackInfo for pinned stack", e);
+            return false;
+        }
+
+        // Calculate the snap fraction of the current stack along the old movement bounds
+        final Rect postChangeStackBounds = new Rect(mLastDestinationBounds);
+        final float snapFraction = getSnapFraction(postChangeStackBounds);
+
+        // Populate the new {@link #mDisplayInfo}.
+        // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
+        // therefore, the width/height may require a swap first.
+        // Moving forward, we should get the new dimensions after rotation from DisplayLayout.
+        mDisplayInfo.rotation = toRotation;
+        updateDisplayInfoIfNeeded();
+
+        // Calculate the stack bounds in the new orientation based on same fraction along the
+        // rotated movement bounds.
+        final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
+                false /* adjustForIme */);
+        mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
+                snapFraction);
+        if (mIsMinimized) {
+            applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
+        }
+
+        try {
+            outBounds.set(postChangeStackBounds);
+            mLastDestinationBounds.set(outBounds);
+            mPinnedStackController.resetBoundsAnimation(outBounds);
+            mPinnedStackController.reportBounds(outBounds, getMovementBounds(outBounds));
+            t.setBounds(pinnedStackInfo.stackToken, outBounds);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to resize PiP on display rotation", e);
+        }
+        return true;
+    }
+
+    private void updateDisplayInfoIfNeeded() {
+        final boolean updateNeeded;
+        if ((mDisplayInfo.rotation == ROTATION_0) || (mDisplayInfo.rotation == ROTATION_180)) {
+            updateNeeded = (mDisplayInfo.logicalWidth > mDisplayInfo.logicalHeight);
+        } else {
+            updateNeeded = (mDisplayInfo.logicalWidth < mDisplayInfo.logicalHeight);
+        }
+        if (updateNeeded) {
+            final int newLogicalHeight = mDisplayInfo.logicalWidth;
+            mDisplayInfo.logicalWidth = mDisplayInfo.logicalHeight;
+            mDisplayInfo.logicalHeight = newLogicalHeight;
+        }
+    }
+
+    /**
      * @return whether the given {@param aspectRatio} is valid.
      */
     private boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java
similarity index 99%
rename from core/java/com/android/internal/policy/PipSnapAlgorithm.java
rename to packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java
index e3623c5..f3e707c 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipSnapAlgorithm.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.policy;
+package com.android.systemui.pip;
 
 import android.content.Context;
 import android.content.res.Configuration;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 583ce67..29de90b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -28,6 +28,7 @@
 import com.android.systemui.SystemUI;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.wm.DisplayWindowController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -44,15 +45,17 @@
     private final CommandQueue mCommandQueue;
     private BasePipManager mPipManager;
     private final BroadcastDispatcher mBroadcastDispatcher;
-
+    private final DisplayWindowController mDisplayWindowController;
     private boolean mSupportsPip;
 
     @Inject
     public PipUI(Context context, CommandQueue commandQueue,
-            BroadcastDispatcher broadcastDispatcher) {
+            BroadcastDispatcher broadcastDispatcher,
+            DisplayWindowController displayWindowController) {
         super(context);
         mBroadcastDispatcher = broadcastDispatcher;
         mCommandQueue = commandQueue;
+        mDisplayWindowController = displayWindowController;
     }
 
     @Override
@@ -72,7 +75,7 @@
         mPipManager = pm.hasSystemFeature(FEATURE_LEANBACK_ONLY)
                 ? com.android.systemui.pip.tv.PipManager.getInstance()
                 : com.android.systemui.pip.phone.PipManager.getInstance();
-        mPipManager.initialize(mContext, mBroadcastDispatcher);
+        mPipManager.initialize(mContext, mBroadcastDispatcher, mDisplayWindowController);
 
         mCommandQueue.addCallback(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index a4707cf..0a89017 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -34,6 +34,7 @@
 import android.util.Pair;
 import android.view.DisplayInfo;
 import android.view.IPinnedStackController;
+import android.view.WindowContainerTransaction;
 
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
@@ -45,6 +46,7 @@
 import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.wm.DisplayWindowController;
 
 import java.io.PrintWriter;
 
@@ -75,9 +77,22 @@
     private PipAppOpsListener mAppOpsListener;
 
     /**
+     * Handler for display rotation changes.
+     */
+    private final DisplayWindowController.OnDisplayWindowRotationController mRotationController = (
+            int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
+        final boolean changed = mPipBoundsHandler.onDisplayRotationChanged(mTmpNormalBounds,
+                displayId, fromRotation, toRotation, t);
+        if (changed) {
+            updateMovementBounds(mTmpNormalBounds, false /* fromImeAdjustment */,
+                    false /* fromShelfAdjustment */);
+        }
+    };
+
+    /**
      * Handler for system task stack changes.
      */
-    TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
+    private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
         @Override
         public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
             mTouchHandler.onActivityPinned();
@@ -214,7 +229,8 @@
     /**
      * Initializes {@link PipManager}.
      */
-    public void initialize(Context context, BroadcastDispatcher broadcastDispatcher) {
+    public void initialize(Context context, BroadcastDispatcher broadcastDispatcher,
+            DisplayWindowController displayWindowController) {
         mContext = context;
         mActivityManager = ActivityManager.getService();
         mActivityTaskManager = ActivityTaskManager.getService();
@@ -235,6 +251,7 @@
                 mMenuController, mInputConsumerController, mPipBoundsHandler);
         mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
                 mTouchHandler.getMotionHelper());
+        displayWindowController.addRotationController(mRotationController);
 
         // If SystemUI restart, and it already existed a pinned stack,
         // register the pip input consumer to ensure touch can send to it.
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index fa60477..6afa0bf 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -46,7 +46,7 @@
 
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
 import com.android.internal.os.SomeArgs;
-import com.android.internal.policy.PipSnapAlgorithm;
+import com.android.systemui.pip.PipSnapAlgorithm;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 2347a47..95e3444 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -46,9 +46,9 @@
 import android.view.accessibility.AccessibilityWindowInfo;
 
 import com.android.internal.os.logging.MetricsLoggerWrapper;
-import com.android.internal.policy.PipSnapAlgorithm;
 import com.android.systemui.R;
 import com.android.systemui.pip.PipBoundsHandler;
+import com.android.systemui.pip.PipSnapAlgorithm;
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 195fca8..696db68 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -55,6 +55,7 @@
 import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.wm.DisplayWindowController;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -228,7 +229,8 @@
     /**
      * Initializes {@link PipManager}.
      */
-    public void initialize(Context context, BroadcastDispatcher broadcastDispatcher) {
+    public void initialize(Context context, BroadcastDispatcher broadcastDispatcher,
+            DisplayWindowController displayWindowController) {
         if (mInitialized) {
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
index ae82115..aa56ffb 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
@@ -101,10 +101,11 @@
                             }
                             DisplayRecord record = new DisplayRecord();
                             record.mDisplayId = displayId;
-                            Display display = getDisplay(displayId);
-                            record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
-                                    : mContext.createDisplayContext(display);
-                            record.mDisplayLayout = new DisplayLayout(record.mContext, display);
+                            // TODO(b/146566787): disabled for MultiDisplayActivityLaunchTests
+                            // Display display = getDisplay(displayId);
+                            // record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
+                            //         : mContext.createDisplayContext(display);
+                            // record.mDisplayLayout = new DisplayLayout(record.mContext, display);
                             mDisplays.put(displayId, record);
                             for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
                                 mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
@@ -123,13 +124,14 @@
                                         + " display.");
                                 return;
                             }
-                            Display display = getDisplay(displayId);
-                            Context perDisplayContext = mContext;
-                            if (displayId != Display.DEFAULT_DISPLAY) {
-                                perDisplayContext = mContext.createDisplayContext(display);
-                            }
-                            dr.mContext = perDisplayContext.createConfigurationContext(newConfig);
-                            dr.mDisplayLayout = new DisplayLayout(dr.mContext, display);
+                            // TODO(b/146566787): disabled for MultiDisplaySystemDecorationTests
+                            // Display display = getDisplay(displayId);
+                            // Context perDisplayContext = mContext;
+                            // if (displayId != Display.DEFAULT_DISPLAY) {
+                            //     perDisplayContext = mContext.createDisplayContext(display);
+                            // }
+                            // dr.mContext = perDisplayContext.createConfigurationContext(newConfig);
+                            // dr.mDisplayLayout = new DisplayLayout(dr.mContext, display);
                             for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
                                 mDisplayChangedListeners.get(i).onDisplayConfigurationChanged(
                                         displayId, newConfig);
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index d2f1113..78f278e 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -63,6 +63,9 @@
     public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 10;
     public static final int PACKAGE_APP_PREDICTOR = 11;
     public static final int PACKAGE_TELEPHONY = 12;
+    public static final int PACKAGE_WIFI = 13;
+    public static final int PACKAGE_COMPANION = 14;
+
     @IntDef(value = {
         PACKAGE_SYSTEM,
         PACKAGE_SETUP_WIZARD,
@@ -77,6 +80,8 @@
         PACKAGE_INCIDENT_REPORT_APPROVER,
         PACKAGE_APP_PREDICTOR,
         PACKAGE_TELEPHONY,
+        PACKAGE_WIFI,
+        PACKAGE_COMPANION,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface KnownPackage {}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 335cac8..21cecc2 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -310,7 +310,8 @@
         7,  // STREAM_SYSTEM_ENFORCED
         15, // STREAM_DTMF
         15, // STREAM_TTS
-        15  // STREAM_ACCESSIBILITY
+        15, // STREAM_ACCESSIBILITY
+        15  // STREAM_ASSISTANT
     };
 
     /** Minimum volume index values for audio streams */
@@ -325,7 +326,8 @@
         0,  // STREAM_SYSTEM_ENFORCED
         0,  // STREAM_DTMF
         0,  // STREAM_TTS
-        1   // STREAM_ACCESSIBILITY
+        1,  // STREAM_ACCESSIBILITY
+        0   // STREAM_ASSISTANT
     };
 
     /* mStreamVolumeAlias[] indicates for each stream if it uses the volume settings
@@ -348,7 +350,8 @@
         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
         AudioSystem.STREAM_RING,            // STREAM_DTMF
         AudioSystem.STREAM_MUSIC,           // STREAM_TTS
-        AudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY
+        AudioSystem.STREAM_MUSIC,           // STREAM_ACCESSIBILITY
+        AudioSystem.STREAM_MUSIC            // STREAM_ASSISTANT
     };
     private final int[] STREAM_VOLUME_ALIAS_TELEVISION = new int[] {
         AudioSystem.STREAM_MUSIC,       // STREAM_VOICE_CALL
@@ -361,7 +364,8 @@
         AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM_ENFORCED
         AudioSystem.STREAM_MUSIC,       // STREAM_DTMF
         AudioSystem.STREAM_MUSIC,       // STREAM_TTS
-        AudioSystem.STREAM_MUSIC        // STREAM_ACCESSIBILITY
+        AudioSystem.STREAM_MUSIC,       // STREAM_ACCESSIBILITY
+        AudioSystem.STREAM_MUSIC        // STREAM_ASSISTANT
     };
     private final int[] STREAM_VOLUME_ALIAS_DEFAULT = new int[] {
         AudioSystem.STREAM_VOICE_CALL,      // STREAM_VOICE_CALL
@@ -374,7 +378,8 @@
         AudioSystem.STREAM_RING,            // STREAM_SYSTEM_ENFORCED
         AudioSystem.STREAM_RING,            // STREAM_DTMF
         AudioSystem.STREAM_MUSIC,           // STREAM_TTS
-        AudioSystem.STREAM_MUSIC            // STREAM_ACCESSIBILITY
+        AudioSystem.STREAM_MUSIC,           // STREAM_ACCESSIBILITY
+        AudioSystem.STREAM_MUSIC            // STREAM_ASSISTANT
     };
     protected static int[] mStreamVolumeAlias;
 
@@ -394,6 +399,7 @@
         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_DTMF
         AppOpsManager.OP_AUDIO_MEDIA_VOLUME,            // STREAM_TTS
         AppOpsManager.OP_AUDIO_ACCESSIBILITY_VOLUME,    // STREAM_ACCESSIBILITY
+        AppOpsManager.OP_AUDIO_MEDIA_VOLUME             // STREAM_ASSISTANT
     };
 
     private final boolean mUseFixedVolume;
@@ -1253,6 +1259,9 @@
         int dtmfStreamAlias;
         final int a11yStreamAlias = sIndependentA11yVolume ?
                 AudioSystem.STREAM_ACCESSIBILITY : AudioSystem.STREAM_MUSIC;
+        final int assistantStreamAlias = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_useAssistantVolume) ?
+                AudioSystem.STREAM_ASSISTANT : AudioSystem.STREAM_MUSIC;
 
         if (mIsSingleVolume) {
             mStreamVolumeAlias = STREAM_VOLUME_ALIAS_TELEVISION;
@@ -1282,6 +1291,7 @@
 
         mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias;
         mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY] = a11yStreamAlias;
+        mStreamVolumeAlias[AudioSystem.STREAM_ASSISTANT] = assistantStreamAlias;
 
         if (updateVolumes && mStreamStates != null) {
             updateDefaultVolumes();
@@ -1808,6 +1818,17 @@
             return;
         }
 
+        // If the stream is STREAM_ASSISTANT,
+        // make sure that the calling app have the MODIFY_AUDIO_ROUTING permission.
+        if (streamType == AudioSystem.STREAM_ASSISTANT &&
+            mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+                    != PackageManager.PERMISSION_GRANTED) {
+            Log.w(TAG, "MODIFY_AUDIO_ROUTING Permission Denial: adjustStreamVolume from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
         // use stream type alias here so that streams with same alias have the same behavior,
         // including with regard to silent mode control (e.g the use of STREAM_RING below and in
         // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
@@ -2244,6 +2265,14 @@
                     + " MODIFY_PHONE_STATE  callingPackage=" + callingPackage);
             return;
         }
+        if ((streamType == AudioManager.STREAM_ASSISTANT)
+            && (mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.MODIFY_AUDIO_ROUTING)
+                    != PackageManager.PERMISSION_GRANTED)) {
+            Log.w(TAG, "Trying to call setStreamVolume() for STREAM_ASSISTANT without"
+                    + " MODIFY_AUDIO_ROUTING  callingPackage=" + callingPackage);
+            return;
+        }
         sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
                 index/*val1*/, flags/*val2*/, callingPackage));
         setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cb362b0..0e9199f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -96,6 +96,8 @@
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
 import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
+import static com.android.internal.util.ArrayUtils.emptyIfNull;
+import static com.android.internal.util.ArrayUtils.filter;
 import static com.android.server.pm.ComponentResolver.RESOLVE_PRIORITY_SORTER;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
@@ -249,7 +251,6 @@
 import android.os.storage.VolumeRecord;
 import android.permission.IPermissionManager;
 import android.provider.DeviceConfig;
-import android.provider.MediaStore;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
 import android.security.KeyStore;
@@ -385,6 +386,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 /**
@@ -16629,37 +16631,48 @@
                 + " Activities needs verification ...");
 
         int count = 0;
-
+        boolean handlesWebUris = false;
+        final boolean alreadyVerified;
         synchronized (mLock) {
             // If this is a new install and we see that we've already run verification for this
             // package, we have nothing to do: it means the state was restored from backup.
-            if (!replacing) {
-                IntentFilterVerificationInfo ivi =
-                        mSettings.getIntentFilterVerificationLPr(packageName);
-                if (ivi != null) {
-                    if (DEBUG_DOMAIN_VERIFICATION) {
-                        Slog.i(TAG, "Package " + packageName+ " already verified: status="
-                                + ivi.getStatusString());
-                    }
-                    return;
+            final IntentFilterVerificationInfo ivi =
+                    mSettings.getIntentFilterVerificationLPr(packageName);
+            alreadyVerified = (ivi != null);
+            if (!replacing && alreadyVerified) {
+                if (DEBUG_DOMAIN_VERIFICATION) {
+                    Slog.i(TAG, "Package " + packageName + " already verified: status="
+                            + ivi.getStatusString());
                 }
+                return;
             }
 
-            // If any filters need to be verified, then all need to be.
+            // If any filters need to be verified, then all need to be.  In addition, we need to
+            // know whether an updating app has any web navigation intent filters, to re-
+            // examine handling policy even if not re-verifying.
             boolean needToVerify = false;
             for (ParsedActivity a : activities) {
                 for (ParsedActivityIntentInfo filter : a.intents) {
+                    if (filter.handlesWebUris(true)) {
+                        handlesWebUris = true;
+                    }
                     if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
                         if (DEBUG_DOMAIN_VERIFICATION) {
                             Slog.d(TAG,
                                     "Intent filter needs verification, so processing all filters");
                         }
                         needToVerify = true;
+                        // It's safe to break out here because filter.needsVerification()
+                        // can only be true if filter.handlesWebUris(true) returns true, so
+                        // we've already noted that.
                         break;
                     }
                 }
             }
 
+            // Note whether this app publishes any web navigation handling support at all,
+            // and whether there are any web-nav filters that fit the profile for running
+            // a verification pass now.
             if (needToVerify) {
                 final int verificationId = mIntentFilterVerificationToken++;
                 for (ParsedActivity a : activities) {
@@ -16677,13 +16690,23 @@
         }
 
         if (count > 0) {
+            // count > 0 means that we're running a full verification pass
             if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
                     + " IntentFilter verification" + (count > 1 ? "s" : "")
                     +  " for userId:" + userId);
             mIntentFilterVerifier.startVerifications(userId);
+        } else if (alreadyVerified && handlesWebUris) {
+            // App used autoVerify in the past, no longer does, but still handles web
+            // navigation starts.
+            if (DEBUG_DOMAIN_VERIFICATION) {
+                Slog.d(TAG, "App changed web filters but no longer verifying - resetting policy");
+            }
+            synchronized (mLock) {
+                clearIntentFilterVerificationsLPw(packageName, userId);
+            }
         } else {
             if (DEBUG_DOMAIN_VERIFICATION) {
-                Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
+                Slog.d(TAG, "No web filters or no prior verify policy for " + packageName);
             }
         }
     }
@@ -19261,6 +19284,18 @@
         return ensureSystemPackageName(appPredictionServiceComponentName.getPackageName());
     }
 
+    private @NonNull String[] dropNonSystemPackages(@NonNull String[] pkgNames) {
+        return emptyIfNull(filter(pkgNames, String[]::new, mIsSystemPackage), String.class);
+    }
+
+    private Predicate<String> mIsSystemPackage = (pkgName) -> {
+        if ("android".equals(pkgName)) {
+            return true;
+        }
+        AndroidPackage pkg = mPackages.get(pkgName);
+        return pkg != null && pkg.isSystem();
+    };
+
     @Override
     public String getSystemCaptionsServicePackageName() {
         String flattenedSystemCaptionsServiceComponentName =
@@ -22539,7 +22574,11 @@
 
         @Override
         public @NonNull String[] getKnownPackageNames(int knownPackage, int userId) {
-            switch (knownPackage) {
+            return dropNonSystemPackages(getKnownPackageNamesInternal(knownPackage, userId));
+        }
+
+        private String[] getKnownPackageNamesInternal(int knownPackage, int userId) {
+            switch(knownPackage) {
                 case PackageManagerInternal.PACKAGE_BROWSER:
                     return new String[]{mPermissionManager.getDefaultBrowser(userId)};
                 case PackageManagerInternal.PACKAGE_INSTALLER:
@@ -22566,6 +22605,8 @@
                     return filterOnlySystemPackages(mAppPredictionServicePackage);
                 case PackageManagerInternal.PACKAGE_TELEPHONY:
                     return filterOnlySystemPackages(mTelephonyPackages);
+                case PackageManagerInternal.PACKAGE_COMPANION:
+                    return filterOnlySystemPackages("com.android.companiondevicemanager");
                 default:
                     return ArrayUtils.emptyArray(String.class);
             }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 6653011..9642a1a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1249,6 +1249,7 @@
             return false;
         }
         ps.clearDomainVerificationStatusForUser(userId);
+        ps.setIntentFilterVerificationInfo(null);
         return true;
     }
 
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 05545cd..565a85f 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -280,6 +280,9 @@
     public boolean isTelephony() {
         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_TELEPHONY) != 0;
     }
+    public boolean isCompanion() {
+        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_COMPANION) != 0;
+    }
 
     public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
         if (!origPackageName.equals(sourcePackageName)) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 7580a30..a6ba77c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -3330,6 +3330,13 @@
                 // Special permissions for the system telephony apps.
                 allowed = true;
             }
+            if (!allowed && bp.isCompanion()
+                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
+                        PackageManagerInternal.PACKAGE_COMPANION, UserHandle.USER_SYSTEM),
+                    pkg.getPackageName())) {
+                // Special permissions for the system companion device manager.
+                allowed = true;
+            }
         }
         return allowed;
     }
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index a741d45..62dd7bb 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -821,10 +821,7 @@
         // Update bounds if applicable
         boolean hasNewOverrideBounds = false;
         // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
-        if (overrideWindowingMode == WINDOWING_MODE_PINNED) {
-            // Pinned calculation already includes rotation
-            hasNewOverrideBounds = calculatePinnedBoundsForConfigChange(newBounds);
-        } else if (!matchParentBounds()) {
+        if ((overrideWindowingMode != WINDOWING_MODE_PINNED) && !matchParentBounds()) {
             // If the parent (display) has rotated, rotate our bounds to best-fit where their
             // bounds were on the pre-rotated display.
             final int newRotation = getWindowConfiguration().getRotation();
@@ -882,9 +879,6 @@
                         null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
                         null /* tempOtherTaskBounds */, null /* tempOtherTaskInsetBounds */,
                         PRESERVE_WINDOWS, true /* deferResume */);
-            } else {
-                resize(new Rect(newBounds), null /* tempTaskBounds */,
-                        null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, true /* deferResume */);
             }
         }
         if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
@@ -4089,45 +4083,27 @@
     }
 
     /**
-     * Updates the passed-in {@code inOutBounds} based on the current state of the
-     * pinned controller. This gets run *after* the override configuration is updated, so it's
-     * safe to rely on the controller's state in here (though eventually this dependence should
-     * be removed).
+     * Reset the current animation running on {@link #mBoundsAnimationTarget}.
      *
-     * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
-     * update pinned controller state.
-     *
-     * @param inOutBounds the bounds to update (both input and output).
-     * @return true if bounds were updated to some non-empty value.
+     * @param destinationBounds the final destination bounds
      */
-    boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) {
-        boolean animating = false;
-        if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
-            animating = true;
-            getFinalAnimationBounds(mTmpRect2);
-        } else {
-            mTmpRect2.set(inOutBounds);
-        }
-        boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
-                mTmpRect2, mTmpRect3);
-        if (updated) {
-            inOutBounds.set(mTmpRect3);
+    void resetCurrentBoundsAnimation(Rect destinationBounds) {
+        boolean animating = (mBoundsAnimatingRequested || mBoundsAnimating)
+                && !mBoundsAnimationTarget.isEmpty();
 
-            // The final boundary is updated while there is an existing boundary animation. Let's
-            // cancel this animation to prevent the obsolete animation overwritten updated bounds.
-            if (animating && !inOutBounds.equals(mBoundsAnimationTarget)) {
-                final DisplayContent displayContent = getDisplayContent();
-                displayContent.mBoundsAnimationController.getHandler().post(() ->
-                        displayContent.mBoundsAnimationController.cancel(this));
-            }
-            // Once we've set the bounds based on the rotation of the old bounds in the new
-            // orientation, clear the animation target bounds since they are obsolete, and
-            // cancel any currently running animations
-            mBoundsAnimationTarget.setEmpty();
-            mBoundsAnimationSourceHintBounds.setEmpty();
-            mCancelCurrentBoundsAnimation = true;
+        // The final boundary is updated while there is an existing boundary animation. Let's
+        // cancel this animation to prevent the obsolete animation overwritten updated bounds.
+        if (animating && !destinationBounds.equals(mBoundsAnimationTarget)) {
+            final BoundsAnimationController controller =
+                    getDisplayContent().mBoundsAnimationController;
+            controller.getHandler().post(() -> controller.cancel(this));
         }
-        return updated;
+        // Once we've set the bounds based on the rotation of the old bounds in the new
+        // orientation, clear the animation target bounds since they are obsolete, and
+        // cancel any currently running animations
+        mBoundsAnimationTarget.setEmpty();
+        mBoundsAnimationSourceHintBounds.setEmpty();
+        mCancelCurrentBoundsAnimation = true;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 674955e..6ad439e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -51,7 +51,6 @@
 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
@@ -1688,19 +1687,9 @@
             return START_SUCCESS;
         }
 
-        // True if we are clearing top and resetting of a standard (default) launch mode
-        // ({@code LAUNCH_MULTIPLE}) activity. The existing activity will be finished.
-        final boolean clearTopAndResetStandardLaunchMode =
-                (mLaunchFlags & (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED))
-                        == (FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
-                        && mLaunchMode == LAUNCH_MULTIPLE;
-
         boolean clearTaskForReuse = false;
         if (reusedTask != null) {
-            // If mStartActivity does not have a task associated with it, associate it with the
-            // reused activity's task. Do not do so if we're clearing top and resetting for a
-            // standard launchMode activity.
-            if (mStartActivity.getTask() == null && !clearTopAndResetStandardLaunchMode) {
+            if (mStartActivity.getTask() == null) {
                 mStartActivity.setTaskForReuse(reusedTask);
                 clearTaskForReuse = true;
             }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index e02456e..45b4818 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3302,6 +3302,23 @@
         Configuration c = new Configuration(container.getRequestedOverrideConfiguration());
         c.setTo(change.getConfiguration(), configMask, windowMask);
         container.onRequestedOverrideConfigurationChanged(c);
+        // TODO(b/145675353): remove the following once we could apply new bounds to the
+        // pinned stack together with its children.
+        resizePinnedStackIfNeeded(container, configMask, windowMask, c);
+    }
+
+    private void resizePinnedStackIfNeeded(ConfigurationContainer container, int configMask,
+            int windowMask, Configuration config) {
+        if ((container instanceof ActivityStack)
+                && ((configMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0)
+                && ((windowMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS) != 0)) {
+            final ActivityStack stack = (ActivityStack) container;
+            if (stack.inPinnedWindowingMode()) {
+                stack.resize(config.windowConfiguration.getBounds(),
+                        null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
+                        PRESERVE_WINDOWS, true /* deferResume */);
+            }
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 5dc88b3..9b464c2 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -185,6 +185,10 @@
             resume();
         };
 
+        // If this animator is explicitly cancelled when it's in paused state, we should not
+        // attempt to resume the animation. Use this flag to avoid such behavior.
+        private boolean mIsCancelled;
+
         BoundsAnimator(BoundsAnimationTarget target, @AnimationType int animationType, Rect from,
                 Rect to, @SchedulePipModeChangedState int schedulePipModeChangedState,
                 @SchedulePipModeChangedState int prevShedulePipModeChangedState,
@@ -221,6 +225,7 @@
             if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
                     + " mPrevSchedulePipModeChangedState=" + mPrevSchedulePipModeChangedState
                     + " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState);
+            mIsCancelled = false;
             mFinishAnimationAfterTransition = false;
             mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth,
                     mFrom.top + mFrozenTaskHeight);
@@ -293,7 +298,7 @@
         public void resume() {
             if (DEBUG) Slog.d(TAG, "resume:");
             mHandler.removeCallbacks(mResumeRunnable);
-            super.resume();
+            if (!mIsCancelled) super.resume();
         }
 
         @Override
@@ -376,6 +381,7 @@
 
         @Override
         public void onAnimationCancel(Animator animation) {
+            mIsCancelled = true;
             // Always skip the final resize when the animation is canceled
             mSkipFinalResize = true;
             mMoveToFullscreen = false;
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index a8e7aea..b4f75e5 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -16,38 +16,29 @@
 
 package com.android.server.wm;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.util.TypedValue.COMPLEX_UNIT_DIP;
 
 import static com.android.server.wm.PinnedStackControllerProto.DEFAULT_BOUNDS;
 import static com.android.server.wm.PinnedStackControllerProto.MOVEMENT_BOUNDS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
-import android.annotation.NonNull;
 import android.app.RemoteAction;
 import android.content.ComponentName;
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
-import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.util.Log;
-import android.util.Size;
 import android.util.Slog;
-import android.util.TypedValue;
 import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
-import android.view.Gravity;
 import android.view.IPinnedStackController;
 import android.view.IPinnedStackListener;
 
-import com.android.internal.policy.PipSnapAlgorithm;
-import com.android.internal.util.Preconditions;
 import com.android.server.UiThread;
 
 import java.io.PrintWriter;
@@ -74,7 +65,6 @@
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "PinnedStackController" : TAG_WM;
 
-    private static final float INVALID_SNAP_FRACTION = -1f;
     private final WindowManagerService mService;
     private final DisplayContent mDisplayContent;
     private final Handler mHandler = UiThread.getHandler();
@@ -84,7 +74,6 @@
             new PinnedStackListenerDeathHandler();
 
     private final PinnedStackControllerCallback mCallbacks = new PinnedStackControllerCallback();
-    private final PipSnapAlgorithm mSnapAlgorithm;
 
     // States that affect how the PIP can be manipulated
     private boolean mIsMinimized;
@@ -97,13 +86,9 @@
 
     // Used to calculate stack bounds across rotations
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
-    private final Rect mStableInsets = new Rect();
 
     // The size and position information that describes where the pinned stack will go by default.
-    private int mDefaultMinSize;
-    private int mDefaultStackGravity;
     private float mDefaultAspectRatio;
-    private Point mScreenEdgeInsets;
 
     // The aspect ratio bounds of the PIP.
     private float mMinAspectRatio;
@@ -111,10 +96,11 @@
 
     // Temp vars for calculation
     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
-    private final Rect mTmpInsets = new Rect();
-    private final Rect mTmpRect = new Rect();
-    private final Point mTmpDisplaySize = new Point();
 
+    // TODO(b/141200935): remove this when we have default/movement bounds tests in SysUI.
+    // Keep record of the default and movement bounds
+    private final Rect mLastReportedDefaultBounds = new Rect();
+    private final Rect mLastReportedMovementBounds = new Rect();
 
     /**
      * The callback object passed to listeners for them to notify the controller of state changes.
@@ -125,7 +111,6 @@
         public void setIsMinimized(final boolean isMinimized) {
             mHandler.post(() -> {
                 mIsMinimized = isMinimized;
-                mSnapAlgorithm.setMinimized(isMinimized);
             });
         }
 
@@ -145,6 +130,27 @@
                         sourceRectHint, animationDuration, true /* fromFullscreen */);
             }
         }
+
+        @Override
+        public void resetBoundsAnimation(Rect bounds) {
+            synchronized (mService.mGlobalLock) {
+                if (mDisplayContent.hasPinnedStack()) {
+                    final ActivityStack pinnedStack = mDisplayContent.getTopStackInWindowingMode(
+                            WINDOWING_MODE_PINNED);
+                    if (pinnedStack != null) {
+                        pinnedStack.resetCurrentBoundsAnimation(bounds);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void reportBounds(Rect defaultBounds, Rect movementBounds) {
+            synchronized (mService.mGlobalLock) {
+                mLastReportedDefaultBounds.set(defaultBounds);
+                mLastReportedMovementBounds.set(movementBounds);
+            }
+        }
     }
 
     /**
@@ -165,7 +171,6 @@
     PinnedStackController(WindowManagerService service, DisplayContent displayContent) {
         mService = service;
         mDisplayContent = displayContent;
-        mSnapAlgorithm = new PipSnapAlgorithm(service.mContext);
         mDisplayInfo.copyFrom(mDisplayContent.getDisplayInfo());
         reloadResources();
         // Initialize the aspect ratio to the default aspect ratio.  Don't do this in reload
@@ -183,21 +188,9 @@
      */
     private void reloadResources() {
         final Resources res = mService.mContext.getResources();
-        mDefaultMinSize = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
         mDefaultAspectRatio = res.getFloat(
                 com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
-        final String screenEdgeInsetsDpString = res.getString(
-                com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
-        final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
-                ? Size.parseSize(screenEdgeInsetsDpString)
-                : null;
-        mDefaultStackGravity = res.getInteger(
-                com.android.internal.R.integer.config_defaultPictureInPictureGravity);
         mDisplayContent.getDisplay().getRealMetrics(mTmpMetrics);
-        mScreenEdgeInsets = screenEdgeInsetsDp == null ? new Point()
-                : new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
-                        dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
         mMinAspectRatio = res.getFloat(
                 com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
         mMaxAspectRatio = res.getFloat(
@@ -215,7 +208,7 @@
             notifyDisplayInfoChanged(mDisplayInfo);
             notifyImeVisibilityChanged(mIsImeShowing, mImeHeight);
             // The movement bounds notification needs to be sent before the minimized state, since
-            // SystemUI may use the bounds to retore the minimized position
+            // SystemUI may use the bounds to restore the minimized position
             notifyMovementBoundsChanged(false /* fromImeAdjustment */,
                     false /* fromShelfAdjustment */);
             notifyActionsChanged(mActions);
@@ -257,30 +250,6 @@
         }
     }
 
-    /**
-     * @return the default bounds to show the PIP, if a {@param snapFraction} is provided, then it
-     * will apply the default bounds to the provided snap fraction.
-     */
-    private Rect getDefaultBounds(float snapFraction) {
-        synchronized (mService.mGlobalLock) {
-            final Rect insetBounds = new Rect();
-            getInsetBounds(insetBounds);
-
-            final Rect defaultBounds = new Rect();
-            final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio,
-                    mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
-            if (snapFraction != INVALID_SNAP_FRACTION) {
-                defaultBounds.set(0, 0, size.getWidth(), size.getHeight());
-                final Rect movementBounds = getMovementBounds(defaultBounds);
-                mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
-            } else {
-                Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
-                        0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
-            }
-            return defaultBounds;
-        }
-    }
-
     private void setDisplayInfo(DisplayInfo displayInfo) {
         mDisplayInfo.copyFrom(displayInfo);
         notifyDisplayInfoChanged(mDisplayInfo);
@@ -300,51 +269,6 @@
     }
 
     /**
-     * Updates the display info, calculating and returning the new stack and movement bounds in the
-     * new orientation of the device if necessary.
-     */
-    boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
-        synchronized (mService.mGlobalLock) {
-            final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
-            if (isSameDimensionAndRotation(mDisplayInfo, displayInfo)) {
-                // No dimension/rotation change, ignore
-                outBounds.setEmpty();
-                return false;
-            } else if (targetBounds.isEmpty()) {
-                // The stack is null, we are just initializing the stack, so just store the display
-                // info and ignore
-                setDisplayInfo(displayInfo);
-                outBounds.setEmpty();
-                return false;
-            }
-
-            mTmpRect.set(targetBounds);
-            final Rect postChangeStackBounds = mTmpRect;
-
-            // Calculate the snap fraction of the current stack along the old movement bounds
-            final float snapFraction = getSnapFraction(postChangeStackBounds);
-
-            setDisplayInfo(displayInfo);
-
-            // Calculate the stack bounds in the new orientation to the same same fraction along the
-            // rotated movement bounds.
-            final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
-                    false /* adjustForIme */);
-            mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
-                    snapFraction);
-            if (mIsMinimized) {
-                applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
-            }
-
-            notifyMovementBoundsChanged(false /* fromImeAdjustment */,
-                    false /* fromShelfAdjustment */);
-
-            outBounds.set(postChangeStackBounds);
-            return true;
-        }
-    }
-
-    /**
      * Sets the Ime state and height.
      */
     void setAdjustedForIme(boolean adjustedForIme, int imeHeight) {
@@ -400,15 +324,6 @@
         notifyPrepareAnimation(sourceRectHint, aspectRatio, stackBounds);
     }
 
-    private boolean isSameDimensionAndRotation(@NonNull DisplayInfo display1,
-            @NonNull DisplayInfo display2) {
-        Preconditions.checkNotNull(display1);
-        Preconditions.checkNotNull(display2);
-        return ((display1.rotation == display2.rotation)
-                && (display1.logicalWidth == display2.logicalWidth)
-                && (display1.logicalHeight == display2.logicalHeight));
-    }
-
     /**
      * Notifies listeners that the PIP needs to be adjusted for the IME.
      */
@@ -504,86 +419,11 @@
         }
     }
 
-    /**
-     * @return the bounds on the screen that the PIP can be visible in.
-     */
-    private void getInsetBounds(Rect outRect) {
-        synchronized (mService.mGlobalLock) {
-            mDisplayContent.getDisplayPolicy().getStableInsetsLw(mDisplayInfo.rotation,
-                    mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
-                    mDisplayInfo.displayCutout, mTmpInsets);
-            outRect.set(mTmpInsets.left + mScreenEdgeInsets.x, mTmpInsets.top + mScreenEdgeInsets.y,
-                    mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
-                    mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
-        }
-    }
-
-    /**
-     * @return the movement bounds for the given {@param stackBounds} and the current state of the
-     *         controller.
-     */
-    private Rect getMovementBounds(Rect stackBounds) {
-        synchronized (mService.mGlobalLock) {
-            return getMovementBounds(stackBounds, true /* adjustForIme */);
-        }
-    }
-
-    /**
-     * @return the movement bounds for the given {@param stackBounds} and the current state of the
-     *         controller.
-     */
-    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
-        synchronized (mService.mGlobalLock) {
-            final Rect movementBounds = new Rect();
-            getInsetBounds(movementBounds);
-
-            // Apply the movement bounds adjustments based on the current state.
-            // Note that shelf offset does not affect the movement bounds here
-            // since it's been taken care of in system UI.
-            mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
-                    (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
-            return movementBounds;
-        }
-    }
-
-    /**
-     * Applies the minimized offsets to the given stack bounds.
-     */
-    private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
-        synchronized (mService.mGlobalLock) {
-            mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
-            mService.getStableInsetsLocked(mDisplayContent.getDisplayId(), mStableInsets);
-            mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
-                    mStableInsets);
-        }
-    }
-
-    /**
-     * @return the default snap fraction to apply instead of the default gravity when calculating
-     *         the default stack bounds when first entering PiP.
-     */
-    private float getSnapFraction(Rect stackBounds) {
-        return mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds));
-    }
-
-    /**
-     * @return the pixels for a given dp value.
-     */
-    private int dpToPx(float dpValue, DisplayMetrics dm) {
-        return (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, dpValue, dm);
-    }
-
     void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "PinnedStackController");
-        pw.print(prefix + "  defaultBounds=");
-        getDefaultBounds(INVALID_SNAP_FRACTION).printShortString(pw);
-        pw.println();
-        pw.println(prefix + "  mDefaultMinSize=" + mDefaultMinSize);
-        pw.println(prefix + "  mDefaultStackGravity=" + mDefaultStackGravity);
+        pw.println(prefix + "  mLastReportedDefaultBounds=" + mLastReportedDefaultBounds);
+        pw.println(prefix + "  mLastReportedMovementBounds=" + mLastReportedMovementBounds);
         pw.println(prefix + "  mDefaultAspectRatio=" + mDefaultAspectRatio);
-        mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect);
-        pw.print(prefix + "  movementBounds="); getMovementBounds(mTmpRect).printShortString(pw);
-        pw.println();
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
         pw.println(prefix + "  mImeHeight=" + mImeHeight);
         pw.println(prefix + "  mIsMinimized=" + mIsMinimized);
@@ -606,9 +446,8 @@
 
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
-        getDefaultBounds(INVALID_SNAP_FRACTION).dumpDebug(proto, DEFAULT_BOUNDS);
-        mService.getStackBounds(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mTmpRect);
-        getMovementBounds(mTmpRect).dumpDebug(proto, MOVEMENT_BOUNDS);
+        mLastReportedDefaultBounds.dumpDebug(proto, DEFAULT_BOUNDS);
+        mLastReportedMovementBounds.dumpDebug(proto, MOVEMENT_BOUNDS);
         proto.end(token);
     }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 8cd803c..eda69a9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -254,6 +254,7 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
+import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.Preconditions;
@@ -2105,6 +2106,10 @@
              Binder.withCleanCallingIdentity(action);
         }
 
+        final <T> T binderWithCleanCallingIdentity(@NonNull ThrowingSupplier<T> action) {
+            return Binder.withCleanCallingIdentity(action);
+        }
+
         final int userHandleGetCallingUserId() {
             return UserHandle.getUserId(binderGetCallingUid());
         }
@@ -2369,12 +2374,7 @@
      * @return
      */
     DevicePolicyData getUserDataUnchecked(int userHandle) {
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
-            return getUserData(userHandle);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        return mInjector.binderWithCleanCallingIdentity(() -> getUserData(userHandle));
     }
 
     void removeUserData(int userHandle) {
@@ -2691,8 +2691,7 @@
             alarmTime = now + alarmInterval;
         }
 
-        long token = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             int affectedUserHandle = parent ? getProfileParentId(userHandle) : userHandle;
             AlarmManager am = mInjector.getAlarmManager();
             PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
@@ -2703,9 +2702,7 @@
             if (alarmTime != 0) {
                 am.set(AlarmManager.RTC, alarmTime, pi);
             }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        });
     }
 
     ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
@@ -3269,12 +3266,8 @@
     private void sendChangedNotification(int userHandle) {
         Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
         intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
-            mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        mInjector.binderWithCleanCallingIdentity(() ->
+                mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle)));
     }
 
     private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
@@ -3842,8 +3835,7 @@
                 /* throwForMissingPermission= */ true);
         synchronized (getLockObject()) {
             checkActiveAdminPrecondition(adminReceiver, info, policy);
-            long ident = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 final ActiveAdmin existingAdmin
                         = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
                 if (!refreshing && existingAdmin != null) {
@@ -3874,9 +3866,7 @@
                 saveSettingsLocked(userHandle);
                 sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
                         onEnableData, null);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
         }
     }
 
@@ -4058,8 +4048,7 @@
         }
         Preconditions.checkNotNull(adminReceiver, "ComponentName is null");
         enforceShell("forceRemoveActiveAdmin");
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             synchronized (getLockObject()) {
                 if (!isAdminTestOnlyLocked(adminReceiver, userHandle)) {
                     throw new SecurityException("Attempt to remove non-test admin "
@@ -4079,9 +4068,7 @@
             // Remove the admin skipping sending the broadcast.
             removeAdminArtifacts(adminReceiver, userHandle);
             Slog.i(LOG_TAG, "Admin " + adminReceiver + " removed from user " + userHandle);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
     private void clearDeviceOwnerUserRestrictionLocked(UserHandle userHandle) {
@@ -4156,12 +4143,8 @@
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
             }
-            long ident = mInjector.binderClearCallingIdentity();
-            try {
-                removeActiveAdminLocked(adminReceiver, userHandle);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            mInjector.binderWithCleanCallingIdentity(() ->
+                    removeActiveAdminLocked(adminReceiver, userHandle));
         }
     }
 
@@ -4187,8 +4170,7 @@
         synchronized (getLockObject()) {
             ActiveAdmin ap = getActiveAdminForCallerLocked(
                     who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
-            final long ident = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 final PasswordPolicy passwordPolicy = ap.mPasswordPolicy;
                 if (passwordPolicy.quality != quality) {
                     passwordPolicy.quality = quality;
@@ -4198,9 +4180,7 @@
                     saveSettingsLocked(userId);
                 }
                 maybeLogPasswordComplexitySet(who, userId, parent, passwordPolicy);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_PASSWORD_QUALITY)
@@ -4387,12 +4367,8 @@
     }
 
     private boolean isSeparateProfileChallengeEnabled(int userHandle) {
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
-            return mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        return mInjector.binderWithCleanCallingIdentity(() ->
+                mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle));
     }
 
     @Override
@@ -5129,12 +5105,7 @@
     }
 
     private UserInfo getUserInfo(@UserIdInt int userId) {
-        final long token = mInjector.binderClearCallingIdentity();
-        try {
-            return mUserManager.getUserInfo(userId);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        return mInjector.binderWithCleanCallingIdentity(() -> mUserManager.getUserInfo(userId));
     }
 
     private boolean setPasswordPrivileged(@NonNull String password, int flags, int callingUid) {
@@ -5259,12 +5230,7 @@
     }
 
     private boolean isLockScreenSecureUnchecked(int userId) {
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
-            return mLockPatternUtils.isSecure(userId);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        return mInjector.binderWithCleanCallingIdentity(() -> mLockPatternUtils.isSecure(userId));
     }
 
     private void setDoNotAskCredentialsOnBoot() {
@@ -5316,12 +5282,10 @@
             updateProfileLockTimeoutLocked(userId);
         }
 
-        final long timeMs;
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             // Update the device timeout
             final int parentId = getProfileParentId(userId);
-            timeMs = getMaximumTimeToLockPolicyFromAdmins(
+            final long timeMs = getMaximumTimeToLockPolicyFromAdmins(
                     getActiveAdminsForLockscreenPoliciesLocked(parentId, false));
 
             final DevicePolicyData policy = getUserDataUnchecked(parentId);
@@ -5337,9 +5301,7 @@
             }
             getPowerManagerInternal().setMaximumScreenOffTimeoutFromDeviceAdmin(
                     UserHandle.USER_SYSTEM, timeMs);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
     private void updateProfileLockTimeoutLocked(@UserIdInt int userId) {
@@ -5357,13 +5319,9 @@
         }
         policy.mLastMaximumTimeToLock = timeMs;
 
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
-            getPowerManagerInternal().setMaximumScreenOffTimeoutFromDeviceAdmin(
-                    userId, policy.mLastMaximumTimeToLock);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        mInjector.binderWithCleanCallingIdentity(() ->
+                getPowerManagerInternal().setMaximumScreenOffTimeoutFromDeviceAdmin(
+                        userId, policy.mLastMaximumTimeToLock));
     }
 
     @Override
@@ -5631,24 +5589,21 @@
         }
         enforceCanManageCaCerts(admin, callerPackage);
 
-        final String alias;
-
         final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            alias = mCertificateMonitor.installCaCert(userHandle, certBuffer);
+        final String alias = mInjector.binderWithCleanCallingIdentity(() -> {
+            String installedAlias = mCertificateMonitor.installCaCert(userHandle, certBuffer);
             final boolean isDelegate = (admin == null);
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.INSTALL_CA_CERT)
                     .setAdmin(callerPackage)
                     .setBoolean(isDelegate)
                     .write();
-            if (alias == null) {
-                Log.w(LOG_TAG, "Problem installing cert");
-                return false;
-            }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
+            return installedAlias;
+        });
+
+        if (alias == null) {
+            Log.w(LOG_TAG, "Problem installing cert");
+            return false;
         }
 
         synchronized (getLockObject()) {
@@ -5666,8 +5621,7 @@
         enforceCanManageCaCerts(admin, callerPackage);
 
         final int userId = mInjector.userHandleGetCallingUserId();
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             mCertificateMonitor.uninstallCaCerts(UserHandle.of(userId), aliases);
             final boolean isDelegate = (admin == null);
             DevicePolicyEventLogger
@@ -5675,9 +5629,7 @@
                     .setAdmin(callerPackage)
                     .setBoolean(isDelegate)
                     .write();
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        });
 
         synchronized (getLockObject()) {
             if (getUserData(userId).mOwnerInstalledCaCerts.removeAll(Arrays.asList(aliases))) {
@@ -6081,8 +6033,7 @@
             isDelegate = false;
         }
 
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             mContext.sendOrderedBroadcastAsUser(intent, caller, null, new BroadcastReceiver() {
                 @Override
                 public void onReceive(Context context, Intent intent) {
@@ -6095,9 +6046,7 @@
                     .setAdmin(intent.getComponent())
                     .setBoolean(isDelegate)
                     .write();
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        });
     }
 
     private void sendPrivateKeyAliasResponse(final String alias, final IBinder responseBinder) {
@@ -6513,8 +6462,7 @@
         enforceProfileOrDeviceOwner(admin);
 
         final int userId = mInjector.userHandleGetCallingUserId();
-        final long token = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             if (vpnPackage != null && !isPackageInstalledForUser(vpnPackage, userId)) {
                 Slog.w(LOG_TAG, "Non-existent VPN package specified: " + vpnPackage);
                 throw new ServiceSpecificException(
@@ -6542,9 +6490,7 @@
                     .setBoolean(lockdown)
                     .setInt(lockdownWhitelist != null ? lockdownWhitelist.size() : 0)
                     .write();
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        });
         return true;
     }
 
@@ -6553,12 +6499,8 @@
         enforceProfileOrDeviceOwner(admin);
 
         final int userId = mInjector.userHandleGetCallingUserId();
-        final long token = mInjector.binderClearCallingIdentity();
-        try {
-            return mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        return mInjector.binderWithCleanCallingIdentity(
+                () -> mInjector.getConnectivityManager().getAlwaysOnVpnPackageForUser(userId));
     }
 
     @Override
@@ -6566,12 +6508,8 @@
         enforceProfileOrDeviceOwner(admin);
 
         final int userId = mInjector.userHandleGetCallingUserId();
-        final long token = mInjector.binderClearCallingIdentity();
-        try {
-            return mInjector.getConnectivityManager().isVpnLockdownEnabled(userId);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        return mInjector.binderWithCleanCallingIdentity(
+                () -> mInjector.getConnectivityManager().isVpnLockdownEnabled(userId));
     }
 
     @Override
@@ -6580,12 +6518,8 @@
         enforceProfileOrDeviceOwner(admin);
 
         final int userId = mInjector.userHandleGetCallingUserId();
-        final long token = mInjector.binderClearCallingIdentity();
-        try {
-            return mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        return mInjector.binderWithCleanCallingIdentity(
+                () -> mInjector.getConnectivityManager().getVpnLockdownWhitelist(userId));
     }
 
     private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc) {
@@ -6682,8 +6616,7 @@
                 // control over the device, wiping only the work profile. So the user restriction
                 // on profile removal needs to be removed first.
 
-                final long ident = mInjector.binderClearCallingIdentity();
-                try {
+                mInjector.binderWithCleanCallingIdentity(() -> {
                     // Clear restriction as user.
                     mUserManager.setUserRestriction(
                             UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, false,
@@ -6691,9 +6624,7 @@
 
                     // Device-wide policies set by the profile owner need to be cleaned up here.
                     mLockPatternUtils.setDeviceOwnerInfo(null);
-                } finally {
-                    mInjector.binderRestoreCallingIdentity(ident);
-                }
+                });
             }
         }
 
@@ -6715,8 +6646,7 @@
                                 String wipeReasonForUser, int userId) {
         wtfIfInLock();
 
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             // First check whether the admin is allowed to wipe the device/user/profile.
             final String restriction;
             if (userId == UserHandle.USER_SYSTEM) {
@@ -6750,9 +6680,7 @@
             } else {
                 forceWipeUser(userId, wipeReasonForUser, (flags & WIPE_SILENTLY) != 0);
             }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
     private void sendWipeProfileNotification(String wipeReasonForUser) {
@@ -6927,8 +6855,7 @@
         synchronized (getLockObject()) {
             DevicePolicyData policy = getUserData(userHandle);
             if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) {
-                long ident = mInjector.binderClearCallingIdentity();
-                try {
+                mInjector.binderWithCleanCallingIdentity(() -> {
                     policy.mFailedPasswordAttempts = 0;
                     policy.mPasswordOwner = -1;
                     saveSettingsLocked(userHandle);
@@ -6937,9 +6864,7 @@
                                 DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
                                 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
                     }
-                } finally {
-                    mInjector.binderRestoreCallingIdentity(ident);
-                }
+                });
             }
         }
 
@@ -7038,12 +6963,7 @@
 
             // Reset the global proxy accordingly
             // Do this using system permissions, as apps cannot write to secure settings
-            long origId = mInjector.binderClearCallingIdentity();
-            try {
-                resetGlobalProxyLocked(policy);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(origId);
-            }
+            mInjector.binderWithCleanCallingIdentity(() -> resetGlobalProxyLocked(policy));
             return null;
         }
     }
@@ -7075,12 +6995,8 @@
     @Override
     public void setRecommendedGlobalProxy(ComponentName who, ProxyInfo proxyInfo) {
         enforceDeviceOwner(who);
-        long token = mInjector.binderClearCallingIdentity();
-        try {
-            mInjector.getConnectivityManager().setGlobalProxy(proxyInfo);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        mInjector.binderWithCleanCallingIdentity(
+                () -> mInjector.getConnectivityManager().setGlobalProxy(proxyInfo));
     }
 
     private void resetGlobalProxyLocked(DevicePolicyData policy) {
@@ -7372,12 +7288,9 @@
         // TODO: (b/145604635) Add upgrade case
         // Turn AUTO_TIME on in settings if it is required
         if (required) {
-            long ident = mInjector.binderClearCallingIdentity();
-            try {
-                mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1 /* AUTO_TIME on */);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            mInjector.binderWithCleanCallingIdentity(
+                    () -> mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME,
+                            1 /* AUTO_TIME on */));
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_AUTO_TIME_REQUIRED)
@@ -7508,12 +7421,7 @@
             }
         }
         if (removeAllUsers) {
-            long identitity = mInjector.binderClearCallingIdentity();
-            try {
-                mUserManagerInternal.removeAllUsers();
-            } finally {
-                mInjector.binderRestoreCallingIdentity(identitity);
-            }
+            mInjector.binderWithCleanCallingIdentity(() -> mUserManagerInternal.removeAllUsers());
         }
     }
 
@@ -8026,13 +7934,10 @@
             updateDeviceOwnerLocked();
             setDeviceOwnerSystemPropertyLocked();
 
-            long ident = mInjector.binderClearCallingIdentity();
-            try {
-                // TODO Send to system too?
-                sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED, userId);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            // TODO Send to system too?
+            mInjector.binderWithCleanCallingIdentity(
+                    () -> sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED,
+                            userId));
             mDeviceAdminServiceController.startServiceForOwner(
                     admin.getPackageName(), userId, "set-device-owner");
 
@@ -8213,15 +8118,12 @@
             }
 
             final ActiveAdmin admin = getDeviceOwnerAdminLocked();
-            long ident = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 clearDeviceOwnerLocked(admin, deviceOwnerUserId);
                 removeActiveAdminLocked(deviceOwnerComponent, deviceOwnerUserId);
                 sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED,
                         deviceOwnerUserId);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
             Slog.i(LOG_TAG, "Device owner removed: " + deviceOwnerComponent);
         }
     }
@@ -8307,8 +8209,7 @@
             mOwners.writeProfileOwner(userHandle);
             Slog.i(LOG_TAG, "Profile owner set: " + who + " on user " + userHandle);
 
-            final long id = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 if (mUserManager.isManagedProfile(userHandle)) {
                     maybeSetDefaultRestrictionsForAdminLocked(userHandle, admin,
                             UserRestrictionsUtils.getDefaultEnabledForManagedProfiles());
@@ -8317,9 +8218,7 @@
                 }
                 sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
                         userHandle);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(id);
-            }
+            });
             mDeviceAdminServiceController.startServiceForOwner(
                     who.getPackageName(), userHandle, "set-profile-owner");
             return true;
@@ -8357,15 +8256,12 @@
             final ActiveAdmin admin =
                     getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            final long ident = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 clearProfileOwnerLocked(admin, userId);
                 removeActiveAdminLocked(who, userId);
                 sendOwnerChangedBroadcast(DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED,
                         userId);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
             Slog.i(LOG_TAG, "Profile owner " + who + " removed from user " + userId);
         }
     }
@@ -8574,8 +8470,7 @@
                         "setProfileEnabled is called when the profile is already enabled");
                 return;
             }
-            long id = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 mUserManager.setUserEnabled(userId);
                 UserInfo parent = mUserManager.getProfileParent(userId);
                 Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
@@ -8583,9 +8478,7 @@
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
                         Intent.FLAG_RECEIVER_FOREGROUND);
                 mContext.sendBroadcastAsUser(intent, new UserHandle(parent.id));
-            } finally {
-                mInjector.binderRestoreCallingIdentity(id);
-            }
+            });
         }
     }
 
@@ -8595,16 +8488,13 @@
         enforceProfileOrDeviceOwner(who);
 
         final int userId = UserHandle.getCallingUserId();
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             mUserManager.setUserName(userId, profileName);
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.SET_PROFILE_NAME)
                     .setAdmin(who)
                     .write();
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        });
     }
 
     @Override
@@ -8646,8 +8536,7 @@
 
     @GuardedBy("getLockObject()")
     ActiveAdmin getProfileOwnerOfOrganizationOwnedDeviceLocked(int userHandle) {
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
                 if (userInfo.isManagedProfile()) {
                     if (getProfileOwner(userInfo.id) != null
@@ -8657,10 +8546,8 @@
                     }
                 }
             }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
-        return null;
+            return null;
+        });
     }
 
     @Override
@@ -8763,8 +8650,7 @@
      * Canonical name for a given package.
      */
     private String getApplicationLabel(String packageName, int userHandle) {
-        long token = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             final Context userContext;
             try {
                 UserHandle handle = new UserHandle(userHandle);
@@ -8779,9 +8665,7 @@
                 result = appInfo.loadUnsafeLabel(userContext.getPackageManager());
             }
             return result != null ? result.toString() : null;
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        });
     }
 
     /**
@@ -9072,28 +8956,23 @@
     }
 
     protected int getProfileParentId(int userHandle) {
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             UserInfo parentUser = mUserManager.getProfileParent(userHandle);
             return parentUser != null ? parentUser.id : userHandle;
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
-    private int getCredentialOwner(int userHandle, boolean parent) {
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+    private int getCredentialOwner(final int userHandle, final boolean parent) {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
+            int effectiveUserHandle = userHandle;
             if (parent) {
                 UserInfo parentProfile = mUserManager.getProfileParent(userHandle);
                 if (parentProfile != null) {
-                    userHandle = parentProfile.id;
+                    effectiveUserHandle = parentProfile.id;
                 }
             }
-            return mUserManager.getCredentialOwnerProfile(userHandle);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+            return mUserManager.getCredentialOwnerProfile(effectiveUserHandle);
+        });
     }
 
     private boolean isManagedProfile(int userHandle) {
@@ -9280,8 +9159,7 @@
                 DELEGATION_APP_RESTRICTIONS);
 
         final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             mUserManager.setApplicationRestrictions(packageName, settings, userHandle);
             final boolean isDelegate = (who == null);
             DevicePolicyEventLogger
@@ -9290,9 +9168,7 @@
                     .setBoolean(isDelegate)
                     .setStrings(packageName)
                     .write();
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        });
     }
 
     @Override
@@ -10035,8 +9911,7 @@
         enforceDeviceOwner(who);
 
         final int callingUserId = mInjector.userHandleGetCallingUserId();
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             String restriction = isManagedProfile(userHandle.getIdentifier())
                     ? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE
                     : UserManager.DISALLOW_REMOVE_USER;
@@ -10046,9 +9921,7 @@
                 return false;
             }
             return mUserManagerInternal.removeUserEvenWhenDisallowed(userHandle.getIdentifier());
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        });
     }
 
     private boolean isAdminAffectedByRestriction(
@@ -10194,8 +10067,7 @@
         Preconditions.checkNotNull(who, "ComponentName is null");
         enforceDeviceOwner(who);
 
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             final List<UserInfo> userInfos = mInjector.getUserManager().getUsers(true
                     /*excludeDying*/);
             final List<UserHandle> userHandles = new ArrayList<>();
@@ -10206,9 +10078,7 @@
                 }
             }
             return userHandles;
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        });
     }
 
     @Override
@@ -10217,12 +10087,8 @@
         enforceProfileOrDeviceOwner(who);
 
         final int callingUserId = mInjector.userHandleGetCallingUserId();
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            return mInjector.getUserManager().isUserEphemeral(callingUserId);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        return mInjector.binderWithCleanCallingIdentity(
+                () -> mInjector.getUserManager().isUserEphemeral(callingUserId));
     }
 
     @Override
@@ -10232,15 +10098,12 @@
                 DELEGATION_APP_RESTRICTIONS);
 
         final UserHandle userHandle = mInjector.binderGetCallingUserHandle();
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-           Bundle bundle = mUserManager.getApplicationRestrictions(packageName, userHandle);
+        return mInjector.binderWithCleanCallingIdentity(() -> {
+            Bundle bundle = mUserManager.getApplicationRestrictions(packageName, userHandle);
            // if no restrictions were saved, mUserManager.getApplicationRestrictions
            // returns null, but DPM method should return an empty Bundle as per JavaDoc
            return bundle != null ? bundle : Bundle.EMPTY;
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        });
     }
 
     @Override
@@ -10865,8 +10728,7 @@
                 actualContactId, isContactIdIgnored, actualDirectoryId, originalIntent);
         final int callingUserId = UserHandle.getCallingUserId();
 
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             synchronized (getLockObject()) {
                 final int managedUserId = getManagedUserId(callingUserId);
                 if (managedUserId < 0) {
@@ -10882,9 +10744,7 @@
                 ContactsInternal.startQuickContactWithErrorToastForUser(
                         mContext, intent, new UserHandle(managedUserId));
             }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
     /**
@@ -11044,8 +10904,7 @@
     }
 
     private void maybeClearLockTaskPolicyLocked() {
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
             for (int i = userInfos.size() - 1; i >= 0; i--) {
                 int userId = userInfos.get(i).id;
@@ -11066,9 +10925,7 @@
                     setLockTaskFeaturesLocked(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE);
                 }
             }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
     @Override
@@ -11141,12 +10998,8 @@
                 }
             }
 
-            long id = mInjector.binderClearCallingIdentity();
-            try {
-                mInjector.settingsGlobalPutString(setting, value);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(id);
-            }
+            mInjector.binderWithCleanCallingIdentity(
+                    () -> mInjector.settingsGlobalPutString(setting, value));
         }
     }
 
@@ -11266,8 +11119,7 @@
                 }
                 return;
             }
-            long id = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 if (Settings.Secure.DEFAULT_INPUT_METHOD.equals(setting)) {
                     final String currentValue = mInjector.settingsSecureGetStringForUser(
                             Settings.Secure.DEFAULT_INPUT_METHOD, callingUserId);
@@ -11283,9 +11135,7 @@
                     saveSettingsLocked(callingUserId);
                 }
                 mInjector.settingsSecurePutStringForUser(setting, value, callingUserId);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(id);
-            }
+            });
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_SECURE_SETTING)
@@ -11327,12 +11177,8 @@
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
             int userId = UserHandle.getCallingUserId();
-            long id = mInjector.binderClearCallingIdentity();
-            try {
-                mUserManagerInternal.setUserIcon(userId, icon);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(id);
-            }
+            mInjector.binderWithCleanCallingIdentity(
+                    () -> mUserManagerInternal.setUserIcon(userId, icon));
         }
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_USER_ICON)
@@ -11731,15 +11577,12 @@
 
         @Override
         public void reportSeparateProfileChallengeChanged(@UserIdInt int userId) {
-            final long ident = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 synchronized (getLockObject()) {
                     updateMaximumTimeToLockLocked(userId);
                     updatePasswordQualityCacheForUserGroup(userId);
                 }
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.SEPARATE_PROFILE_CHALLENGE_CHANGED)
                     .setBoolean(isSeparateProfileChallengeEnabled(userId))
@@ -12031,8 +11874,7 @@
                 .putExtra(DeviceAdminReceiver.EXTRA_SYSTEM_UPDATE_RECEIVED_TIME,
                         info == null ? -1 : info.getReceivedTime());
 
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             synchronized (getLockObject()) {
                 // Broadcast to device owner first if there is one.
                 if (mOwners.hasDeviceOwner()) {
@@ -12062,9 +11904,7 @@
                     }
                 }
             }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
     @Override
@@ -12188,8 +12028,7 @@
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, DELEGATION_PERMISSION_GRANT);
         }
         synchronized (getLockObject()) {
-            long ident = mInjector.binderClearCallingIdentity();
-            try {
+            return mInjector.binderWithCleanCallingIdentity(() -> {
                 int granted;
                 if (getTargetSdk(callerPackage, user.getIdentifier())
                         < android.os.Build.VERSION_CODES.Q) {
@@ -12224,9 +12063,7 @@
                             ? DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
                             : DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
                 }
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
         }
     }
 
@@ -12466,8 +12303,7 @@
         // Make sure caller has DO.
         enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(admin);
 
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             String[] macAddresses = mInjector.getWifiManager().getFactoryMacAddresses();
             if (macAddresses == null) {
                 return null;
@@ -12477,9 +12313,7 @@
                     .setAdmin(admin)
                     .write();
             return macAddresses.length > 0 ? macAddresses[0] : null;
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
     /**
@@ -12515,8 +12349,7 @@
         Preconditions.checkNotNull(admin);
         // Make sure caller has DO.
         enforceDeviceOwner(admin);
-        long ident = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             // Make sure there are no ongoing calls on the device.
             if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) {
                 throw new IllegalStateException("Cannot be called with ongoing call on the device");
@@ -12526,9 +12359,7 @@
                     .setAdmin(admin)
                     .write();
             mInjector.powerManagerReboot(PowerManager.REBOOT_REQUESTED_BY_DEVICE_OWNER);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
+        });
     }
 
     @Override
@@ -12765,17 +12596,14 @@
             final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
                     DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
             final int callingUserId = mInjector.userHandleGetCallingUserId();
-            final long identity = mInjector.binderClearCallingIdentity();
-            try {
+            return mInjector.binderWithCleanCallingIdentity(() -> {
                 final List<String> excludedPkgs
                         = removeInvalidPkgsForMeteredDataRestriction(callingUserId, packageNames);
                 admin.meteredDisabledPackages = packageNames;
                 pushMeteredDisabledPackagesLocked(callingUserId);
                 saveSettingsLocked(callingUserId);
                 return excludedPkgs;
-            } finally {
-                mInjector.binderRestoreCallingIdentity(identity);
-            }
+            });
         }
     }
 
@@ -12888,8 +12716,7 @@
                     who.flattenToString(), userId));
 
             // First, set restriction on removing the profile.
-            final long ident = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 // Clear restriction as user.
                 UserHandle parentUser = mUserManager.getProfileParent(UserHandle.of(userId));
                 if (!parentUser.isSystem()) {
@@ -12901,9 +12728,7 @@
 
                 mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, true,
                         parentUser);
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
 
             // markProfileOwnerOfOrganizationOwnedDevice will trigger writing of the profile owner
             // data, no need to do it manually.
@@ -13021,8 +12846,7 @@
     }
 
     private boolean areAllUsersAffiliatedWithDeviceLocked() {
-        final long ident = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             final List<UserInfo> userInfos = mUserManager.getUsers(/*excludeDying=*/ true);
             for (int i = 0; i < userInfos.size(); i++) {
                 int userId = userInfos.get(i).id;
@@ -13031,11 +12855,8 @@
                     return false;
                 }
             }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(ident);
-        }
-
-        return true;
+            return true;
+        });
     }
 
     @Override
@@ -13245,12 +13066,8 @@
     private boolean isCurrentUserDemo() {
         if (UserManager.isDeviceInDemoMode(mContext)) {
             final int userId = mInjector.userHandleGetCallingUserId();
-            final long callingIdentity = mInjector.binderClearCallingIdentity();
-            try {
-                return mUserManager.getUserInfo(userId).isDemo();
-            } finally {
-                mInjector.binderRestoreCallingIdentity(callingIdentity);
-            }
+            return mInjector.binderWithCleanCallingIdentity(
+                    () -> mUserManager.getUserInfo(userId).isDemo());
         }
         return false;
     }
@@ -13466,8 +13283,7 @@
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
             final int callingUserId = mInjector.userHandleGetCallingUserId();
-            final long callingIdentity = mInjector.binderClearCallingIdentity();
-            try {
+            return mInjector.binderWithCleanCallingIdentity(() -> {
                 ArrayList<UserHandle> targetUsers = new ArrayList<>();
                 if (!isDeviceOwner(admin, callingUserId)) {
                     // Profile owners can only bind to the device owner.
@@ -13486,9 +13302,7 @@
                 }
 
                 return targetUsers;
-            } finally {
-                mInjector.binderRestoreCallingIdentity(callingIdentity);
-            }
+            });
         }
     }
 
@@ -13529,8 +13343,7 @@
         }
         wtfIfInLock();
 
-        final long token = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             final AccountManager am = AccountManager.get(mContext);
             final Account accounts[] = am.getAccountsAsUser(userId);
             if (accounts.length == 0) {
@@ -13568,9 +13381,7 @@
                 Log.e(LOG_TAG, "Found incompatible accounts");
             }
             return !compatible;
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
+        });
     }
 
     private boolean hasAccountFeatures(AccountManager am, Account account, String[] features) {
@@ -13623,8 +13434,7 @@
 
     private void setNetworkLoggingActiveInternal(boolean active) {
         synchronized (getLockObject()) {
-            final long callingIdentity = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 if (active) {
                     mNetworkLogger = new NetworkLogger(this, mInjector.getPackageManagerInternal());
                     if (!mNetworkLogger.startNetworkLogging()) {
@@ -13642,9 +13452,7 @@
                     mNetworkLogger = null;
                     mInjector.getNotificationManager().cancel(SystemMessage.NOTE_NETWORK_LOGGING);
                 }
-            } finally {
-                mInjector.binderRestoreCallingIdentity(callingIdentity);
-            }
+            });
         }
     }
 
@@ -13656,12 +13464,8 @@
                 throw new IllegalStateException("logging is not available");
             }
             if (mNetworkLogger != null) {
-                final long ident = mInjector.binderClearCallingIdentity();
-                try {
-                    return mNetworkLogger.forceBatchFinalization();
-                } finally {
-                    mInjector.binderRestoreCallingIdentity(ident);
-                }
+                return mInjector.binderWithCleanCallingIdentity(
+                        () -> mNetworkLogger.forceBatchFinalization());
             }
             return 0;
         }
@@ -13684,15 +13488,12 @@
     @GuardedBy("getLockObject()")
     private void maybeResumeDeviceWideLoggingLocked() {
         if (areAllUsersAffiliatedWithDeviceLocked()) {
-            final long ident = mInjector.binderClearCallingIdentity();
-            try {
+            mInjector.binderWithCleanCallingIdentity(() -> {
                 mSecurityLogMonitor.resume();
                 if (mNetworkLogger != null) {
                     mNetworkLogger.resume();
                 }
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
         }
     }
 
@@ -13881,8 +13682,7 @@
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
             DevicePolicyData policy = getUserData(userHandle);
-            long ident = mInjector.binderClearCallingIdentity();
-            try {
+            return mInjector.binderWithCleanCallingIdentity(() -> {
                 if (policy.mPasswordTokenHandle != 0) {
                     mLockPatternUtils.removeEscrowToken(policy.mPasswordTokenHandle, userHandle);
                 }
@@ -13890,9 +13690,7 @@
                         userHandle, /*EscrowTokenStateChangeCallback*/ null);
                 saveSettingsLocked(userHandle);
                 return policy.mPasswordTokenHandle != 0;
-            } finally {
-                mInjector.binderRestoreCallingIdentity(ident);
-            }
+            });
         }
     }
 
@@ -13907,16 +13705,13 @@
 
             DevicePolicyData policy = getUserData(userHandle);
             if (policy.mPasswordTokenHandle != 0) {
-                long ident = mInjector.binderClearCallingIdentity();
-                try {
+                return mInjector.binderWithCleanCallingIdentity(() -> {
                     boolean result = mLockPatternUtils.removeEscrowToken(
                             policy.mPasswordTokenHandle, userHandle);
                     policy.mPasswordTokenHandle = 0;
                     saveSettingsLocked(userHandle);
                     return result;
-                } finally {
-                    mInjector.binderRestoreCallingIdentity(ident);
-                }
+                });
             }
         }
         return false;
@@ -13933,13 +13728,9 @@
 
             DevicePolicyData policy = getUserData(userHandle);
             if (policy.mPasswordTokenHandle != 0) {
-                long ident = mInjector.binderClearCallingIdentity();
-                try {
-                    return mLockPatternUtils.isEscrowTokenActive(policy.mPasswordTokenHandle,
-                            userHandle);
-                } finally {
-                    mInjector.binderRestoreCallingIdentity(ident);
-                }
+                return mInjector.binderWithCleanCallingIdentity(
+                        () -> mLockPatternUtils.isEscrowTokenActive(policy.mPasswordTokenHandle,
+                                userHandle));
             }
         }
         return false;
@@ -14309,13 +14100,8 @@
         enforceDeviceOwner(who);
 
         int operatedId = -1;
-        Uri resultUri;
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            resultUri = mContext.getContentResolver().insert(DPC_URI, apnSetting.toContentValues());
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        Uri resultUri = mInjector.binderWithCleanCallingIdentity(() ->
+                mContext.getContentResolver().insert(DPC_URI, apnSetting.toContentValues()));
         if (resultUri != null) {
             try {
                 operatedId = Integer.parseInt(resultUri.getLastPathSegment());
@@ -14340,14 +14126,10 @@
         if (apnId < 0) {
             return false;
         }
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            return mContext.getContentResolver().update(
-                    Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
-                    apnSetting.toContentValues(), null, null) > 0;
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        return mInjector.binderWithCleanCallingIdentity(() ->
+                mContext.getContentResolver().update(
+                        Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)),
+                        apnSetting.toContentValues(), null, null) > 0);
     }
 
     @Override
@@ -14365,14 +14147,9 @@
         if(apnId < 0) {
             return false;
         }
-        int numDeleted = 0;
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            numDeleted = mContext.getContentResolver().delete(
-                    Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)), null, null);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        int numDeleted = mInjector.binderWithCleanCallingIdentity(
+                () -> mContext.getContentResolver().delete(
+                        Uri.withAppendedPath(DPC_URI, Integer.toString(apnId)), null, null));
         return numDeleted > 0;
     }
 
@@ -14388,13 +14165,8 @@
     }
 
     private List<ApnSetting> getOverrideApnsUnchecked() {
-        final Cursor cursor;
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            cursor = mContext.getContentResolver().query(DPC_URI, null, null, null, null);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        final Cursor cursor = mInjector.binderWithCleanCallingIdentity(
+                () -> mContext.getContentResolver().query(DPC_URI, null, null, null, null));
 
         if (cursor == null) {
             return Collections.emptyList();
@@ -14426,13 +14198,8 @@
     private void setOverrideApnsEnabledUnchecked(boolean enabled) {
         ContentValues value = new ContentValues();
         value.put(ENFORCE_KEY, enabled);
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            mContext.getContentResolver().update(
-                    ENFORCE_MANAGED_URI, value, null, null);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        mInjector.binderWithCleanCallingIdentity(() -> mContext.getContentResolver().update(
+                    ENFORCE_MANAGED_URI, value, null, null));
     }
 
     @Override
@@ -14443,14 +14210,9 @@
         Preconditions.checkNotNull(who, "ComponentName is null in isOverrideApnEnabled");
         enforceDeviceOwner(who);
 
-        Cursor enforceCursor;
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
-            enforceCursor = mContext.getContentResolver().query(
-                    ENFORCE_MANAGED_URI, null, null, null, null);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        Cursor enforceCursor = mInjector.binderWithCleanCallingIdentity(
+                () -> mContext.getContentResolver().query(
+                        ENFORCE_MANAGED_URI, null, null, null, null));
 
         if (enforceCursor == null) {
             return false;
@@ -14517,13 +14279,10 @@
     private void putPrivateDnsSettings(@Nullable String mode, @Nullable String host) {
         // Set Private DNS settings using system permissions, as apps cannot write
         // to global settings.
-        long origId = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             mInjector.settingsGlobalPutString(PRIVATE_DNS_MODE, mode);
             mInjector.settingsGlobalPutString(PRIVATE_DNS_SPECIFIER, host);
-        } finally {
-            mInjector.binderRestoreCallingIdentity(origId);
-        }
+        });
     }
 
     @Override
@@ -14609,8 +14368,7 @@
                 .setBoolean(isDeviceAB())
                 .write();
         enforceDeviceOwner(admin);
-        final long id = mInjector.binderClearCallingIdentity();
-        try {
+        mInjector.binderWithCleanCallingIdentity(() -> {
             UpdateInstaller updateInstaller;
             if (isDeviceAB()) {
                 updateInstaller = new AbUpdateInstaller(
@@ -14620,9 +14378,7 @@
                         mContext, updateFileDescriptor, callback, mInjector, mConstants);
             }
             updateInstaller.startInstallUpdate();
-        } finally {
-            mInjector.binderRestoreCallingIdentity(id);
-        }
+        });
     }
 
     private boolean isDeviceAB() {
@@ -14823,8 +14579,7 @@
             throw new SecurityException("Input package name doesn't align with actual "
                     + "calling package.");
         }
-        final long identity = mInjector.binderClearCallingIdentity();
-        try {
+        return mInjector.binderWithCleanCallingIdentity(() -> {
             final int workProfileUserId = getManagedUserId(callingUserId);
             if (workProfileUserId < 0) {
                 return false;
@@ -14848,10 +14603,8 @@
                 Log.e(LOG_TAG, "View event activity not found", e);
                 return false;
             }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(identity);
-        }
-        return true;
+            return true;
+        });
     }
 
     private boolean isCallingFromPackage(String packageName, int callingUid) {
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 67ba895..c49c370 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -147,10 +147,11 @@
   ResourceId(uint32_t res_id);  // NOLINT(google-explicit-constructor)
   ResourceId(uint8_t p, uint8_t t, uint16_t e);
 
-  bool is_valid() const;
+  // Returns true if the ID is a valid ID that is not dynamic (package ID cannot be 0)
+  bool is_valid_static() const;
 
   // Returns true if the ID is a valid ID or dynamic ID (package ID can be 0).
-  bool is_valid_dynamic() const;
+  bool is_valid() const;
 
   uint8_t package_id() const;
   uint8_t type_id() const;
@@ -233,11 +234,11 @@
 inline ResourceId::ResourceId(uint8_t p, uint8_t t, uint16_t e)
     : id((p << 24) | (t << 16) | e) {}
 
-inline bool ResourceId::is_valid() const {
+inline bool ResourceId::is_valid_static() const {
   return (id & 0xff000000u) != 0 && (id & 0x00ff0000u) != 0;
 }
 
-inline bool ResourceId::is_valid_dynamic() const {
+inline bool ResourceId::is_valid() const {
   return (id & 0x00ff0000u) != 0;
 }
 
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 1773b5a..e0a9a31e 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -398,7 +398,7 @@
 
   // Check for package names appearing twice with two different package ids
   ResourceTablePackage* package = FindOrCreatePackage(name.package);
-  if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) {
+  if (res_id.is_valid() && package->id && package->id.value() != res_id.package_id()) {
     diag->Error(DiagMessage(source)
                     << "trying to add resource '" << name << "' with ID " << res_id
                     << " but package '" << package->name << "' already has ID "
@@ -407,9 +407,9 @@
   }
 
   // Whether or not to error on duplicate resources
-  bool check_id = validate_resources_ && res_id.is_valid_dynamic();
+  bool check_id = validate_resources_ && res_id.is_valid();
   // Whether or not to create a duplicate resource if the id does not match
-  bool use_id = !validate_resources_ && res_id.is_valid_dynamic();
+  bool use_id = !validate_resources_ && res_id.is_valid();
 
   ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
                                                                         : Maybe<uint8_t>());
@@ -463,7 +463,7 @@
     }
   }
 
-  if (res_id.is_valid_dynamic()) {
+  if (res_id.is_valid()) {
     package->id = res_id.package_id();
     type->id = res_id.type_id();
     entry->id = res_id.entry_id();
@@ -504,7 +504,7 @@
 
   // Check for package names appearing twice with two different package ids
   ResourceTablePackage* package = FindOrCreatePackage(name.package);
-  if (res_id.is_valid_dynamic() && package->id && package->id.value() != res_id.package_id()) {
+  if (res_id.is_valid() && package->id && package->id.value() != res_id.package_id()) {
     diag->Error(DiagMessage(source)
                     << "trying to add resource '" << name << "' with ID " << res_id
                     << " but package '" << package->name << "' already has ID "
@@ -513,9 +513,9 @@
   }
 
   // Whether or not to error on duplicate resources
-  bool check_id = validate_resources_ && res_id.is_valid_dynamic();
+  bool check_id = validate_resources_ && res_id.is_valid();
   // Whether or not to create a duplicate resource if the id does not match
-  bool use_id = !validate_resources_ && res_id.is_valid_dynamic();
+  bool use_id = !validate_resources_ && res_id.is_valid();
 
   ResourceTableType* type = package->FindOrCreateType(name.type, use_id ? res_id.type_id()
                                                                         : Maybe<uint8_t>());
@@ -541,7 +541,7 @@
     return false;
   }
 
-  if (res_id.is_valid_dynamic()) {
+  if (res_id.is_valid()) {
     package->id = res_id.package_id();
     type->id = res_id.type_id();
     entry->id = res_id.entry_id();
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 03009aa..3623b11 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -516,7 +516,7 @@
   if (android::ResTable::stringToInt(str16.data(), str16.size(), &value)) {
     if (value.dataType == android::Res_value::TYPE_INT_HEX) {
       ResourceId id(value.data);
-      if (id.is_valid_dynamic()) {
+      if (id.is_valid()) {
         return id;
       }
     }
diff --git a/tools/aapt2/ResourceValues.cpp b/tools/aapt2/ResourceValues.cpp
index 34b46c5..4f0fa8a 100644
--- a/tools/aapt2/ResourceValues.cpp
+++ b/tools/aapt2/ResourceValues.cpp
@@ -117,7 +117,7 @@
 
 bool Reference::Flatten(android::Res_value* out_value) const {
   const ResourceId resid = id.value_or_default(ResourceId(0));
-  const bool dynamic = resid.is_valid_dynamic() && is_dynamic;
+  const bool dynamic = resid.is_valid() && is_dynamic;
 
   if (reference_type == Reference::Type::kResource) {
     if (dynamic) {
@@ -159,7 +159,7 @@
     *out << name.value();
   }
 
-  if (id && id.value().is_valid_dynamic()) {
+  if (id && id.value().is_valid()) {
     if (name) {
       *out << " ";
     }
@@ -196,7 +196,7 @@
       printer->Print("/");
       printer->Print(name.entry);
     }
-  } else if (ref.id && ref.id.value().is_valid_dynamic()) {
+  } else if (ref.id && ref.id.value().is_valid()) {
     printer->Print(ref.id.value().to_string());
   }
 }
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index bc09f19..83e20b5 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -340,7 +340,7 @@
     }
 
     res_id = asset_manager_.GetResourceId(real_name.to_string());
-    if (res_id.is_valid() && asset_manager_.GetResourceFlags(res_id.id, &type_spec_flags)) {
+    if (res_id.is_valid_static() && asset_manager_.GetResourceFlags(res_id.id, &type_spec_flags)) {
       found = true;
       return false;
     }
@@ -379,7 +379,7 @@
 
 std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindById(
     ResourceId id) {
-  if (!id.is_valid()) {
+  if (!id.is_valid_static()) {
     // Exit early and avoid the error logs from AssetManager.
     return {};
   }
diff --git a/wifi/java/android/net/wifi/aware/Characteristics.java b/wifi/java/android/net/wifi/aware/Characteristics.java
index e2cf4dc..d5fd48e 100644
--- a/wifi/java/android/net/wifi/aware/Characteristics.java
+++ b/wifi/java/android/net/wifi/aware/Characteristics.java
@@ -16,10 +16,14 @@
 
 package android.net.wifi.aware;
 
+import android.annotation.IntDef;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * The characteristics of the Wi-Fi Aware implementation.
  */
@@ -31,6 +35,8 @@
             "key_max_service_specific_info_length";
     /** @hide */
     public static final String KEY_MAX_MATCH_FILTER_LENGTH = "key_max_match_filter_length";
+    /** @hide */
+    public static final String KEY_SUPPORTED_CIPHER_SUITES = "key_supported_cipher_suites";
 
     private Bundle mCharacteristics = new Bundle();
 
@@ -71,12 +77,41 @@
      * {@link PublishConfig.Builder#setMatchFilter(java.util.List)} and
      * {@link SubscribeConfig.Builder#setMatchFilter(java.util.List)}.
      *
-     * @return A positive integer, maximum legngth of byte array for Aware discovery match filter.
+     * @return A positive integer, maximum length of byte array for Aware discovery match filter.
      */
     public int getMaxMatchFilterLength() {
         return mCharacteristics.getInt(KEY_MAX_MATCH_FILTER_LENGTH);
     }
 
+    /** @hide */
+    @IntDef(flag = true, prefix = { "WIFI_AWARE_CIPHER_SUITE_" }, value = {
+            WIFI_AWARE_CIPHER_SUITE_NCS_SK_128,
+            WIFI_AWARE_CIPHER_SUITE_NCS_SK_256,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface WifiAwareCipherSuites {}
+
+    /**
+     * Wi-Fi Aware supported ciphier suite representing NCS SK 128: 128 bit shared-key.
+     */
+    public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_128 = 1 << 0;
+
+    /**
+     * Wi-Fi Aware supported ciphier suite representing NCS SK 256: 256 bit shared-key.
+     */
+    public static final int WIFI_AWARE_CIPHER_SUITE_NCS_SK_256 = 1 << 1;
+
+    /**
+     * Returns the set of cipher suites supported by the device for use in Wi-Fi Aware data-paths.
+     * The device automatically picks the strongest cipher suite when initiating a data-path setup.
+     *
+     * @return A set of flags from {@link #WIFI_AWARE_CIPHER_SUITE_NCS_SK_128}, or
+     * {@link #WIFI_AWARE_CIPHER_SUITE_NCS_SK_256}.
+     */
+    public @WifiAwareCipherSuites int getSupportedCipherSuites() {
+        return mCharacteristics.getInt(KEY_SUPPORTED_CIPHER_SUITES);
+    }
+
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeBundle(mCharacteristics);