Merge "Remove appLayerReplacesLauncher test from transfer splash screen test." into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 372ae6d..76377e7 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -29,6 +29,7 @@
     ":android.service.notification.flags-aconfig-java{.generated_srcjars}",
     ":android.view.flags-aconfig-java{.generated_srcjars}",
     ":android.view.accessibility.flags-aconfig-java{.generated_srcjars}",
+    ":audio-framework-aconfig",
     ":camera_platform_flags_core_java_lib{.generated_srcjars}",
     ":com.android.window.flags.window-aconfig-java{.generated_srcjars}",
     ":android.hardware.biometrics.flags-aconfig-java{.generated_srcjars}",
@@ -39,7 +40,6 @@
     ":android.companion.virtual.flags-aconfig-java{.generated_srcjars}",
     ":android.view.inputmethod.flags-aconfig-java{.generated_srcjars}",
     ":android.widget.flags-aconfig-java{.generated_srcjars}",
-    ":com.android.media.audio.flags-aconfig-java{.generated_srcjars}",
     ":com.android.media.flags.bettertogether-aconfig-java{.generated_srcjars}",
     ":sdk_sandbox_flags_lib{.generated_srcjars}",
     ":android.permission.flags-aconfig-java{.generated_srcjars}",
@@ -54,7 +54,6 @@
     ":android.view.contentprotection.flags-aconfig-java{.generated_srcjars}",
     ":android.service.voice.flags-aconfig-java{.generated_srcjars}",
     ":android.media.tv.flags-aconfig-java{.generated_srcjars}",
-    ":aconfig_midi_flags_java_lib{.generated_srcjars}",
     ":android.service.autofill.flags-aconfig-java{.generated_srcjars}",
     ":com.android.net.flags-aconfig-java{.generated_srcjars}",
     ":device_policy_aconfig_flags_lib{.generated_srcjars}",
@@ -393,13 +392,6 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
-// Media Audio
-java_aconfig_library {
-    name: "com.android.media.audio.flags-aconfig-java",
-    aconfig_declarations: "aconfig_audio_flags",
-    defaults: ["framework-minus-apex-aconfig-java-defaults"],
-}
-
 // Permissions
 aconfig_declarations {
     name: "android.permission.flags-aconfig",
@@ -584,6 +576,24 @@
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
+// Media
+aconfig_declarations {
+    name: "android.media.playback.flags-aconfig",
+    package: "com.android.media.playback.flags",
+    srcs: ["media/jni/playback_flags.aconfig"],
+}
+
+cc_aconfig_library {
+    name: "android.media.playback.flags-aconfig-cc",
+    aconfig_declarations: "android.media.playback.flags-aconfig",
+}
+
+java_aconfig_library {
+    name: "android.media.playback.flags-aconfig-java",
+    aconfig_declarations: "android.media.playback.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 // VCN
 aconfig_declarations {
     name: "android.net.vcn.flags-aconfig",
diff --git a/Android.bp b/Android.bp
index 8c4d769..49386d4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -614,19 +614,6 @@
     ],
 }
 
-packages_to_document = [
-    "android",
-    "dalvik",
-    "java",
-    "javax",
-    "junit",
-    "org.apache.http",
-    "org.json",
-    "org.w3c.dom",
-    "org.xml.sax",
-    "org.xmlpull",
-]
-
 filegroup {
     name: "android-non-updatable-stub-sources",
     srcs: [
@@ -641,142 +628,6 @@
     visibility: ["//frameworks/base/api"],
 }
 
-// Defaults for all stubs that include the non-updatable framework. These defaults do not include
-// module symbols, so will not compile correctly on their own. Users must add module APIs to the
-// classpath (or sources) somehow.
-stubs_defaults {
-    name: "android-non-updatable-stubs-defaults",
-    srcs: [":android-non-updatable-stub-sources"],
-    sdk_version: "none",
-    system_modules: "none",
-    java_version: "1.8",
-    arg_files: [":frameworks-base-core-AndroidManifest.xml"],
-    aidl: {
-        include_dirs: [
-            "frameworks/av/aidl",
-            "frameworks/base/media/aidl",
-            "frameworks/base/telephony/java",
-            "frameworks/native/libs/permission/aidl",
-            "packages/modules/Bluetooth/framework/aidl-export",
-            "packages/modules/Connectivity/framework/aidl-export",
-            "packages/modules/Media/apex/aidl/stable",
-            "hardware/interfaces/biometrics/common/aidl",
-            "hardware/interfaces/biometrics/fingerprint/aidl",
-            "hardware/interfaces/graphics/common/aidl",
-            "hardware/interfaces/keymaster/aidl",
-            "system/hardware/interfaces/media/aidl",
-        ],
-    },
-    // These are libs from framework-internal-utils that are required (i.e. being referenced)
-    // from framework-non-updatable-sources. Add more here when there's a need.
-    // DO NOT add the entire framework-internal-utils. It might cause unnecessary circular
-    // dependencies gets bigger.
-    libs: [
-        "android.hardware.cas-V1.2-java",
-        "android.hardware.health-V1.0-java-constants",
-        "android.hardware.thermal-V1.0-java-constants",
-        "android.hardware.thermal-V2.0-java",
-        "android.hardware.tv.input-V1.0-java-constants",
-        "android.hardware.usb-V1.0-java-constants",
-        "android.hardware.usb-V1.1-java-constants",
-        "android.hardware.usb.gadget-V1.0-java",
-        "android.hardware.vibrator-V1.3-java",
-        "framework-protos",
-    ],
-    flags: [
-        "--api-lint-ignore-prefix android.icu.",
-        "--api-lint-ignore-prefix java.",
-        "--api-lint-ignore-prefix junit.",
-        "--api-lint-ignore-prefix org.",
-        "--error NoSettingsProvider",
-        "--error UnhiddenSystemApi",
-        "--error UnflaggedApi",
-        "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*",
-        "--hide BroadcastBehavior",
-        "--hide CallbackInterface",
-        "--hide DeprecationMismatch",
-        "--hide HiddenSuperclass",
-        "--hide MissingPermission",
-        "--hide RequiresPermission",
-        "--hide SdkConstant",
-        "--hide Todo",
-        "--hide-package android.audio.policy.configuration.V7_0",
-        "--hide-package com.android.server",
-        "--manifest $(location :frameworks-base-core-AndroidManifest.xml)",
-    ],
-    filter_packages: packages_to_document,
-    high_mem: true, // Lots of sources => high memory use, see b/170701554
-    installable: false,
-    annotations_enabled: true,
-    previous_api: ":android.api.public.latest",
-    merge_annotations_dirs: ["metalava-manual"],
-    defaults_visibility: ["//frameworks/base/api"],
-    visibility: ["//frameworks/base/api"],
-}
-
-// Defaults with module APIs in the classpath (mostly from prebuilts).
-// Suitable for compiling android-non-updatable.
-stubs_defaults {
-    name: "module-classpath-stubs-defaults",
-    aidl: {
-        include_dirs: [
-            "packages/modules/Bluetooth/framework/aidl-export",
-            "packages/modules/Connectivity/framework/aidl-export",
-            "packages/modules/Media/apex/aidl/stable",
-        ],
-    },
-    libs: [
-        "art.module.public.api",
-        "sdk_module-lib_current_framework-tethering",
-        "sdk_module-lib_current_framework-connectivity-t",
-        "sdk_public_current_framework-bluetooth",
-        // There are a few classes from modules used by the core that
-        // need to be resolved by metalava. We use a prebuilt stub of the
-        // full sdk to ensure we can resolve them. If a new class gets added,
-        // the prebuilts/sdk/current needs to be updated.
-        "sdk_system_current_android",
-        // NOTE: The below can be removed once the prebuilt stub contains IKE.
-        "sdk_system_current_android.net.ipsec.ike",
-    ],
-}
-
-// Defaults for the java_sdk_libraries of unbundled jars from framework.
-// java_sdk_libraries using these defaults should also add themselves to the
-// non_updatable_modules list in frameworks/base/api/api.go
-java_defaults {
-    name: "framework-non-updatable-unbundled-defaults",
-    defaults: [
-        "framework-non-updatable-lint-defaults",
-        "non-updatable-framework-module-defaults",
-    ],
-    public: {
-        libs: ["android_module_lib_stubs_current"],
-    },
-    system: {
-        libs: ["android_module_lib_stubs_current"],
-    },
-    module_lib: {
-        libs: ["android_module_lib_stubs_current"],
-    },
-    test: {
-        libs: ["android_test_frameworks_core_stubs_current"],
-    },
-    sdk_version: "core_platform",
-    stub_only_libs: ["framework-protos"],
-    impl_only_libs: ["framework-minus-apex-headers"], // the framework, including hidden API
-    impl_library_visibility: ["//frameworks/base"],
-    defaults_visibility: ["//frameworks/base/location"],
-    plugins: ["error_prone_android_framework"],
-    errorprone: {
-        javacflags: [
-            "-Xep:AndroidFrameworkCompatChange:ERROR",
-            "-Xep:AndroidFrameworkUid:ERROR",
-        ],
-    },
-    // Include manual annotations in API txt files
-    merge_annotations_dirs: ["metalava-manual"],
-}
-
 build = [
     "AconfigFlags.bp",
     "ProtoLibraries.bp",
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index a92a01f..9961c4f 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -432,7 +432,6 @@
     @UnsupportedAppUsage
     private final ComponentName service;
     private final int constraintFlags;
-    private final int mPreferredConstraintFlags;
     private final TriggerContentUri[] triggerContentUris;
     private final long triggerContentUpdateDelay;
     private final long triggerContentMaxDelay;
@@ -523,30 +522,6 @@
     }
 
     /**
-     * @hide
-     * @see JobInfo.Builder#setPrefersBatteryNotLow(boolean)
-     */
-    public boolean isPreferBatteryNotLow() {
-        return (mPreferredConstraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0;
-    }
-
-    /**
-     * @hide
-     * @see JobInfo.Builder#setPrefersCharging(boolean)
-     */
-    public boolean isPreferCharging() {
-        return (mPreferredConstraintFlags & CONSTRAINT_FLAG_CHARGING) != 0;
-    }
-
-    /**
-     * @hide
-     * @see JobInfo.Builder#setPrefersDeviceIdle(boolean)
-     */
-    public boolean isPreferDeviceIdle() {
-        return (mPreferredConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0;
-    }
-
-    /**
      * @see JobInfo.Builder#setRequiresCharging(boolean)
      */
     public boolean isRequireCharging() {
@@ -582,13 +557,6 @@
     }
 
     /**
-     * @hide
-     */
-    public int getPreferredConstraintFlags() {
-        return mPreferredConstraintFlags;
-    }
-
-    /**
      * Which content: URIs must change for the job to be scheduled.  Returns null
      * if there are none required.
      * @see JobInfo.Builder#addTriggerContentUri(TriggerContentUri)
@@ -832,9 +800,6 @@
         if (constraintFlags != j.constraintFlags) {
             return false;
         }
-        if (mPreferredConstraintFlags != j.mPreferredConstraintFlags) {
-            return false;
-        }
         if (!Arrays.equals(triggerContentUris, j.triggerContentUris)) {
             return false;
         }
@@ -915,7 +880,6 @@
             hashCode = 31 * hashCode + service.hashCode();
         }
         hashCode = 31 * hashCode + constraintFlags;
-        hashCode = 31 * hashCode + mPreferredConstraintFlags;
         if (triggerContentUris != null) {
             hashCode = 31 * hashCode + Arrays.hashCode(triggerContentUris);
         }
@@ -958,7 +922,6 @@
         }
         service = in.readParcelable(null);
         constraintFlags = in.readInt();
-        mPreferredConstraintFlags = in.readInt();
         triggerContentUris = in.createTypedArray(TriggerContentUri.CREATOR);
         triggerContentUpdateDelay = in.readLong();
         triggerContentMaxDelay = in.readLong();
@@ -993,7 +956,6 @@
         clipGrantFlags = b.mClipGrantFlags;
         service = b.mJobService;
         constraintFlags = b.mConstraintFlags;
-        mPreferredConstraintFlags = b.mPreferredConstraintFlags;
         triggerContentUris = b.mTriggerContentUris != null
                 ? b.mTriggerContentUris.toArray(new TriggerContentUri[b.mTriggerContentUris.size()])
                 : null;
@@ -1037,7 +999,6 @@
         }
         out.writeParcelable(service, flags);
         out.writeInt(constraintFlags);
-        out.writeInt(mPreferredConstraintFlags);
         out.writeTypedArray(triggerContentUris, flags);
         out.writeLong(triggerContentUpdateDelay);
         out.writeLong(triggerContentMaxDelay);
@@ -1185,7 +1146,6 @@
         private int mFlags;
         // Requirements.
         private int mConstraintFlags;
-        private int mPreferredConstraintFlags;
         private NetworkRequest mNetworkRequest;
         private long mNetworkDownloadBytes = NETWORK_BYTES_UNKNOWN;
         private long mNetworkUploadBytes = NETWORK_BYTES_UNKNOWN;
@@ -1239,7 +1199,6 @@
             mBias = job.getBias();
             mFlags = job.getFlags();
             mConstraintFlags = job.getConstraintFlags();
-            mPreferredConstraintFlags = job.getPreferredConstraintFlags();
             mNetworkRequest = job.getRequiredNetwork();
             mNetworkDownloadBytes = job.getEstimatedNetworkDownloadBytes();
             mNetworkUploadBytes = job.getEstimatedNetworkUploadBytes();
@@ -1389,6 +1348,10 @@
          * {@link android.Manifest.permission#ACCESS_NETWORK_STATE} permission to
          * schedule a job that requires a network.
          *
+         * <p> Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+         * {@link JobScheduler} may try to shift the execution of jobs requiring
+         * {@link #NETWORK_TYPE_ANY} to when there is access to an un-metered network.
+         *
          * <p class="note">
          * When your job executes in
          * {@link JobService#onStartJob(JobParameters)}, be sure to use the
@@ -1555,100 +1518,6 @@
         }
 
         /**
-         * Specify that this job would prefer to be run when the device's battery is not low.
-         * This defaults to {@code false}.
-         *
-         * <p>The system may attempt to delay this job until the device's battery is not low,
-         * but may choose to run it even if the device's battery is low. JobScheduler will not stop
-         * this job if this constraint is no longer satisfied after the job has started running.
-         * If this job must only run when the device's battery is not low,
-         * use {@link #setRequiresBatteryNotLow(boolean)} instead.
-         *
-         * <p>
-         * Because it doesn't make sense for a constraint to be both preferred and required,
-         * calling both this and {@link #setRequiresBatteryNotLow(boolean)} with {@code true}
-         * will result in an {@link java.lang.IllegalArgumentException} when
-         * {@link android.app.job.JobInfo.Builder#build()} is called.
-         *
-         * @param prefersBatteryNotLow Pass {@code true} to prefer that the device's battery level
-         *                             not be low in order to run the job.
-         * @return This object for method chaining
-         * @see JobInfo#isPreferBatteryNotLow()
-         * @hide
-         */
-        @NonNull
-        public Builder setPrefersBatteryNotLow(boolean prefersBatteryNotLow) {
-            mPreferredConstraintFlags =
-                    (mPreferredConstraintFlags & ~CONSTRAINT_FLAG_BATTERY_NOT_LOW)
-                            | (prefersBatteryNotLow ? CONSTRAINT_FLAG_BATTERY_NOT_LOW : 0);
-            return this;
-        }
-
-        /**
-         * Specify that this job would prefer to be run when the device is charging (or be a
-         * non-battery-powered device connected to permanent power, such as Android TV
-         * devices). This defaults to {@code false}.
-         *
-         * <p>
-         * The system may attempt to delay this job until the device is charging, but may
-         * choose to run it even if the device is not charging. JobScheduler will not stop
-         * this job if this constraint is no longer satisfied after the job has started running.
-         * If this job must only run when the device is charging,
-         * use {@link #setRequiresCharging(boolean)} instead.
-         *
-         * <p>
-         * Because it doesn't make sense for a constraint to be both preferred and required,
-         * calling both this and {@link #setRequiresCharging(boolean)} with {@code true}
-         * will result in an {@link java.lang.IllegalArgumentException} when
-         * {@link android.app.job.JobInfo.Builder#build()} is called.
-         *
-         * @param prefersCharging Pass {@code true} to prefer that the device be
-         *                        charging in order to run the job.
-         * @return This object for method chaining
-         * @see JobInfo#isPreferCharging()
-         * @hide
-         */
-        @NonNull
-        public Builder setPrefersCharging(boolean prefersCharging) {
-            mPreferredConstraintFlags = (mPreferredConstraintFlags & ~CONSTRAINT_FLAG_CHARGING)
-                    | (prefersCharging ? CONSTRAINT_FLAG_CHARGING : 0);
-            return this;
-        }
-
-        /**
-         * Specify that this job would prefer to be run when the device is not in active use.
-         * This defaults to {@code false}.
-         *
-         * <p>The system may attempt to delay this job until the device is not in active use,
-         * but may choose to run it even if the device is not idle. JobScheduler will not stop
-         * this job if this constraint is no longer satisfied after the job has started running.
-         * If this job must only run when the device is not in active use,
-         * use {@link #setRequiresDeviceIdle(boolean)} instead.
-         *
-         * <p>
-         * Because it doesn't make sense for a constraint to be both preferred and required,
-         * calling both this and {@link #setRequiresDeviceIdle(boolean)} with {@code true}
-         * will result in an {@link java.lang.IllegalArgumentException} when
-         * {@link android.app.job.JobInfo.Builder#build()} is called.
-         *
-         * <p class="note">Despite the similar naming, this job constraint is <em>not</em>
-         * related to the system's "device idle" or "doze" states.  This constraint only
-         * determines whether a job is allowed to run while the device is directly in use.
-         *
-         * @param prefersDeviceIdle Pass {@code true} to prefer that the device not be in active
-         *                          use when running this job.
-         * @return This object for method chaining
-         * @see JobInfo#isRequireDeviceIdle()
-         * @hide
-         */
-        @NonNull
-        public Builder setPrefersDeviceIdle(boolean prefersDeviceIdle) {
-            mPreferredConstraintFlags = (mPreferredConstraintFlags & ~CONSTRAINT_FLAG_DEVICE_IDLE)
-                    | (prefersDeviceIdle ? CONSTRAINT_FLAG_DEVICE_IDLE : 0);
-            return this;
-        }
-
-        /**
          * Specify that to run this job, the device must be charging (or be a
          * non-battery-powered device connected to permanent power, such as Android TV
          * devices). This defaults to {@code false}. Setting this to {@code false} <b>DOES NOT</b>
@@ -1922,7 +1791,10 @@
          * <ol>
          *     <li>Run as soon as possible</li>
          *     <li>Be less restricted during Doze and battery saver</li>
-         *     <li>Bypass Doze, app standby, and battery saver network restrictions</li>
+         *     <li>
+         *         Bypass Doze, app standby, and battery saver network restrictions (if the job
+         *         has a {@link #setRequiredNetwork(NetworkRequest) connectivity constraint})
+         *     </li>
          *     <li>Be less likely to be killed than regular jobs</li>
          *     <li>Be subject to background location throttling</li>
          *     <li>Be exempt from delay to optimize job execution</li>
@@ -2306,29 +2178,6 @@
             }
         }
 
-        if ((constraintFlags & mPreferredConstraintFlags) != 0) {
-            // Something is marked as both preferred and required. Try to give a clear exception
-            // reason.
-            if ((constraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0
-                    && (mPreferredConstraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0) {
-                throw new IllegalArgumentException(
-                        "battery-not-low constraint cannot be both preferred and required");
-            }
-            if ((constraintFlags & CONSTRAINT_FLAG_CHARGING) != 0
-                    && (mPreferredConstraintFlags & CONSTRAINT_FLAG_CHARGING) != 0) {
-                throw new IllegalArgumentException(
-                        "charging constraint cannot be both preferred and required");
-            }
-            if ((constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0
-                    && (mPreferredConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
-                throw new IllegalArgumentException(
-                        "device idle constraint cannot be both preferred and required");
-            }
-            // Couldn't figure out what the overlap was. Just use a generic message.
-            throw new IllegalArgumentException(
-                    "constraints cannot be both preferred and required");
-        }
-
         if (isUserInitiated) {
             if (hasEarlyConstraint) {
                 throw new IllegalArgumentException("A user-initiated job cannot have a time delay");
@@ -2346,8 +2195,7 @@
             if (mPriority != PRIORITY_MAX) {
                 throw new IllegalArgumentException("A user-initiated job must be max priority.");
             }
-            if ((constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0
-                    || (mPreferredConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
+            if ((constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
                 throw new IllegalArgumentException(
                         "A user-initiated job cannot have a device-idle constraint");
             }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 23b36e2..bff4353 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -3859,10 +3859,16 @@
             // Only let the app use the higher runtime if it hasn't repeatedly timed out.
             final String timeoutTag = job.shouldTreatAsExpeditedJob()
                     ? QUOTA_TRACKER_TIMEOUT_EJ_TAG : QUOTA_TRACKER_TIMEOUT_REG_TAG;
+            // Developers are informed that expedited jobs can be stopped earlier than regular jobs
+            // and so shouldn't use them for long pieces of work. There's little reason to let
+            // them run longer than the normal 10 minutes.
+            final long normalUpperLimitMs = job.shouldTreatAsExpeditedJob()
+                    ? mConstants.RUNTIME_MIN_GUARANTEE_MS
+                    : mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
             final long upperLimitMs =
                     mQuotaTracker.isWithinQuota(job.getTimeoutBlameUserId(),
                             job.getTimeoutBlamePackageName(), timeoutTag)
-                            ? mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS
+                            ? normalUpperLimitMs
                             : mConstants.RUNTIME_MIN_GUARANTEE_MS;
             return Math.min(upperLimitMs,
                     mConstants.USE_TARE_POLICY
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 2d49cfb..721a8bd 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -427,34 +427,30 @@
             boolean binding = false;
             boolean startedWithForegroundFlag = false;
             try {
-                final Context.BindServiceFlags bindFlags;
+                long bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_APP_COMPONENT_USAGE;
                 if (job.shouldTreatAsUserInitiatedJob() && !job.isUserBgRestricted()) {
                     // If the user has bg restricted the app, don't give the job FG privileges
                     // such as bypassing data saver or getting the higher foreground proc state.
                     // If we've gotten to this point, the app is most likely in the foreground,
                     // so the job will run just fine while the user keeps the app in the foreground.
-                    bindFlags = Context.BindServiceFlags.of(
-                            Context.BIND_AUTO_CREATE
-                                    | Context.BIND_ALMOST_PERCEPTIBLE
-                                    | Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS
-                                    | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS
-                                    | Context.BIND_NOT_APP_COMPONENT_USAGE);
+                    bindFlags |= Context.BIND_ALMOST_PERCEPTIBLE;
+                    if (job.hasConnectivityConstraint()) {
+                        // Only add network restriction bypass flags if the job requires network.
+                        bindFlags |= Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS
+                                | Context.BIND_BYPASS_USER_NETWORK_RESTRICTIONS;
+                    }
                     startedWithForegroundFlag = true;
                 } else if (job.shouldTreatAsExpeditedJob() || job.shouldTreatAsUserInitiatedJob()) {
-                    bindFlags = Context.BindServiceFlags.of(
-                            Context.BIND_AUTO_CREATE
-                                    | Context.BIND_NOT_FOREGROUND
-                                    | Context.BIND_ALMOST_PERCEPTIBLE
-                                    | Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS
-                                    | Context.BIND_NOT_APP_COMPONENT_USAGE);
+                    bindFlags |= Context.BIND_NOT_FOREGROUND | Context.BIND_ALMOST_PERCEPTIBLE;
+                    if (job.hasConnectivityConstraint()) {
+                        // Only add network restriction bypass flags if the job requires network.
+                        bindFlags |= Context.BIND_BYPASS_POWER_NETWORK_RESTRICTIONS;
+                    }
                 } else {
-                    bindFlags = Context.BindServiceFlags.of(
-                            Context.BIND_AUTO_CREATE
-                                    | Context.BIND_NOT_FOREGROUND
-                                    | Context.BIND_NOT_PERCEPTIBLE
-                                    | Context.BIND_NOT_APP_COMPONENT_USAGE);
+                    bindFlags |= Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_PERCEPTIBLE;
                 }
-                binding = mContext.bindServiceAsUser(intent, this, bindFlags,
+                binding = mContext.bindServiceAsUser(intent, this,
+                        Context.BindServiceFlags.of(bindFlags),
                         UserHandle.of(job.getUserId()));
             } catch (SecurityException e) {
                 // Some permission policy, for example INTERACT_ACROSS_USERS and
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index 1fdf906..d466f0d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -938,15 +938,6 @@
             if (job.isRequireStorageNotLow()) {
                 out.attribute(null, "storage-not-low", Boolean.toString(true));
             }
-            if (job.isPreferBatteryNotLow()) {
-                out.attributeBoolean(null, "prefer-battery-not-low", true);
-            }
-            if (job.isPreferCharging()) {
-                out.attributeBoolean(null, "prefer-charging", true);
-            }
-            if (job.isPreferDeviceIdle()) {
-                out.attributeBoolean(null, "prefer-idle", true);
-            }
             out.endTag(null, XML_TAG_PARAMS_CONSTRAINTS);
         }
 
@@ -1638,13 +1629,6 @@
             if (val != null) {
                 jobBuilder.setRequiresStorageNotLow(true);
             }
-
-            jobBuilder.setPrefersBatteryNotLow(
-                    parser.getAttributeBoolean(null, "prefer-battery-not-low", false));
-            jobBuilder.setPrefersCharging(
-                    parser.getAttributeBoolean(null, "prefer-charging", false));
-            jobBuilder.setPrefersDeviceIdle(
-                    parser.getAttributeBoolean(null, "prefer-idle", false));
         }
 
         /**
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 63eaa63..ae4e99c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -1263,9 +1263,10 @@
 
         final boolean changed = jobStatus.setConnectivityConstraintSatisfied(nowElapsed, satisfied);
 
-        jobStatus.setHasAccessToUnmetered(satisfied && capabilities != null
-                && capabilities.hasCapability(NET_CAPABILITY_NOT_METERED));
         if (jobStatus.getPreferUnmetered()) {
+            jobStatus.setHasAccessToUnmetered(satisfied && capabilities != null
+                    && capabilities.hasCapability(NET_CAPABILITY_NOT_METERED));
+
             jobStatus.setFlexibilityConstraintSatisfied(nowElapsed,
                     mFlexibilityController.isFlexibilitySatisfiedLocked(jobStatus));
         }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
index b9e3b76..0e03ea1 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
@@ -252,15 +252,15 @@
     boolean isFlexibilitySatisfiedLocked(JobStatus js) {
         return !mFlexibilityEnabled
                 || mService.getUidBias(js.getSourceUid()) == JobInfo.BIAS_TOP_APP
-                || getNumSatisfiedFlexibleConstraintsLocked(js)
+                || getNumSatisfiedRequiredConstraintsLocked(js)
                         >= js.getNumRequiredFlexibleConstraints()
                 || mService.isCurrentlyRunningLocked(js);
     }
 
     @VisibleForTesting
     @GuardedBy("mLock")
-    int getNumSatisfiedFlexibleConstraintsLocked(JobStatus js) {
-        return Integer.bitCount(mSatisfiedFlexibleConstraints & js.getPreferredConstraintFlags())
+    int getNumSatisfiedRequiredConstraintsLocked(JobStatus js) {
+        return Integer.bitCount(mSatisfiedFlexibleConstraints)
                 // Connectivity is job-specific, so must be handled separately.
                 + (js.getHasAccessToUnmetered() ? 1 : 0);
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
index a25af71..47d3fd5 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
@@ -18,13 +18,16 @@
 
 import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.UserHandle;
+import android.provider.DeviceConfig;
 import android.util.ArraySet;
 import android.util.IndentingPrintWriter;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
 import com.android.server.job.controllers.idle.CarIdlenessTracker;
@@ -89,6 +92,19 @@
         }
     }
 
+    @Override
+    public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
+            @NonNull String key) {
+        mIdleTracker.processConstant(properties, key);
+    }
+
+    @Override
+    @GuardedBy("mLock")
+    public void onBatteryStateChangedLocked() {
+        mIdleTracker.onBatteryStateChanged(
+                mService.isBatteryCharging(), mService.isBatteryNotLow());
+    }
+
     /**
      * State-change notifications from the idleness tracker
      */
@@ -119,7 +135,16 @@
         } else {
             mIdleTracker = new DeviceIdlenessTracker();
         }
-        mIdleTracker.startTracking(ctx, this);
+        mIdleTracker.startTracking(ctx, mService, this);
+    }
+
+    @Override
+    public void dumpConstants(IndentingPrintWriter pw) {
+        pw.println();
+        pw.println("IdleController:");
+        pw.increaseIndent();
+        mIdleTracker.dumpConstants(pw);
+        pw.decreaseIndent();
     }
 
     @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 1fb54d5..cb6cc2b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -16,6 +16,7 @@
 
 package com.android.server.job.controllers;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 
 import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
@@ -24,6 +25,8 @@
 import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
 import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
 import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.controllers.FlexibilityController.NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
+import static com.android.server.job.controllers.FlexibilityController.SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
 
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
@@ -124,11 +127,12 @@
     static final int CONSTRAINT_WITHIN_QUOTA = 1 << 24;      // Implicit constraint
     static final int CONSTRAINT_PREFETCH = 1 << 23;
     static final int CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 1 << 22; // Implicit constraint
-    static final int CONSTRAINT_FLEXIBLE = 1 << 21;
+    static final int CONSTRAINT_FLEXIBLE = 1 << 21; // Implicit constraint
 
     private static final int IMPLICIT_CONSTRAINTS = 0
             | CONSTRAINT_BACKGROUND_NOT_RESTRICTED
             | CONSTRAINT_DEVICE_NOT_DOZING
+            | CONSTRAINT_FLEXIBLE
             | CONSTRAINT_TARE_WEALTH
             | CONSTRAINT_WITHIN_QUOTA;
 
@@ -323,7 +327,6 @@
 
     // Constraints.
     final int requiredConstraints;
-    private final int mPreferredConstraints;
     private final int mRequiredConstraintsOfInterest;
     int satisfiedConstraints = 0;
     private int mSatisfiedConstraintsOfInterest = 0;
@@ -668,26 +671,24 @@
         }
         mHasExemptedMediaUrisOnly = exemptedMediaUrisOnly;
 
-        mPreferredConstraints = job.getPreferredConstraintFlags();
+        mPreferUnmetered = job.getRequiredNetwork() != null
+                && !job.getRequiredNetwork().hasCapability(NET_CAPABILITY_NOT_METERED);
 
-        // Exposing a preferredNetworkRequest API requires that we make sure that the preferred
-        // NetworkRequest is a subset of the required NetworkRequest. We currently don't have the
-        // code to ensure that, so disable this part for now.
-        // TODO(236261941): look into enabling flexible network constraint requests
-        mPreferUnmetered = false;
-                // && job.getRequiredNetwork() != null
-                // && !job.getRequiredNetwork().hasCapability(NET_CAPABILITY_NOT_METERED);
-
+        final boolean lacksSomeFlexibleConstraints =
+                ((~requiredConstraints) & SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS) != 0
+                        || mPreferUnmetered;
         final boolean satisfiesMinWindowException =
                 (latestRunTimeElapsedMillis - earliestRunTimeElapsedMillis)
                 >= MIN_WINDOW_FOR_FLEXIBILITY_MS;
 
         // The first time a job is rescheduled it will not be subject to flexible constraints.
         // Otherwise, every consecutive reschedule increases a jobs' flexibility deadline.
-        if (mPreferredConstraints != 0 && !isRequestedExpeditedJob() && !job.isUserInitiated()
+        if (!isRequestedExpeditedJob() && !job.isUserInitiated()
                 && satisfiesMinWindowException
-                && (numFailures + numSystemStops) != 1) {
-            mNumRequiredFlexibleConstraints = Integer.bitCount(mPreferredConstraints);
+                && (numFailures + numSystemStops) != 1
+                && lacksSomeFlexibleConstraints) {
+            mNumRequiredFlexibleConstraints =
+                    NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS + (mPreferUnmetered ? 1 : 0);
             requiredConstraints |= CONSTRAINT_FLEXIBLE;
         } else {
             mNumRequiredFlexibleConstraints = 0;
@@ -1393,10 +1394,6 @@
         mInternalFlags = mInternalFlags & ~flags;
     }
 
-    int getPreferredConstraintFlags() {
-        return mPreferredConstraints;
-    }
-
     public int getSatisfiedConstraintFlags() {
         return satisfiedConstraints;
     }
@@ -2778,9 +2775,6 @@
         pw.print("Required constraints:");
         dumpConstraints(pw, requiredConstraints);
         pw.println();
-        pw.print("Preferred constraints:");
-        dumpConstraints(pw, mPreferredConstraints);
-        pw.println();
         pw.print("Dynamic constraints:");
         dumpConstraints(pw, mDynamicConstraints);
         pw.println();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
index c458cae..ba0e633 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
@@ -16,10 +16,13 @@
 
 package com.android.server.job.controllers.idle;
 
+import android.annotation.NonNull;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.provider.DeviceConfig;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
@@ -73,7 +76,8 @@
     }
 
     @Override
-    public void startTracking(Context context, IdlenessListener listener) {
+    public void startTracking(Context context, JobSchedulerService service,
+            IdlenessListener listener) {
         mIdleListener = listener;
 
         IntentFilter filter = new IntentFilter();
@@ -94,6 +98,15 @@
         context.registerReceiver(this, filter, null, AppSchedulingModuleThread.getHandler());
     }
 
+    /** Process the specified constant and update internal constants if relevant. */
+    public void processConstant(@NonNull DeviceConfig.Properties properties,
+            @NonNull String key) {
+    }
+
+    @Override
+    public void onBatteryStateChanged(boolean isCharging, boolean isBatteryNotLow) {
+    }
+
     @Override
     public void dump(PrintWriter pw) {
         pw.print("  mIdle: "); pw.println(mIdle);
@@ -119,6 +132,10 @@
     }
 
     @Override
+    public void dumpConstants(IndentingPrintWriter pw) {
+    }
+
+    @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
         logIfDebug("Received action: " + action);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
index c943e73..7dd3d13 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
@@ -17,9 +17,12 @@
 package com.android.server.job.controllers.idle;
 
 import static android.app.UiModeManager.PROJECTION_TYPE_NONE;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 
 import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
 
+import android.annotation.NonNull;
 import android.app.AlarmManager;
 import android.app.UiModeManager;
 import android.content.BroadcastReceiver;
@@ -27,10 +30,13 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.PowerManager;
+import android.provider.DeviceConfig;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.AppSchedulingModuleThread;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.job.JobSchedulerService;
@@ -45,17 +51,38 @@
     private static final boolean DEBUG = JobSchedulerService.DEBUG
             || Log.isLoggable(TAG, Log.DEBUG);
 
+    /** Prefix to use with all constant keys in order to "sub-namespace" the keys. */
+    private static final String IC_DIT_CONSTANT_PREFIX = "ic_dit_";
+    @VisibleForTesting
+    static final String KEY_INACTIVITY_IDLE_THRESHOLD_MS =
+            IC_DIT_CONSTANT_PREFIX + "inactivity_idle_threshold_ms";
+    @VisibleForTesting
+    static final String KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS =
+            IC_DIT_CONSTANT_PREFIX + "inactivity_idle_stable_power_threshold_ms";
+    private static final String KEY_IDLE_WINDOW_SLOP_MS =
+            IC_DIT_CONSTANT_PREFIX + "idle_window_slop_ms";
+
     private AlarmManager mAlarm;
     private PowerManager mPowerManager;
 
     // After construction, mutations of idle/screen-on/projection states will only happen
     // on the JobScheduler thread, either in onReceive(), in an alarm callback, or in on.*Changed.
     private long mInactivityIdleThreshold;
+    private long mInactivityStablePowerIdleThreshold;
     private long mIdleWindowSlop;
+    /** Stable power is defined as "charging + battery not low." */
+    private boolean mIsStablePower;
     private boolean mIdle;
     private boolean mScreenOn;
     private boolean mDockIdle;
     private boolean mProjectionActive;
+
+    /**
+     * Time (in the elapsed realtime timebase) when the idleness check was scheduled. This should
+     * be a negative value if the device is not in state to be considered idle.
+     */
+    private long mIdlenessCheckScheduledElapsed = -1;
+
     private IdlenessListener mIdleListener;
     private final UiModeManager.OnProjectionStateChangedListener mOnProjectionStateChangedListener =
             this::onProjectionStateChanged;
@@ -76,10 +103,14 @@
     }
 
     @Override
-    public void startTracking(Context context, IdlenessListener listener) {
+    public void startTracking(Context context, JobSchedulerService service,
+            IdlenessListener listener) {
         mIdleListener = listener;
         mInactivityIdleThreshold = context.getResources().getInteger(
                 com.android.internal.R.integer.config_jobSchedulerInactivityIdleThreshold);
+        mInactivityStablePowerIdleThreshold = context.getResources().getInteger(
+                com.android.internal.R.integer
+                        .config_jobSchedulerInactivityIdleThresholdOnStablePower);
         mIdleWindowSlop = context.getResources().getInteger(
                 com.android.internal.R.integer.config_jobSchedulerIdleWindowSlop);
         mAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -107,6 +138,46 @@
         context.getSystemService(UiModeManager.class).addOnProjectionStateChangedListener(
                 UiModeManager.PROJECTION_TYPE_ALL, AppSchedulingModuleThread.getExecutor(),
                 mOnProjectionStateChangedListener);
+
+        mIsStablePower = service.isBatteryCharging() && service.isBatteryNotLow();
+    }
+
+    /** Process the specified constant and update internal constants if relevant. */
+    public void processConstant(@NonNull DeviceConfig.Properties properties,
+            @NonNull String key) {
+        switch (key) {
+            case KEY_INACTIVITY_IDLE_THRESHOLD_MS:
+                // Keep the threshold in the range [1 minute, 4 hours].
+                mInactivityIdleThreshold = Math.max(MINUTE_IN_MILLIS, Math.min(4 * HOUR_IN_MILLIS,
+                        properties.getLong(key, mInactivityIdleThreshold)));
+                // Don't bother updating any pending alarms. Just wait until the next time we
+                // attempt to check for idle state to use the new value.
+                break;
+            case KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS:
+                // Keep the threshold in the range [1 minute, 4 hours].
+                mInactivityStablePowerIdleThreshold = Math.max(MINUTE_IN_MILLIS,
+                        Math.min(4 * HOUR_IN_MILLIS,
+                                properties.getLong(key, mInactivityStablePowerIdleThreshold)));
+                // Don't bother updating any pending alarms. Just wait until the next time we
+                // attempt to check for idle state to use the new value.
+                break;
+            case KEY_IDLE_WINDOW_SLOP_MS:
+                // Keep the slop in the range [1 minute, 15 minutes].
+                mIdleWindowSlop = Math.max(MINUTE_IN_MILLIS, Math.min(15 * MINUTE_IN_MILLIS,
+                        properties.getLong(key, mIdleWindowSlop)));
+                // Don't bother updating any pending alarms. Just wait until the next time we
+                // attempt to check for idle state to use the new value.
+                break;
+        }
+    }
+
+    @Override
+    public void onBatteryStateChanged(boolean isCharging, boolean isBatteryNotLow) {
+        final boolean isStablePower = isCharging && isBatteryNotLow;
+        if (mIsStablePower != isStablePower) {
+            mIsStablePower = isStablePower;
+            maybeScheduleIdlenessCheck("stable power changed");
+        }
     }
 
     private void onProjectionStateChanged(@UiModeManager.ProjectionType int activeProjectionTypes,
@@ -134,8 +205,10 @@
     public void dump(PrintWriter pw) {
         pw.print("  mIdle: "); pw.println(mIdle);
         pw.print("  mScreenOn: "); pw.println(mScreenOn);
+        pw.print("  mIsStablePower: "); pw.println(mIsStablePower);
         pw.print("  mDockIdle: "); pw.println(mDockIdle);
         pw.print("  mProjectionActive: "); pw.println(mProjectionActive);
+        pw.print("  mIdlenessCheckScheduledElapsed: "); pw.println(mIdlenessCheckScheduledElapsed);
     }
 
     @Override
@@ -162,6 +235,17 @@
     }
 
     @Override
+    public void dumpConstants(IndentingPrintWriter pw) {
+        pw.println("DeviceIdlenessTracker:");
+        pw.increaseIndent();
+        pw.print(KEY_INACTIVITY_IDLE_THRESHOLD_MS, mInactivityIdleThreshold).println();
+        pw.print(KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS, mInactivityStablePowerIdleThreshold)
+                .println();
+        pw.print(KEY_IDLE_WINDOW_SLOP_MS, mIdleWindowSlop).println();
+        pw.decreaseIndent();
+    }
+
+    @Override
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
         if (DEBUG) {
@@ -220,9 +304,24 @@
     private void maybeScheduleIdlenessCheck(String reason) {
         if ((!mScreenOn || mDockIdle) && !mProjectionActive) {
             final long nowElapsed = sElapsedRealtimeClock.millis();
-            final long when = nowElapsed + mInactivityIdleThreshold;
+            final long inactivityThresholdMs = mIsStablePower
+                    ? mInactivityStablePowerIdleThreshold : mInactivityIdleThreshold;
+            if (mIdlenessCheckScheduledElapsed >= 0) {
+                if (mIdlenessCheckScheduledElapsed + inactivityThresholdMs <= nowElapsed) {
+                    if (DEBUG) {
+                        Slog.v(TAG, "Previous idle check @ " + mIdlenessCheckScheduledElapsed
+                                + " allows device to be idle now");
+                    }
+                    handleIdleTrigger();
+                    return;
+                }
+            } else {
+                mIdlenessCheckScheduledElapsed = nowElapsed;
+            }
+            final long when = mIdlenessCheckScheduledElapsed + inactivityThresholdMs;
             if (DEBUG) {
-                Slog.v(TAG, "Scheduling idle : " + reason + " now:" + nowElapsed + " when=" + when);
+                Slog.v(TAG, "Scheduling idle : " + reason + " now:" + nowElapsed
+                        + " checkElapsed=" + mIdlenessCheckScheduledElapsed + " when=" + when);
             }
             mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                     when, mIdleWindowSlop, "JS idleness",
@@ -232,6 +331,7 @@
 
     private void cancelIdlenessCheck() {
         mAlarm.cancel(mIdleAlarmListener);
+        mIdlenessCheckScheduledElapsed = -1;
     }
 
     private void handleIdleTrigger() {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
index cdab7e5..92ad4df 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/IdlenessTracker.java
@@ -16,9 +16,14 @@
 
 package com.android.server.job.controllers.idle;
 
+import android.annotation.NonNull;
 import android.content.Context;
+import android.provider.DeviceConfig;
+import android.util.IndentingPrintWriter;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.server.job.JobSchedulerService;
+
 import java.io.PrintWriter;
 
 public interface IdlenessTracker {
@@ -29,7 +34,7 @@
      * non-interacting state.  When the idle state changes thereafter, the given
      * listener must be called to report the new state.
      */
-    void startTracking(Context context, IdlenessListener listener);
+    void startTracking(Context context, JobSchedulerService service, IdlenessListener listener);
 
     /**
      * Report whether the device is currently considered "idle" for purposes of
@@ -40,6 +45,12 @@
      */
     boolean isIdle();
 
+    /** Process the specified constant and update internal constants if relevant. */
+    void processConstant(@NonNull DeviceConfig.Properties properties, @NonNull String key);
+
+    /** Called when the battery state changes. */
+    void onBatteryStateChanged(boolean isCharging, boolean isBatteryNotLow);
+
     /**
      * Dump useful information about tracked idleness-related state in plaintext.
      */
@@ -49,4 +60,7 @@
      * Dump useful information about tracked idleness-related state to proto.
      */
     void dump(ProtoOutputStream proto, long fieldId);
+
+    /** Dump any internal constants the tracker may have. */
+    void dumpConstants(IndentingPrintWriter pw);
 }
diff --git a/api/Android.bp b/api/Android.bp
index d11ea7b..de4435e 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -251,6 +251,152 @@
     cmd: "cat $(in) | md5sum | cut -d' ' -f1 > $(out)",
 }
 
+packages_to_document = [
+    "android",
+    "dalvik",
+    "java",
+    "javax",
+    "junit",
+    "org.apache.http",
+    "org.json",
+    "org.w3c.dom",
+    "org.xml.sax",
+    "org.xmlpull",
+]
+
+// Defaults for all stubs that include the non-updatable framework. These defaults do not include
+// module symbols, so will not compile correctly on their own. Users must add module APIs to the
+// classpath (or sources) somehow.
+stubs_defaults {
+    name: "android-non-updatable-stubs-defaults",
+    srcs: [":android-non-updatable-stub-sources"],
+    sdk_version: "none",
+    system_modules: "none",
+    java_version: "1.8",
+    arg_files: [":frameworks-base-core-AndroidManifest.xml"],
+    aidl: {
+        include_dirs: [
+            "frameworks/av/aidl",
+            "frameworks/base/media/aidl",
+            "frameworks/base/telephony/java",
+            "frameworks/native/libs/permission/aidl",
+            "packages/modules/Bluetooth/framework/aidl-export",
+            "packages/modules/Connectivity/framework/aidl-export",
+            "packages/modules/Media/apex/aidl/stable",
+            "hardware/interfaces/biometrics/common/aidl",
+            "hardware/interfaces/biometrics/fingerprint/aidl",
+            "hardware/interfaces/graphics/common/aidl",
+            "hardware/interfaces/keymaster/aidl",
+            "system/hardware/interfaces/media/aidl",
+        ],
+    },
+    // These are libs from framework-internal-utils that are required (i.e. being referenced)
+    // from framework-non-updatable-sources. Add more here when there's a need.
+    // DO NOT add the entire framework-internal-utils. It might cause unnecessary circular
+    // dependencies gets bigger.
+    libs: [
+        "android.hardware.cas-V1.2-java",
+        "android.hardware.health-V1.0-java-constants",
+        "android.hardware.thermal-V1.0-java-constants",
+        "android.hardware.thermal-V2.0-java",
+        "android.hardware.tv.input-V1.0-java-constants",
+        "android.hardware.usb-V1.0-java-constants",
+        "android.hardware.usb-V1.1-java-constants",
+        "android.hardware.usb.gadget-V1.0-java",
+        "android.hardware.vibrator-V1.3-java",
+        "framework-protos",
+    ],
+    flags: [
+        "--api-lint-ignore-prefix android.icu.",
+        "--api-lint-ignore-prefix java.",
+        "--api-lint-ignore-prefix junit.",
+        "--api-lint-ignore-prefix org.",
+        "--error NoSettingsProvider",
+        "--error UnhiddenSystemApi",
+        "--error UnflaggedApi",
+        "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*",
+        // Disable CallbackInterface, as Java 8 default interface methods avoid the extensibility
+        // issue interfaces had previously.
+        "--hide CallbackInterface",
+        // Disable HiddenSuperclass, as Metalava handles this fine (it should be hidden by default)
+        "--hide HiddenSuperclass",
+        "--hide-package android.audio.policy.configuration.V7_0",
+        "--hide-package com.android.server",
+        "--manifest $(location :frameworks-base-core-AndroidManifest.xml)",
+    ],
+    filter_packages: packages_to_document,
+    high_mem: true, // Lots of sources => high memory use, see b/170701554
+    installable: false,
+    annotations_enabled: true,
+    previous_api: ":android.api.public.latest",
+    merge_annotations_dirs: ["metalava-manual"],
+    defaults_visibility: ["//frameworks/base/api"],
+    visibility: ["//frameworks/base/api"],
+}
+
+// Defaults with module APIs in the classpath (mostly from prebuilts).
+// Suitable for compiling android-non-updatable.
+stubs_defaults {
+    name: "module-classpath-stubs-defaults",
+    aidl: {
+        include_dirs: [
+            "packages/modules/Bluetooth/framework/aidl-export",
+            "packages/modules/Connectivity/framework/aidl-export",
+            "packages/modules/Media/apex/aidl/stable",
+        ],
+    },
+    libs: [
+        "art.module.public.api",
+        "sdk_module-lib_current_framework-tethering",
+        "sdk_module-lib_current_framework-connectivity-t",
+        "sdk_public_current_framework-bluetooth",
+        // There are a few classes from modules used by the core that
+        // need to be resolved by metalava. We use a prebuilt stub of the
+        // full sdk to ensure we can resolve them. If a new class gets added,
+        // the prebuilts/sdk/current needs to be updated.
+        "sdk_system_current_android",
+        // NOTE: The below can be removed once the prebuilt stub contains IKE.
+        "sdk_system_current_android.net.ipsec.ike",
+    ],
+}
+
+// Defaults for the java_sdk_libraries of unbundled jars from framework.
+// java_sdk_libraries using these defaults should also add themselves to the
+// non_updatable_modules list in frameworks/base/api/api.go
+java_defaults {
+    name: "framework-non-updatable-unbundled-defaults",
+    defaults: [
+        "framework-non-updatable-lint-defaults",
+        "non-updatable-framework-module-defaults",
+    ],
+    public: {
+        libs: ["android_module_lib_stubs_current"],
+    },
+    system: {
+        libs: ["android_module_lib_stubs_current"],
+    },
+    module_lib: {
+        libs: ["android_module_lib_stubs_current"],
+    },
+    test: {
+        libs: ["android_test_frameworks_core_stubs_current"],
+    },
+    sdk_version: "core_platform",
+    stub_only_libs: ["framework-protos"],
+    impl_only_libs: ["framework-minus-apex-headers"], // the framework, including hidden API
+    impl_library_visibility: ["//frameworks/base"],
+    defaults_visibility: ["//frameworks/base/location"],
+    plugins: ["error_prone_android_framework"],
+    errorprone: {
+        javacflags: [
+            "-Xep:AndroidFrameworkCompatChange:ERROR",
+            "-Xep:AndroidFrameworkUid:ERROR",
+        ],
+    },
+    // Include manual annotations in API txt files
+    merge_annotations_dirs: ["metalava-manual"],
+}
+
 build = [
     "ApiDocs.bp",
     "StubLibraries.bp",
diff --git a/api/ApiDocs.bp b/api/ApiDocs.bp
index 5744bdf..bcfb68f 100644
--- a/api/ApiDocs.bp
+++ b/api/ApiDocs.bp
@@ -30,6 +30,18 @@
         ":android-test-mock-sources",
         ":android-test-runner-sources",
     ],
+    flags: [
+        // These errors are suppressed in the doc stubs as it isn't easy to suppress them.
+        // They remain unsuppressed/active in the "main" stubs build (the jar stubs).
+        // These can be removed when either a) all the issues have been fixed or
+        // b) these reporting of these issues is gated behind api lint being enabled in metalava.
+        "--hide BroadcastBehavior",
+        "--hide DeprecationMismatch",
+        "--hide MissingPermission",
+        "--hide RequiresPermission",
+        "--hide SdkConstant",
+        "--hide Todo",
+    ],
     create_doc_stubs: true,
     write_sdk_values: true,
 }
diff --git a/core/api/current.txt b/core/api/current.txt
index 7e3da22..013010b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6727,7 +6727,7 @@
     field protected android.app.Notification.Builder mBuilder;
   }
 
-  public static final class Notification.TvExtender implements android.app.Notification.Extender {
+  @FlaggedApi("android.app.api_tvextender") public static final class Notification.TvExtender implements android.app.Notification.Extender {
     ctor public Notification.TvExtender();
     ctor public Notification.TvExtender(@NonNull android.app.Notification);
     method @NonNull public android.app.Notification.Builder extend(@NonNull android.app.Notification.Builder);
@@ -9321,6 +9321,21 @@
     field public static final int USER_INTERACTION = 7; // 0x7
   }
 
+  @FlaggedApi("android.app.usage.filter_based_event_query_api") public final class UsageEventsQuery implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getBeginTimeMillis();
+    method public long getEndTimeMillis();
+    method @NonNull public java.util.Set<java.lang.Integer> getEventTypes();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.UsageEventsQuery> CREATOR;
+  }
+
+  public static final class UsageEventsQuery.Builder {
+    ctor public UsageEventsQuery.Builder(long, long);
+    method @NonNull public android.app.usage.UsageEventsQuery.Builder addEventTypes(@NonNull int...);
+    method @NonNull public android.app.usage.UsageEventsQuery build();
+  }
+
   public final class UsageStats implements android.os.Parcelable {
     ctor public UsageStats(android.app.usage.UsageStats);
     method public void add(android.app.usage.UsageStats);
@@ -9345,6 +9360,7 @@
     method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long);
     method public java.util.List<android.app.usage.EventStats> queryEventStats(int, long, long);
     method public android.app.usage.UsageEvents queryEvents(long, long);
+    method @FlaggedApi("android.app.usage.filter_based_event_query_api") @NonNull @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public android.app.usage.UsageEvents queryEvents(@NonNull android.app.usage.UsageEventsQuery);
     method public android.app.usage.UsageEvents queryEventsForSelf(long, long);
     method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long);
     field public static final int INTERVAL_BEST = 4; // 0x4
@@ -18526,11 +18542,13 @@
   public class BiometricManager {
     method @Deprecated @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public int canAuthenticate();
     method @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public int canAuthenticate(int);
+    method @FlaggedApi("android.hardware.biometrics.last_authentication_time") @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public long getLastAuthenticationTime(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.USE_BIOMETRIC) public android.hardware.biometrics.BiometricManager.Strings getStrings(int);
     field public static final int BIOMETRIC_ERROR_HW_UNAVAILABLE = 1; // 0x1
     field public static final int BIOMETRIC_ERROR_NONE_ENROLLED = 11; // 0xb
     field public static final int BIOMETRIC_ERROR_NO_HARDWARE = 12; // 0xc
     field public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15; // 0xf
+    field @FlaggedApi("android.hardware.biometrics.last_authentication_time") public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
     field public static final int BIOMETRIC_SUCCESS = 0; // 0x0
   }
 
@@ -18576,6 +18594,7 @@
     field public static final int BIOMETRIC_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
     field public static final int BIOMETRIC_ERROR_USER_CANCELED = 10; // 0xa
     field public static final int BIOMETRIC_ERROR_VENDOR = 8; // 0x8
+    field @FlaggedApi("android.hardware.biometrics.last_authentication_time") public static final long BIOMETRIC_NO_AUTHENTICATION = -1L; // 0xffffffffffffffffL
   }
 
   public abstract static class BiometricPrompt.AuthenticationCallback {
@@ -18614,6 +18633,7 @@
     method @Deprecated @Nullable public android.security.identity.IdentityCredential getIdentityCredential();
     method @FlaggedApi("android.hardware.biometrics.add_key_agreement_crypto_object") @Nullable public javax.crypto.KeyAgreement getKeyAgreement();
     method @Nullable public javax.crypto.Mac getMac();
+    method @FlaggedApi("android.hardware.biometrics.get_op_id_crypto_object") public long getOpId();
     method @Nullable public android.security.identity.PresentationSession getPresentationSession();
     method @Nullable public java.security.Signature getSignature();
   }
@@ -23842,14 +23862,14 @@
     field @FlaggedApi("com.android.media.flags.enable_audio_policies_device_and_bluetooth_controller") public static final int TYPE_HDMI_EARC = 29; // 0x1d
     field public static final int TYPE_HEARING_AID = 23; // 0x17
     field public static final int TYPE_REMOTE_AUDIO_VIDEO_RECEIVER = 1003; // 0x3eb
-    field public static final int TYPE_REMOTE_CAR = 1008; // 0x3f0
-    field public static final int TYPE_REMOTE_COMPUTER = 1006; // 0x3ee
-    field public static final int TYPE_REMOTE_GAME_CONSOLE = 1007; // 0x3ef
-    field public static final int TYPE_REMOTE_SMARTPHONE = 1010; // 0x3f2
-    field public static final int TYPE_REMOTE_SMARTWATCH = 1009; // 0x3f1
+    field @FlaggedApi("com.android.media.flags.enable_new_media_route_2_info_types") public static final int TYPE_REMOTE_CAR = 1008; // 0x3f0
+    field @FlaggedApi("com.android.media.flags.enable_new_media_route_2_info_types") public static final int TYPE_REMOTE_COMPUTER = 1006; // 0x3ee
+    field @FlaggedApi("com.android.media.flags.enable_new_media_route_2_info_types") public static final int TYPE_REMOTE_GAME_CONSOLE = 1007; // 0x3ef
+    field @FlaggedApi("com.android.media.flags.enable_new_media_route_2_info_types") public static final int TYPE_REMOTE_SMARTPHONE = 1010; // 0x3f2
+    field @FlaggedApi("com.android.media.flags.enable_new_media_route_2_info_types") public static final int TYPE_REMOTE_SMARTWATCH = 1009; // 0x3f1
     field public static final int TYPE_REMOTE_SPEAKER = 1002; // 0x3ea
-    field public static final int TYPE_REMOTE_TABLET = 1004; // 0x3ec
-    field public static final int TYPE_REMOTE_TABLET_DOCKED = 1005; // 0x3ed
+    field @FlaggedApi("com.android.media.flags.enable_new_media_route_2_info_types") public static final int TYPE_REMOTE_TABLET = 1004; // 0x3ec
+    field @FlaggedApi("com.android.media.flags.enable_new_media_route_2_info_types") public static final int TYPE_REMOTE_TABLET_DOCKED = 1005; // 0x3ed
     field public static final int TYPE_REMOTE_TV = 1001; // 0x3e9
     field public static final int TYPE_UNKNOWN = 0; // 0x0
     field public static final int TYPE_USB_ACCESSORY = 12; // 0xc
@@ -25847,15 +25867,15 @@
     method public abstract void onDisconnect(android.media.midi.MidiReceiver);
   }
 
-  @FlaggedApi("com.android.media.midi.flags.virtual_ump") public abstract class MidiUmpDeviceService extends android.app.Service {
+  @FlaggedApi("android.media.midi.virtual_ump") public abstract class MidiUmpDeviceService extends android.app.Service {
     ctor public MidiUmpDeviceService();
-    method @FlaggedApi("com.android.media.midi.flags.virtual_ump") @Nullable public final android.media.midi.MidiDeviceInfo getDeviceInfo();
-    method @FlaggedApi("com.android.media.midi.flags.virtual_ump") @NonNull public final java.util.List<android.media.midi.MidiReceiver> getOutputPortReceivers();
-    method @FlaggedApi("com.android.media.midi.flags.virtual_ump") @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
-    method @FlaggedApi("com.android.media.midi.flags.virtual_ump") public void onClose();
-    method @FlaggedApi("com.android.media.midi.flags.virtual_ump") public void onDeviceStatusChanged(@NonNull android.media.midi.MidiDeviceStatus);
-    method @FlaggedApi("com.android.media.midi.flags.virtual_ump") @NonNull public abstract java.util.List<android.media.midi.MidiReceiver> onGetInputPortReceivers();
-    field @FlaggedApi("com.android.media.midi.flags.virtual_ump") public static final String SERVICE_INTERFACE = "android.media.midi.MidiUmpDeviceService";
+    method @FlaggedApi("android.media.midi.virtual_ump") @Nullable public final android.media.midi.MidiDeviceInfo getDeviceInfo();
+    method @FlaggedApi("android.media.midi.virtual_ump") @NonNull public final java.util.List<android.media.midi.MidiReceiver> getOutputPortReceivers();
+    method @FlaggedApi("android.media.midi.virtual_ump") @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
+    method @FlaggedApi("android.media.midi.virtual_ump") public void onClose();
+    method @FlaggedApi("android.media.midi.virtual_ump") public void onDeviceStatusChanged(@NonNull android.media.midi.MidiDeviceStatus);
+    method @FlaggedApi("android.media.midi.virtual_ump") @NonNull public abstract java.util.List<android.media.midi.MidiReceiver> onGetInputPortReceivers();
+    field @FlaggedApi("android.media.midi.virtual_ump") public static final String SERVICE_INTERFACE = "android.media.midi.MidiUmpDeviceService";
   }
 
 }
@@ -28503,12 +28523,12 @@
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addGatewayOption(int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build();
-    method @FlaggedApi("android.net.vcn.safe_mode_config") @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder enableSafeMode(boolean);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeGatewayOption(int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=0x500) int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMinUdpPort4500NatTimeoutSeconds(@IntRange(from=0x78) int);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryIntervalsMillis(@NonNull long[]);
+    method @FlaggedApi("android.net.vcn.safe_mode_config") @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setSafeModeEnabled(boolean);
     method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setVcnUnderlyingNetworkPriorities(@NonNull java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate>);
   }
 
@@ -49810,6 +49830,7 @@
     method public default void removeOnBufferTransformHintChangedListener(@NonNull android.view.AttachedSurfaceControl.OnBufferTransformHintChangedListener);
     method public default void setChildBoundingInsets(@NonNull android.graphics.Rect);
     method public default void setTouchableRegion(@Nullable android.graphics.Region);
+    method @FlaggedApi("com.android.window.flags.transfer_gesture_to_embedded") public default boolean transferHostTouchGestureToEmbedded(@NonNull android.view.SurfaceControlViewHost.SurfacePackage);
   }
 
   @UiThread public static interface AttachedSurfaceControl.OnBufferTransformHintChangedListener {
diff --git a/core/api/lint-baseline.txt b/core/api/lint-baseline.txt
index afb10f5..1e6aa49 100644
--- a/core/api/lint-baseline.txt
+++ b/core/api/lint-baseline.txt
@@ -1,4 +1,1168 @@
 // Baseline format: 1.0
+BroadcastBehavior: android.app.AlarmManager#ACTION_NEXT_ALARM_CLOCK_CHANGED:
+    Field 'ACTION_NEXT_ALARM_CLOCK_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.AlarmManager#ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED:
+    Field 'ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED:
+    Field 'ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_MANAGED_PROFILE_PROVISIONED:
+    Field 'ACTION_MANAGED_PROFILE_PROVISIONED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_AIRPLANE_MODE_CHANGED:
+    Field 'ACTION_AIRPLANE_MODE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_LOCALE_CHANGED:
+    Field 'ACTION_APPLICATION_LOCALE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED:
+    Field 'ACTION_APPLICATION_RESTRICTIONS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_CHANGED:
+    Field 'ACTION_BATTERY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_LOW:
+    Field 'ACTION_BATTERY_LOW' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_OKAY:
+    Field 'ACTION_BATTERY_OKAY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CAMERA_BUTTON:
+    Field 'ACTION_CAMERA_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CLOSE_SYSTEM_DIALOGS:
+    Field 'ACTION_CLOSE_SYSTEM_DIALOGS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CONFIGURATION_CHANGED:
+    Field 'ACTION_CONFIGURATION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DATE_CHANGED:
+    Field 'ACTION_DATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_LOW:
+    Field 'ACTION_DEVICE_STORAGE_LOW' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_OK:
+    Field 'ACTION_DEVICE_STORAGE_OK' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DOCK_EVENT:
+    Field 'ACTION_DOCK_EVENT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STARTED:
+    Field 'ACTION_DREAMING_STARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STOPPED:
+    Field 'ACTION_DREAMING_STOPPED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
+    Field 'ACTION_EXTERNAL_APPLICATIONS_AVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+    Field 'ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_CONNECTED:
+    Field 'ACTION_GTALK_SERVICE_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_DISCONNECTED:
+    Field 'ACTION_GTALK_SERVICE_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_HEADSET_PLUG:
+    Field 'ACTION_HEADSET_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INPUT_METHOD_CHANGED:
+    Field 'ACTION_INPUT_METHOD_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOCALE_CHANGED:
+    Field 'ACTION_LOCALE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED:
+    Field 'ACTION_LOCKED_BOOT_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MANAGE_PACKAGE_STORAGE:
+    Field 'ACTION_MANAGE_PACKAGE_STORAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BAD_REMOVAL:
+    Field 'ACTION_MEDIA_BAD_REMOVAL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BUTTON:
+    Field 'ACTION_MEDIA_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_CHECKING:
+    Field 'ACTION_MEDIA_CHECKING' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_EJECT:
+    Field 'ACTION_MEDIA_EJECT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_MOUNTED:
+    Field 'ACTION_MEDIA_MOUNTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_NOFS:
+    Field 'ACTION_MEDIA_NOFS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_REMOVED:
+    Field 'ACTION_MEDIA_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_FINISHED:
+    Field 'ACTION_MEDIA_SCANNER_FINISHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_SCAN_FILE:
+    Field 'ACTION_MEDIA_SCANNER_SCAN_FILE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_STARTED:
+    Field 'ACTION_MEDIA_SCANNER_STARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SHARED:
+    Field 'ACTION_MEDIA_SHARED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTABLE:
+    Field 'ACTION_MEDIA_UNMOUNTABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTED:
+    Field 'ACTION_MEDIA_UNMOUNTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_REPLACED:
+    Field 'ACTION_MY_PACKAGE_REPLACED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_SUSPENDED:
+    Field 'ACTION_MY_PACKAGE_SUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_UNSUSPENDED:
+    Field 'ACTION_MY_PACKAGE_UNSUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_NEW_OUTGOING_CALL:
+    Field 'ACTION_NEW_OUTGOING_CALL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_SUSPENDED:
+    Field 'ACTION_PACKAGES_SUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_UNSUSPENDED:
+    Field 'ACTION_PACKAGES_UNSUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_ADDED:
+    Field 'ACTION_PACKAGE_ADDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_CHANGED:
+    Field 'ACTION_PACKAGE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_DATA_CLEARED:
+    Field 'ACTION_PACKAGE_DATA_CLEARED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FIRST_LAUNCH:
+    Field 'ACTION_PACKAGE_FIRST_LAUNCH' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FULLY_REMOVED:
+    Field 'ACTION_PACKAGE_FULLY_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_INSTALL:
+    Field 'ACTION_PACKAGE_INSTALL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_NEEDS_VERIFICATION:
+    Field 'ACTION_PACKAGE_NEEDS_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REMOVED:
+    Field 'ACTION_PACKAGE_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REPLACED:
+    Field 'ACTION_PACKAGE_REPLACED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_RESTARTED:
+    Field 'ACTION_PACKAGE_RESTARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_UNSTOPPED:
+    Field 'ACTION_PACKAGE_UNSTOPPED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_VERIFIED:
+    Field 'ACTION_PACKAGE_VERIFIED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_POWER_CONNECTED:
+    Field 'ACTION_POWER_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_POWER_DISCONNECTED:
+    Field 'ACTION_POWER_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PROVIDER_CHANGED:
+    Field 'ACTION_PROVIDER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_REBOOT:
+    Field 'ACTION_REBOOT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_OFF:
+    Field 'ACTION_SCREEN_OFF' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_ON:
+    Field 'ACTION_SCREEN_ON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SHUTDOWN:
+    Field 'ACTION_SHUTDOWN' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIMEZONE_CHANGED:
+    Field 'ACTION_TIMEZONE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIME_CHANGED:
+    Field 'ACTION_TIME_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIME_TICK:
+    Field 'ACTION_TIME_TICK' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UID_REMOVED:
+    Field 'ACTION_UID_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UMS_CONNECTED:
+    Field 'ACTION_UMS_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UMS_DISCONNECTED:
+    Field 'ACTION_UMS_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_USER_PRESENT:
+    Field 'ACTION_USER_PRESENT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_USER_UNLOCKED:
+    Field 'ACTION_USER_UNLOCKED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_WALLPAPER_CHANGED:
+    Field 'ACTION_WALLPAPER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_COMMITTED:
+    Field 'ACTION_SESSION_COMMITTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_UPDATED:
+    Field 'ACTION_SESSION_UPDATED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_PICTURE:
+    Field 'ACTION_NEW_PICTURE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_VIDEO:
+    Field 'ACTION_NEW_VIDEO' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.input.InputManager#ACTION_QUERY_KEYBOARD_LAYOUTS:
+    Field 'ACTION_QUERY_KEYBOARD_LAYOUTS' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_ACCESSORY_DETACHED:
+    Field 'ACTION_USB_ACCESSORY_DETACHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_DEVICE_DETACHED:
+    Field 'ACTION_USB_DEVICE_DETACHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_HDMI_AUDIO_PLUG:
+    Field 'ACTION_HDMI_AUDIO_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_HEADSET_PLUG:
+    Field 'ACTION_HEADSET_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_MICROPHONE_MUTE_CHANGED:
+    Field 'ACTION_MICROPHONE_MUTE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_SPEAKERPHONE_STATE_CHANGED:
+    Field 'ACTION_SPEAKERPHONE_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_INITIALIZE_PROGRAMS:
+    Field 'ACTION_INITIALIZE_PROGRAMS' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT:
+    Field 'ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED:
+    Field 'ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED:
+    Field 'ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.Proxy#PROXY_CHANGE_ACTION:
+    Field 'PROXY_CHANGE_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
+    Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
+    Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
+    Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.os.DropBoxManager#ACTION_DROPBOX_ENTRY_ADDED:
+    Field 'ACTION_DROPBOX_ENTRY_ADDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.CalendarContract#ACTION_EVENT_REMINDER:
+    Field 'ACTION_EVENT_REMINDER' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.ContactsContract.SimContacts#ACTION_SIM_ACCOUNTS_CHANGED:
+    Field 'ACTION_SIM_ACCOUNTS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#DATA_SMS_RECEIVED_ACTION:
+    Field 'DATA_SMS_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SECRET_CODE_ACTION:
+    Field 'SECRET_CODE_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SIM_FULL_ACTION:
+    Field 'SIM_FULL_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION:
+    Field 'SMS_CB_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION:
+    Field 'SMS_DELIVER_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION:
+    Field 'SMS_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_REJECTED_ACTION:
+    Field 'SMS_REJECTED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION:
+    Field 'SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION:
+    Field 'WAP_PUSH_DELIVER_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_RECEIVED_ACTION:
+    Field 'WAP_PUSH_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_KEYCHAIN_CHANGED:
+    Field 'ACTION_KEYCHAIN_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_KEY_ACCESS_CHANGED:
+    Field 'ACTION_KEY_ACCESS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_STORAGE_CHANGED:
+    Field 'ACTION_STORAGE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_TRUST_STORE_CHANGED:
+    Field 'ACTION_TRUST_STORE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.speech.tts.TextToSpeech#ACTION_TTS_QUEUE_PROCESSING_COMPLETED:
+    Field 'ACTION_TTS_QUEUE_PROCESSING_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.speech.tts.TextToSpeech.Engine#ACTION_TTS_DATA_INSTALLED:
+    Field 'ACTION_TTS_DATA_INSTALLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_REFRESH_SUBSCRIPTION_PLANS:
+    Field 'ACTION_REFRESH_SUBSCRIPTION_PLANS' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE:
+    Field 'ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_PCO_VALUE:
+    Field 'ACTION_CARRIER_SIGNAL_PCO_VALUE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_REDIRECTED:
+    Field 'ACTION_CARRIER_SIGNAL_REDIRECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED:
+    Field 'ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_RESET:
+    Field 'ACTION_CARRIER_SIGNAL_RESET' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SECRET_CODE:
+    Field 'ACTION_SECRET_CODE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.euicc.EuiccManager#ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE:
+    Field 'ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE' is missing @BroadcastBehavior
+
+
+DeprecationMismatch: android.accounts.AccountManager#newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle):
+    Method android.accounts.AccountManager.newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Activity#enterPictureInPictureMode():
+    Method android.app.Activity.enterPictureInPictureMode(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Instrumentation#startAllocCounting():
+    Method android.app.Instrumentation.startAllocCounting(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Instrumentation#stopAllocCounting():
+    Method android.app.Instrumentation.stopAllocCounting(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#bigContentView:
+    Field Notification.bigContentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#contentView:
+    Field Notification.contentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#headsUpContentView:
+    Field Notification.headsUpContentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#tickerView:
+    Field Notification.tickerView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.Builder#Builder(int, CharSequence, android.app.PendingIntent):
+    Constructor android.app.Notification.Action.Builder.Builder(int, CharSequence, android.app.PendingIntent): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getCancelLabel():
+    Method android.app.Notification.Action.WearableExtender.getCancelLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getConfirmLabel():
+    Method android.app.Notification.Action.WearableExtender.getConfirmLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getInProgressLabel():
+    Method android.app.Notification.Action.WearableExtender.getInProgressLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setCancelLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setCancelLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setConfirmLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setConfirmLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setInProgressLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setInProgressLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Builder#setContent(android.widget.RemoteViews):
+    Method android.app.Notification.Builder.setContent(android.widget.RemoteViews): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Builder#setTicker(CharSequence, android.widget.RemoteViews):
+    Method android.app.Notification.Builder.setTicker(CharSequence, android.widget.RemoteViews): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIcon():
+    Method android.app.Notification.WearableExtender.getContentIcon(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIconGravity():
+    Method android.app.Notification.WearableExtender.getContentIconGravity(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomContentHeight():
+    Method android.app.Notification.WearableExtender.getCustomContentHeight(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomSizePreset():
+    Method android.app.Notification.WearableExtender.getCustomSizePreset(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getGravity():
+    Method android.app.Notification.WearableExtender.getGravity(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintAvoidBackgroundClipping():
+    Method android.app.Notification.WearableExtender.getHintAvoidBackgroundClipping(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintHideIcon():
+    Method android.app.Notification.WearableExtender.getHintHideIcon(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintScreenTimeout():
+    Method android.app.Notification.WearableExtender.getHintScreenTimeout(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintShowBackgroundOnly():
+    Method android.app.Notification.WearableExtender.getHintShowBackgroundOnly(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIcon(int):
+    Method android.app.Notification.WearableExtender.setContentIcon(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIconGravity(int):
+    Method android.app.Notification.WearableExtender.setContentIconGravity(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomContentHeight(int):
+    Method android.app.Notification.WearableExtender.setCustomContentHeight(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomSizePreset(int):
+    Method android.app.Notification.WearableExtender.setCustomSizePreset(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setGravity(int):
+    Method android.app.Notification.WearableExtender.setGravity(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintAvoidBackgroundClipping(boolean):
+    Method android.app.Notification.WearableExtender.setHintAvoidBackgroundClipping(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintHideIcon(boolean):
+    Method android.app.Notification.WearableExtender.setHintHideIcon(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintScreenTimeout(int):
+    Method android.app.Notification.WearableExtender.setHintScreenTimeout(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintShowBackgroundOnly(boolean):
+    Method android.app.Notification.WearableExtender.setHintShowBackgroundOnly(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.ComposeShader#ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode):
+    Constructor android.graphics.ComposeShader.ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#A_8:
+    Field PixelFormat.A_8: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#LA_88:
+    Field PixelFormat.LA_88: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#L_8:
+    Field PixelFormat.L_8: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_4444:
+    Field PixelFormat.RGBA_4444: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_5551:
+    Field PixelFormat.RGBA_5551: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGB_332:
+    Field PixelFormat.RGB_332: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.EGL14#eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int):
+    Method android.opengl.EGL14.eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.GLES20#GL_STENCIL_INDEX:
+    Field GLES20.GL_STENCIL_INDEX: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.GLSurfaceView#surfaceRedrawNeeded(android.view.SurfaceHolder):
+    Method android.opengl.GLSurfaceView.surfaceRedrawNeeded(android.view.SurfaceHolder): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle):
+    Method android.os.UserManager.setUserRestrictions(android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle, android.os.UserHandle):
+    Method android.os.UserManager.setUserRestrictions(android.os.Bundle, android.os.UserHandle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.provider.Contacts.People#markAsContacted(android.content.ContentResolver, long):
+    Method android.provider.Contacts.People.markAsContacted(android.content.ContentResolver, long): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_X:
+    Field Type.CubemapFace.POSITVE_X: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Y:
+    Field Type.CubemapFace.POSITVE_Y: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Z:
+    Field Type.CubemapFace.POSITVE_Z: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.speech.tts.TextToSpeech#areDefaultsEnforced():
+    Method android.speech.tts.TextToSpeech.areDefaultsEnforced(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.PhoneStateListener#PhoneStateListener(java.util.concurrent.Executor):
+    Constructor android.telephony.PhoneStateListener.PhoneStateListener(java.util.concurrent.Executor): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_12HOUR:
+    Field DateUtils.FORMAT_12HOUR: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_24HOUR:
+    Field DateUtils.FORMAT_24HOUR: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_AMPM:
+    Field DateUtils.FORMAT_CAP_AMPM: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_MIDNIGHT:
+    Field DateUtils.FORMAT_CAP_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON:
+    Field DateUtils.FORMAT_CAP_NOON: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON_MIDNIGHT:
+    Field DateUtils.FORMAT_CAP_NOON_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_NO_NOON_MIDNIGHT:
+    Field DateUtils.FORMAT_NO_NOON_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.ViewGroup.LayoutParams#FILL_PARENT:
+    Field ViewGroup.LayoutParams.FILL_PARENT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.Window#setTitleColor(int):
+    Method android.view.Window.setTitleColor(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.accessibility.AccessibilityEvent#MAX_TEXT_LENGTH:
+    Field AccessibilityEvent.MAX_TEXT_LENGTH: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebSettings#getSaveFormData():
+    Method android.webkit.WebSettings.getSaveFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebView#shouldDelayChildPressedState():
+    Method android.webkit.WebView.shouldDelayChildPressedState(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebViewDatabase#clearFormData():
+    Method android.webkit.WebViewDatabase.clearFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebViewDatabase#hasFormData():
+    Method android.webkit.WebViewDatabase.hasFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: javax.microedition.khronos.egl.EGL10#eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]):
+    Method javax.microedition.khronos.egl.EGL10.eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+
+
+RequiresPermission: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
+    Method 'getAccountsByTypeAndFeatures' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+    Method 'hasFeatures' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getHistoricalProcessExitReasons(String, int, int):
+    Method 'getHistoricalProcessExitReasons' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getProcessesInErrorState():
+    Method 'getProcessesInErrorState' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent):
+    Method 'setAlarmClock' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setExact(int, long, android.app.PendingIntent):
+    Method 'setExact' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setExactAndAllowWhileIdle(int, long, android.app.PendingIntent):
+    Method 'setExactAndAllowWhileIdle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setTime(long):
+    Method 'setTime' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#isOpActive(String, int, String):
+    Method 'isOpActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#startWatchingActive(String[], java.util.concurrent.Executor, android.app.AppOpsManager.OnOpActiveChangedListener):
+    Method 'startWatchingActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setDestinationInExternalPublicDir(String, String):
+    Method 'setDestinationInExternalPublicDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setDestinationUri(android.net.Uri):
+    Method 'setDestinationUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setNotificationVisibility(int):
+    Method 'setNotificationVisibility' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setShowRunningNotification(boolean):
+    Method 'setShowRunningNotification' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.LocaleManager#getApplicationLocales(String):
+    Method 'getApplicationLocales' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.Notification.Builder#setFullScreenIntent(android.app.PendingIntent, boolean):
+    Method 'setFullScreenIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.NotificationManager#canUseFullScreenIntent():
+    Method 'canUseFullScreenIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.Service#startForeground(int, android.app.Notification):
+    Method 'startForeground' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.StatusBarManager#canLaunchCaptureContentActivityForNote(android.app.Activity):
+    Method 'canLaunchCaptureContentActivityForNote' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperInfo#getSettingsSliceUri():
+    Method 'getSettingsSliceUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#clear():
+    Method 'clear' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getDrawable():
+    Method 'getDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getDrawable(int):
+    Method 'getDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getFastDrawable():
+    Method 'getFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getFastDrawable(int):
+    Method 'getFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getWallpaperFile(int):
+    Method 'getWallpaperFile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getWallpaperInfo(int):
+    Method 'getWallpaperInfo' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekDrawable():
+    Method 'peekDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekDrawable(int):
+    Method 'peekDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekFastDrawable():
+    Method 'peekFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekFastDrawable(int):
+    Method 'peekFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap):
+    Method 'setBitmap' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean):
+    Method 'setBitmap' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setDisplayPadding(android.graphics.Rect):
+    Method 'setDisplayPadding' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setResource(int):
+    Method 'setResource' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream):
+    Method 'setStream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream, android.graphics.Rect, boolean):
+    Method 'setStream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#suggestDesiredDimensions(int, int):
+    Method 'suggestDesiredDimensions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#addCrossProfileWidgetProvider(android.content.ComponentName, String):
+    Method 'addCrossProfileWidgetProvider' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName):
+    Method 'addPersistentPreferredActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    Method 'bindDeviceAdminServiceAsUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#clearPackagePersistentPreferredActivities(android.content.ComponentName, String):
+    Method 'clearPackagePersistentPreferredActivities' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#clearResetPasswordToken(android.content.ComponentName):
+    Method 'clearResetPasswordToken' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#generateKeyPair(android.content.ComponentName, String, android.security.keystore.KeyGenParameterSpec, int):
+    Method 'generateKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getCrossProfileWidgetProviders(android.content.ComponentName):
+    Method 'getCrossProfileWidgetProviders' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getLockTaskFeatures(android.content.ComponentName):
+    Method 'getLockTaskFeatures' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getLockTaskPackages(android.content.ComponentName):
+    Method 'getLockTaskPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getNearbyAppStreamingPolicy():
+    Method 'getNearbyAppStreamingPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getNearbyNotificationStreamingPolicy():
+    Method 'getNearbyNotificationStreamingPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getOrganizationName(android.content.ComponentName):
+    Method 'getOrganizationName' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getPasswordComplexity():
+    Method 'getPasswordComplexity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getShortSupportMessage(android.content.ComponentName):
+    Method 'getShortSupportMessage' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getUserControlDisabledPackages(android.content.ComponentName):
+    Method 'getUserControlDisabledPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#hasKeyPair(String):
+    Method 'hasKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, String):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], String, boolean):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], String, int):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isPackageSuspended(android.content.ComponentName, String):
+    Method 'isPackageSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isResetPasswordTokenActive(android.content.ComponentName):
+    Method 'isResetPasswordTokenActive' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#lockNow(int):
+    Method 'lockNow' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#removeCrossProfileWidgetProvider(android.content.ComponentName, String):
+    Method 'removeCrossProfileWidgetProvider' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setAlwaysOnVpnPackage(android.content.ComponentName, String, boolean):
+    Method 'setAlwaysOnVpnPackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setLockTaskFeatures(android.content.ComponentName, int):
+    Method 'setLockTaskFeatures' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setLockTaskPackages(android.content.ComponentName, String[]):
+    Method 'setLockTaskPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>):
+    Method 'setPermittedInputMethods' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setUninstallBlocked(android.content.ComponentName, String, boolean):
+    Method 'setUninstallBlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setUserControlDisabledPackages(android.content.ComponentName, java.util.List<java.lang.String>):
+    Method 'setUserControlDisabledPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeData(int):
+    Method 'wipeData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeData(int, CharSequence):
+    Method 'wipeData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeDevice(int):
+    Method 'wipeDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.PolicyUpdateReceiver#onPolicyChanged(android.content.Context, String, android.os.Bundle, android.app.admin.TargetUser, android.app.admin.PolicyUpdateResult):
+    Method 'onPolicyChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.PolicyUpdateReceiver#onPolicySetResult(android.content.Context, String, android.os.Bundle, android.app.admin.TargetUser, android.app.admin.PolicyUpdateResult):
+    Method 'onPolicySetResult' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#dataChanged(String):
+    Method 'dataChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setRequiredNetwork(android.net.NetworkRequest):
+    Method 'setRequiredNetwork' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setRequiredNetworkType(int):
+    Method 'setRequiredNetworkType' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setUserInitiated(boolean):
+    Method 'setUserInitiated' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.job.JobParameters#isUserInitiatedJob():
+    Method 'isUserInitiatedJob' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobScheduler#canRunUserInitiatedJobs():
+    Method 'canRunUserInitiatedJobs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryExternalStatsForUser(java.util.UUID, android.os.UserHandle):
+    Method 'queryExternalStatsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForPackage(java.util.UUID, String, android.os.UserHandle):
+    Method 'queryStatsForPackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUid(java.util.UUID, int):
+    Method 'queryStatsForUid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUser(java.util.UUID, android.os.UserHandle):
+    Method 'queryStatsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#isAppInactive(String):
+    Method 'isAppInactive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryAndAggregateUsageStats(long, long):
+    Method 'queryAndAggregateUsageStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryConfigurations(int, long, long):
+    Method 'queryConfigurations' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryEventStats(int, long, long):
+    Method 'queryEventStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryEvents(long, long):
+    Method 'queryEvents' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryUsageStats(int, long, long):
+    Method 'queryUsageStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int, android.os.UserHandle, android.content.ComponentName, android.os.Bundle):
+    Method 'bindAppWidgetIdIfAllowed' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#startObservingDevicePresence(String):
+    Method 'startObservingDevicePresence' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#stopObservingDevicePresence(String):
+    Method 'stopObservingDevicePresence' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.ContentResolver#addPeriodicSync(android.accounts.Account, String, android.os.Bundle, long):
+    Method 'addPeriodicSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#cancelSync(android.content.SyncRequest):
+    Method 'cancelSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getCurrentSync():
+    Method 'getCurrentSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getCurrentSyncs():
+    Method 'getCurrentSyncs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getIsSyncable(android.accounts.Account, String):
+    Method 'getIsSyncable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getMasterSyncAutomatically():
+    Method 'getMasterSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getPeriodicSyncs(android.accounts.Account, String):
+    Method 'getPeriodicSyncs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getSyncAutomatically(android.accounts.Account, String):
+    Method 'getSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#isSyncActive(android.accounts.Account, String):
+    Method 'isSyncActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#isSyncPending(android.accounts.Account, String):
+    Method 'isSyncPending' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#removePeriodicSync(android.accounts.Account, String, android.os.Bundle):
+    Method 'removePeriodicSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setIsSyncable(android.accounts.Account, String, int):
+    Method 'setIsSyncable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setMasterSyncAutomatically(boolean):
+    Method 'setMasterSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setSyncAutomatically(android.accounts.Account, String, boolean):
+    Method 'setSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    Method 'bindServiceAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.Context#clearWallpaper():
+    Method 'clearWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalCacheDir():
+    Method 'getExternalCacheDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalCacheDirs():
+    Method 'getExternalCacheDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalFilesDir(String):
+    Method 'getExternalFilesDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalFilesDirs(String):
+    Method 'getExternalFilesDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalMediaDirs():
+    Method 'getExternalMediaDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getObbDir():
+    Method 'getObbDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getObbDirs():
+    Method 'getObbDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle):
+    Method 'removeStickyBroadcastAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.Context#setWallpaper(android.graphics.Bitmap):
+    Method 'setWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#setWallpaper(java.io.InputStream):
+    Method 'setWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#canRequestInteractAcrossProfiles():
+    Method 'canRequestInteractAcrossProfiles' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.Intent, android.os.UserHandle, android.app.Activity):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.Intent, android.os.UserHandle, android.app.Activity, android.os.Bundle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps#getAllPackageInstallerSessions():
+    Method 'getAllPackageInstallerSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps#registerPackageInstallerSessionCallback(java.util.concurrent.Executor, android.content.pm.PackageInstaller.SessionCallback):
+    Method 'registerPackageInstallerSessionCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps.Callback#onPackagesSuspended(String[], android.os.UserHandle, android.os.Bundle):
+    Method 'onPackagesSuspended' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getAllSessions():
+    Method 'getAllSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getSessionInfo(int):
+    Method 'getSessionInfo' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getStagedSessions():
+    Method 'getStagedSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback):
+    Method 'registerSessionCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.Session#requestUserPreapproval(android.content.pm.PackageInstaller.PreapprovalDetails, android.content.IntentSender):
+    Method 'requestUserPreapproval' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setInstallerPackageName(String):
+    Method 'setInstallerPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setPermissionState(String, int):
+    Method 'setPermissionState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setRequestUpdateOwnership(boolean):
+    Method 'setRequestUpdateOwnership' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(int):
+    Method 'setRequireUserAction' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#canRequestPackageInstalls():
+    Method 'canRequestPackageInstalls' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#getSuspendedPackageAppExtras():
+    Method 'getSuspendedPackageAppExtras' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#isAutoRevokeWhitelisted(String):
+    Method 'isAutoRevokeWhitelisted' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#isPackageSuspended():
+    Method 'isPackageSuspended' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.Sensor#getHighestDirectReportRateLevel():
+    Method 'getHighestDirectReportRateLevel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.Sensor#getMinDelay():
+    Method 'getMinDelay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraCharacteristics#getKeysNeedingPermission():
+    Method 'getKeysNeedingPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#hasPermission(android.hardware.usb.UsbDevice):
+    Method 'hasPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#requestPermission(android.hardware.usb.UsbDevice, android.app.PendingIntent):
+    Method 'requestPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.AudioAttributes.Builder#setHapticChannelsMuted(boolean):
+    Method 'setHapticChannelsMuted' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(String):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(String, java.util.Map<java.lang.String,java.lang.String>):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String,java.lang.String>):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaPlayer#setWakeMode(android.content.Context, int):
+    Method 'setWakeMode' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.RingtoneManager#getCursor():
+    Method 'getCursor' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.RingtoneManager#getValidRingtoneUri(android.content.Context):
+    Method 'getValidRingtoneUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.audiofx.HapticGenerator#setEnabled(boolean):
+    Method 'setEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.projection.MediaProjection#createVirtualDisplay(String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback, android.os.Handler):
+    Method 'createVirtualDisplay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.projection.MediaProjectionManager#getMediaProjection(int, android.content.Intent):
+    Method 'getMediaProjection' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnMediaKeyEventSessionChangedListener(java.util.concurrent.Executor, android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener):
+    Method 'addOnMediaKeyEventSessionChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getActiveSessions(android.content.ComponentName):
+    Method 'getActiveSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getMediaKeyEventSession():
+    Method 'getMediaKeyEventSession' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getMediaKeyEventSessionPackageName():
+    Method 'getMediaKeyEventSessionPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#isTrustedForMediaControl(android.media.session.MediaSessionManager.RemoteUserInfo):
+    Method 'isTrustedForMediaControl' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.net.sip.SipAudioCall#setSpeakerMode(boolean):
+    Method 'setSpeakerMode' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.net.sip.SipAudioCall#startAudio():
+    Method 'startAudio' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
+    Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
+    Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
+    Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
+    Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
+    Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
+    Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
+    Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
+    Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
+    Method 'increment' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
+    Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
+    Method 'restore' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
+    Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
+    Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
+    Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
+    Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
+    Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#isWritable():
+    Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
+    Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
+    Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
+    Method 'format' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
+    Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#close():
+    Method 'close' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#connect():
+    Method 'connect' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.BugreportManager#cancelBugreport():
+    Method 'cancelBugreport' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Build#getSerial():
+    Method 'getSerial' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Debug#dumpService(String, java.io.FileDescriptor, String[]):
+    Method 'dumpService' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.DropBoxManager#getNextEntry(String, long):
+    Method 'getNextEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Environment#getExternalStorageDirectory():
+    Method 'getExternalStorageDirectory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Environment#isExternalStorageManager():
+    Method 'isExternalStorageManager' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Environment#isExternalStorageManager(java.io.File):
+    Method 'isExternalStorageManager' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#newWakeLock(int, String):
+    Method 'newWakeLock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#reboot(String):
+    Method 'reboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.RecoverySystem#rebootWipeUserData(android.content.Context):
+    Method 'rebootWipeUserData' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.StrictMode.VmPolicy.Builder#detectFileUriExposure():
+    Method 'detectFileUriExposure' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.UserManager#getUserRestrictions(android.os.UserHandle):
+    Method 'getUserRestrictions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isUserUnlocked(android.os.UserHandle):
+    Method 'isUserUnlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#requestQuietModeEnabled(boolean, android.os.UserHandle):
+    Method 'requestQuietModeEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#setUserRestriction(String, boolean):
+    Method 'setUserRestriction' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshot(int):
+    Method 'takeUidSnapshot' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshots(int[]):
+    Method 'takeUidSnapshots' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#getManageSpaceActivityIntent(String, int):
+    Method 'getManageSpaceActivityIntent' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.storage.StorageVolume#createAccessIntent(String):
+    Method 'createAccessIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.provider.Settings#canDrawOverlays(android.content.Context):
+    Method 'canDrawOverlays' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.provider.Settings.System#canWrite(android.content.Context):
+    Method 'canWrite' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.security.KeyChain#removeCredentialManagementApp(android.content.Context):
+    Method 'removeCredentialManagementApp' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.BeginCreateCredentialResponse.Builder#setRemoteCreateEntry(android.service.credentials.RemoteEntry):
+    Method 'setRemoteCreateEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.BeginGetCredentialResponse.Builder#setRemoteCredentialEntry(android.service.credentials.RemoteEntry):
+    Method 'setRemoteCredentialEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.CallingAppInfo#getOrigin():
+    Method 'getOrigin' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.Call.Details#getContactDisplayName():
+    Method 'getContactDisplayName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.Call.Details#getContactPhotoUri():
+    Method 'getContactPhotoUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle):
+    Method 'acceptHandover' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    Method 'addNewIncomingCall' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingConference(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    Method 'addNewIncomingConference' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getLine1Number(android.telecom.PhoneAccountHandle):
+    Method 'getLine1Number' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getOwnSelfManagedPhoneAccounts():
+    Method 'getOwnSelfManagedPhoneAccounts' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getPhoneAccount(android.telecom.PhoneAccountHandle):
+    Method 'getPhoneAccount' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getSelfManagedPhoneAccounts():
+    Method 'getSelfManagedPhoneAccounts' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#hasManageOngoingCallsPermission():
+    Method 'hasManageOngoingCallsPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#placeCall(android.net.Uri, android.os.Bundle):
+    Method 'placeCall' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#showInCallScreen(boolean):
+    Method 'showInCallScreen' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#silenceRinger():
+    Method 'silenceRinger' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig():
+    Method 'getConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig(java.lang.String...):
+    Method 'getConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigByComponentForSubId(String, int):
+    Method 'getConfigByComponentForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int):
+    Method 'getConfigForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int, java.lang.String...):
+    Method 'getConfigForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#notifyConfigChangedForSubId(int):
+    Method 'notifyConfigChangedForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CellLocation#requestLocationUpdate():
+    Method 'requestLocationUpdate' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.NetworkRegistrationInfo#getCellIdentity():
+    Method 'getCellIdentity' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onActiveDataSubscriptionIdChanged(int):
+    Method 'onActiveDataSubscriptionIdChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onCallStateChanged(int, String):
+    Method 'onCallStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onDisplayInfoChanged(android.telephony.TelephonyDisplayInfo):
+    Method 'onDisplayInfoChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState):
+    Method 'onPreciseDataConnectionStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onServiceStateChanged(android.telephony.ServiceState):
+    Method 'onServiceStateChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getCdmaNetworkId():
+    Method 'getCdmaNetworkId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getCdmaSystemId():
+    Method 'getCdmaSystemId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorAlphaLong():
+    Method 'getOperatorAlphaLong' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorAlphaShort():
+    Method 'getOperatorAlphaShort' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorNumeric():
+    Method 'getOperatorNumeric' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#getSmscAddress():
+    Method 'getSmscAddress' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#injectSmsPdu(byte[], String, android.app.PendingIntent):
+    Method 'injectSmsPdu' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendDataMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>):
+    Method 'sendMultipartTextMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendTextMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendTextMessageWithoutPersisting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#setSmscAddress(String):
+    Method 'setSmscAddress' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#addSubscriptionsIntoGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    Method 'addSubscriptionsIntoGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#createSubscriptionGroup(java.util.List<java.lang.Integer>):
+    Method 'createSubscriptionGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfo(int):
+    Method 'getActiveSubscriptionInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoForSimSlotIndex(int):
+    Method 'getActiveSubscriptionInfoForSimSlotIndex' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoList():
+    Method 'getActiveSubscriptionInfoList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getCompleteActiveSubscriptionInfoList():
+    Method 'getCompleteActiveSubscriptionInfoList' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getOpportunisticSubscriptions():
+    Method 'getOpportunisticSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getSubscriptionsInGroup(android.os.ParcelUuid):
+    Method 'getSubscriptionsInGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#removeSubscriptionsFromGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    Method 'removeSubscriptionsFromGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#setOpportunistic(boolean, int):
+    Method 'setOpportunistic' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener#onActiveDataSubscriptionIdChanged(int):
+    Method 'onActiveDataSubscriptionIdChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.BarringInfoListener#onBarringInfoChanged(android.telephony.BarringInfo):
+    Method 'onBarringInfoChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallForwardingIndicatorListener#onCallForwardingIndicatorChanged(boolean):
+    Method 'onCallForwardingIndicatorChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.EmergencyNumberListListener#onEmergencyNumberListChanged(java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>):
+    Method 'onEmergencyNumberListChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ImsCallDisconnectCauseListener#onImsCallDisconnectCauseChanged(android.telephony.ims.ImsReasonInfo):
+    Method 'onImsCallDisconnectCauseChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.MessageWaitingIndicatorListener#onMessageWaitingIndicatorChanged(boolean):
+    Method 'onMessageWaitingIndicatorChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PhysicalChannelConfigListener#onPhysicalChannelConfigChanged(java.util.List<android.telephony.PhysicalChannelConfig>):
+    Method 'onPhysicalChannelConfigChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PreciseDataConnectionStateListener#onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState):
+    Method 'onPreciseDataConnectionStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.RegistrationFailedListener#onRegistrationFailed(android.telephony.CellIdentity, String, int, int, int):
+    Method 'onRegistrationFailed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ServiceStateListener#onServiceStateChanged(android.telephony.ServiceState):
+    Method 'onServiceStateChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#clearSignalStrengthUpdateRequest(android.telephony.SignalStrengthUpdateRequest):
+    Method 'clearSignalStrengthUpdateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#doesSwitchMultiSimConfigTriggerReboot():
+    Method 'doesSwitchMultiSimConfigTriggerReboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypesForReason(int):
+    Method 'getAllowedNetworkTypesForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCallState():
+    Method 'getCallState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCallStateForSubscription():
+    Method 'getCallStateForSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierConfig():
+    Method 'getCarrierConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierRestrictionStatus(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getCarrierRestrictionStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDataNetworkType():
+    Method 'getDataNetworkType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId():
+    Method 'getDeviceId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId(int):
+    Method 'getDeviceId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList():
+    Method 'getEmergencyNumberList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList(int):
+    Method 'getEmergencyNumberList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEquivalentHomePlmns():
+    Method 'getEquivalentHomePlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getForbiddenPlmns():
+    Method 'getForbiddenPlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getGroupIdLevel1():
+    Method 'getGroupIdLevel1' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getImei(int):
+    Method 'getImei' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getLine1Number():
+    Method 'getLine1Number' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getManualNetworkSelectionPlmn():
+    Method 'getManualNetworkSelectionPlmn' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getMeid():
+    Method 'getMeid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getMeid(int):
+    Method 'getMeid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNai():
+    Method 'getNai' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNetworkSelectionMode():
+    Method 'getNetworkSelectionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNetworkSlicingConfiguration(java.util.concurrent.Executor, android.os.OutcomeReceiver<android.telephony.data.NetworkSlicingConfig,android.telephony.TelephonyManager.NetworkSlicingException>):
+    Method 'getNetworkSlicingConfiguration' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPhoneAccountHandle():
+    Method 'getPhoneAccountHandle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPreferredOpportunisticDataSubscription():
+    Method 'getPreferredOpportunisticDataSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getServiceState():
+    Method 'getServiceState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getServiceState(int):
+    Method 'getServiceState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSimSerialNumber():
+    Method 'getSimSerialNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSubscriberId():
+    Method 'getSubscriberId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSupportedRadioAccessFamily():
+    Method 'getSupportedRadioAccessFamily' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVisualVoicemailPackageName():
+    Method 'getVisualVoicemailPackageName' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailAlphaTag():
+    Method 'getVoiceMailAlphaTag' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailNumber():
+    Method 'getVoiceMailNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceNetworkType():
+    Method 'getVoiceNetworkType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccCloseLogicalChannel(int):
+    Method 'iccCloseLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccExchangeSimIO(int, int, int, int, int, String):
+    Method 'iccExchangeSimIO' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String):
+    Method 'iccOpenLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String, int):
+    Method 'iccOpenLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduBasicChannel(int, int, int, int, int, String):
+    Method 'iccTransmitApduBasicChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduLogicalChannel(int, int, int, int, int, int, String):
+    Method 'iccTransmitApduLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabled():
+    Method 'isDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabledForReason(int):
+    Method 'isDataEnabledForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataRoamingEnabled():
+    Method 'isDataRoamingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isManualNetworkSelectionAllowed():
+    Method 'isManualNetworkSelectionAllowed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isModemEnabledForSlot(int):
+    Method 'isModemEnabledForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isMultiSimSupported():
+    Method 'isMultiSimSupported' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isPremiumCapabilityAvailableForPurchase(int):
+    Method 'isPremiumCapabilityAvailableForPurchase' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#purchasePremiumCapability(int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'purchasePremiumCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#rebootModem():
+    Method 'rebootModem' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    Method 'requestNetworkScan' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(int, android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    Method 'requestNetworkScan' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendEnvelopeWithStatus(String):
+    Method 'sendEnvelopeWithStatus' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler):
+    Method 'sendUssdRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendVisualVoicemailSms(String, int, String, android.app.PendingIntent):
+    Method 'sendVisualVoicemailSms' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setAllowedNetworkTypesForReason(int, long):
+    Method 'setAllowedNetworkTypesForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabled(boolean):
+    Method 'setDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabledForReason(int, boolean):
+    Method 'setDataEnabledForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setForbiddenPlmns(java.util.List<java.lang.String>):
+    Method 'setForbiddenPlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeAutomatic():
+    Method 'setNetworkSelectionModeAutomatic' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean):
+    Method 'setNetworkSelectionModeManual' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean, int):
+    Method 'setNetworkSelectionModeManual' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setPreferredOpportunisticDataSubscription(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setPreferredOpportunisticDataSubscription' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSignalStrengthUpdateRequest(android.telephony.SignalStrengthUpdateRequest):
+    Method 'setSignalStrengthUpdateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri):
+    Method 'setVoicemailRingtoneUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean):
+    Method 'setVoicemailVibrationEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#switchMultiSimConfig(int):
+    Method 'switchMultiSimConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'updateAvailableNetworks' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#deleteSubscription(int, android.app.PendingIntent):
+    Method 'deleteSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent):
+    Method 'downloadSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, android.app.PendingIntent):
+    Method 'switchToSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, int, android.app.PendingIntent):
+    Method 'switchToSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#updateSubscriptionNickname(int, String, android.app.PendingIntent):
+    Method 'updateSubscriptionNickname' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#getRegistrationTransportType(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationTransportType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#getVoWiFiModeSetting():
+    Method 'getVoWiFiModeSetting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isAdvancedCallingSettingEnabled():
+    Method 'isAdvancedCallingSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isCrossSimCallingEnabled():
+    Method 'isCrossSimCallingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isTtyOverVolteEnabled():
+    Method 'isTtyOverVolteEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVoWiFiRoamingSettingEnabled():
+    Method 'isVoWiFiRoamingSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVoWiFiSettingEnabled():
+    Method 'isVoWiFiSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVtSettingEnabled():
+    Method 'isVtSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerImsRegistrationCallback(java.util.concurrent.Executor, android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'registerImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerImsStateCallback(java.util.concurrent.Executor, android.telephony.ims.ImsStateCallback):
+    Method 'registerImsStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerMmTelCapabilityCallback(java.util.concurrent.Executor, android.telephony.ims.ImsMmTelManager.CapabilityCallback):
+    Method 'registerMmTelCapabilityCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#unregisterImsRegistrationCallback(android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'unregisterImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#unregisterMmTelCapabilityCallback(android.telephony.ims.ImsMmTelManager.CapabilityCallback):
+    Method 'unregisterMmTelCapabilityCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#getRegistrationState(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#getRegistrationTransportType(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationTransportType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#registerImsRegistrationCallback(java.util.concurrent.Executor, android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'registerImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#registerImsStateCallback(java.util.concurrent.Executor, android.telephony.ims.ImsStateCallback):
+    Method 'registerImsStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#unregisterImsRegistrationCallback(android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'unregisterImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#getProvisioningStatusForCapability(int, int):
+    Method 'getProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#getRcsProvisioningStatusForCapability(int, int):
+    Method 'getRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isProvisioningRequiredForCapability(int, int):
+    Method 'isProvisioningRequiredForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isRcsProvisioningRequiredForCapability(int, int):
+    Method 'isRcsProvisioningRequiredForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerFeatureProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback):
+    Method 'registerFeatureProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setProvisioningStatusForCapability(int, int, boolean):
+    Method 'setProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setRcsProvisioningStatusForCapability(int, int, boolean):
+    Method 'setRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.inputmethod.InputMethodManager#setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype):
+    Method 'setCurrentInputMethodSubtype' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.webkit.WebSettings#setBlockNetworkLoads(boolean):
+    Method 'setBlockNetworkLoads' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.webkit.WebSettings#setGeolocationEnabled(boolean):
+    Method 'setGeolocationEnabled' documentation mentions permissions without declaring @RequiresPermission
+
+
+Todo: android.hardware.camera2.params.StreamConfigurationMap:
+    Documentation mentions 'TODO'
+Todo: android.provider.ContactsContract.RawContacts#newEntityIterator(android.database.Cursor):
+    Documentation mentions 'TODO'
+
+
 UnflaggedApi: android.accessibilityservice.AccessibilityService#OVERLAY_RESULT_INTERNAL_ERROR:
     New API must be flagged with @FlaggedApi: field android.accessibilityservice.AccessibilityService.OVERLAY_RESULT_INTERNAL_ERROR
 UnflaggedApi: android.accessibilityservice.AccessibilityService#OVERLAY_RESULT_INVALID:
diff --git a/core/api/module-lib-lint-baseline.txt b/core/api/module-lib-lint-baseline.txt
index 1633835..e49d6e3 100644
--- a/core/api/module-lib-lint-baseline.txt
+++ b/core/api/module-lib-lint-baseline.txt
@@ -1,4 +1,1714 @@
 // Baseline format: 1.0
+BroadcastBehavior: android.app.AlarmManager#ACTION_NEXT_ALARM_CLOCK_CHANGED:
+    Field 'ACTION_NEXT_ALARM_CLOCK_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.AlarmManager#ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED:
+    Field 'ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.NotificationManager#ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL:
+    Field 'ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED:
+    Field 'ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_MANAGED_PROFILE_PROVISIONED:
+    Field 'ACTION_MANAGED_PROFILE_PROVISIONED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_AIRPLANE_MODE_CHANGED:
+    Field 'ACTION_AIRPLANE_MODE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_LOCALE_CHANGED:
+    Field 'ACTION_APPLICATION_LOCALE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED:
+    Field 'ACTION_APPLICATION_RESTRICTIONS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_CHANGED:
+    Field 'ACTION_BATTERY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED:
+    Field 'ACTION_BATTERY_LEVEL_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_LOW:
+    Field 'ACTION_BATTERY_LOW' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_OKAY:
+    Field 'ACTION_BATTERY_OKAY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CAMERA_BUTTON:
+    Field 'ACTION_CAMERA_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CLOSE_SYSTEM_DIALOGS:
+    Field 'ACTION_CLOSE_SYSTEM_DIALOGS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CONFIGURATION_CHANGED:
+    Field 'ACTION_CONFIGURATION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DATE_CHANGED:
+    Field 'ACTION_DATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_CUSTOMIZATION_READY:
+    Field 'ACTION_DEVICE_CUSTOMIZATION_READY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_LOW:
+    Field 'ACTION_DEVICE_STORAGE_LOW' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_OK:
+    Field 'ACTION_DEVICE_STORAGE_OK' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DOCK_EVENT:
+    Field 'ACTION_DOCK_EVENT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DOMAINS_NEED_VERIFICATION:
+    Field 'ACTION_DOMAINS_NEED_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STARTED:
+    Field 'ACTION_DREAMING_STARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STOPPED:
+    Field 'ACTION_DREAMING_STOPPED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
+    Field 'ACTION_EXTERNAL_APPLICATIONS_AVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+    Field 'ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GLOBAL_BUTTON:
+    Field 'ACTION_GLOBAL_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_CONNECTED:
+    Field 'ACTION_GTALK_SERVICE_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_DISCONNECTED:
+    Field 'ACTION_GTALK_SERVICE_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_HEADSET_PLUG:
+    Field 'ACTION_HEADSET_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INPUT_METHOD_CHANGED:
+    Field 'ACTION_INPUT_METHOD_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INSTALL_INSTANT_APP_PACKAGE:
+    Field 'ACTION_INSTALL_INSTANT_APP_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS:
+    Field 'ACTION_INSTANT_APP_RESOLVER_SETTINGS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION:
+    Field 'ACTION_INTENT_FILTER_NEEDS_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOAD_DATA:
+    Field 'ACTION_LOAD_DATA' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOCALE_CHANGED:
+    Field 'ACTION_LOCALE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED:
+    Field 'ACTION_LOCKED_BOOT_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MANAGE_PACKAGE_STORAGE:
+    Field 'ACTION_MANAGE_PACKAGE_STORAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BAD_REMOVAL:
+    Field 'ACTION_MEDIA_BAD_REMOVAL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BUTTON:
+    Field 'ACTION_MEDIA_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_CHECKING:
+    Field 'ACTION_MEDIA_CHECKING' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_EJECT:
+    Field 'ACTION_MEDIA_EJECT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_MOUNTED:
+    Field 'ACTION_MEDIA_MOUNTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_NOFS:
+    Field 'ACTION_MEDIA_NOFS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_REMOVED:
+    Field 'ACTION_MEDIA_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_FINISHED:
+    Field 'ACTION_MEDIA_SCANNER_FINISHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_SCAN_FILE:
+    Field 'ACTION_MEDIA_SCANNER_SCAN_FILE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_STARTED:
+    Field 'ACTION_MEDIA_SCANNER_STARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SHARED:
+    Field 'ACTION_MEDIA_SHARED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTABLE:
+    Field 'ACTION_MEDIA_UNMOUNTABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTED:
+    Field 'ACTION_MEDIA_UNMOUNTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_REPLACED:
+    Field 'ACTION_MY_PACKAGE_REPLACED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_SUSPENDED:
+    Field 'ACTION_MY_PACKAGE_SUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_UNSUSPENDED:
+    Field 'ACTION_MY_PACKAGE_UNSUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_NEW_OUTGOING_CALL:
+    Field 'ACTION_NEW_OUTGOING_CALL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_SUSPENDED:
+    Field 'ACTION_PACKAGES_SUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_UNSUSPENDED:
+    Field 'ACTION_PACKAGES_UNSUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_ADDED:
+    Field 'ACTION_PACKAGE_ADDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_CHANGED:
+    Field 'ACTION_PACKAGE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_DATA_CLEARED:
+    Field 'ACTION_PACKAGE_DATA_CLEARED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FIRST_LAUNCH:
+    Field 'ACTION_PACKAGE_FIRST_LAUNCH' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FULLY_REMOVED:
+    Field 'ACTION_PACKAGE_FULLY_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_INSTALL:
+    Field 'ACTION_PACKAGE_INSTALL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION:
+    Field 'ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_NEEDS_VERIFICATION:
+    Field 'ACTION_PACKAGE_NEEDS_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REMOVED:
+    Field 'ACTION_PACKAGE_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REPLACED:
+    Field 'ACTION_PACKAGE_REPLACED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_RESTARTED:
+    Field 'ACTION_PACKAGE_RESTARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_UNSTOPPED:
+    Field 'ACTION_PACKAGE_UNSTOPPED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY:
+    Field 'ACTION_PACKAGE_UNSUSPENDED_MANUALLY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_VERIFIED:
+    Field 'ACTION_PACKAGE_VERIFIED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_POWER_CONNECTED:
+    Field 'ACTION_POWER_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_POWER_DISCONNECTED:
+    Field 'ACTION_POWER_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PRE_BOOT_COMPLETED:
+    Field 'ACTION_PRE_BOOT_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PROVIDER_CHANGED:
+    Field 'ACTION_PROVIDER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_QUERY_PACKAGE_RESTART:
+    Field 'ACTION_QUERY_PACKAGE_RESTART' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_REBOOT:
+    Field 'ACTION_REBOOT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_RESOLVE_INSTANT_APP_PACKAGE:
+    Field 'ACTION_RESOLVE_INSTANT_APP_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_ROLLBACK_COMMITTED:
+    Field 'ACTION_ROLLBACK_COMMITTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_OFF:
+    Field 'ACTION_SCREEN_OFF' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_ON:
+    Field 'ACTION_SCREEN_ON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS:
+    Field 'ACTION_SHOW_SUSPENDED_APP_DETAILS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SHUTDOWN:
+    Field 'ACTION_SHUTDOWN' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SIM_STATE_CHANGED:
+    Field 'ACTION_SIM_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SPLIT_CONFIGURATION_CHANGED:
+    Field 'ACTION_SPLIT_CONFIGURATION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIMEZONE_CHANGED:
+    Field 'ACTION_TIMEZONE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIME_CHANGED:
+    Field 'ACTION_TIME_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIME_TICK:
+    Field 'ACTION_TIME_TICK' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UID_REMOVED:
+    Field 'ACTION_UID_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UMS_CONNECTED:
+    Field 'ACTION_UMS_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UMS_DISCONNECTED:
+    Field 'ACTION_UMS_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UNARCHIVE_PACKAGE:
+    Field 'ACTION_UNARCHIVE_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_USER_PRESENT:
+    Field 'ACTION_USER_PRESENT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_USER_UNLOCKED:
+    Field 'ACTION_USER_UNLOCKED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_WALLPAPER_CHANGED:
+    Field 'ACTION_WALLPAPER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_COMMITTED:
+    Field 'ACTION_SESSION_COMMITTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_UPDATED:
+    Field 'ACTION_SESSION_UPDATED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_PICTURE:
+    Field 'ACTION_NEW_PICTURE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_VIDEO:
+    Field 'ACTION_NEW_VIDEO' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.hdmi.HdmiControlManager#ACTION_OSD_MESSAGE:
+    Field 'ACTION_OSD_MESSAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.input.InputManager#ACTION_QUERY_KEYBOARD_LAYOUTS:
+    Field 'ACTION_QUERY_KEYBOARD_LAYOUTS' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_ACCESSORY_DETACHED:
+    Field 'ACTION_USB_ACCESSORY_DETACHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_ACCESSORY_HANDSHAKE:
+    Field 'ACTION_USB_ACCESSORY_HANDSHAKE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_DEVICE_DETACHED:
+    Field 'ACTION_USB_DEVICE_DETACHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_PORT_CHANGED:
+    Field 'ACTION_USB_PORT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_PORT_COMPLIANCE_CHANGED:
+    Field 'ACTION_USB_PORT_COMPLIANCE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_STATE:
+    Field 'ACTION_USB_STATE' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_HDMI_AUDIO_PLUG:
+    Field 'ACTION_HDMI_AUDIO_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_HEADSET_PLUG:
+    Field 'ACTION_HEADSET_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_MICROPHONE_MUTE_CHANGED:
+    Field 'ACTION_MICROPHONE_MUTE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_SPEAKERPHONE_STATE_CHANGED:
+    Field 'ACTION_SPEAKERPHONE_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_CHANNEL_BROWSABLE_REQUESTED:
+    Field 'ACTION_CHANNEL_BROWSABLE_REQUESTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_INITIALIZE_PROGRAMS:
+    Field 'ACTION_INITIALIZE_PROGRAMS' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT:
+    Field 'ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED:
+    Field 'ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED:
+    Field 'ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.NetworkScoreManager#ACTION_SCORER_CHANGED:
+    Field 'ACTION_SCORER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.NetworkScoreManager#ACTION_SCORE_NETWORKS:
+    Field 'ACTION_SCORE_NETWORKS' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.Proxy#PROXY_CHANGE_ACTION:
+    Field 'PROXY_CHANGE_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
+    Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
+    Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
+    Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.os.DropBoxManager#ACTION_DROPBOX_ENTRY_ADDED:
+    Field 'ACTION_DROPBOX_ENTRY_ADDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.CalendarContract#ACTION_EVENT_REMINDER:
+    Field 'ACTION_EVENT_REMINDER' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.ContactsContract.SimContacts#ACTION_SIM_ACCOUNTS_CHANGED:
+    Field 'ACTION_SIM_ACCOUNTS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#ACTION_SMS_EMERGENCY_CB_RECEIVED:
+    Field 'ACTION_SMS_EMERGENCY_CB_RECEIVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#DATA_SMS_RECEIVED_ACTION:
+    Field 'DATA_SMS_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SECRET_CODE_ACTION:
+    Field 'SECRET_CODE_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SIM_FULL_ACTION:
+    Field 'SIM_FULL_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION:
+    Field 'SMS_CB_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION:
+    Field 'SMS_DELIVER_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION:
+    Field 'SMS_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_REJECTED_ACTION:
+    Field 'SMS_REJECTED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION:
+    Field 'SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION:
+    Field 'WAP_PUSH_DELIVER_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_RECEIVED_ACTION:
+    Field 'WAP_PUSH_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_KEYCHAIN_CHANGED:
+    Field 'ACTION_KEYCHAIN_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_KEY_ACCESS_CHANGED:
+    Field 'ACTION_KEY_ACCESS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_STORAGE_CHANGED:
+    Field 'ACTION_STORAGE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_TRUST_STORE_CHANGED:
+    Field 'ACTION_TRUST_STORE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_DELETE_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_RENAME_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_START_EUICC_ACTIVATION:
+    Field 'ACTION_START_EUICC_ACTIVATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.speech.tts.TextToSpeech#ACTION_TTS_QUEUE_PROCESSING_COMPLETED:
+    Field 'ACTION_TTS_QUEUE_PROCESSING_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.speech.tts.TextToSpeech.Engine#ACTION_TTS_DATA_INSTALLED:
+    Field 'ACTION_TTS_DATA_INSTALLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_REFRESH_SUBSCRIPTION_PLANS:
+    Field 'ACTION_REFRESH_SUBSCRIPTION_PLANS' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_SUBSCRIPTION_PLANS_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_PLANS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE:
+    Field 'ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_PCO_VALUE:
+    Field 'ACTION_CARRIER_SIGNAL_PCO_VALUE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_REDIRECTED:
+    Field 'ACTION_CARRIER_SIGNAL_REDIRECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED:
+    Field 'ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_RESET:
+    Field 'ACTION_CARRIER_SIGNAL_RESET' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_EMERGENCY_CALLBACK_MODE_CHANGED:
+    Field 'ACTION_EMERGENCY_CALLBACK_MODE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_EMERGENCY_CALL_STATE_CHANGED:
+    Field 'ACTION_EMERGENCY_CALL_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE:
+    Field 'ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SECRET_CODE:
+    Field 'ACTION_SECRET_CODE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS:
+    Field 'ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED:
+    Field 'ACTION_SIM_APPLICATION_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED:
+    Field 'ACTION_SIM_CARD_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_SLOT_STATUS_CHANGED:
+    Field 'ACTION_SIM_SLOT_STATUS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.euicc.EuiccManager#ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE:
+    Field 'ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.euicc.EuiccManager#ACTION_OTA_STATUS_CHANGED:
+    Field 'ACTION_OTA_STATUS_CHANGED' is missing @BroadcastBehavior
+
+
+DeprecationMismatch: android.accounts.AccountManager#newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle):
+    Method android.accounts.AccountManager.newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Activity#enterPictureInPictureMode():
+    Method android.app.Activity.enterPictureInPictureMode(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Instrumentation#startAllocCounting():
+    Method android.app.Instrumentation.startAllocCounting(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Instrumentation#stopAllocCounting():
+    Method android.app.Instrumentation.stopAllocCounting(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#bigContentView:
+    Field Notification.bigContentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#contentView:
+    Field Notification.contentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#headsUpContentView:
+    Field Notification.headsUpContentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#tickerView:
+    Field Notification.tickerView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.Builder#Builder(int, CharSequence, android.app.PendingIntent):
+    Constructor android.app.Notification.Action.Builder.Builder(int, CharSequence, android.app.PendingIntent): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getCancelLabel():
+    Method android.app.Notification.Action.WearableExtender.getCancelLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getConfirmLabel():
+    Method android.app.Notification.Action.WearableExtender.getConfirmLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getInProgressLabel():
+    Method android.app.Notification.Action.WearableExtender.getInProgressLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setCancelLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setCancelLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setConfirmLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setConfirmLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setInProgressLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setInProgressLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Builder#setContent(android.widget.RemoteViews):
+    Method android.app.Notification.Builder.setContent(android.widget.RemoteViews): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Builder#setTicker(CharSequence, android.widget.RemoteViews):
+    Method android.app.Notification.Builder.setTicker(CharSequence, android.widget.RemoteViews): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIcon():
+    Method android.app.Notification.WearableExtender.getContentIcon(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIconGravity():
+    Method android.app.Notification.WearableExtender.getContentIconGravity(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomContentHeight():
+    Method android.app.Notification.WearableExtender.getCustomContentHeight(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomSizePreset():
+    Method android.app.Notification.WearableExtender.getCustomSizePreset(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getGravity():
+    Method android.app.Notification.WearableExtender.getGravity(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintAvoidBackgroundClipping():
+    Method android.app.Notification.WearableExtender.getHintAvoidBackgroundClipping(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintHideIcon():
+    Method android.app.Notification.WearableExtender.getHintHideIcon(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintScreenTimeout():
+    Method android.app.Notification.WearableExtender.getHintScreenTimeout(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintShowBackgroundOnly():
+    Method android.app.Notification.WearableExtender.getHintShowBackgroundOnly(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIcon(int):
+    Method android.app.Notification.WearableExtender.setContentIcon(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIconGravity(int):
+    Method android.app.Notification.WearableExtender.setContentIconGravity(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomContentHeight(int):
+    Method android.app.Notification.WearableExtender.setCustomContentHeight(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomSizePreset(int):
+    Method android.app.Notification.WearableExtender.setCustomSizePreset(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setGravity(int):
+    Method android.app.Notification.WearableExtender.setGravity(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintAvoidBackgroundClipping(boolean):
+    Method android.app.Notification.WearableExtender.setHintAvoidBackgroundClipping(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintHideIcon(boolean):
+    Method android.app.Notification.WearableExtender.setHintHideIcon(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintScreenTimeout(int):
+    Method android.app.Notification.WearableExtender.setHintScreenTimeout(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintShowBackgroundOnly(boolean):
+    Method android.app.Notification.WearableExtender.setHintShowBackgroundOnly(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.backup.BackupManager#selectBackupTransport(String):
+    Method android.app.backup.BackupManager.selectBackupTransport(String): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.content.Context#BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND:
+    Field Context.BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.content.Context#WIFI_RTT_SERVICE:
+    Field Context.WIFI_RTT_SERVICE: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.ComposeShader#ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode):
+    Constructor android.graphics.ComposeShader.ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#A_8:
+    Field PixelFormat.A_8: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#LA_88:
+    Field PixelFormat.LA_88: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#L_8:
+    Field PixelFormat.L_8: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_4444:
+    Field PixelFormat.RGBA_4444: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_5551:
+    Field PixelFormat.RGBA_5551: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGB_332:
+    Field PixelFormat.RGB_332: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.hardware.hdmi.HdmiControlManager#RESULT_ALREADY_IN_PROGRESS:
+    Field HdmiControlManager.RESULT_ALREADY_IN_PROGRESS: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder#setCodeRate(int):
+    Method android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder.setCodeRate(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder#setModulation(int):
+    Method android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder.setModulation(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.EGL14#eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int):
+    Method android.opengl.EGL14.eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.GLES20#GL_STENCIL_INDEX:
+    Field GLES20.GL_STENCIL_INDEX: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.GLSurfaceView#surfaceRedrawNeeded(android.view.SurfaceHolder):
+    Method android.opengl.GLSurfaceView.surfaceRedrawNeeded(android.view.SurfaceHolder): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle):
+    Method android.os.UserManager.setUserRestrictions(android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle, android.os.UserHandle):
+    Method android.os.UserManager.setUserRestrictions(android.os.Bundle, android.os.UserHandle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.provider.Contacts.People#markAsContacted(android.content.ContentResolver, long):
+    Method android.provider.Contacts.People.markAsContacted(android.content.ContentResolver, long): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_X:
+    Field Type.CubemapFace.POSITVE_X: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Y:
+    Field Type.CubemapFace.POSITVE_Y: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Z:
+    Field Type.CubemapFace.POSITVE_Z: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.speech.tts.TextToSpeech#areDefaultsEnforced():
+    Method android.speech.tts.TextToSpeech.areDefaultsEnforced(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#StatusHints(android.content.ComponentName, CharSequence, int, android.os.Bundle):
+    Constructor android.telecom.StatusHints.StatusHints(android.content.ComponentName, CharSequence, int, android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getIcon(android.content.Context):
+    Method android.telecom.StatusHints.getIcon(android.content.Context): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getIconResId():
+    Method android.telecom.StatusHints.getIconResId(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getPackageName():
+    Method android.telecom.StatusHints.getPackageName(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.PhoneStateListener#PhoneStateListener(java.util.concurrent.Executor):
+    Constructor android.telephony.PhoneStateListener.PhoneStateListener(java.util.concurrent.Executor): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionManager#PROFILE_CLASS_DEFAULT:
+    Field SubscriptionManager.PROFILE_CLASS_DEFAULT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringDaily(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringDaily(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringMonthly(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringMonthly(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringWeekly(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringWeekly(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_12HOUR:
+    Field DateUtils.FORMAT_12HOUR: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_24HOUR:
+    Field DateUtils.FORMAT_24HOUR: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_AMPM:
+    Field DateUtils.FORMAT_CAP_AMPM: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_MIDNIGHT:
+    Field DateUtils.FORMAT_CAP_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON:
+    Field DateUtils.FORMAT_CAP_NOON: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON_MIDNIGHT:
+    Field DateUtils.FORMAT_CAP_NOON_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_NO_NOON_MIDNIGHT:
+    Field DateUtils.FORMAT_NO_NOON_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.ViewGroup.LayoutParams#FILL_PARENT:
+    Field ViewGroup.LayoutParams.FILL_PARENT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.Window#setTitleColor(int):
+    Method android.view.Window.setTitleColor(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.accessibility.AccessibilityEvent#MAX_TEXT_LENGTH:
+    Field AccessibilityEvent.MAX_TEXT_LENGTH: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebSettings#getSaveFormData():
+    Method android.webkit.WebSettings.getSaveFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebView#shouldDelayChildPressedState():
+    Method android.webkit.WebView.shouldDelayChildPressedState(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebViewDatabase#clearFormData():
+    Method android.webkit.WebViewDatabase.clearFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebViewDatabase#hasFormData():
+    Method android.webkit.WebViewDatabase.hasFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: javax.microedition.khronos.egl.EGL10#eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]):
+    Method javax.microedition.khronos.egl.EGL10.eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+
+
+RequiresPermission: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
+    Method 'getAccountsByTypeAndFeatures' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+    Method 'hasFeatures' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
+    Method 'addOnUidImportanceListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getHistoricalProcessExitReasons(String, int, int):
+    Method 'getHistoricalProcessExitReasons' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getProcessesInErrorState():
+    Method 'getProcessesInErrorState' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#killProcessesWhenImperceptible(int[], String):
+    Method 'killProcessesWhenImperceptible' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.ActivityManager#setDeviceLocales(android.os.LocaleList):
+    Method 'setDeviceLocales' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent):
+    Method 'setAlarmClock' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setExact(int, long, android.app.PendingIntent):
+    Method 'setExact' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setExactAndAllowWhileIdle(int, long, android.app.PendingIntent):
+    Method 'setExactAndAllowWhileIdle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setTime(long):
+    Method 'setTime' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#isOpActive(String, int, String):
+    Method 'isOpActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#startWatchingActive(String[], java.util.concurrent.Executor, android.app.AppOpsManager.OnOpActiveChangedListener):
+    Method 'startWatchingActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#startWatchingNoted(String[], java.util.concurrent.Executor, android.app.AppOpsManager.OnOpNotedListener):
+    Method 'startWatchingNoted' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setDestinationInExternalPublicDir(String, String):
+    Method 'setDestinationInExternalPublicDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setDestinationUri(android.net.Uri):
+    Method 'setDestinationUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setNotificationVisibility(int):
+    Method 'setNotificationVisibility' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setShowRunningNotification(boolean):
+    Method 'setShowRunningNotification' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.GameManager#setGameMode(String, int):
+    Method 'setGameMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.GameManager#updateCustomGameModeConfiguration(String, android.app.GameModeConfiguration):
+    Method 'updateCustomGameModeConfiguration' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.LocaleManager#getApplicationLocales(String):
+    Method 'getApplicationLocales' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.Notification.Builder#setFullScreenIntent(android.app.PendingIntent, boolean):
+    Method 'setFullScreenIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.NotificationManager#canUseFullScreenIntent():
+    Method 'canUseFullScreenIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.Service#startForeground(int, android.app.Notification):
+    Method 'startForeground' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.StatusBarManager#canLaunchCaptureContentActivityForNote(android.app.Activity):
+    Method 'canLaunchCaptureContentActivityForNote' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.UiModeManager#releaseProjection(int):
+    Method 'releaseProjection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.UiModeManager#requestProjection(int):
+    Method 'requestProjection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperInfo#getSettingsSliceUri():
+    Method 'getSettingsSliceUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#clear():
+    Method 'clear' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#clearWallpaper(int, int):
+    Method 'clearWallpaper' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getDrawable():
+    Method 'getDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getDrawable(int):
+    Method 'getDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getFastDrawable():
+    Method 'getFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getFastDrawable(int):
+    Method 'getFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getWallpaperFile(int):
+    Method 'getWallpaperFile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getWallpaperInfo(int):
+    Method 'getWallpaperInfo' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekDrawable():
+    Method 'peekDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekDrawable(int):
+    Method 'peekDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekFastDrawable():
+    Method 'peekFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekFastDrawable(int):
+    Method 'peekFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap):
+    Method 'setBitmap' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean):
+    Method 'setBitmap' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setDisplayPadding(android.graphics.Rect):
+    Method 'setDisplayPadding' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setResource(int):
+    Method 'setResource' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream):
+    Method 'setStream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream, android.graphics.Rect, boolean):
+    Method 'setStream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setWallpaperComponentWithFlags(android.content.ComponentName, int):
+    Method 'setWallpaperComponentWithFlags' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#suggestDesiredDimensions(int, int):
+    Method 'suggestDesiredDimensions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#addCrossProfileWidgetProvider(android.content.ComponentName, String):
+    Method 'addCrossProfileWidgetProvider' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName):
+    Method 'addPersistentPreferredActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    Method 'bindDeviceAdminServiceAsUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#clearPackagePersistentPreferredActivities(android.content.ComponentName, String):
+    Method 'clearPackagePersistentPreferredActivities' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#clearResetPasswordToken(android.content.ComponentName):
+    Method 'clearResetPasswordToken' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#createAndProvisionManagedProfile(android.app.admin.ManagedProfileProvisioningParams):
+    Method 'createAndProvisionManagedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#finalizeWorkProfileProvisioning(android.os.UserHandle, android.accounts.Account):
+    Method 'finalizeWorkProfileProvisioning' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#generateKeyPair(android.content.ComponentName, String, android.security.keystore.KeyGenParameterSpec, int):
+    Method 'generateKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getApplicationExemptions(String):
+    Method 'getApplicationExemptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getCrossProfileWidgetProviders(android.content.ComponentName):
+    Method 'getCrossProfileWidgetProviders' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getLockTaskFeatures(android.content.ComponentName):
+    Method 'getLockTaskFeatures' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getLockTaskPackages(android.content.ComponentName):
+    Method 'getLockTaskPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getNearbyAppStreamingPolicy():
+    Method 'getNearbyAppStreamingPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getNearbyNotificationStreamingPolicy():
+    Method 'getNearbyNotificationStreamingPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getOrganizationName(android.content.ComponentName):
+    Method 'getOrganizationName' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getPasswordComplexity():
+    Method 'getPasswordComplexity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getShortSupportMessage(android.content.ComponentName):
+    Method 'getShortSupportMessage' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getUserControlDisabledPackages(android.content.ComponentName):
+    Method 'getUserControlDisabledPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#hasKeyPair(String):
+    Method 'hasKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, String):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], String, boolean):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], String, int):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isDeviceProvisioningConfigApplied():
+    Method 'isDeviceProvisioningConfigApplied' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isPackageSuspended(android.content.ComponentName, String):
+    Method 'isPackageSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isResetPasswordTokenActive(android.content.ComponentName):
+    Method 'isResetPasswordTokenActive' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#lockNow(int):
+    Method 'lockNow' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#provisionFullyManagedDevice(android.app.admin.FullyManagedDeviceProvisioningParams):
+    Method 'provisionFullyManagedDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#removeCrossProfileWidgetProvider(android.content.ComponentName, String):
+    Method 'removeCrossProfileWidgetProvider' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#sendLostModeLocationUpdate(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
+    Method 'sendLostModeLocationUpdate' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setActiveProfileOwner(android.content.ComponentName, String):
+    Method 'setActiveProfileOwner' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setAlwaysOnVpnPackage(android.content.ComponentName, String, boolean):
+    Method 'setAlwaysOnVpnPackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setApplicationExemptions(String, java.util.Set<java.lang.Integer>):
+    Method 'setApplicationExemptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setDeviceProvisioningConfigApplied():
+    Method 'setDeviceProvisioningConfigApplied' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setLockTaskFeatures(android.content.ComponentName, int):
+    Method 'setLockTaskFeatures' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setLockTaskPackages(android.content.ComponentName, String[]):
+    Method 'setLockTaskPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>):
+    Method 'setPermittedInputMethods' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setUninstallBlocked(android.content.ComponentName, String, boolean):
+    Method 'setUninstallBlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setUserControlDisabledPackages(android.content.ComponentName, java.util.List<java.lang.String>):
+    Method 'setUserControlDisabledPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeData(int):
+    Method 'wipeData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeData(int, CharSequence):
+    Method 'wipeData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeDevice(int):
+    Method 'wipeDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.PolicyUpdateReceiver#onPolicyChanged(android.content.Context, String, android.os.Bundle, android.app.admin.TargetUser, android.app.admin.PolicyUpdateResult):
+    Method 'onPolicyChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.PolicyUpdateReceiver#onPolicySetResult(android.content.Context, String, android.os.Bundle, android.app.admin.TargetUser, android.app.admin.PolicyUpdateResult):
+    Method 'onPolicySetResult' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#dataChanged(String):
+    Method 'dataChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#requestBackup(String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int):
+    Method 'requestBackup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#setFrameworkSchedulingEnabled(boolean):
+    Method 'setFrameworkSchedulingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#updateTransportAttributes(android.content.ComponentName, String, android.content.Intent, String, android.content.Intent, CharSequence):
+    Method 'updateTransportAttributes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#updateTransportAttributes(android.content.ComponentName, String, android.content.Intent, String, android.content.Intent, String):
+    Method 'updateTransportAttributes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restoreAll(long, android.app.backup.RestoreObserver):
+    Method 'restoreAll' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restoreAll(long, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor):
+    Method 'restoreAll' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackage(String, android.app.backup.RestoreObserver):
+    Method 'restorePackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackage(String, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor):
+    Method 'restorePackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackages(long, android.app.backup.RestoreObserver, java.util.Set<java.lang.String>):
+    Method 'restorePackages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackages(long, android.app.backup.RestoreObserver, java.util.Set<java.lang.String>, android.app.backup.BackupManagerMonitor):
+    Method 'restorePackages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setRequiredNetwork(android.net.NetworkRequest):
+    Method 'setRequiredNetwork' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setRequiredNetworkType(int):
+    Method 'setRequiredNetworkType' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setUserInitiated(boolean):
+    Method 'setUserInitiated' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.job.JobParameters#isUserInitiatedJob():
+    Method 'isUserInitiatedJob' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobScheduler#canRunUserInitiatedJobs():
+    Method 'canRunUserInitiatedJobs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.people.PeopleManager#isConversation(String, String):
+    Method 'isConversation' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryExternalStatsForUser(java.util.UUID, android.os.UserHandle):
+    Method 'queryExternalStatsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForPackage(java.util.UUID, String, android.os.UserHandle):
+    Method 'queryStatsForPackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUid(java.util.UUID, int):
+    Method 'queryStatsForUid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUser(java.util.UUID, android.os.UserHandle):
+    Method 'queryStatsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageEvents.Event#getTaskRootClassName():
+    Method 'getTaskRootClassName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageEvents.Event#getTaskRootPackageName():
+    Method 'getTaskRootPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#getAppStandbyBucket(String):
+    Method 'getAppStandbyBucket' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#getAppStandbyBuckets():
+    Method 'getAppStandbyBuckets' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#isAppInactive(String):
+    Method 'isAppInactive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#onCarrierPrivilegedAppsChanged():
+    Method 'onCarrierPrivilegedAppsChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryAndAggregateUsageStats(long, long):
+    Method 'queryAndAggregateUsageStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryConfigurations(int, long, long):
+    Method 'queryConfigurations' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryEventStats(int, long, long):
+    Method 'queryEventStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryEvents(long, long):
+    Method 'queryEvents' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryUsageStats(int, long, long):
+    Method 'queryUsageStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerAppUsageLimitObserver(int, String[], java.time.Duration, java.time.Duration, android.app.PendingIntent):
+    Method 'registerAppUsageLimitObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerAppUsageObserver(int, String[], long, java.util.concurrent.TimeUnit, android.app.PendingIntent):
+    Method 'registerAppUsageObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerUsageSessionObserver(int, String[], java.time.Duration, java.time.Duration, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'registerUsageSessionObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#reportUsageStart(android.app.Activity, String):
+    Method 'reportUsageStart' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#reportUsageStart(android.app.Activity, String, long):
+    Method 'reportUsageStart' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterAppUsageLimitObserver(int):
+    Method 'unregisterAppUsageLimitObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterAppUsageObserver(int):
+    Method 'unregisterAppUsageObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterUsageSessionObserver(int):
+    Method 'unregisterUsageSessionObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int, android.os.UserHandle, android.content.ComponentName, android.os.Bundle):
+    Method 'bindAppWidgetIdIfAllowed' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#isDeviceAssociatedForWifiConnection(String, android.net.MacAddress, android.os.UserHandle):
+    Method 'isDeviceAssociatedForWifiConnection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#startObservingDevicePresence(String):
+    Method 'startObservingDevicePresence' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#stopObservingDevicePresence(String):
+    Method 'stopObservingDevicePresence' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.virtual.VirtualDeviceManager#createVirtualDevice(int, android.companion.virtual.VirtualDeviceParams):
+    Method 'createVirtualDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.virtual.VirtualDeviceParams.Builder#setLockState(int):
+    Method 'setLockState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.ContentResolver#addPeriodicSync(android.accounts.Account, String, android.os.Bundle, long):
+    Method 'addPeriodicSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#cancelSync(android.content.SyncRequest):
+    Method 'cancelSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getCurrentSync():
+    Method 'getCurrentSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getCurrentSyncs():
+    Method 'getCurrentSyncs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getIsSyncable(android.accounts.Account, String):
+    Method 'getIsSyncable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getMasterSyncAutomatically():
+    Method 'getMasterSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getPeriodicSyncs(android.accounts.Account, String):
+    Method 'getPeriodicSyncs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getSyncAutomatically(android.accounts.Account, String):
+    Method 'getSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#isSyncActive(android.accounts.Account, String):
+    Method 'isSyncActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#isSyncPending(android.accounts.Account, String):
+    Method 'isSyncPending' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#registerContentObserverAsUser(android.net.Uri, boolean, android.database.ContentObserver, android.os.UserHandle):
+    Method 'registerContentObserverAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.ContentResolver#removePeriodicSync(android.accounts.Account, String, android.os.Bundle):
+    Method 'removePeriodicSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setIsSyncable(android.accounts.Account, String, int):
+    Method 'setIsSyncable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setMasterSyncAutomatically(boolean):
+    Method 'setMasterSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setSyncAutomatically(android.accounts.Account, String, boolean):
+    Method 'setSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    Method 'bindServiceAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.Context#clearWallpaper():
+    Method 'clearWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalCacheDir():
+    Method 'getExternalCacheDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalCacheDirs():
+    Method 'getExternalCacheDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalFilesDir(String):
+    Method 'getExternalFilesDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalFilesDirs(String):
+    Method 'getExternalFilesDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalMediaDirs():
+    Method 'getExternalMediaDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getObbDir():
+    Method 'getObbDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getObbDirs():
+    Method 'getObbDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle):
+    Method 'removeStickyBroadcastAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.Context#setWallpaper(android.graphics.Bitmap):
+    Method 'setWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#setWallpaper(java.io.InputStream):
+    Method 'setWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#canRequestInteractAcrossProfiles():
+    Method 'canRequestInteractAcrossProfiles' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.ComponentName, android.os.UserHandle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.ComponentName, android.os.UserHandle, android.app.Activity, android.os.Bundle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.Intent, android.os.UserHandle, android.app.Activity):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.Intent, android.os.UserHandle, android.app.Activity, android.os.Bundle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps#getAllPackageInstallerSessions():
+    Method 'getAllPackageInstallerSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps#registerPackageInstallerSessionCallback(java.util.concurrent.Executor, android.content.pm.PackageInstaller.SessionCallback):
+    Method 'registerPackageInstallerSessionCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps.Callback#onPackagesSuspended(String[], android.os.UserHandle, android.os.Bundle):
+    Method 'onPackagesSuspended' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getAllSessions():
+    Method 'getAllSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getSessionInfo(int):
+    Method 'getSessionInfo' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getStagedSessions():
+    Method 'getStagedSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback):
+    Method 'registerSessionCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.Session#requestUserPreapproval(android.content.pm.PackageInstaller.PreapprovalDetails, android.content.IntentSender):
+    Method 'requestUserPreapproval' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setInstallerPackageName(String):
+    Method 'setInstallerPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setPermissionState(String, int):
+    Method 'setPermissionState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setRequestUpdateOwnership(boolean):
+    Method 'setRequestUpdateOwnership' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(int):
+    Method 'setRequireUserAction' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#canRequestPackageInstalls():
+    Method 'canRequestPackageInstalls' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#getSuspendedPackageAppExtras():
+    Method 'getSuspendedPackageAppExtras' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#getUnsuspendablePackages(String[]):
+    Method 'getUnsuspendablePackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#grantRuntimePermission(String, String, android.os.UserHandle):
+    Method 'grantRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#isAutoRevokeWhitelisted(String):
+    Method 'isAutoRevokeWhitelisted' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#isPackageSuspended():
+    Method 'isPackageSuspended' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle):
+    Method 'revokeRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle, String):
+    Method 'revokeRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setDistractingPackageRestrictions(String[], int):
+    Method 'setDistractingPackageRestrictions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, String):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, android.content.pm.SuspendDialogInfo):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, android.content.pm.SuspendDialogInfo, int):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#verifyIntentFilter(int, int, java.util.List<java.lang.String>):
+    Method 'verifyIntentFilter' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.Sensor#getHighestDirectReportRateLevel():
+    Method 'getHighestDirectReportRateLevel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.Sensor#getMinDelay():
+    Method 'getMinDelay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraCharacteristics#getKeysNeedingPermission():
+    Method 'getKeysNeedingPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraManager.AvailabilityCallback#onCameraClosed(String):
+    Method 'onCameraClosed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraManager.AvailabilityCallback#onCameraOpened(String, String):
+    Method 'onCameraOpened' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.hdmi.HdmiControlManager#getHdmiCecVersion():
+    Method 'getHdmiCecVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.hdmi.HdmiControlManager#setHdmiCecVersion(int):
+    Method 'setHdmiCecVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback):
+    Method 'addGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#getMonitoringTypes():
+    Method 'getMonitoringTypes' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#pauseGeofence(int, int):
+    Method 'pauseGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback):
+    Method 'registerForMonitorStateChangeCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#removeGeofence(int, int):
+    Method 'removeGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#resumeGeofence(int, int, int):
+    Method 'resumeGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback):
+    Method 'unregisterForMonitorStateChangeCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#grantPermission(android.hardware.usb.UsbDevice, String):
+    Method 'grantPermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#hasPermission(android.hardware.usb.UsbDevice):
+    Method 'hasPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#requestPermission(android.hardware.usb.UsbDevice, android.app.PendingIntent):
+    Method 'requestPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.AudioAttributes.Builder#setHapticChannelsMuted(boolean):
+    Method 'setHapticChannelsMuted' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.AudioManager#getCallDownlinkExtractionAudioRecord(android.media.AudioFormat):
+    Method 'getCallDownlinkExtractionAudioRecord' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioManager#getCallUplinkInjectionAudioTrack(android.media.AudioFormat):
+    Method 'getCallUplinkInjectionAudioTrack' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioManager#registerAudioPolicy(android.media.audiopolicy.AudioPolicy):
+    Method 'registerAudioPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioRecord#shareAudioHistory(String, long):
+    Method 'shareAudioHistory' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioRecordingConfiguration#getClientUid():
+    Method 'getClientUid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.MediaCodec#createByCodecNameForClient(String, int, int):
+    Method 'createByCodecNameForClient' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(String):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(String, java.util.Map<java.lang.String,java.lang.String>):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String,java.lang.String>):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaPlayer#setWakeMode(android.content.Context, int):
+    Method 'setWakeMode' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaRouter2#getInstance(android.content.Context, String):
+    Method 'getInstance' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.RingtoneManager#getCursor():
+    Method 'getCursor' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.RingtoneManager#getValidRingtoneUri(android.content.Context):
+    Method 'getValidRingtoneUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.audiofx.HapticGenerator#setEnabled(boolean):
+    Method 'setEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.projection.MediaProjection#createVirtualDisplay(String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback, android.os.Handler):
+    Method 'createVirtualDisplay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.projection.MediaProjectionManager#getMediaProjection(int, android.content.Intent):
+    Method 'getMediaProjection' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.content.ComponentName, android.os.UserHandle, java.util.concurrent.Executor, android.media.session.MediaSessionManager.OnActiveSessionsChangedListener):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnMediaKeyEventSessionChangedListener(java.util.concurrent.Executor, android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener):
+    Method 'addOnMediaKeyEventSessionChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getActiveSessions(android.content.ComponentName):
+    Method 'getActiveSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getActiveSessionsForUser(android.content.ComponentName, android.os.UserHandle):
+    Method 'getActiveSessionsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getMediaKeyEventSession():
+    Method 'getMediaKeyEventSession' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getMediaKeyEventSessionPackageName():
+    Method 'getMediaKeyEventSessionPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#isTrustedForMediaControl(android.media.session.MediaSessionManager.RemoteUserInfo):
+    Method 'isTrustedForMediaControl' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#deleteKeyphraseSoundModel(int, java.util.Locale):
+    Method 'deleteKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#getKeyphraseSoundModel(int, java.util.Locale):
+    Method 'getKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#updateKeyphraseSoundModel(android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel):
+    Method 'updateKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#clearScores():
+    Method 'clearScores' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#disableScoring():
+    Method 'disableScoring' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#getActiveScorerPackage():
+    Method 'getActiveScorerPackage' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#registerNetworkScoreCallback(int, int, java.util.concurrent.Executor, android.net.NetworkScoreManager.NetworkScoreCallback):
+    Method 'registerNetworkScoreCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#requestScores(java.util.Collection<android.net.NetworkKey>):
+    Method 'requestScores' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#setActiveScorer(String):
+    Method 'setActiveScorer' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.VpnService#prepareAndAuthorize(android.content.Context):
+    Method 'prepareAndAuthorize' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.sip.SipAudioCall#setSpeakerMode(boolean):
+    Method 'setSpeakerMode' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.net.sip.SipAudioCall#startAudio():
+    Method 'startAudio' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#addVcnNetworkPolicyChangeListener(java.util.concurrent.Executor, android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener):
+    Method 'addVcnNetworkPolicyChangeListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#applyVcnNetworkPolicy(android.net.NetworkCapabilities, android.net.LinkProperties):
+    Method 'applyVcnNetworkPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#removeVcnNetworkPolicyChangeListener(android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener):
+    Method 'removeVcnNetworkPolicyChangeListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
+    Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
+    Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
+    Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
+    Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
+    Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
+    Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
+    Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
+    Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
+    Method 'increment' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
+    Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
+    Method 'restore' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
+    Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
+    Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
+    Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
+    Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
+    Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#isWritable():
+    Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
+    Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
+    Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
+    Method 'format' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
+    Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#close():
+    Method 'close' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#connect():
+    Method 'connect' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.BugreportManager#cancelBugreport():
+    Method 'cancelBugreport' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.BugreportManager#preDumpUiData():
+    Method 'preDumpUiData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Build#getSerial():
+    Method 'getSerial' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Debug#dumpService(String, java.io.FileDescriptor, String[]):
+    Method 'dumpService' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.DropBoxManager#getNextEntry(String, long):
+    Method 'getNextEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Environment#getExternalStorageDirectory():
+    Method 'getExternalStorageDirectory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Environment#isExternalStorageManager():
+    Method 'isExternalStorageManager' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Environment#isExternalStorageManager(java.io.File):
+    Method 'isExternalStorageManager' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#dream(long):
+    Method 'dream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#forceSuspend():
+    Method 'forceSuspend' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#getPowerSaveModeTrigger():
+    Method 'getPowerSaveModeTrigger' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#newWakeLock(int, String):
+    Method 'newWakeLock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#reboot(String):
+    Method 'reboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#setBatteryDischargePrediction(java.time.Duration, boolean):
+    Method 'setBatteryDischargePrediction' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#setDynamicPowerSaveHint(boolean, int):
+    Method 'setDynamicPowerSaveHint' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#userActivity(long, int, int):
+    Method 'userActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.RecoverySystem#rebootWipeUserData(android.content.Context):
+    Method 'rebootWipeUserData' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.StrictMode.VmPolicy.Builder#detectFileUriExposure():
+    Method 'detectFileUriExposure' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.SystemUpdateManager#retrieveSystemUpdateInfo():
+    Method 'retrieveSystemUpdateInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.SystemUpdateManager#updateSystemUpdateInfo(android.os.PersistableBundle):
+    Method 'updateSystemUpdateInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#getUserProperties(android.os.UserHandle):
+    Method 'getUserProperties' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#getUserRestrictions(android.os.UserHandle):
+    Method 'getUserRestrictions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#hasUserRestrictionForUser(String, android.os.UserHandle):
+    Method 'hasUserRestrictionForUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isManagedProfile(int):
+    Method 'isManagedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isRestrictedProfile():
+    Method 'isRestrictedProfile' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.UserManager#isRestrictedProfile(android.os.UserHandle):
+    Method 'isRestrictedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isUserUnlocked(android.os.UserHandle):
+    Method 'isUserUnlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isUserUnlockingOrUnlocked(android.os.UserHandle):
+    Method 'isUserUnlockingOrUnlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#requestQuietModeEnabled(boolean, android.os.UserHandle):
+    Method 'requestQuietModeEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#setUserRestriction(String, boolean):
+    Method 'setUserRestriction' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshot(int):
+    Method 'takeUidSnapshot' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshots(int[]):
+    Method 'takeUidSnapshots' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#getCloudMediaProvider():
+    Method 'getCloudMediaProvider' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#getManageSpaceActivityIntent(String, int):
+    Method 'getManageSpaceActivityIntent' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#notifyAppIoBlocked(java.util.UUID, int, int, int):
+    Method 'notifyAppIoBlocked' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#notifyAppIoResumed(java.util.UUID, int, int, int):
+    Method 'notifyAppIoResumed' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#setCloudMediaProvider(String):
+    Method 'setCloudMediaProvider' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageVolume#createAccessIntent(String):
+    Method 'createAccessIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForDataDelivery(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForDataDelivery' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForDataDeliveryFromDataSource(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForDataDeliveryFromDataSource' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForStartDataDelivery(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForStartDataDelivery' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.provider.Settings#canDrawOverlays(android.content.Context):
+    Method 'canDrawOverlays' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.provider.Settings.System#canWrite(android.content.Context):
+    Method 'canWrite' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.security.KeyChain#removeCredentialManagementApp(android.content.Context):
+    Method 'removeCredentialManagementApp' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.BeginCreateCredentialResponse.Builder#setRemoteCreateEntry(android.service.credentials.RemoteEntry):
+    Method 'setRemoteCreateEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.BeginGetCredentialResponse.Builder#setRemoteCredentialEntry(android.service.credentials.RemoteEntry):
+    Method 'setRemoteCredentialEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.CallingAppInfo#getOrigin():
+    Method 'getOrigin' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.Call.Details#getContactDisplayName():
+    Method 'getContactDisplayName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.Call.Details#getContactPhotoUri():
+    Method 'getContactPhotoUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle):
+    Method 'acceptHandover' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    Method 'addNewIncomingCall' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingConference(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    Method 'addNewIncomingConference' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getCallState():
+    Method 'getCallState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getLine1Number(android.telecom.PhoneAccountHandle):
+    Method 'getLine1Number' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getOwnSelfManagedPhoneAccounts():
+    Method 'getOwnSelfManagedPhoneAccounts' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getPhoneAccount(android.telecom.PhoneAccountHandle):
+    Method 'getPhoneAccount' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getSelfManagedPhoneAccounts():
+    Method 'getSelfManagedPhoneAccounts' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#hasManageOngoingCallsPermission():
+    Method 'hasManageOngoingCallsPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#placeCall(android.net.Uri, android.os.Bundle):
+    Method 'placeCall' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#showInCallScreen(boolean):
+    Method 'showInCallScreen' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#silenceRinger():
+    Method 'silenceRinger' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig():
+    Method 'getConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig(java.lang.String...):
+    Method 'getConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigByComponentForSubId(String, int):
+    Method 'getConfigByComponentForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int):
+    Method 'getConfigForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int, java.lang.String...):
+    Method 'getConfigForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#notifyConfigChangedForSubId(int):
+    Method 'notifyConfigChangedForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CellLocation#requestLocationUpdate():
+    Method 'requestLocationUpdate' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.NetworkRegistrationInfo#getCellIdentity():
+    Method 'getCellIdentity' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onActiveDataSubscriptionIdChanged(int):
+    Method 'onActiveDataSubscriptionIdChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onCallAttributesChanged(android.telephony.CallAttributes):
+    Method 'onCallAttributesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onCallStateChanged(int, String):
+    Method 'onCallStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onDisplayInfoChanged(android.telephony.TelephonyDisplayInfo):
+    Method 'onDisplayInfoChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState):
+    Method 'onPreciseDataConnectionStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onRadioPowerStateChanged(int):
+    Method 'onRadioPowerStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onServiceStateChanged(android.telephony.ServiceState):
+    Method 'onServiceStateChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getCdmaNetworkId():
+    Method 'getCdmaNetworkId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getCdmaSystemId():
+    Method 'getCdmaSystemId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorAlphaLong():
+    Method 'getOperatorAlphaLong' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorAlphaShort():
+    Method 'getOperatorAlphaShort' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorNumeric():
+    Method 'getOperatorNumeric' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SignalStrengthUpdateRequest.Builder#setSystemThresholdReportingRequestedWhileIdle(boolean):
+    Method 'setSystemThresholdReportingRequestedWhileIdle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#disableCellBroadcastRange(int, int, int):
+    Method 'disableCellBroadcastRange' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#enableCellBroadcastRange(int, int, int):
+    Method 'enableCellBroadcastRange' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#getSmscAddress():
+    Method 'getSmscAddress' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#injectSmsPdu(byte[], String, android.app.PendingIntent):
+    Method 'injectSmsPdu' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendDataMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>):
+    Method 'sendMultipartTextMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>):
+    Method 'sendMultipartTextMessageWithoutPersisting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendTextMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendTextMessageWithoutPersisting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#setSmscAddress(String):
+    Method 'setSmscAddress' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#addSubscriptionsIntoGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    Method 'addSubscriptionsIntoGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#createSubscriptionGroup(java.util.List<java.lang.Integer>):
+    Method 'createSubscriptionGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfo(int):
+    Method 'getActiveSubscriptionInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoForSimSlotIndex(int):
+    Method 'getActiveSubscriptionInfoForSimSlotIndex' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoList():
+    Method 'getActiveSubscriptionInfoList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList():
+    Method 'getAvailableSubscriptionInfoList' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getCompleteActiveSubscriptionInfoList():
+    Method 'getCompleteActiveSubscriptionInfoList' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getOpportunisticSubscriptions():
+    Method 'getOpportunisticSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getResourcesForSubId(android.content.Context, int):
+    Method 'getResourcesForSubId' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getSubscriptionsInGroup(android.os.ParcelUuid):
+    Method 'getSubscriptionsInGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#removeSubscriptionsFromGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    Method 'removeSubscriptionsFromGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh():
+    Method 'requestEmbeddedSubscriptionInfoListRefresh' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh(int):
+    Method 'requestEmbeddedSubscriptionInfoListRefresh' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#setOpportunistic(boolean, int):
+    Method 'setOpportunistic' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#setPreferredDataSubscriptionId(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setPreferredDataSubscriptionId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener#onActiveDataSubscriptionIdChanged(int):
+    Method 'onActiveDataSubscriptionIdChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.BarringInfoListener#onBarringInfoChanged(android.telephony.BarringInfo):
+    Method 'onBarringInfoChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallAttributesListener#onCallAttributesChanged(android.telephony.CallAttributes):
+    Method 'onCallAttributesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallAttributesListener#onCallStatesChanged(java.util.List<android.telephony.CallState>):
+    Method 'onCallStatesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallForwardingIndicatorListener#onCallForwardingIndicatorChanged(boolean):
+    Method 'onCallForwardingIndicatorChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.DataEnabledListener#onDataEnabledChanged(boolean, int):
+    Method 'onDataEnabledChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.EmergencyNumberListListener#onEmergencyNumberListChanged(java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>):
+    Method 'onEmergencyNumberListChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ImsCallDisconnectCauseListener#onImsCallDisconnectCauseChanged(android.telephony.ims.ImsReasonInfo):
+    Method 'onImsCallDisconnectCauseChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.MessageWaitingIndicatorListener#onMessageWaitingIndicatorChanged(boolean):
+    Method 'onMessageWaitingIndicatorChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PhysicalChannelConfigListener#onPhysicalChannelConfigChanged(java.util.List<android.telephony.PhysicalChannelConfig>):
+    Method 'onPhysicalChannelConfigChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PreciseCallStateListener#onPreciseCallStateChanged(android.telephony.PreciseCallState):
+    Method 'onPreciseCallStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PreciseDataConnectionStateListener#onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState):
+    Method 'onPreciseDataConnectionStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.RegistrationFailedListener#onRegistrationFailed(android.telephony.CellIdentity, String, int, int, int):
+    Method 'onRegistrationFailed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ServiceStateListener#onServiceStateChanged(android.telephony.ServiceState):
+    Method 'onServiceStateChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#bootstrapAuthenticationRequest(int, android.net.Uri, android.telephony.gba.UaSecurityProtocolIdentifier, boolean, java.util.concurrent.Executor, android.telephony.TelephonyManager.BootstrapAuthenticationCallback):
+    Method 'bootstrapAuthenticationRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#changeIccLockPin(String, String):
+    Method 'changeIccLockPin' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#clearRadioPowerOffForReason(int):
+    Method 'clearRadioPowerOffForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#clearSignalStrengthUpdateRequest(android.telephony.SignalStrengthUpdateRequest):
+    Method 'clearSignalStrengthUpdateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#doesSwitchMultiSimConfigTriggerReboot():
+    Method 'doesSwitchMultiSimConfigTriggerReboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#enableModemForSlot(int, boolean):
+    Method 'enableModemForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAidForAppType(int):
+    Method 'getAidForAppType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypes():
+    Method 'getAllowedNetworkTypes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypesBitmask():
+    Method 'getAllowedNetworkTypesBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypesForReason(int):
+    Method 'getAllowedNetworkTypesForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCallState():
+    Method 'getCallState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCallStateForSubscription():
+    Method 'getCallStateForSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierConfig():
+    Method 'getCarrierConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierInfoForImsiEncryption(int):
+    Method 'getCarrierInfoForImsiEncryption' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierRestrictionStatus(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getCarrierRestrictionStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCdmaRoamingMode():
+    Method 'getCdmaRoamingMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCdmaSubscriptionMode():
+    Method 'getCdmaSubscriptionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDataActivationState():
+    Method 'getDataActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDataNetworkType():
+    Method 'getDataNetworkType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId():
+    Method 'getDeviceId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId(int):
+    Method 'getDeviceId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceSoftwareVersion(int):
+    Method 'getDeviceSoftwareVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberDbVersion():
+    Method 'getEmergencyNumberDbVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList():
+    Method 'getEmergencyNumberList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList(int):
+    Method 'getEmergencyNumberList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEquivalentHomePlmns():
+    Method 'getEquivalentHomePlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getForbiddenPlmns():
+    Method 'getForbiddenPlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getGroupIdLevel1():
+    Method 'getGroupIdLevel1' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getImei(int):
+    Method 'getImei' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getIsimDomain():
+    Method 'getIsimDomain' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getLine1Number():
+    Method 'getLine1Number' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getManualNetworkSelectionPlmn():
+    Method 'getManualNetworkSelectionPlmn' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getMeid():
+    Method 'getMeid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getMeid(int):
+    Method 'getMeid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNai():
+    Method 'getNai' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNetworkSelectionMode():
+    Method 'getNetworkSelectionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNetworkSlicingConfiguration(java.util.concurrent.Executor, android.os.OutcomeReceiver<android.telephony.data.NetworkSlicingConfig,android.telephony.TelephonyManager.NetworkSlicingException>):
+    Method 'getNetworkSlicingConfiguration' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPhoneAccountHandle():
+    Method 'getPhoneAccountHandle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPreferredNetworkTypeBitmask():
+    Method 'getPreferredNetworkTypeBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPreferredOpportunisticDataSubscription():
+    Method 'getPreferredOpportunisticDataSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getRadioPowerOffReasons():
+    Method 'getRadioPowerOffReasons' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getRadioPowerState():
+    Method 'getRadioPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getServiceState():
+    Method 'getServiceState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getServiceState(int):
+    Method 'getServiceState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSimLocale():
+    Method 'getSimLocale' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSimSerialNumber():
+    Method 'getSimSerialNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSubscriberId():
+    Method 'getSubscriberId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSupportedRadioAccessFamily():
+    Method 'getSupportedRadioAccessFamily' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSystemSelectionChannels():
+    Method 'getSystemSelectionChannels' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getTelephonyHistograms():
+    Method 'getTelephonyHistograms' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVisualVoicemailPackageName():
+    Method 'getVisualVoicemailPackageName' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceActivationState():
+    Method 'getVoiceActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailAlphaTag():
+    Method 'getVoiceMailAlphaTag' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailNumber():
+    Method 'getVoiceMailNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceNetworkType():
+    Method 'getVoiceNetworkType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccCloseLogicalChannel(int):
+    Method 'iccCloseLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccCloseLogicalChannelBySlot(int, int):
+    Method 'iccCloseLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccExchangeSimIO(int, int, int, int, int, String):
+    Method 'iccExchangeSimIO' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String):
+    Method 'iccOpenLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String, int):
+    Method 'iccOpenLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannelBySlot(int, String, int):
+    Method 'iccOpenLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduBasicChannel(int, int, int, int, int, String):
+    Method 'iccTransmitApduBasicChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, String):
+    Method 'iccTransmitApduBasicChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduLogicalChannel(int, int, int, int, int, int, String):
+    Method 'iccTransmitApduLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, String):
+    Method 'iccTransmitApduLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isApplicationOnUicc(int):
+    Method 'isApplicationOnUicc' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabled():
+    Method 'isDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabledForReason(int):
+    Method 'isDataEnabledForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataRoamingEnabled():
+    Method 'isDataRoamingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isEmergencyAssistanceEnabled():
+    Method 'isEmergencyAssistanceEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isIccLockEnabled():
+    Method 'isIccLockEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isManualNetworkSelectionAllowed():
+    Method 'isManualNetworkSelectionAllowed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isModemEnabledForSlot(int):
+    Method 'isModemEnabledForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isMultiSimSupported():
+    Method 'isMultiSimSupported' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isOpportunisticNetworkEnabled():
+    Method 'isOpportunisticNetworkEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isPotentialEmergencyNumber(String):
+    Method 'isPotentialEmergencyNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isPremiumCapabilityAvailableForPurchase(int):
+    Method 'isPremiumCapabilityAvailableForPurchase' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isTetheringApnRequired():
+    Method 'isTetheringApnRequired' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#notifyOtaEmergencyNumberDbInstalled():
+    Method 'notifyOtaEmergencyNumberDbInstalled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#prepareForUnattendedReboot():
+    Method 'prepareForUnattendedReboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#purchasePremiumCapability(int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'purchasePremiumCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#rebootModem():
+    Method 'rebootModem' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#rebootRadio():
+    Method 'rebootRadio' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#reportDefaultNetworkStatus(boolean):
+    Method 'reportDefaultNetworkStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    Method 'requestNetworkScan' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(int, android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    Method 'requestNetworkScan' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNumberVerification(android.telephony.PhoneNumberRange, long, java.util.concurrent.Executor, android.telephony.NumberVerificationCallback):
+    Method 'requestNumberVerification' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestRadioPowerOffForReason(int):
+    Method 'requestRadioPowerOffForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetAllCarrierActions():
+    Method 'resetAllCarrierActions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetCarrierKeysForImsiEncryption():
+    Method 'resetCarrierKeysForImsiEncryption' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetOtaEmergencyNumberDbFilePath():
+    Method 'resetOtaEmergencyNumberDbFilePath' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetRadioConfig():
+    Method 'resetRadioConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendEnvelopeWithStatus(String):
+    Method 'sendEnvelopeWithStatus' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendThermalMitigationRequest(android.telephony.ThermalMitigationRequest):
+    Method 'sendThermalMitigationRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler):
+    Method 'sendUssdRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendVisualVoicemailSms(String, int, String, android.app.PendingIntent):
+    Method 'sendVisualVoicemailSms' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>):
+    Method 'setAllowedCarriers' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setAllowedNetworkTypesForReason(int, long):
+    Method 'setAllowedNetworkTypesForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCarrierDataEnabled(boolean):
+    Method 'setCarrierDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCarrierRestrictionRules(android.telephony.CarrierRestrictionRules):
+    Method 'setCarrierRestrictionRules' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCdmaRoamingMode(int):
+    Method 'setCdmaRoamingMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCdmaSubscriptionMode(int):
+    Method 'setCdmaSubscriptionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataActivationState(int):
+    Method 'setDataActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabled(boolean):
+    Method 'setDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabledForReason(int, boolean):
+    Method 'setDataEnabledForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataRoamingEnabled(boolean):
+    Method 'setDataRoamingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setForbiddenPlmns(java.util.List<java.lang.String>):
+    Method 'setForbiddenPlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setIccLockEnabled(boolean, String):
+    Method 'setIccLockEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeAutomatic():
+    Method 'setNetworkSelectionModeAutomatic' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean):
+    Method 'setNetworkSelectionModeManual' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean, int):
+    Method 'setNetworkSelectionModeManual' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setOpportunisticNetworkState(boolean):
+    Method 'setOpportunisticNetworkState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setPreferredNetworkTypeBitmask(long):
+    Method 'setPreferredNetworkTypeBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setPreferredOpportunisticDataSubscription(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setPreferredOpportunisticDataSubscription' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setRadioEnabled(boolean):
+    Method 'setRadioEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSignalStrengthUpdateRequest(android.telephony.SignalStrengthUpdateRequest):
+    Method 'setSignalStrengthUpdateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerState(int):
+    Method 'setSimPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerState(int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setSimPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerStateForSlot(int, int):
+    Method 'setSimPowerStateForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerStateForSlot(int, int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setSimPowerStateForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoiceActivationState(int):
+    Method 'setVoiceActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri):
+    Method 'setVoicemailRingtoneUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean):
+    Method 'setVoicemailVibrationEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#supplyIccLockPin(String):
+    Method 'supplyIccLockPin' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#supplyIccLockPuk(String, String):
+    Method 'supplyIccLockPuk' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#switchMultiSimConfig(int):
+    Method 'switchMultiSimConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'updateAvailableNetworks' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#updateOtaEmergencyNumberDbFilePath(android.os.ParcelFileDescriptor):
+    Method 'updateOtaEmergencyNumberDbFilePath' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.VisualVoicemailService#sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent):
+    Method 'sendVisualVoicemailSms' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.VisualVoicemailService#setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings):
+    Method 'setSmsFilterSettings' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#continueOperation(android.content.Intent, android.os.Bundle):
+    Method 'continueOperation' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#deleteSubscription(int, android.app.PendingIntent):
+    Method 'deleteSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent):
+    Method 'downloadSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#eraseSubscriptions(android.app.PendingIntent):
+    Method 'eraseSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#eraseSubscriptions(int, android.app.PendingIntent):
+    Method 'eraseSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getDefaultDownloadableSubscriptionList(android.app.PendingIntent):
+    Method 'getDefaultDownloadableSubscriptionList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent):
+    Method 'getDownloadableSubscriptionMetadata' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getOtaStatus():
+    Method 'getOtaStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getSupportedCountries():
+    Method 'getSupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getUnsupportedCountries():
+    Method 'getUnsupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#setSupportedCountries(java.util.List<java.lang.String>):
+    Method 'setSupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#setUnsupportedCountries(java.util.List<java.lang.String>):
+    Method 'setUnsupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, android.app.PendingIntent):
+    Method 'switchToSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, int, android.app.PendingIntent):
+    Method 'switchToSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#updateSubscriptionNickname(int, String, android.app.PendingIntent):
+    Method 'updateSubscriptionNickname' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#createForSubscriptionId(int):
+    Method 'createForSubscriptionId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#getRegistrationTransportType(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationTransportType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#getVoWiFiModeSetting():
+    Method 'getVoWiFiModeSetting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isAdvancedCallingSettingEnabled():
+    Method 'isAdvancedCallingSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isCrossSimCallingEnabled():
+    Method 'isCrossSimCallingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isTtyOverVolteEnabled():
+    Method 'isTtyOverVolteEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVoWiFiRoamingSettingEnabled():
+    Method 'isVoWiFiRoamingSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVoWiFiSettingEnabled():
+    Method 'isVoWiFiSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVtSettingEnabled():
+    Method 'isVtSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerImsRegistrationCallback(java.util.concurrent.Executor, android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'registerImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerImsStateCallback(java.util.concurrent.Executor, android.telephony.ims.ImsStateCallback):
+    Method 'registerImsStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerMmTelCapabilityCallback(java.util.concurrent.Executor, android.telephony.ims.ImsMmTelManager.CapabilityCallback):
+    Method 'registerMmTelCapabilityCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#unregisterImsRegistrationCallback(android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'unregisterImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#unregisterMmTelCapabilityCallback(android.telephony.ims.ImsMmTelManager.CapabilityCallback):
+    Method 'unregisterMmTelCapabilityCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#getRegistrationState(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#getRegistrationTransportType(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationTransportType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#registerImsRegistrationCallback(java.util.concurrent.Executor, android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'registerImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#registerImsStateCallback(java.util.concurrent.Executor, android.telephony.ims.ImsStateCallback):
+    Method 'registerImsStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#unregisterImsRegistrationCallback(android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'unregisterImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#getProvisioningStatusForCapability(int, int):
+    Method 'getProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#getRcsProvisioningStatusForCapability(int, int):
+    Method 'getRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isProvisioningRequiredForCapability(int, int):
+    Method 'isProvisioningRequiredForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isRcsProvisioningRequiredForCapability(int, int):
+    Method 'isRcsProvisioningRequiredForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable():
+    Method 'isRcsVolteSingleRegistrationCapable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#notifyRcsAutoConfigurationReceived(byte[], boolean):
+    Method 'notifyRcsAutoConfigurationReceived' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerFeatureProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback):
+    Method 'registerFeatureProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.Callback):
+    Method 'registerProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.RcsProvisioningCallback):
+    Method 'registerRcsProvisioningCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setProvisioningStatusForCapability(int, int, boolean):
+    Method 'setProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setRcsProvisioningStatusForCapability(int, boolean):
+    Method 'setRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setRcsProvisioningStatusForCapability(int, int, boolean):
+    Method 'setRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#unregisterProvisioningChangedCallback(android.telephony.ims.ProvisioningManager.Callback):
+    Method 'unregisterProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback(android.telephony.ims.ProvisioningManager.RcsProvisioningCallback):
+    Method 'unregisterRcsProvisioningCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.SipDelegateManager#registerSipDialogStateCallback(java.util.concurrent.Executor, android.telephony.ims.SipDialogStateCallback):
+    Method 'registerSipDialogStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.SipDelegateManager#unregisterSipDialogStateCallback(android.telephony.ims.SipDialogStateCallback):
+    Method 'unregisterSipDialogStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.WindowManager.LayoutParams#isSystemApplicationOverlay():
+    Method 'isSystemApplicationOverlay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.view.accessibility.AccessibilityManager#registerDisplayProxy(android.view.accessibility.AccessibilityDisplayProxy):
+    Method 'registerDisplayProxy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.AccessibilityManager#unregisterDisplayProxy(android.view.accessibility.AccessibilityDisplayProxy):
+    Method 'unregisterDisplayProxy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.CaptioningManager#setSystemAudioCaptioningEnabled(boolean):
+    Method 'setSystemAudioCaptioningEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.CaptioningManager#setSystemAudioCaptioningUiEnabled(boolean):
+    Method 'setSystemAudioCaptioningUiEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.inputmethod.InputMethodManager#setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype):
+    Method 'setCurrentInputMethodSubtype' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.webkit.WebSettings#setBlockNetworkLoads(boolean):
+    Method 'setBlockNetworkLoads' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.webkit.WebSettings#setGeolocationEnabled(boolean):
+    Method 'setGeolocationEnabled' documentation mentions permissions without declaring @RequiresPermission
+
+
 SamShouldBeLast: android.app.Activity#convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions):
     SAM-compatible parameters (such as parameter 1, "callback", in android.app.Activity.convertToTranslucent) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
@@ -37,6 +1747,80 @@
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.session.MediaSessionManager.setOnVolumeKeyLongPressListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 
 
+SdkConstant: android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED:
+    Field 'ACTION_BATTERY_LEVEL_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_DEVICE_CUSTOMIZATION_READY:
+    Field 'ACTION_DEVICE_CUSTOMIZATION_READY' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_GLOBAL_BUTTON:
+    Field 'ACTION_GLOBAL_BUTTON' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_PRE_BOOT_COMPLETED:
+    Field 'ACTION_PRE_BOOT_COMPLETED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_UNARCHIVE_PACKAGE:
+    Field 'ACTION_UNARCHIVE_PACKAGE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.pm.PackageInstaller#ACTION_CONFIRM_PRE_APPROVAL:
+    Field 'ACTION_CONFIRM_PRE_APPROVAL' is missing @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_PORT_CHANGED:
+    Field 'ACTION_USB_PORT_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_PORT_COMPLIANCE_CHANGED:
+    Field 'ACTION_USB_PORT_COMPLIANCE_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_STATE:
+    Field 'ACTION_USB_STATE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_DELETE_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_RENAME_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE:
+    Field 'ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS:
+    Field 'ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+
+
+Todo: android.Manifest.permission#DOMAIN_VERIFICATION_AGENT:
+    Documentation mentions 'TODO'
+Todo: android.Manifest.permission#INSTALL_EXISTING_PACKAGES:
+    Documentation mentions 'TODO'
+Todo: android.Manifest.permission#READ_PEOPLE_DATA:
+    Documentation mentions 'TODO'
+Todo: android.app.NotificationManager#isNotificationAssistantAccessGranted(android.content.ComponentName):
+    Documentation mentions 'TODO'
+Todo: android.hardware.camera2.params.StreamConfigurationMap:
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#getNanoAppInstanceInfo(int):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#loadNanoApp(int, android.hardware.location.NanoApp):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#unloadNanoApp(int):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.NanoAppInstanceInfo:
+    Documentation mentions 'TODO'
+Todo: android.media.tv.TvContentRatingSystemInfo#getXmlUri():
+    Documentation mentions 'TODO'
+Todo: android.media.tv.TvInputInfo#isConnectedToHdmiSwitch():
+    Documentation mentions 'TODO'
+Todo: android.os.RecoverySystem#prepareForUnattendedUpdate(android.content.Context, String, android.content.IntentSender):
+    Documentation mentions 'TODO'
+Todo: android.os.RecoverySystem#rebootAndApply(android.content.Context, String, String):
+    Documentation mentions 'TODO'
+Todo: android.os.SystemConfigManager:
+    Documentation mentions 'TODO'
+Todo: android.os.UpdateEngineCallback#onStatusUpdate(int, float):
+    Documentation mentions 'TODO'
+Todo: android.provider.ContactsContract.RawContacts#newEntityIterator(android.database.Cursor):
+    Documentation mentions 'TODO'
+Todo: android.service.voice.AlwaysOnHotwordDetector:
+    Documentation mentions 'TODO'
+Todo: android.telephony.TelephonyManager#getCurrentPhoneType():
+    Documentation mentions 'TODO'
+
+
 UnflaggedApi: android.Manifest.permission#MANAGE_REMOTE_AUTH:
     New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_REMOTE_AUTH
 UnflaggedApi: android.Manifest.permission#USE_COMPANION_TRANSPORTS:
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 183b925..346d62b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -261,6 +261,7 @@
     field public static final String PROVIDE_RESOLVER_RANKER_SERVICE = "android.permission.PROVIDE_RESOLVER_RANKER_SERVICE";
     field public static final String PROVIDE_TRUST_AGENT = "android.permission.PROVIDE_TRUST_AGENT";
     field public static final String PROVISION_DEMO_DEVICE = "android.permission.PROVISION_DEMO_DEVICE";
+    field @FlaggedApi("android.content.pm.quarantined_enabled") public static final String QUARANTINE_APPS = "android.permission.QUARANTINE_APPS";
     field public static final String QUERY_ADMIN_POLICY = "android.permission.QUERY_ADMIN_POLICY";
     field public static final String QUERY_CLONED_APPS = "android.permission.QUERY_CLONED_APPS";
     field @Deprecated public static final String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES";
@@ -981,7 +982,7 @@
     field public static final int SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY = 11; // 0xb
   }
 
-  public static final class Notification.TvExtender implements android.app.Notification.Extender {
+  @FlaggedApi("android.app.api_tvextender") public static final class Notification.TvExtender implements android.app.Notification.Extender {
     method public boolean getSuppressShowOverApps();
     method public android.app.Notification.TvExtender setChannel(String);
   }
@@ -3253,6 +3254,7 @@
     field @Deprecated public static final int NAVIGATION_POLICY_DEFAULT_BLOCKED = 1; // 0x1
     field @FlaggedApi("android.companion.virtual.flags.dynamic_policy") public static final int POLICY_TYPE_ACTIVITY = 3; // 0x3
     field public static final int POLICY_TYPE_AUDIO = 1; // 0x1
+    field @FlaggedApi("android.companion.virtual.flags.cross_device_clipboard") public static final int POLICY_TYPE_CLIPBOARD = 4; // 0x4
     field public static final int POLICY_TYPE_RECENTS = 2; // 0x2
     field public static final int POLICY_TYPE_SENSORS = 0; // 0x0
   }
@@ -3860,7 +3862,7 @@
     method public boolean getInstallAsVirtualPreload();
     method public int getPendingUserActionReason();
     method public boolean getRequestDowngrade();
-    method @Nullable @RequiresPermission(android.Manifest.permission.READ_INSTALLED_SESSION_PATHS) public String getResolvedBaseApkPath();
+    method @FlaggedApi("android.content.pm.get_resolved_apk_path") @Nullable @RequiresPermission(android.Manifest.permission.READ_INSTALLED_SESSION_PATHS) public String getResolvedBaseApkPath();
     method public int getRollbackDataPolicy();
     method @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions();
   }
@@ -3915,6 +3917,7 @@
     method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @Deprecated public abstract int installExistingPackage(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Deprecated public abstract int installExistingPackage(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @FlaggedApi("android.content.pm.archiving") public boolean isAppArchivable(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, int, android.os.UserHandle);
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
@@ -4087,7 +4090,7 @@
     field public static final int PROTECTION_FLAG_MODULE = 4194304; // 0x400000
     field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000
     field public static final int PROTECTION_FLAG_RECENTS = 33554432; // 0x2000000
-    field public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
+    field @Deprecated public static final int PROTECTION_FLAG_RETAIL_DEMO = 16777216; // 0x1000000
     field public static final int PROTECTION_FLAG_ROLE = 67108864; // 0x4000000
     field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000
     field public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 32768; // 0x8000
@@ -6748,7 +6751,7 @@
     method public boolean setUidDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
     method public boolean setUserIdDeviceAffinity(int, @NonNull java.util.List<android.media.AudioDeviceInfo>);
     method public String toLogFriendlyString();
-    method @FlaggedApi("com.android.media.audio.flags.audio_policy_update_mixing_rules_api") @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int updateMixingRules(@NonNull java.util.List<android.util.Pair<android.media.audiopolicy.AudioMix,android.media.audiopolicy.AudioMixingRule>>);
+    method @FlaggedApi("android.media.audiopolicy.audio_policy_update_mixing_rules_api") @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int updateMixingRules(@NonNull java.util.List<android.util.Pair<android.media.audiopolicy.AudioMix,android.media.audiopolicy.AudioMixingRule>>);
     field public static final int FOCUS_POLICY_DUCKING_DEFAULT = 0; // 0x0
     field public static final int FOCUS_POLICY_DUCKING_IN_APP = 0; // 0x0
     field public static final int FOCUS_POLICY_DUCKING_IN_POLICY = 1; // 0x1
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index a501031..8652402 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -3,6 +3,512 @@
     Method should return Collection<CharSequence> (or subclass) instead of raw array; was `java.lang.CharSequence[]`
 
 
+BroadcastBehavior: android.app.AlarmManager#ACTION_NEXT_ALARM_CLOCK_CHANGED:
+    Field 'ACTION_NEXT_ALARM_CLOCK_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.AlarmManager#ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED:
+    Field 'ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.NotificationManager#ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL:
+    Field 'ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED:
+    Field 'ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_MANAGED_PROFILE_PROVISIONED:
+    Field 'ACTION_MANAGED_PROFILE_PROVISIONED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_AIRPLANE_MODE_CHANGED:
+    Field 'ACTION_AIRPLANE_MODE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_LOCALE_CHANGED:
+    Field 'ACTION_APPLICATION_LOCALE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED:
+    Field 'ACTION_APPLICATION_RESTRICTIONS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_CHANGED:
+    Field 'ACTION_BATTERY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED:
+    Field 'ACTION_BATTERY_LEVEL_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_LOW:
+    Field 'ACTION_BATTERY_LOW' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_OKAY:
+    Field 'ACTION_BATTERY_OKAY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CAMERA_BUTTON:
+    Field 'ACTION_CAMERA_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CLOSE_SYSTEM_DIALOGS:
+    Field 'ACTION_CLOSE_SYSTEM_DIALOGS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CONFIGURATION_CHANGED:
+    Field 'ACTION_CONFIGURATION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DATE_CHANGED:
+    Field 'ACTION_DATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_CUSTOMIZATION_READY:
+    Field 'ACTION_DEVICE_CUSTOMIZATION_READY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_LOW:
+    Field 'ACTION_DEVICE_STORAGE_LOW' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_OK:
+    Field 'ACTION_DEVICE_STORAGE_OK' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DOCK_EVENT:
+    Field 'ACTION_DOCK_EVENT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DOMAINS_NEED_VERIFICATION:
+    Field 'ACTION_DOMAINS_NEED_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STARTED:
+    Field 'ACTION_DREAMING_STARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STOPPED:
+    Field 'ACTION_DREAMING_STOPPED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
+    Field 'ACTION_EXTERNAL_APPLICATIONS_AVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+    Field 'ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GLOBAL_BUTTON:
+    Field 'ACTION_GLOBAL_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_CONNECTED:
+    Field 'ACTION_GTALK_SERVICE_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_DISCONNECTED:
+    Field 'ACTION_GTALK_SERVICE_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_HEADSET_PLUG:
+    Field 'ACTION_HEADSET_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INPUT_METHOD_CHANGED:
+    Field 'ACTION_INPUT_METHOD_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INSTALL_INSTANT_APP_PACKAGE:
+    Field 'ACTION_INSTALL_INSTANT_APP_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS:
+    Field 'ACTION_INSTANT_APP_RESOLVER_SETTINGS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION:
+    Field 'ACTION_INTENT_FILTER_NEEDS_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOAD_DATA:
+    Field 'ACTION_LOAD_DATA' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOCALE_CHANGED:
+    Field 'ACTION_LOCALE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED:
+    Field 'ACTION_LOCKED_BOOT_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MANAGE_PACKAGE_STORAGE:
+    Field 'ACTION_MANAGE_PACKAGE_STORAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BAD_REMOVAL:
+    Field 'ACTION_MEDIA_BAD_REMOVAL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BUTTON:
+    Field 'ACTION_MEDIA_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_CHECKING:
+    Field 'ACTION_MEDIA_CHECKING' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_EJECT:
+    Field 'ACTION_MEDIA_EJECT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_MOUNTED:
+    Field 'ACTION_MEDIA_MOUNTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_NOFS:
+    Field 'ACTION_MEDIA_NOFS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_REMOVED:
+    Field 'ACTION_MEDIA_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_FINISHED:
+    Field 'ACTION_MEDIA_SCANNER_FINISHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_SCAN_FILE:
+    Field 'ACTION_MEDIA_SCANNER_SCAN_FILE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_STARTED:
+    Field 'ACTION_MEDIA_SCANNER_STARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SHARED:
+    Field 'ACTION_MEDIA_SHARED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTABLE:
+    Field 'ACTION_MEDIA_UNMOUNTABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTED:
+    Field 'ACTION_MEDIA_UNMOUNTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_REPLACED:
+    Field 'ACTION_MY_PACKAGE_REPLACED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_SUSPENDED:
+    Field 'ACTION_MY_PACKAGE_SUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_UNSUSPENDED:
+    Field 'ACTION_MY_PACKAGE_UNSUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_NEW_OUTGOING_CALL:
+    Field 'ACTION_NEW_OUTGOING_CALL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_SUSPENDED:
+    Field 'ACTION_PACKAGES_SUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_UNSUSPENDED:
+    Field 'ACTION_PACKAGES_UNSUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_ADDED:
+    Field 'ACTION_PACKAGE_ADDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_CHANGED:
+    Field 'ACTION_PACKAGE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_DATA_CLEARED:
+    Field 'ACTION_PACKAGE_DATA_CLEARED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FIRST_LAUNCH:
+    Field 'ACTION_PACKAGE_FIRST_LAUNCH' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FULLY_REMOVED:
+    Field 'ACTION_PACKAGE_FULLY_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_INSTALL:
+    Field 'ACTION_PACKAGE_INSTALL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION:
+    Field 'ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_NEEDS_VERIFICATION:
+    Field 'ACTION_PACKAGE_NEEDS_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REMOVED:
+    Field 'ACTION_PACKAGE_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REPLACED:
+    Field 'ACTION_PACKAGE_REPLACED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_RESTARTED:
+    Field 'ACTION_PACKAGE_RESTARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_UNSTOPPED:
+    Field 'ACTION_PACKAGE_UNSTOPPED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY:
+    Field 'ACTION_PACKAGE_UNSUSPENDED_MANUALLY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_VERIFIED:
+    Field 'ACTION_PACKAGE_VERIFIED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_POWER_CONNECTED:
+    Field 'ACTION_POWER_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_POWER_DISCONNECTED:
+    Field 'ACTION_POWER_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PRE_BOOT_COMPLETED:
+    Field 'ACTION_PRE_BOOT_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PROVIDER_CHANGED:
+    Field 'ACTION_PROVIDER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_QUERY_PACKAGE_RESTART:
+    Field 'ACTION_QUERY_PACKAGE_RESTART' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_REBOOT:
+    Field 'ACTION_REBOOT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_RESOLVE_INSTANT_APP_PACKAGE:
+    Field 'ACTION_RESOLVE_INSTANT_APP_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_ROLLBACK_COMMITTED:
+    Field 'ACTION_ROLLBACK_COMMITTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_OFF:
+    Field 'ACTION_SCREEN_OFF' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_ON:
+    Field 'ACTION_SCREEN_ON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS:
+    Field 'ACTION_SHOW_SUSPENDED_APP_DETAILS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SHUTDOWN:
+    Field 'ACTION_SHUTDOWN' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SIM_STATE_CHANGED:
+    Field 'ACTION_SIM_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SPLIT_CONFIGURATION_CHANGED:
+    Field 'ACTION_SPLIT_CONFIGURATION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIMEZONE_CHANGED:
+    Field 'ACTION_TIMEZONE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIME_CHANGED:
+    Field 'ACTION_TIME_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIME_TICK:
+    Field 'ACTION_TIME_TICK' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UID_REMOVED:
+    Field 'ACTION_UID_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UMS_CONNECTED:
+    Field 'ACTION_UMS_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UMS_DISCONNECTED:
+    Field 'ACTION_UMS_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UNARCHIVE_PACKAGE:
+    Field 'ACTION_UNARCHIVE_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_USER_PRESENT:
+    Field 'ACTION_USER_PRESENT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_USER_UNLOCKED:
+    Field 'ACTION_USER_UNLOCKED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_WALLPAPER_CHANGED:
+    Field 'ACTION_WALLPAPER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_COMMITTED:
+    Field 'ACTION_SESSION_COMMITTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_UPDATED:
+    Field 'ACTION_SESSION_UPDATED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_PICTURE:
+    Field 'ACTION_NEW_PICTURE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_VIDEO:
+    Field 'ACTION_NEW_VIDEO' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.hdmi.HdmiControlManager#ACTION_OSD_MESSAGE:
+    Field 'ACTION_OSD_MESSAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.input.InputManager#ACTION_QUERY_KEYBOARD_LAYOUTS:
+    Field 'ACTION_QUERY_KEYBOARD_LAYOUTS' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_ACCESSORY_DETACHED:
+    Field 'ACTION_USB_ACCESSORY_DETACHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_ACCESSORY_HANDSHAKE:
+    Field 'ACTION_USB_ACCESSORY_HANDSHAKE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_DEVICE_DETACHED:
+    Field 'ACTION_USB_DEVICE_DETACHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_PORT_CHANGED:
+    Field 'ACTION_USB_PORT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_PORT_COMPLIANCE_CHANGED:
+    Field 'ACTION_USB_PORT_COMPLIANCE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_STATE:
+    Field 'ACTION_USB_STATE' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_HDMI_AUDIO_PLUG:
+    Field 'ACTION_HDMI_AUDIO_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_HEADSET_PLUG:
+    Field 'ACTION_HEADSET_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_MICROPHONE_MUTE_CHANGED:
+    Field 'ACTION_MICROPHONE_MUTE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_SPEAKERPHONE_STATE_CHANGED:
+    Field 'ACTION_SPEAKERPHONE_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_CHANNEL_BROWSABLE_REQUESTED:
+    Field 'ACTION_CHANNEL_BROWSABLE_REQUESTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_INITIALIZE_PROGRAMS:
+    Field 'ACTION_INITIALIZE_PROGRAMS' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT:
+    Field 'ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED:
+    Field 'ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED:
+    Field 'ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.NetworkScoreManager#ACTION_SCORER_CHANGED:
+    Field 'ACTION_SCORER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.NetworkScoreManager#ACTION_SCORE_NETWORKS:
+    Field 'ACTION_SCORE_NETWORKS' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.Proxy#PROXY_CHANGE_ACTION:
+    Field 'PROXY_CHANGE_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
+    Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
+    Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
+    Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.os.DropBoxManager#ACTION_DROPBOX_ENTRY_ADDED:
+    Field 'ACTION_DROPBOX_ENTRY_ADDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.CalendarContract#ACTION_EVENT_REMINDER:
+    Field 'ACTION_EVENT_REMINDER' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.ContactsContract.SimContacts#ACTION_SIM_ACCOUNTS_CHANGED:
+    Field 'ACTION_SIM_ACCOUNTS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#ACTION_SMS_EMERGENCY_CB_RECEIVED:
+    Field 'ACTION_SMS_EMERGENCY_CB_RECEIVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#DATA_SMS_RECEIVED_ACTION:
+    Field 'DATA_SMS_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SECRET_CODE_ACTION:
+    Field 'SECRET_CODE_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SIM_FULL_ACTION:
+    Field 'SIM_FULL_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION:
+    Field 'SMS_CB_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION:
+    Field 'SMS_DELIVER_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION:
+    Field 'SMS_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_REJECTED_ACTION:
+    Field 'SMS_REJECTED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION:
+    Field 'SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION:
+    Field 'WAP_PUSH_DELIVER_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_RECEIVED_ACTION:
+    Field 'WAP_PUSH_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_KEYCHAIN_CHANGED:
+    Field 'ACTION_KEYCHAIN_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_KEY_ACCESS_CHANGED:
+    Field 'ACTION_KEY_ACCESS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_STORAGE_CHANGED:
+    Field 'ACTION_STORAGE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_TRUST_STORE_CHANGED:
+    Field 'ACTION_TRUST_STORE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_DELETE_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_RENAME_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_START_EUICC_ACTIVATION:
+    Field 'ACTION_START_EUICC_ACTIVATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.speech.tts.TextToSpeech#ACTION_TTS_QUEUE_PROCESSING_COMPLETED:
+    Field 'ACTION_TTS_QUEUE_PROCESSING_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.speech.tts.TextToSpeech.Engine#ACTION_TTS_DATA_INSTALLED:
+    Field 'ACTION_TTS_DATA_INSTALLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_REFRESH_SUBSCRIPTION_PLANS:
+    Field 'ACTION_REFRESH_SUBSCRIPTION_PLANS' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_SUBSCRIPTION_PLANS_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_PLANS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE:
+    Field 'ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_PCO_VALUE:
+    Field 'ACTION_CARRIER_SIGNAL_PCO_VALUE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_REDIRECTED:
+    Field 'ACTION_CARRIER_SIGNAL_REDIRECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED:
+    Field 'ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_RESET:
+    Field 'ACTION_CARRIER_SIGNAL_RESET' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_EMERGENCY_CALLBACK_MODE_CHANGED:
+    Field 'ACTION_EMERGENCY_CALLBACK_MODE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_EMERGENCY_CALL_STATE_CHANGED:
+    Field 'ACTION_EMERGENCY_CALL_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE:
+    Field 'ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SECRET_CODE:
+    Field 'ACTION_SECRET_CODE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS:
+    Field 'ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED:
+    Field 'ACTION_SIM_APPLICATION_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED:
+    Field 'ACTION_SIM_CARD_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_SLOT_STATUS_CHANGED:
+    Field 'ACTION_SIM_SLOT_STATUS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.euicc.EuiccManager#ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE:
+    Field 'ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.euicc.EuiccManager#ACTION_OTA_STATUS_CHANGED:
+    Field 'ACTION_OTA_STATUS_CHANGED' is missing @BroadcastBehavior
+
+
+DeprecationMismatch: android.accounts.AccountManager#newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle):
+    Method android.accounts.AccountManager.newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Activity#enterPictureInPictureMode():
+    Method android.app.Activity.enterPictureInPictureMode(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Instrumentation#startAllocCounting():
+    Method android.app.Instrumentation.startAllocCounting(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Instrumentation#stopAllocCounting():
+    Method android.app.Instrumentation.stopAllocCounting(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#bigContentView:
+    Field Notification.bigContentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#contentView:
+    Field Notification.contentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#headsUpContentView:
+    Field Notification.headsUpContentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#tickerView:
+    Field Notification.tickerView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.Builder#Builder(int, CharSequence, android.app.PendingIntent):
+    Constructor android.app.Notification.Action.Builder.Builder(int, CharSequence, android.app.PendingIntent): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getCancelLabel():
+    Method android.app.Notification.Action.WearableExtender.getCancelLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getConfirmLabel():
+    Method android.app.Notification.Action.WearableExtender.getConfirmLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getInProgressLabel():
+    Method android.app.Notification.Action.WearableExtender.getInProgressLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setCancelLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setCancelLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setConfirmLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setConfirmLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setInProgressLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setInProgressLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Builder#setContent(android.widget.RemoteViews):
+    Method android.app.Notification.Builder.setContent(android.widget.RemoteViews): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Builder#setTicker(CharSequence, android.widget.RemoteViews):
+    Method android.app.Notification.Builder.setTicker(CharSequence, android.widget.RemoteViews): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIcon():
+    Method android.app.Notification.WearableExtender.getContentIcon(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIconGravity():
+    Method android.app.Notification.WearableExtender.getContentIconGravity(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomContentHeight():
+    Method android.app.Notification.WearableExtender.getCustomContentHeight(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomSizePreset():
+    Method android.app.Notification.WearableExtender.getCustomSizePreset(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getGravity():
+    Method android.app.Notification.WearableExtender.getGravity(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintAvoidBackgroundClipping():
+    Method android.app.Notification.WearableExtender.getHintAvoidBackgroundClipping(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintHideIcon():
+    Method android.app.Notification.WearableExtender.getHintHideIcon(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintScreenTimeout():
+    Method android.app.Notification.WearableExtender.getHintScreenTimeout(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintShowBackgroundOnly():
+    Method android.app.Notification.WearableExtender.getHintShowBackgroundOnly(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIcon(int):
+    Method android.app.Notification.WearableExtender.setContentIcon(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIconGravity(int):
+    Method android.app.Notification.WearableExtender.setContentIconGravity(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomContentHeight(int):
+    Method android.app.Notification.WearableExtender.setCustomContentHeight(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomSizePreset(int):
+    Method android.app.Notification.WearableExtender.setCustomSizePreset(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setGravity(int):
+    Method android.app.Notification.WearableExtender.setGravity(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintAvoidBackgroundClipping(boolean):
+    Method android.app.Notification.WearableExtender.setHintAvoidBackgroundClipping(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintHideIcon(boolean):
+    Method android.app.Notification.WearableExtender.setHintHideIcon(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintScreenTimeout(int):
+    Method android.app.Notification.WearableExtender.setHintScreenTimeout(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintShowBackgroundOnly(boolean):
+    Method android.app.Notification.WearableExtender.setHintShowBackgroundOnly(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.backup.BackupManager#selectBackupTransport(String):
+    Method android.app.backup.BackupManager.selectBackupTransport(String): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.content.Context#BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND:
+    Field Context.BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.content.Context#WIFI_RTT_SERVICE:
+    Field Context.WIFI_RTT_SERVICE: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.ComposeShader#ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode):
+    Constructor android.graphics.ComposeShader.ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#A_8:
+    Field PixelFormat.A_8: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#LA_88:
+    Field PixelFormat.LA_88: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#L_8:
+    Field PixelFormat.L_8: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_4444:
+    Field PixelFormat.RGBA_4444: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_5551:
+    Field PixelFormat.RGBA_5551: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGB_332:
+    Field PixelFormat.RGB_332: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.hardware.hdmi.HdmiControlManager#RESULT_ALREADY_IN_PROGRESS:
+    Field HdmiControlManager.RESULT_ALREADY_IN_PROGRESS: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder#setCodeRate(int):
+    Method android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder.setCodeRate(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder#setModulation(int):
+    Method android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder.setModulation(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.EGL14#eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int):
+    Method android.opengl.EGL14.eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.GLES20#GL_STENCIL_INDEX:
+    Field GLES20.GL_STENCIL_INDEX: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.GLSurfaceView#surfaceRedrawNeeded(android.view.SurfaceHolder):
+    Method android.opengl.GLSurfaceView.surfaceRedrawNeeded(android.view.SurfaceHolder): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle):
+    Method android.os.UserManager.setUserRestrictions(android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle, android.os.UserHandle):
+    Method android.os.UserManager.setUserRestrictions(android.os.Bundle, android.os.UserHandle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.provider.Contacts.People#markAsContacted(android.content.ContentResolver, long):
+    Method android.provider.Contacts.People.markAsContacted(android.content.ContentResolver, long): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_X:
+    Field Type.CubemapFace.POSITVE_X: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Y:
+    Field Type.CubemapFace.POSITVE_Y: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Z:
+    Field Type.CubemapFace.POSITVE_Z: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.speech.tts.TextToSpeech#areDefaultsEnforced():
+    Method android.speech.tts.TextToSpeech.areDefaultsEnforced(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#StatusHints(android.content.ComponentName, CharSequence, int, android.os.Bundle):
+    Constructor android.telecom.StatusHints.StatusHints(android.content.ComponentName, CharSequence, int, android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getIcon(android.content.Context):
+    Method android.telecom.StatusHints.getIcon(android.content.Context): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getIconResId():
+    Method android.telecom.StatusHints.getIconResId(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getPackageName():
+    Method android.telecom.StatusHints.getPackageName(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.PhoneStateListener#PhoneStateListener(java.util.concurrent.Executor):
+    Constructor android.telephony.PhoneStateListener.PhoneStateListener(java.util.concurrent.Executor): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionManager#PROFILE_CLASS_DEFAULT:
+    Field SubscriptionManager.PROFILE_CLASS_DEFAULT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringDaily(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringDaily(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringMonthly(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringMonthly(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringWeekly(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringWeekly(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_12HOUR:
+    Field DateUtils.FORMAT_12HOUR: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_24HOUR:
+    Field DateUtils.FORMAT_24HOUR: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_AMPM:
+    Field DateUtils.FORMAT_CAP_AMPM: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_MIDNIGHT:
+    Field DateUtils.FORMAT_CAP_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON:
+    Field DateUtils.FORMAT_CAP_NOON: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON_MIDNIGHT:
+    Field DateUtils.FORMAT_CAP_NOON_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_NO_NOON_MIDNIGHT:
+    Field DateUtils.FORMAT_NO_NOON_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.ViewGroup.LayoutParams#FILL_PARENT:
+    Field ViewGroup.LayoutParams.FILL_PARENT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.Window#setTitleColor(int):
+    Method android.view.Window.setTitleColor(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.accessibility.AccessibilityEvent#MAX_TEXT_LENGTH:
+    Field AccessibilityEvent.MAX_TEXT_LENGTH: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebSettings#getSaveFormData():
+    Method android.webkit.WebSettings.getSaveFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebView#shouldDelayChildPressedState():
+    Method android.webkit.WebView.shouldDelayChildPressedState(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebViewDatabase#clearFormData():
+    Method android.webkit.WebViewDatabase.clearFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebViewDatabase#hasFormData():
+    Method android.webkit.WebViewDatabase.hasFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: javax.microedition.khronos.egl.EGL10#eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]):
+    Method javax.microedition.khronos.egl.EGL10.eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+
+
 GenericException: android.app.prediction.AppPredictor#finalize():
     Methods must not throw generic exceptions (`java.lang.Throwable`)
 GenericException: android.hardware.location.ContextHubClient#finalize():
@@ -19,12 +525,16 @@
     Listeners should always be at end of argument list (method `stopSatelliteTransmissionUpdates`)
 ListenerLast: android.telephony.satellite.SatelliteManager#stopSatelliteTransmissionUpdates(android.telephony.satellite.SatelliteTransmissionUpdateCallback, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>) parameter #2:
     Listeners should always be at end of argument list (method `stopSatelliteTransmissionUpdates`)
+
+
 MissingGetterMatchingBuilder: android.service.voice.HotwordTrainingData.Builder#addTrainingAudio(android.service.voice.HotwordTrainingAudio):
     android.service.voice.HotwordTrainingData does not declare a `getTrainingAudios()` method matching method android.service.voice.HotwordTrainingData.Builder.addTrainingAudio(android.service.voice.HotwordTrainingAudio)
 MissingGetterMatchingBuilder: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallViaAudioProcessing(boolean):
     android.telecom.CallScreeningService.CallResponse does not declare a `shouldScreenCallViaAudioProcessing()` method matching method android.telecom.CallScreeningService.CallResponse.Builder.setShouldScreenCallViaAudioProcessing(boolean)
 MissingGetterMatchingBuilder: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
     android.telephony.mbms.DownloadRequest does not declare a `getServiceId()` method matching method android.telephony.mbms.DownloadRequest.Builder.setServiceId(String)
+
+
 MissingNullability: android.media.soundtrigger.SoundTriggerDetectionService#onUnbind(android.content.Intent) parameter #0:
     Missing nullability on parameter `intent` in method `onUnbind`
 MissingNullability: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context) parameter #0:
@@ -57,6 +567,1196 @@
     Protected methods not allowed; must be public: method android.service.notification.NotificationAssistantService.attachBaseContext(android.content.Context)}
 
 
+RequiresPermission: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
+    Method 'getAccountsByTypeAndFeatures' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+    Method 'hasFeatures' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
+    Method 'addOnUidImportanceListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getHistoricalProcessExitReasons(String, int, int):
+    Method 'getHistoricalProcessExitReasons' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getProcessesInErrorState():
+    Method 'getProcessesInErrorState' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#killProcessesWhenImperceptible(int[], String):
+    Method 'killProcessesWhenImperceptible' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.ActivityManager#setDeviceLocales(android.os.LocaleList):
+    Method 'setDeviceLocales' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent):
+    Method 'setAlarmClock' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setExact(int, long, android.app.PendingIntent):
+    Method 'setExact' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setExactAndAllowWhileIdle(int, long, android.app.PendingIntent):
+    Method 'setExactAndAllowWhileIdle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setTime(long):
+    Method 'setTime' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#isOpActive(String, int, String):
+    Method 'isOpActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#startWatchingActive(String[], java.util.concurrent.Executor, android.app.AppOpsManager.OnOpActiveChangedListener):
+    Method 'startWatchingActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#startWatchingNoted(String[], java.util.concurrent.Executor, android.app.AppOpsManager.OnOpNotedListener):
+    Method 'startWatchingNoted' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setDestinationInExternalPublicDir(String, String):
+    Method 'setDestinationInExternalPublicDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setDestinationUri(android.net.Uri):
+    Method 'setDestinationUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setNotificationVisibility(int):
+    Method 'setNotificationVisibility' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setShowRunningNotification(boolean):
+    Method 'setShowRunningNotification' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.GameManager#setGameMode(String, int):
+    Method 'setGameMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.GameManager#updateCustomGameModeConfiguration(String, android.app.GameModeConfiguration):
+    Method 'updateCustomGameModeConfiguration' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.LocaleManager#getApplicationLocales(String):
+    Method 'getApplicationLocales' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.Notification.Builder#setFullScreenIntent(android.app.PendingIntent, boolean):
+    Method 'setFullScreenIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.NotificationManager#canUseFullScreenIntent():
+    Method 'canUseFullScreenIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.Service#startForeground(int, android.app.Notification):
+    Method 'startForeground' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.StatusBarManager#canLaunchCaptureContentActivityForNote(android.app.Activity):
+    Method 'canLaunchCaptureContentActivityForNote' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.UiModeManager#releaseProjection(int):
+    Method 'releaseProjection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.UiModeManager#requestProjection(int):
+    Method 'requestProjection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperInfo#getSettingsSliceUri():
+    Method 'getSettingsSliceUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#clear():
+    Method 'clear' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#clearWallpaper(int, int):
+    Method 'clearWallpaper' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getDrawable():
+    Method 'getDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getDrawable(int):
+    Method 'getDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getFastDrawable():
+    Method 'getFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getFastDrawable(int):
+    Method 'getFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getWallpaperFile(int):
+    Method 'getWallpaperFile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getWallpaperInfo(int):
+    Method 'getWallpaperInfo' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekDrawable():
+    Method 'peekDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekDrawable(int):
+    Method 'peekDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekFastDrawable():
+    Method 'peekFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekFastDrawable(int):
+    Method 'peekFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap):
+    Method 'setBitmap' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean):
+    Method 'setBitmap' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setDisplayPadding(android.graphics.Rect):
+    Method 'setDisplayPadding' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setResource(int):
+    Method 'setResource' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream):
+    Method 'setStream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream, android.graphics.Rect, boolean):
+    Method 'setStream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setWallpaperComponentWithFlags(android.content.ComponentName, int):
+    Method 'setWallpaperComponentWithFlags' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#suggestDesiredDimensions(int, int):
+    Method 'suggestDesiredDimensions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#addCrossProfileWidgetProvider(android.content.ComponentName, String):
+    Method 'addCrossProfileWidgetProvider' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName):
+    Method 'addPersistentPreferredActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    Method 'bindDeviceAdminServiceAsUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#clearPackagePersistentPreferredActivities(android.content.ComponentName, String):
+    Method 'clearPackagePersistentPreferredActivities' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#clearResetPasswordToken(android.content.ComponentName):
+    Method 'clearResetPasswordToken' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#createAndProvisionManagedProfile(android.app.admin.ManagedProfileProvisioningParams):
+    Method 'createAndProvisionManagedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#finalizeWorkProfileProvisioning(android.os.UserHandle, android.accounts.Account):
+    Method 'finalizeWorkProfileProvisioning' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#generateKeyPair(android.content.ComponentName, String, android.security.keystore.KeyGenParameterSpec, int):
+    Method 'generateKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getApplicationExemptions(String):
+    Method 'getApplicationExemptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getCrossProfileWidgetProviders(android.content.ComponentName):
+    Method 'getCrossProfileWidgetProviders' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getLockTaskFeatures(android.content.ComponentName):
+    Method 'getLockTaskFeatures' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getLockTaskPackages(android.content.ComponentName):
+    Method 'getLockTaskPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getNearbyAppStreamingPolicy():
+    Method 'getNearbyAppStreamingPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getNearbyNotificationStreamingPolicy():
+    Method 'getNearbyNotificationStreamingPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getOrganizationName(android.content.ComponentName):
+    Method 'getOrganizationName' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getPasswordComplexity():
+    Method 'getPasswordComplexity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getShortSupportMessage(android.content.ComponentName):
+    Method 'getShortSupportMessage' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getUserControlDisabledPackages(android.content.ComponentName):
+    Method 'getUserControlDisabledPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#hasKeyPair(String):
+    Method 'hasKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, String):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], String, boolean):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], String, int):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isDeviceProvisioningConfigApplied():
+    Method 'isDeviceProvisioningConfigApplied' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isPackageSuspended(android.content.ComponentName, String):
+    Method 'isPackageSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isResetPasswordTokenActive(android.content.ComponentName):
+    Method 'isResetPasswordTokenActive' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#lockNow(int):
+    Method 'lockNow' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#provisionFullyManagedDevice(android.app.admin.FullyManagedDeviceProvisioningParams):
+    Method 'provisionFullyManagedDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#removeCrossProfileWidgetProvider(android.content.ComponentName, String):
+    Method 'removeCrossProfileWidgetProvider' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#sendLostModeLocationUpdate(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
+    Method 'sendLostModeLocationUpdate' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setActiveProfileOwner(android.content.ComponentName, String):
+    Method 'setActiveProfileOwner' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setAlwaysOnVpnPackage(android.content.ComponentName, String, boolean):
+    Method 'setAlwaysOnVpnPackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setApplicationExemptions(String, java.util.Set<java.lang.Integer>):
+    Method 'setApplicationExemptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setDeviceProvisioningConfigApplied():
+    Method 'setDeviceProvisioningConfigApplied' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setLockTaskFeatures(android.content.ComponentName, int):
+    Method 'setLockTaskFeatures' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setLockTaskPackages(android.content.ComponentName, String[]):
+    Method 'setLockTaskPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>):
+    Method 'setPermittedInputMethods' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setUninstallBlocked(android.content.ComponentName, String, boolean):
+    Method 'setUninstallBlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setUserControlDisabledPackages(android.content.ComponentName, java.util.List<java.lang.String>):
+    Method 'setUserControlDisabledPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeData(int):
+    Method 'wipeData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeData(int, CharSequence):
+    Method 'wipeData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeDevice(int):
+    Method 'wipeDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.PolicyUpdateReceiver#onPolicyChanged(android.content.Context, String, android.os.Bundle, android.app.admin.TargetUser, android.app.admin.PolicyUpdateResult):
+    Method 'onPolicyChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.PolicyUpdateReceiver#onPolicySetResult(android.content.Context, String, android.os.Bundle, android.app.admin.TargetUser, android.app.admin.PolicyUpdateResult):
+    Method 'onPolicySetResult' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#dataChanged(String):
+    Method 'dataChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#requestBackup(String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int):
+    Method 'requestBackup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#setFrameworkSchedulingEnabled(boolean):
+    Method 'setFrameworkSchedulingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#updateTransportAttributes(android.content.ComponentName, String, android.content.Intent, String, android.content.Intent, CharSequence):
+    Method 'updateTransportAttributes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#updateTransportAttributes(android.content.ComponentName, String, android.content.Intent, String, android.content.Intent, String):
+    Method 'updateTransportAttributes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restoreAll(long, android.app.backup.RestoreObserver):
+    Method 'restoreAll' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restoreAll(long, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor):
+    Method 'restoreAll' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackage(String, android.app.backup.RestoreObserver):
+    Method 'restorePackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackage(String, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor):
+    Method 'restorePackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackages(long, android.app.backup.RestoreObserver, java.util.Set<java.lang.String>):
+    Method 'restorePackages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackages(long, android.app.backup.RestoreObserver, java.util.Set<java.lang.String>, android.app.backup.BackupManagerMonitor):
+    Method 'restorePackages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setRequiredNetwork(android.net.NetworkRequest):
+    Method 'setRequiredNetwork' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setRequiredNetworkType(int):
+    Method 'setRequiredNetworkType' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setUserInitiated(boolean):
+    Method 'setUserInitiated' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.job.JobParameters#isUserInitiatedJob():
+    Method 'isUserInitiatedJob' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobScheduler#canRunUserInitiatedJobs():
+    Method 'canRunUserInitiatedJobs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.people.PeopleManager#isConversation(String, String):
+    Method 'isConversation' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryExternalStatsForUser(java.util.UUID, android.os.UserHandle):
+    Method 'queryExternalStatsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForPackage(java.util.UUID, String, android.os.UserHandle):
+    Method 'queryStatsForPackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUid(java.util.UUID, int):
+    Method 'queryStatsForUid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUser(java.util.UUID, android.os.UserHandle):
+    Method 'queryStatsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageEvents.Event#getTaskRootClassName():
+    Method 'getTaskRootClassName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageEvents.Event#getTaskRootPackageName():
+    Method 'getTaskRootPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#getAppStandbyBucket(String):
+    Method 'getAppStandbyBucket' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#getAppStandbyBuckets():
+    Method 'getAppStandbyBuckets' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#isAppInactive(String):
+    Method 'isAppInactive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#onCarrierPrivilegedAppsChanged():
+    Method 'onCarrierPrivilegedAppsChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryAndAggregateUsageStats(long, long):
+    Method 'queryAndAggregateUsageStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryConfigurations(int, long, long):
+    Method 'queryConfigurations' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryEventStats(int, long, long):
+    Method 'queryEventStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryEvents(long, long):
+    Method 'queryEvents' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryUsageStats(int, long, long):
+    Method 'queryUsageStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerAppUsageLimitObserver(int, String[], java.time.Duration, java.time.Duration, android.app.PendingIntent):
+    Method 'registerAppUsageLimitObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerAppUsageObserver(int, String[], long, java.util.concurrent.TimeUnit, android.app.PendingIntent):
+    Method 'registerAppUsageObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerUsageSessionObserver(int, String[], java.time.Duration, java.time.Duration, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'registerUsageSessionObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#reportUsageStart(android.app.Activity, String):
+    Method 'reportUsageStart' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#reportUsageStart(android.app.Activity, String, long):
+    Method 'reportUsageStart' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterAppUsageLimitObserver(int):
+    Method 'unregisterAppUsageLimitObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterAppUsageObserver(int):
+    Method 'unregisterAppUsageObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterUsageSessionObserver(int):
+    Method 'unregisterUsageSessionObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int, android.os.UserHandle, android.content.ComponentName, android.os.Bundle):
+    Method 'bindAppWidgetIdIfAllowed' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#isDeviceAssociatedForWifiConnection(String, android.net.MacAddress, android.os.UserHandle):
+    Method 'isDeviceAssociatedForWifiConnection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#startObservingDevicePresence(String):
+    Method 'startObservingDevicePresence' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#stopObservingDevicePresence(String):
+    Method 'stopObservingDevicePresence' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.virtual.VirtualDeviceManager#createVirtualDevice(int, android.companion.virtual.VirtualDeviceParams):
+    Method 'createVirtualDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.virtual.VirtualDeviceParams.Builder#setLockState(int):
+    Method 'setLockState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.ContentResolver#addPeriodicSync(android.accounts.Account, String, android.os.Bundle, long):
+    Method 'addPeriodicSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#cancelSync(android.content.SyncRequest):
+    Method 'cancelSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getCurrentSync():
+    Method 'getCurrentSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getCurrentSyncs():
+    Method 'getCurrentSyncs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getIsSyncable(android.accounts.Account, String):
+    Method 'getIsSyncable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getMasterSyncAutomatically():
+    Method 'getMasterSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getPeriodicSyncs(android.accounts.Account, String):
+    Method 'getPeriodicSyncs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getSyncAutomatically(android.accounts.Account, String):
+    Method 'getSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#isSyncActive(android.accounts.Account, String):
+    Method 'isSyncActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#isSyncPending(android.accounts.Account, String):
+    Method 'isSyncPending' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#removePeriodicSync(android.accounts.Account, String, android.os.Bundle):
+    Method 'removePeriodicSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setIsSyncable(android.accounts.Account, String, int):
+    Method 'setIsSyncable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setMasterSyncAutomatically(boolean):
+    Method 'setMasterSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setSyncAutomatically(android.accounts.Account, String, boolean):
+    Method 'setSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    Method 'bindServiceAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.Context#clearWallpaper():
+    Method 'clearWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalCacheDir():
+    Method 'getExternalCacheDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalCacheDirs():
+    Method 'getExternalCacheDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalFilesDir(String):
+    Method 'getExternalFilesDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalFilesDirs(String):
+    Method 'getExternalFilesDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalMediaDirs():
+    Method 'getExternalMediaDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getObbDir():
+    Method 'getObbDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getObbDirs():
+    Method 'getObbDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle):
+    Method 'removeStickyBroadcastAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.Context#setWallpaper(android.graphics.Bitmap):
+    Method 'setWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#setWallpaper(java.io.InputStream):
+    Method 'setWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#canRequestInteractAcrossProfiles():
+    Method 'canRequestInteractAcrossProfiles' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.ComponentName, android.os.UserHandle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.ComponentName, android.os.UserHandle, android.app.Activity, android.os.Bundle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.Intent, android.os.UserHandle, android.app.Activity):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.Intent, android.os.UserHandle, android.app.Activity, android.os.Bundle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps#getAllPackageInstallerSessions():
+    Method 'getAllPackageInstallerSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps#registerPackageInstallerSessionCallback(java.util.concurrent.Executor, android.content.pm.PackageInstaller.SessionCallback):
+    Method 'registerPackageInstallerSessionCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps.Callback#onPackagesSuspended(String[], android.os.UserHandle, android.os.Bundle):
+    Method 'onPackagesSuspended' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getAllSessions():
+    Method 'getAllSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getSessionInfo(int):
+    Method 'getSessionInfo' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getStagedSessions():
+    Method 'getStagedSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback):
+    Method 'registerSessionCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.Session#requestUserPreapproval(android.content.pm.PackageInstaller.PreapprovalDetails, android.content.IntentSender):
+    Method 'requestUserPreapproval' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setInstallerPackageName(String):
+    Method 'setInstallerPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setPermissionState(String, int):
+    Method 'setPermissionState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setRequestUpdateOwnership(boolean):
+    Method 'setRequestUpdateOwnership' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(int):
+    Method 'setRequireUserAction' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#canRequestPackageInstalls():
+    Method 'canRequestPackageInstalls' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#getSuspendedPackageAppExtras():
+    Method 'getSuspendedPackageAppExtras' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#getUnsuspendablePackages(String[]):
+    Method 'getUnsuspendablePackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#grantRuntimePermission(String, String, android.os.UserHandle):
+    Method 'grantRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#isAutoRevokeWhitelisted(String):
+    Method 'isAutoRevokeWhitelisted' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#isPackageSuspended():
+    Method 'isPackageSuspended' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle):
+    Method 'revokeRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle, String):
+    Method 'revokeRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setDistractingPackageRestrictions(String[], int):
+    Method 'setDistractingPackageRestrictions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, String):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, android.content.pm.SuspendDialogInfo):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, android.content.pm.SuspendDialogInfo, int):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#verifyIntentFilter(int, int, java.util.List<java.lang.String>):
+    Method 'verifyIntentFilter' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.Sensor#getHighestDirectReportRateLevel():
+    Method 'getHighestDirectReportRateLevel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.Sensor#getMinDelay():
+    Method 'getMinDelay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraCharacteristics#getKeysNeedingPermission():
+    Method 'getKeysNeedingPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraManager.AvailabilityCallback#onCameraClosed(String):
+    Method 'onCameraClosed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraManager.AvailabilityCallback#onCameraOpened(String, String):
+    Method 'onCameraOpened' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.hdmi.HdmiControlManager#getHdmiCecVersion():
+    Method 'getHdmiCecVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.hdmi.HdmiControlManager#setHdmiCecVersion(int):
+    Method 'setHdmiCecVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback):
+    Method 'addGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#getMonitoringTypes():
+    Method 'getMonitoringTypes' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#pauseGeofence(int, int):
+    Method 'pauseGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback):
+    Method 'registerForMonitorStateChangeCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#removeGeofence(int, int):
+    Method 'removeGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#resumeGeofence(int, int, int):
+    Method 'resumeGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback):
+    Method 'unregisterForMonitorStateChangeCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#grantPermission(android.hardware.usb.UsbDevice, String):
+    Method 'grantPermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#hasPermission(android.hardware.usb.UsbDevice):
+    Method 'hasPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#requestPermission(android.hardware.usb.UsbDevice, android.app.PendingIntent):
+    Method 'requestPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.AudioAttributes.Builder#setHapticChannelsMuted(boolean):
+    Method 'setHapticChannelsMuted' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.AudioManager#getCallDownlinkExtractionAudioRecord(android.media.AudioFormat):
+    Method 'getCallDownlinkExtractionAudioRecord' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioManager#getCallUplinkInjectionAudioTrack(android.media.AudioFormat):
+    Method 'getCallUplinkInjectionAudioTrack' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioManager#registerAudioPolicy(android.media.audiopolicy.AudioPolicy):
+    Method 'registerAudioPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioRecord#shareAudioHistory(String, long):
+    Method 'shareAudioHistory' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioRecordingConfiguration#getClientUid():
+    Method 'getClientUid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.MediaCodec#createByCodecNameForClient(String, int, int):
+    Method 'createByCodecNameForClient' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(String):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(String, java.util.Map<java.lang.String,java.lang.String>):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String,java.lang.String>):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaPlayer#setWakeMode(android.content.Context, int):
+    Method 'setWakeMode' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaRouter2#getInstance(android.content.Context, String):
+    Method 'getInstance' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.RingtoneManager#getCursor():
+    Method 'getCursor' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.RingtoneManager#getValidRingtoneUri(android.content.Context):
+    Method 'getValidRingtoneUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.audiofx.HapticGenerator#setEnabled(boolean):
+    Method 'setEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.projection.MediaProjection#createVirtualDisplay(String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback, android.os.Handler):
+    Method 'createVirtualDisplay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.projection.MediaProjectionManager#getMediaProjection(int, android.content.Intent):
+    Method 'getMediaProjection' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnMediaKeyEventSessionChangedListener(java.util.concurrent.Executor, android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener):
+    Method 'addOnMediaKeyEventSessionChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getActiveSessions(android.content.ComponentName):
+    Method 'getActiveSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getMediaKeyEventSession():
+    Method 'getMediaKeyEventSession' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getMediaKeyEventSessionPackageName():
+    Method 'getMediaKeyEventSessionPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#isTrustedForMediaControl(android.media.session.MediaSessionManager.RemoteUserInfo):
+    Method 'isTrustedForMediaControl' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#deleteKeyphraseSoundModel(int, java.util.Locale):
+    Method 'deleteKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#getKeyphraseSoundModel(int, java.util.Locale):
+    Method 'getKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#updateKeyphraseSoundModel(android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel):
+    Method 'updateKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#clearScores():
+    Method 'clearScores' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#disableScoring():
+    Method 'disableScoring' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#getActiveScorerPackage():
+    Method 'getActiveScorerPackage' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#registerNetworkScoreCallback(int, int, java.util.concurrent.Executor, android.net.NetworkScoreManager.NetworkScoreCallback):
+    Method 'registerNetworkScoreCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#requestScores(java.util.Collection<android.net.NetworkKey>):
+    Method 'requestScores' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#setActiveScorer(String):
+    Method 'setActiveScorer' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.VpnService#prepareAndAuthorize(android.content.Context):
+    Method 'prepareAndAuthorize' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.sip.SipAudioCall#setSpeakerMode(boolean):
+    Method 'setSpeakerMode' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.net.sip.SipAudioCall#startAudio():
+    Method 'startAudio' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#addVcnNetworkPolicyChangeListener(java.util.concurrent.Executor, android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener):
+    Method 'addVcnNetworkPolicyChangeListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#applyVcnNetworkPolicy(android.net.NetworkCapabilities, android.net.LinkProperties):
+    Method 'applyVcnNetworkPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#removeVcnNetworkPolicyChangeListener(android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener):
+    Method 'removeVcnNetworkPolicyChangeListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
+    Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
+    Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
+    Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
+    Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
+    Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
+    Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
+    Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
+    Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
+    Method 'increment' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
+    Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
+    Method 'restore' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
+    Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
+    Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
+    Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
+    Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
+    Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#isWritable():
+    Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
+    Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
+    Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
+    Method 'format' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
+    Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#close():
+    Method 'close' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#connect():
+    Method 'connect' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.BugreportManager#cancelBugreport():
+    Method 'cancelBugreport' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.BugreportManager#preDumpUiData():
+    Method 'preDumpUiData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Build#getSerial():
+    Method 'getSerial' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Debug#dumpService(String, java.io.FileDescriptor, String[]):
+    Method 'dumpService' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.DropBoxManager#getNextEntry(String, long):
+    Method 'getNextEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Environment#getExternalStorageDirectory():
+    Method 'getExternalStorageDirectory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Environment#isExternalStorageManager():
+    Method 'isExternalStorageManager' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Environment#isExternalStorageManager(java.io.File):
+    Method 'isExternalStorageManager' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#dream(long):
+    Method 'dream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#forceSuspend():
+    Method 'forceSuspend' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#getPowerSaveModeTrigger():
+    Method 'getPowerSaveModeTrigger' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#newWakeLock(int, String):
+    Method 'newWakeLock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#reboot(String):
+    Method 'reboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#setBatteryDischargePrediction(java.time.Duration, boolean):
+    Method 'setBatteryDischargePrediction' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#setDynamicPowerSaveHint(boolean, int):
+    Method 'setDynamicPowerSaveHint' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#userActivity(long, int, int):
+    Method 'userActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.RecoverySystem#rebootWipeUserData(android.content.Context):
+    Method 'rebootWipeUserData' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.StrictMode.VmPolicy.Builder#detectFileUriExposure():
+    Method 'detectFileUriExposure' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.SystemUpdateManager#retrieveSystemUpdateInfo():
+    Method 'retrieveSystemUpdateInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.SystemUpdateManager#updateSystemUpdateInfo(android.os.PersistableBundle):
+    Method 'updateSystemUpdateInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#getUserProperties(android.os.UserHandle):
+    Method 'getUserProperties' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#getUserRestrictions(android.os.UserHandle):
+    Method 'getUserRestrictions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#hasUserRestrictionForUser(String, android.os.UserHandle):
+    Method 'hasUserRestrictionForUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isManagedProfile(int):
+    Method 'isManagedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isRestrictedProfile():
+    Method 'isRestrictedProfile' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.UserManager#isRestrictedProfile(android.os.UserHandle):
+    Method 'isRestrictedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isUserUnlocked(android.os.UserHandle):
+    Method 'isUserUnlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isUserUnlockingOrUnlocked(android.os.UserHandle):
+    Method 'isUserUnlockingOrUnlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#requestQuietModeEnabled(boolean, android.os.UserHandle):
+    Method 'requestQuietModeEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#setUserRestriction(String, boolean):
+    Method 'setUserRestriction' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshot(int):
+    Method 'takeUidSnapshot' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshots(int[]):
+    Method 'takeUidSnapshots' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#getManageSpaceActivityIntent(String, int):
+    Method 'getManageSpaceActivityIntent' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.storage.StorageVolume#createAccessIntent(String):
+    Method 'createAccessIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForDataDelivery(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForDataDelivery' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForDataDeliveryFromDataSource(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForDataDeliveryFromDataSource' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForStartDataDelivery(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForStartDataDelivery' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.provider.Settings#canDrawOverlays(android.content.Context):
+    Method 'canDrawOverlays' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.provider.Settings.System#canWrite(android.content.Context):
+    Method 'canWrite' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.security.KeyChain#removeCredentialManagementApp(android.content.Context):
+    Method 'removeCredentialManagementApp' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.BeginCreateCredentialResponse.Builder#setRemoteCreateEntry(android.service.credentials.RemoteEntry):
+    Method 'setRemoteCreateEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.BeginGetCredentialResponse.Builder#setRemoteCredentialEntry(android.service.credentials.RemoteEntry):
+    Method 'setRemoteCredentialEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.CallingAppInfo#getOrigin():
+    Method 'getOrigin' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.Call.Details#getContactDisplayName():
+    Method 'getContactDisplayName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.Call.Details#getContactPhotoUri():
+    Method 'getContactPhotoUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle):
+    Method 'acceptHandover' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    Method 'addNewIncomingCall' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingConference(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    Method 'addNewIncomingConference' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getCallState():
+    Method 'getCallState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getLine1Number(android.telecom.PhoneAccountHandle):
+    Method 'getLine1Number' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getOwnSelfManagedPhoneAccounts():
+    Method 'getOwnSelfManagedPhoneAccounts' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getPhoneAccount(android.telecom.PhoneAccountHandle):
+    Method 'getPhoneAccount' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getSelfManagedPhoneAccounts():
+    Method 'getSelfManagedPhoneAccounts' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#hasManageOngoingCallsPermission():
+    Method 'hasManageOngoingCallsPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#placeCall(android.net.Uri, android.os.Bundle):
+    Method 'placeCall' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#showInCallScreen(boolean):
+    Method 'showInCallScreen' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#silenceRinger():
+    Method 'silenceRinger' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig():
+    Method 'getConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig(java.lang.String...):
+    Method 'getConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigByComponentForSubId(String, int):
+    Method 'getConfigByComponentForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int):
+    Method 'getConfigForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int, java.lang.String...):
+    Method 'getConfigForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#notifyConfigChangedForSubId(int):
+    Method 'notifyConfigChangedForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CellLocation#requestLocationUpdate():
+    Method 'requestLocationUpdate' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.NetworkRegistrationInfo#getCellIdentity():
+    Method 'getCellIdentity' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onActiveDataSubscriptionIdChanged(int):
+    Method 'onActiveDataSubscriptionIdChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onCallAttributesChanged(android.telephony.CallAttributes):
+    Method 'onCallAttributesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onCallStateChanged(int, String):
+    Method 'onCallStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onDisplayInfoChanged(android.telephony.TelephonyDisplayInfo):
+    Method 'onDisplayInfoChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState):
+    Method 'onPreciseDataConnectionStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onRadioPowerStateChanged(int):
+    Method 'onRadioPowerStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onServiceStateChanged(android.telephony.ServiceState):
+    Method 'onServiceStateChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getCdmaNetworkId():
+    Method 'getCdmaNetworkId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getCdmaSystemId():
+    Method 'getCdmaSystemId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorAlphaLong():
+    Method 'getOperatorAlphaLong' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorAlphaShort():
+    Method 'getOperatorAlphaShort' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorNumeric():
+    Method 'getOperatorNumeric' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SignalStrengthUpdateRequest.Builder#setSystemThresholdReportingRequestedWhileIdle(boolean):
+    Method 'setSystemThresholdReportingRequestedWhileIdle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#disableCellBroadcastRange(int, int, int):
+    Method 'disableCellBroadcastRange' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#enableCellBroadcastRange(int, int, int):
+    Method 'enableCellBroadcastRange' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#getSmscAddress():
+    Method 'getSmscAddress' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#injectSmsPdu(byte[], String, android.app.PendingIntent):
+    Method 'injectSmsPdu' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendDataMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>):
+    Method 'sendMultipartTextMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>):
+    Method 'sendMultipartTextMessageWithoutPersisting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendTextMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendTextMessageWithoutPersisting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#setSmscAddress(String):
+    Method 'setSmscAddress' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#addSubscriptionsIntoGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    Method 'addSubscriptionsIntoGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#createSubscriptionGroup(java.util.List<java.lang.Integer>):
+    Method 'createSubscriptionGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfo(int):
+    Method 'getActiveSubscriptionInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoForSimSlotIndex(int):
+    Method 'getActiveSubscriptionInfoForSimSlotIndex' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoList():
+    Method 'getActiveSubscriptionInfoList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList():
+    Method 'getAvailableSubscriptionInfoList' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getCompleteActiveSubscriptionInfoList():
+    Method 'getCompleteActiveSubscriptionInfoList' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getOpportunisticSubscriptions():
+    Method 'getOpportunisticSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getResourcesForSubId(android.content.Context, int):
+    Method 'getResourcesForSubId' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getSubscriptionsInGroup(android.os.ParcelUuid):
+    Method 'getSubscriptionsInGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#removeSubscriptionsFromGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    Method 'removeSubscriptionsFromGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh():
+    Method 'requestEmbeddedSubscriptionInfoListRefresh' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh(int):
+    Method 'requestEmbeddedSubscriptionInfoListRefresh' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#setOpportunistic(boolean, int):
+    Method 'setOpportunistic' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#setPreferredDataSubscriptionId(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setPreferredDataSubscriptionId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener#onActiveDataSubscriptionIdChanged(int):
+    Method 'onActiveDataSubscriptionIdChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.BarringInfoListener#onBarringInfoChanged(android.telephony.BarringInfo):
+    Method 'onBarringInfoChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallAttributesListener#onCallAttributesChanged(android.telephony.CallAttributes):
+    Method 'onCallAttributesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallAttributesListener#onCallStatesChanged(java.util.List<android.telephony.CallState>):
+    Method 'onCallStatesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallForwardingIndicatorListener#onCallForwardingIndicatorChanged(boolean):
+    Method 'onCallForwardingIndicatorChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.DataEnabledListener#onDataEnabledChanged(boolean, int):
+    Method 'onDataEnabledChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.EmergencyNumberListListener#onEmergencyNumberListChanged(java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>):
+    Method 'onEmergencyNumberListChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ImsCallDisconnectCauseListener#onImsCallDisconnectCauseChanged(android.telephony.ims.ImsReasonInfo):
+    Method 'onImsCallDisconnectCauseChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.MessageWaitingIndicatorListener#onMessageWaitingIndicatorChanged(boolean):
+    Method 'onMessageWaitingIndicatorChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PhysicalChannelConfigListener#onPhysicalChannelConfigChanged(java.util.List<android.telephony.PhysicalChannelConfig>):
+    Method 'onPhysicalChannelConfigChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PreciseCallStateListener#onPreciseCallStateChanged(android.telephony.PreciseCallState):
+    Method 'onPreciseCallStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PreciseDataConnectionStateListener#onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState):
+    Method 'onPreciseDataConnectionStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.RegistrationFailedListener#onRegistrationFailed(android.telephony.CellIdentity, String, int, int, int):
+    Method 'onRegistrationFailed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ServiceStateListener#onServiceStateChanged(android.telephony.ServiceState):
+    Method 'onServiceStateChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#bootstrapAuthenticationRequest(int, android.net.Uri, android.telephony.gba.UaSecurityProtocolIdentifier, boolean, java.util.concurrent.Executor, android.telephony.TelephonyManager.BootstrapAuthenticationCallback):
+    Method 'bootstrapAuthenticationRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#changeIccLockPin(String, String):
+    Method 'changeIccLockPin' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#clearRadioPowerOffForReason(int):
+    Method 'clearRadioPowerOffForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#clearSignalStrengthUpdateRequest(android.telephony.SignalStrengthUpdateRequest):
+    Method 'clearSignalStrengthUpdateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#doesSwitchMultiSimConfigTriggerReboot():
+    Method 'doesSwitchMultiSimConfigTriggerReboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#enableModemForSlot(int, boolean):
+    Method 'enableModemForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAidForAppType(int):
+    Method 'getAidForAppType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypes():
+    Method 'getAllowedNetworkTypes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypesBitmask():
+    Method 'getAllowedNetworkTypesBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypesForReason(int):
+    Method 'getAllowedNetworkTypesForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCallState():
+    Method 'getCallState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCallStateForSubscription():
+    Method 'getCallStateForSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierConfig():
+    Method 'getCarrierConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierInfoForImsiEncryption(int):
+    Method 'getCarrierInfoForImsiEncryption' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierRestrictionStatus(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getCarrierRestrictionStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCdmaRoamingMode():
+    Method 'getCdmaRoamingMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCdmaSubscriptionMode():
+    Method 'getCdmaSubscriptionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDataActivationState():
+    Method 'getDataActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDataNetworkType():
+    Method 'getDataNetworkType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId():
+    Method 'getDeviceId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId(int):
+    Method 'getDeviceId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceSoftwareVersion(int):
+    Method 'getDeviceSoftwareVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberDbVersion():
+    Method 'getEmergencyNumberDbVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList():
+    Method 'getEmergencyNumberList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList(int):
+    Method 'getEmergencyNumberList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEquivalentHomePlmns():
+    Method 'getEquivalentHomePlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getForbiddenPlmns():
+    Method 'getForbiddenPlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getGroupIdLevel1():
+    Method 'getGroupIdLevel1' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getImei(int):
+    Method 'getImei' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getIsimDomain():
+    Method 'getIsimDomain' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getLine1Number():
+    Method 'getLine1Number' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getManualNetworkSelectionPlmn():
+    Method 'getManualNetworkSelectionPlmn' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getMeid():
+    Method 'getMeid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getMeid(int):
+    Method 'getMeid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNai():
+    Method 'getNai' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNetworkSelectionMode():
+    Method 'getNetworkSelectionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNetworkSlicingConfiguration(java.util.concurrent.Executor, android.os.OutcomeReceiver<android.telephony.data.NetworkSlicingConfig,android.telephony.TelephonyManager.NetworkSlicingException>):
+    Method 'getNetworkSlicingConfiguration' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPhoneAccountHandle():
+    Method 'getPhoneAccountHandle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPreferredNetworkTypeBitmask():
+    Method 'getPreferredNetworkTypeBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPreferredOpportunisticDataSubscription():
+    Method 'getPreferredOpportunisticDataSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getRadioPowerOffReasons():
+    Method 'getRadioPowerOffReasons' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getRadioPowerState():
+    Method 'getRadioPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getServiceState():
+    Method 'getServiceState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getServiceState(int):
+    Method 'getServiceState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSimLocale():
+    Method 'getSimLocale' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSimSerialNumber():
+    Method 'getSimSerialNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSubscriberId():
+    Method 'getSubscriberId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSupportedRadioAccessFamily():
+    Method 'getSupportedRadioAccessFamily' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSystemSelectionChannels():
+    Method 'getSystemSelectionChannels' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getTelephonyHistograms():
+    Method 'getTelephonyHistograms' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVisualVoicemailPackageName():
+    Method 'getVisualVoicemailPackageName' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceActivationState():
+    Method 'getVoiceActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailAlphaTag():
+    Method 'getVoiceMailAlphaTag' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailNumber():
+    Method 'getVoiceMailNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceNetworkType():
+    Method 'getVoiceNetworkType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccCloseLogicalChannel(int):
+    Method 'iccCloseLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccCloseLogicalChannelBySlot(int, int):
+    Method 'iccCloseLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccExchangeSimIO(int, int, int, int, int, String):
+    Method 'iccExchangeSimIO' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String):
+    Method 'iccOpenLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String, int):
+    Method 'iccOpenLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannelBySlot(int, String, int):
+    Method 'iccOpenLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduBasicChannel(int, int, int, int, int, String):
+    Method 'iccTransmitApduBasicChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, String):
+    Method 'iccTransmitApduBasicChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduLogicalChannel(int, int, int, int, int, int, String):
+    Method 'iccTransmitApduLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, String):
+    Method 'iccTransmitApduLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isApplicationOnUicc(int):
+    Method 'isApplicationOnUicc' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabled():
+    Method 'isDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabledForReason(int):
+    Method 'isDataEnabledForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataRoamingEnabled():
+    Method 'isDataRoamingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isEmergencyAssistanceEnabled():
+    Method 'isEmergencyAssistanceEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isIccLockEnabled():
+    Method 'isIccLockEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isManualNetworkSelectionAllowed():
+    Method 'isManualNetworkSelectionAllowed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isModemEnabledForSlot(int):
+    Method 'isModemEnabledForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isMultiSimSupported():
+    Method 'isMultiSimSupported' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isOpportunisticNetworkEnabled():
+    Method 'isOpportunisticNetworkEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isPotentialEmergencyNumber(String):
+    Method 'isPotentialEmergencyNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isPremiumCapabilityAvailableForPurchase(int):
+    Method 'isPremiumCapabilityAvailableForPurchase' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isTetheringApnRequired():
+    Method 'isTetheringApnRequired' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#notifyOtaEmergencyNumberDbInstalled():
+    Method 'notifyOtaEmergencyNumberDbInstalled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#prepareForUnattendedReboot():
+    Method 'prepareForUnattendedReboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#purchasePremiumCapability(int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'purchasePremiumCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#rebootModem():
+    Method 'rebootModem' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#rebootRadio():
+    Method 'rebootRadio' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#reportDefaultNetworkStatus(boolean):
+    Method 'reportDefaultNetworkStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    Method 'requestNetworkScan' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(int, android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    Method 'requestNetworkScan' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNumberVerification(android.telephony.PhoneNumberRange, long, java.util.concurrent.Executor, android.telephony.NumberVerificationCallback):
+    Method 'requestNumberVerification' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestRadioPowerOffForReason(int):
+    Method 'requestRadioPowerOffForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetAllCarrierActions():
+    Method 'resetAllCarrierActions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetCarrierKeysForImsiEncryption():
+    Method 'resetCarrierKeysForImsiEncryption' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetOtaEmergencyNumberDbFilePath():
+    Method 'resetOtaEmergencyNumberDbFilePath' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetRadioConfig():
+    Method 'resetRadioConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendEnvelopeWithStatus(String):
+    Method 'sendEnvelopeWithStatus' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendThermalMitigationRequest(android.telephony.ThermalMitigationRequest):
+    Method 'sendThermalMitigationRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler):
+    Method 'sendUssdRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendVisualVoicemailSms(String, int, String, android.app.PendingIntent):
+    Method 'sendVisualVoicemailSms' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>):
+    Method 'setAllowedCarriers' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setAllowedNetworkTypesForReason(int, long):
+    Method 'setAllowedNetworkTypesForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCarrierDataEnabled(boolean):
+    Method 'setCarrierDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCarrierRestrictionRules(android.telephony.CarrierRestrictionRules):
+    Method 'setCarrierRestrictionRules' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCdmaRoamingMode(int):
+    Method 'setCdmaRoamingMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCdmaSubscriptionMode(int):
+    Method 'setCdmaSubscriptionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataActivationState(int):
+    Method 'setDataActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabled(boolean):
+    Method 'setDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabledForReason(int, boolean):
+    Method 'setDataEnabledForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataRoamingEnabled(boolean):
+    Method 'setDataRoamingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setForbiddenPlmns(java.util.List<java.lang.String>):
+    Method 'setForbiddenPlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setIccLockEnabled(boolean, String):
+    Method 'setIccLockEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeAutomatic():
+    Method 'setNetworkSelectionModeAutomatic' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean):
+    Method 'setNetworkSelectionModeManual' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean, int):
+    Method 'setNetworkSelectionModeManual' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setOpportunisticNetworkState(boolean):
+    Method 'setOpportunisticNetworkState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setPreferredNetworkTypeBitmask(long):
+    Method 'setPreferredNetworkTypeBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setPreferredOpportunisticDataSubscription(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setPreferredOpportunisticDataSubscription' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setRadioEnabled(boolean):
+    Method 'setRadioEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSignalStrengthUpdateRequest(android.telephony.SignalStrengthUpdateRequest):
+    Method 'setSignalStrengthUpdateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerState(int):
+    Method 'setSimPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerState(int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setSimPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerStateForSlot(int, int):
+    Method 'setSimPowerStateForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerStateForSlot(int, int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setSimPowerStateForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoiceActivationState(int):
+    Method 'setVoiceActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri):
+    Method 'setVoicemailRingtoneUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean):
+    Method 'setVoicemailVibrationEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#supplyIccLockPin(String):
+    Method 'supplyIccLockPin' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#supplyIccLockPuk(String, String):
+    Method 'supplyIccLockPuk' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#switchMultiSimConfig(int):
+    Method 'switchMultiSimConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'updateAvailableNetworks' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#updateOtaEmergencyNumberDbFilePath(android.os.ParcelFileDescriptor):
+    Method 'updateOtaEmergencyNumberDbFilePath' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.VisualVoicemailService#sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent):
+    Method 'sendVisualVoicemailSms' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.VisualVoicemailService#setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings):
+    Method 'setSmsFilterSettings' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#continueOperation(android.content.Intent, android.os.Bundle):
+    Method 'continueOperation' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#deleteSubscription(int, android.app.PendingIntent):
+    Method 'deleteSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent):
+    Method 'downloadSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#eraseSubscriptions(android.app.PendingIntent):
+    Method 'eraseSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#eraseSubscriptions(int, android.app.PendingIntent):
+    Method 'eraseSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getDefaultDownloadableSubscriptionList(android.app.PendingIntent):
+    Method 'getDefaultDownloadableSubscriptionList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent):
+    Method 'getDownloadableSubscriptionMetadata' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getOtaStatus():
+    Method 'getOtaStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getSupportedCountries():
+    Method 'getSupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getUnsupportedCountries():
+    Method 'getUnsupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#setSupportedCountries(java.util.List<java.lang.String>):
+    Method 'setSupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#setUnsupportedCountries(java.util.List<java.lang.String>):
+    Method 'setUnsupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, android.app.PendingIntent):
+    Method 'switchToSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, int, android.app.PendingIntent):
+    Method 'switchToSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#updateSubscriptionNickname(int, String, android.app.PendingIntent):
+    Method 'updateSubscriptionNickname' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#createForSubscriptionId(int):
+    Method 'createForSubscriptionId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#getRegistrationTransportType(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationTransportType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#getVoWiFiModeSetting():
+    Method 'getVoWiFiModeSetting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isAdvancedCallingSettingEnabled():
+    Method 'isAdvancedCallingSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isCrossSimCallingEnabled():
+    Method 'isCrossSimCallingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isTtyOverVolteEnabled():
+    Method 'isTtyOverVolteEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVoWiFiRoamingSettingEnabled():
+    Method 'isVoWiFiRoamingSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVoWiFiSettingEnabled():
+    Method 'isVoWiFiSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVtSettingEnabled():
+    Method 'isVtSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerImsRegistrationCallback(java.util.concurrent.Executor, android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'registerImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerImsStateCallback(java.util.concurrent.Executor, android.telephony.ims.ImsStateCallback):
+    Method 'registerImsStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerMmTelCapabilityCallback(java.util.concurrent.Executor, android.telephony.ims.ImsMmTelManager.CapabilityCallback):
+    Method 'registerMmTelCapabilityCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#unregisterImsRegistrationCallback(android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'unregisterImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#unregisterMmTelCapabilityCallback(android.telephony.ims.ImsMmTelManager.CapabilityCallback):
+    Method 'unregisterMmTelCapabilityCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#getRegistrationState(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#getRegistrationTransportType(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationTransportType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#registerImsRegistrationCallback(java.util.concurrent.Executor, android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'registerImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#registerImsStateCallback(java.util.concurrent.Executor, android.telephony.ims.ImsStateCallback):
+    Method 'registerImsStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#unregisterImsRegistrationCallback(android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'unregisterImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#getProvisioningStatusForCapability(int, int):
+    Method 'getProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#getRcsProvisioningStatusForCapability(int, int):
+    Method 'getRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isProvisioningRequiredForCapability(int, int):
+    Method 'isProvisioningRequiredForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isRcsProvisioningRequiredForCapability(int, int):
+    Method 'isRcsProvisioningRequiredForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable():
+    Method 'isRcsVolteSingleRegistrationCapable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#notifyRcsAutoConfigurationReceived(byte[], boolean):
+    Method 'notifyRcsAutoConfigurationReceived' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerFeatureProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback):
+    Method 'registerFeatureProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.Callback):
+    Method 'registerProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.RcsProvisioningCallback):
+    Method 'registerRcsProvisioningCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setProvisioningStatusForCapability(int, int, boolean):
+    Method 'setProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setRcsProvisioningStatusForCapability(int, boolean):
+    Method 'setRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setRcsProvisioningStatusForCapability(int, int, boolean):
+    Method 'setRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#unregisterProvisioningChangedCallback(android.telephony.ims.ProvisioningManager.Callback):
+    Method 'unregisterProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback(android.telephony.ims.ProvisioningManager.RcsProvisioningCallback):
+    Method 'unregisterRcsProvisioningCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.SipDelegateManager#registerSipDialogStateCallback(java.util.concurrent.Executor, android.telephony.ims.SipDialogStateCallback):
+    Method 'registerSipDialogStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.SipDelegateManager#unregisterSipDialogStateCallback(android.telephony.ims.SipDialogStateCallback):
+    Method 'unregisterSipDialogStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.WindowManager.LayoutParams#isSystemApplicationOverlay():
+    Method 'isSystemApplicationOverlay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.view.accessibility.AccessibilityManager#registerDisplayProxy(android.view.accessibility.AccessibilityDisplayProxy):
+    Method 'registerDisplayProxy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.AccessibilityManager#unregisterDisplayProxy(android.view.accessibility.AccessibilityDisplayProxy):
+    Method 'unregisterDisplayProxy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.CaptioningManager#setSystemAudioCaptioningEnabled(boolean):
+    Method 'setSystemAudioCaptioningEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.CaptioningManager#setSystemAudioCaptioningUiEnabled(boolean):
+    Method 'setSystemAudioCaptioningUiEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.inputmethod.InputMethodManager#setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype):
+    Method 'setCurrentInputMethodSubtype' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.webkit.WebSettings#setBlockNetworkLoads(boolean):
+    Method 'setBlockNetworkLoads' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.webkit.WebSettings#setGeolocationEnabled(boolean):
+    Method 'setGeolocationEnabled' documentation mentions permissions without declaring @RequiresPermission
+
+
 SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
     SAM-compatible parameters (such as parameter 6, "callback", in android.accounts.AccountManager.addAccount) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean):
@@ -201,6 +1901,80 @@
     SAM-compatible parameters (such as parameter 2, "filePathCallback", in android.webkit.WebChromeClient.onShowFileChooser) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 
 
+SdkConstant: android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED:
+    Field 'ACTION_BATTERY_LEVEL_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_DEVICE_CUSTOMIZATION_READY:
+    Field 'ACTION_DEVICE_CUSTOMIZATION_READY' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_GLOBAL_BUTTON:
+    Field 'ACTION_GLOBAL_BUTTON' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_PRE_BOOT_COMPLETED:
+    Field 'ACTION_PRE_BOOT_COMPLETED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_UNARCHIVE_PACKAGE:
+    Field 'ACTION_UNARCHIVE_PACKAGE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.pm.PackageInstaller#ACTION_CONFIRM_PRE_APPROVAL:
+    Field 'ACTION_CONFIRM_PRE_APPROVAL' is missing @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_PORT_CHANGED:
+    Field 'ACTION_USB_PORT_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_PORT_COMPLIANCE_CHANGED:
+    Field 'ACTION_USB_PORT_COMPLIANCE_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_STATE:
+    Field 'ACTION_USB_STATE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_DELETE_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_RENAME_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE:
+    Field 'ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS:
+    Field 'ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+
+
+Todo: android.Manifest.permission#DOMAIN_VERIFICATION_AGENT:
+    Documentation mentions 'TODO'
+Todo: android.Manifest.permission#INSTALL_EXISTING_PACKAGES:
+    Documentation mentions 'TODO'
+Todo: android.Manifest.permission#READ_PEOPLE_DATA:
+    Documentation mentions 'TODO'
+Todo: android.app.NotificationManager#isNotificationAssistantAccessGranted(android.content.ComponentName):
+    Documentation mentions 'TODO'
+Todo: android.hardware.camera2.params.StreamConfigurationMap:
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#getNanoAppInstanceInfo(int):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#loadNanoApp(int, android.hardware.location.NanoApp):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#unloadNanoApp(int):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.NanoAppInstanceInfo:
+    Documentation mentions 'TODO'
+Todo: android.media.tv.TvContentRatingSystemInfo#getXmlUri():
+    Documentation mentions 'TODO'
+Todo: android.media.tv.TvInputInfo#isConnectedToHdmiSwitch():
+    Documentation mentions 'TODO'
+Todo: android.os.RecoverySystem#prepareForUnattendedUpdate(android.content.Context, String, android.content.IntentSender):
+    Documentation mentions 'TODO'
+Todo: android.os.RecoverySystem#rebootAndApply(android.content.Context, String, String):
+    Documentation mentions 'TODO'
+Todo: android.os.SystemConfigManager:
+    Documentation mentions 'TODO'
+Todo: android.os.UpdateEngineCallback#onStatusUpdate(int, float):
+    Documentation mentions 'TODO'
+Todo: android.provider.ContactsContract.RawContacts#newEntityIterator(android.database.Cursor):
+    Documentation mentions 'TODO'
+Todo: android.service.voice.AlwaysOnHotwordDetector:
+    Documentation mentions 'TODO'
+Todo: android.telephony.TelephonyManager#getCurrentPhoneType():
+    Documentation mentions 'TODO'
+
+
 UnflaggedApi: android.Manifest.permission#ACCESS_SMARTSPACE:
     New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_SMARTSPACE
 UnflaggedApi: android.Manifest.permission#ALWAYS_UPDATE_WALLPAPER:
@@ -325,10 +2099,10 @@
     New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.TIMEOUT_STAGE_VERY_EARLY
 UnflaggedApi: android.service.voice.HotwordTrainingData#describeContents():
     New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.describeContents()
-UnflaggedApi: android.service.voice.HotwordTrainingData#getMaxTrainingDataSize():
-    New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.getMaxTrainingDataSize()
 UnflaggedApi: android.service.voice.HotwordTrainingData#getMaxTrainingDataBytes():
     New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.getMaxTrainingDataBytes()
+UnflaggedApi: android.service.voice.HotwordTrainingData#getMaxTrainingDataSize():
+    New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.getMaxTrainingDataSize()
 UnflaggedApi: android.service.voice.HotwordTrainingData#getTimeoutStage():
     New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.getTimeoutStage()
 UnflaggedApi: android.service.voice.HotwordTrainingData#getTrainingAudioList():
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index aa17df3..402a718 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -15,7 +15,7 @@
     method public static Class<? extends android.app.Notification.Style> getNotificationStyleClass(String);
   }
 
-  public static final class Notification.TvExtender implements android.app.Notification.Extender {
+  @FlaggedApi("android.app.api_tvextender") public static final class Notification.TvExtender implements android.app.Notification.Extender {
     method @Deprecated public String getChannel();
   }
 
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index a3ebe6e..6643663 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -575,7 +575,6 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, int);
     method public void setDeviceOwnerType(@NonNull android.content.ComponentName, int);
     method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public void setNextOperationSafety(int, int);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void setOverrideKeepProfilesRunning(boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}, conditional=true) public void setProfileOwnerOnOrganizationOwnedDevice(@NonNull android.content.ComponentName, boolean);
     method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean triggerDevicePolicyEngineMigration(boolean);
     field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
@@ -1802,8 +1801,8 @@
 
   public class AudioManager {
     method @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int abandonAudioFocusForTest(@NonNull android.media.AudioFocusRequest, @NonNull String);
-    method @FlaggedApi("com.android.media.audio.flags.focus_freeze_test_api") @RequiresPermission("Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED") public boolean enterAudioFocusFreezeForTest(@NonNull java.util.List<java.lang.Integer>);
-    method @FlaggedApi("com.android.media.audio.flags.focus_freeze_test_api") @RequiresPermission("Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED") public boolean exitAudioFocusFreezeForTest();
+    method @FlaggedApi("android.media.audio.focus_freeze_test_api") @RequiresPermission("Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED") public boolean enterAudioFocusFreezeForTest(@NonNull java.util.List<java.lang.Integer>);
+    method @FlaggedApi("android.media.audio.focus_freeze_test_api") @RequiresPermission("Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED") public boolean exitAudioFocusFreezeForTest();
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void forceComputeCsdOnAllDevices(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public void forceUseFrameworkMel(boolean);
     method @NonNull @RequiresPermission(android.Manifest.permission.CALL_AUDIO_INTERCEPTION) public android.media.AudioRecord getCallDownlinkExtractionAudioRecord(@NonNull android.media.AudioFormat);
@@ -1811,9 +1810,9 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED) public float getCsd();
     method @Nullable public static android.media.AudioDeviceInfo getDeviceInfoFromType(int);
     method @IntRange(from=0) @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public long getFadeOutDurationOnFocusLossMillis(@NonNull android.media.AudioAttributes);
-    method @FlaggedApi("com.android.media.audio.flags.focus_freeze_test_api") @NonNull @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public java.util.List<java.lang.Integer> getFocusDuckedUidsForTest();
-    method @FlaggedApi("com.android.media.audio.flags.focus_freeze_test_api") @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public long getFocusFadeOutDurationForTest();
-    method @FlaggedApi("com.android.media.audio.flags.focus_freeze_test_api") @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public long getFocusUnmuteDelayAfterFadeOutForTest();
+    method @FlaggedApi("android.media.audio.focus_freeze_test_api") @NonNull @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public java.util.List<java.lang.Integer> getFocusDuckedUidsForTest();
+    method @FlaggedApi("android.media.audio.focus_freeze_test_api") @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public long getFocusFadeOutDurationForTest();
+    method @FlaggedApi("android.media.audio.focus_freeze_test_api") @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public long getFocusUnmuteDelayAfterFadeOutForTest();
     method @Nullable public static android.media.AudioHalVersionInfo getHalVersion();
     method public static final int[] getPublicStreamTypes();
     method @NonNull public java.util.List<java.lang.Integer> getReportedSurroundFormats();
@@ -1935,7 +1934,7 @@
     field public static final int VIBRATION_SOURCE_URI = 2; // 0x2
   }
 
-  public static final class RingtoneSelection.Builder {
+  @FlaggedApi("android.os.vibrator.haptics_customization_enabled") public static final class RingtoneSelection.Builder {
     ctor public RingtoneSelection.Builder();
     ctor public RingtoneSelection.Builder(@NonNull android.media.RingtoneSelection);
     method @NonNull public android.media.RingtoneSelection build();
@@ -3573,8 +3572,8 @@
     method public default void holdLock(android.os.IBinder, int);
     method public default boolean isGlobalKey(int);
     method public default boolean isTaskSnapshotSupported();
-    method @FlaggedApi("REPLACE_CONTENT_WITH_MIRROR") @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public default boolean replaceContentOnDisplayWithMirror(int, @NonNull android.view.Window);
-    method @FlaggedApi("REPLACE_CONTENT_WITH_MIRROR") @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public default boolean replaceContentOnDisplayWithSc(int, @NonNull android.view.SurfaceControl);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public default boolean replaceContentOnDisplayWithMirror(int, @NonNull android.view.Window);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_SURFACE_FLINGER) public default boolean replaceContentOnDisplayWithSc(int, @NonNull android.view.SurfaceControl);
     method public default void setDisplayImePolicy(int, int);
     method public default void setShouldShowSystemDecors(int, boolean);
     method public default void setShouldShowWithInsecureKeyguard(int, boolean);
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 105e764..559db51 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -1,4 +1,512 @@
 // Baseline format: 1.0
+BroadcastBehavior: android.app.AlarmManager#ACTION_NEXT_ALARM_CLOCK_CHANGED:
+    Field 'ACTION_NEXT_ALARM_CLOCK_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.AlarmManager#ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED:
+    Field 'ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.NotificationManager#ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL:
+    Field 'ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED:
+    Field 'ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.app.admin.DevicePolicyManager#ACTION_MANAGED_PROFILE_PROVISIONED:
+    Field 'ACTION_MANAGED_PROFILE_PROVISIONED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_AIRPLANE_MODE_CHANGED:
+    Field 'ACTION_AIRPLANE_MODE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_LOCALE_CHANGED:
+    Field 'ACTION_APPLICATION_LOCALE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_APPLICATION_RESTRICTIONS_CHANGED:
+    Field 'ACTION_APPLICATION_RESTRICTIONS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_CHANGED:
+    Field 'ACTION_BATTERY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED:
+    Field 'ACTION_BATTERY_LEVEL_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_LOW:
+    Field 'ACTION_BATTERY_LOW' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_BATTERY_OKAY:
+    Field 'ACTION_BATTERY_OKAY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CAMERA_BUTTON:
+    Field 'ACTION_CAMERA_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CLOSE_SYSTEM_DIALOGS:
+    Field 'ACTION_CLOSE_SYSTEM_DIALOGS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_CONFIGURATION_CHANGED:
+    Field 'ACTION_CONFIGURATION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DATE_CHANGED:
+    Field 'ACTION_DATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_CUSTOMIZATION_READY:
+    Field 'ACTION_DEVICE_CUSTOMIZATION_READY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_LOW:
+    Field 'ACTION_DEVICE_STORAGE_LOW' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DEVICE_STORAGE_OK:
+    Field 'ACTION_DEVICE_STORAGE_OK' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DOCK_EVENT:
+    Field 'ACTION_DOCK_EVENT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DOMAINS_NEED_VERIFICATION:
+    Field 'ACTION_DOMAINS_NEED_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STARTED:
+    Field 'ACTION_DREAMING_STARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_DREAMING_STOPPED:
+    Field 'ACTION_DREAMING_STOPPED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
+    Field 'ACTION_EXTERNAL_APPLICATIONS_AVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+    Field 'ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GLOBAL_BUTTON:
+    Field 'ACTION_GLOBAL_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_CONNECTED:
+    Field 'ACTION_GTALK_SERVICE_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_GTALK_SERVICE_DISCONNECTED:
+    Field 'ACTION_GTALK_SERVICE_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_HEADSET_PLUG:
+    Field 'ACTION_HEADSET_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INPUT_METHOD_CHANGED:
+    Field 'ACTION_INPUT_METHOD_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INSTALL_INSTANT_APP_PACKAGE:
+    Field 'ACTION_INSTALL_INSTANT_APP_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INSTANT_APP_RESOLVER_SETTINGS:
+    Field 'ACTION_INSTANT_APP_RESOLVER_SETTINGS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_INTENT_FILTER_NEEDS_VERIFICATION:
+    Field 'ACTION_INTENT_FILTER_NEEDS_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOAD_DATA:
+    Field 'ACTION_LOAD_DATA' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOCALE_CHANGED:
+    Field 'ACTION_LOCALE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED:
+    Field 'ACTION_LOCKED_BOOT_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MANAGE_PACKAGE_STORAGE:
+    Field 'ACTION_MANAGE_PACKAGE_STORAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BAD_REMOVAL:
+    Field 'ACTION_MEDIA_BAD_REMOVAL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_BUTTON:
+    Field 'ACTION_MEDIA_BUTTON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_CHECKING:
+    Field 'ACTION_MEDIA_CHECKING' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_EJECT:
+    Field 'ACTION_MEDIA_EJECT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_MOUNTED:
+    Field 'ACTION_MEDIA_MOUNTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_NOFS:
+    Field 'ACTION_MEDIA_NOFS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_REMOVED:
+    Field 'ACTION_MEDIA_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_FINISHED:
+    Field 'ACTION_MEDIA_SCANNER_FINISHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_SCAN_FILE:
+    Field 'ACTION_MEDIA_SCANNER_SCAN_FILE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SCANNER_STARTED:
+    Field 'ACTION_MEDIA_SCANNER_STARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_SHARED:
+    Field 'ACTION_MEDIA_SHARED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTABLE:
+    Field 'ACTION_MEDIA_UNMOUNTABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MEDIA_UNMOUNTED:
+    Field 'ACTION_MEDIA_UNMOUNTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_REPLACED:
+    Field 'ACTION_MY_PACKAGE_REPLACED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_SUSPENDED:
+    Field 'ACTION_MY_PACKAGE_SUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_MY_PACKAGE_UNSUSPENDED:
+    Field 'ACTION_MY_PACKAGE_UNSUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_NEW_OUTGOING_CALL:
+    Field 'ACTION_NEW_OUTGOING_CALL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_SUSPENDED:
+    Field 'ACTION_PACKAGES_SUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGES_UNSUSPENDED:
+    Field 'ACTION_PACKAGES_UNSUSPENDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_ADDED:
+    Field 'ACTION_PACKAGE_ADDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_CHANGED:
+    Field 'ACTION_PACKAGE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_DATA_CLEARED:
+    Field 'ACTION_PACKAGE_DATA_CLEARED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FIRST_LAUNCH:
+    Field 'ACTION_PACKAGE_FIRST_LAUNCH' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_FULLY_REMOVED:
+    Field 'ACTION_PACKAGE_FULLY_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_INSTALL:
+    Field 'ACTION_PACKAGE_INSTALL' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION:
+    Field 'ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_NEEDS_VERIFICATION:
+    Field 'ACTION_PACKAGE_NEEDS_VERIFICATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REMOVED:
+    Field 'ACTION_PACKAGE_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_REPLACED:
+    Field 'ACTION_PACKAGE_REPLACED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_RESTARTED:
+    Field 'ACTION_PACKAGE_RESTARTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_UNSTOPPED:
+    Field 'ACTION_PACKAGE_UNSTOPPED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_UNSUSPENDED_MANUALLY:
+    Field 'ACTION_PACKAGE_UNSUSPENDED_MANUALLY' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PACKAGE_VERIFIED:
+    Field 'ACTION_PACKAGE_VERIFIED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_POWER_CONNECTED:
+    Field 'ACTION_POWER_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_POWER_DISCONNECTED:
+    Field 'ACTION_POWER_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PRE_BOOT_COMPLETED:
+    Field 'ACTION_PRE_BOOT_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_PROVIDER_CHANGED:
+    Field 'ACTION_PROVIDER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_QUERY_PACKAGE_RESTART:
+    Field 'ACTION_QUERY_PACKAGE_RESTART' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_REBOOT:
+    Field 'ACTION_REBOOT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_RESOLVE_INSTANT_APP_PACKAGE:
+    Field 'ACTION_RESOLVE_INSTANT_APP_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_ROLLBACK_COMMITTED:
+    Field 'ACTION_ROLLBACK_COMMITTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_OFF:
+    Field 'ACTION_SCREEN_OFF' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SCREEN_ON:
+    Field 'ACTION_SCREEN_ON' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SHOW_SUSPENDED_APP_DETAILS:
+    Field 'ACTION_SHOW_SUSPENDED_APP_DETAILS' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SHUTDOWN:
+    Field 'ACTION_SHUTDOWN' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SIM_STATE_CHANGED:
+    Field 'ACTION_SIM_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_SPLIT_CONFIGURATION_CHANGED:
+    Field 'ACTION_SPLIT_CONFIGURATION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIMEZONE_CHANGED:
+    Field 'ACTION_TIMEZONE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIME_CHANGED:
+    Field 'ACTION_TIME_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_TIME_TICK:
+    Field 'ACTION_TIME_TICK' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UID_REMOVED:
+    Field 'ACTION_UID_REMOVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UMS_CONNECTED:
+    Field 'ACTION_UMS_CONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UMS_DISCONNECTED:
+    Field 'ACTION_UMS_DISCONNECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_UNARCHIVE_PACKAGE:
+    Field 'ACTION_UNARCHIVE_PACKAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_USER_PRESENT:
+    Field 'ACTION_USER_PRESENT' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_USER_UNLOCKED:
+    Field 'ACTION_USER_UNLOCKED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.Intent#ACTION_WALLPAPER_CHANGED:
+    Field 'ACTION_WALLPAPER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_COMMITTED:
+    Field 'ACTION_SESSION_COMMITTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.content.pm.PackageInstaller#ACTION_SESSION_UPDATED:
+    Field 'ACTION_SESSION_UPDATED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_PICTURE:
+    Field 'ACTION_NEW_PICTURE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.Camera#ACTION_NEW_VIDEO:
+    Field 'ACTION_NEW_VIDEO' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.hdmi.HdmiControlManager#ACTION_OSD_MESSAGE:
+    Field 'ACTION_OSD_MESSAGE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.input.InputManager#ACTION_QUERY_KEYBOARD_LAYOUTS:
+    Field 'ACTION_QUERY_KEYBOARD_LAYOUTS' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_ACCESSORY_DETACHED:
+    Field 'ACTION_USB_ACCESSORY_DETACHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_ACCESSORY_HANDSHAKE:
+    Field 'ACTION_USB_ACCESSORY_HANDSHAKE' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_DEVICE_DETACHED:
+    Field 'ACTION_USB_DEVICE_DETACHED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_PORT_CHANGED:
+    Field 'ACTION_USB_PORT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_PORT_COMPLIANCE_CHANGED:
+    Field 'ACTION_USB_PORT_COMPLIANCE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.hardware.usb.UsbManager#ACTION_USB_STATE:
+    Field 'ACTION_USB_STATE' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_HDMI_AUDIO_PLUG:
+    Field 'ACTION_HDMI_AUDIO_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_HEADSET_PLUG:
+    Field 'ACTION_HEADSET_PLUG' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_MICROPHONE_MUTE_CHANGED:
+    Field 'ACTION_MICROPHONE_MUTE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.AudioManager#ACTION_SPEAKERPHONE_STATE_CHANGED:
+    Field 'ACTION_SPEAKERPHONE_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_CHANNEL_BROWSABLE_REQUESTED:
+    Field 'ACTION_CHANNEL_BROWSABLE_REQUESTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_INITIALIZE_PROGRAMS:
+    Field 'ACTION_INITIALIZE_PROGRAMS' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT:
+    Field 'ACTION_PREVIEW_PROGRAM_ADDED_TO_WATCH_NEXT' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED:
+    Field 'ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.media.tv.TvContract#ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED:
+    Field 'ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.NetworkScoreManager#ACTION_SCORER_CHANGED:
+    Field 'ACTION_SCORER_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.NetworkScoreManager#ACTION_SCORE_NETWORKS:
+    Field 'ACTION_SCORE_NETWORKS' is missing @BroadcastBehavior
+BroadcastBehavior: android.net.Proxy#PROXY_CHANGE_ACTION:
+    Field 'PROXY_CHANGE_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_ADAPTER_STATE_CHANGED:
+    Field 'ACTION_ADAPTER_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_PREFERRED_PAYMENT_CHANGED:
+    Field 'ACTION_PREFERRED_PAYMENT_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @BroadcastBehavior
+BroadcastBehavior: android.nfc.NfcAdapter#ACTION_TRANSACTION_DETECTED:
+    Field 'ACTION_TRANSACTION_DETECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.os.DropBoxManager#ACTION_DROPBOX_ENTRY_ADDED:
+    Field 'ACTION_DROPBOX_ENTRY_ADDED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.CalendarContract#ACTION_EVENT_REMINDER:
+    Field 'ACTION_EVENT_REMINDER' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.ContactsContract.SimContacts#ACTION_SIM_ACCOUNTS_CHANGED:
+    Field 'ACTION_SIM_ACCOUNTS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#ACTION_SMS_EMERGENCY_CB_RECEIVED:
+    Field 'ACTION_SMS_EMERGENCY_CB_RECEIVED' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#DATA_SMS_RECEIVED_ACTION:
+    Field 'DATA_SMS_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SECRET_CODE_ACTION:
+    Field 'SECRET_CODE_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SIM_FULL_ACTION:
+    Field 'SIM_FULL_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_CB_RECEIVED_ACTION:
+    Field 'SMS_CB_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_DELIVER_ACTION:
+    Field 'SMS_DELIVER_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_RECEIVED_ACTION:
+    Field 'SMS_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_REJECTED_ACTION:
+    Field 'SMS_REJECTED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION:
+    Field 'SMS_SERVICE_CATEGORY_PROGRAM_DATA_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_DELIVER_ACTION:
+    Field 'WAP_PUSH_DELIVER_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.provider.Telephony.Sms.Intents#WAP_PUSH_RECEIVED_ACTION:
+    Field 'WAP_PUSH_RECEIVED_ACTION' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_KEYCHAIN_CHANGED:
+    Field 'ACTION_KEYCHAIN_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_KEY_ACCESS_CHANGED:
+    Field 'ACTION_KEY_ACCESS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_STORAGE_CHANGED:
+    Field 'ACTION_STORAGE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.security.KeyChain#ACTION_TRUST_STORE_CHANGED:
+    Field 'ACTION_TRUST_STORE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_DELETE_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_RENAME_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_START_EUICC_ACTIVATION:
+    Field 'ACTION_START_EUICC_ACTIVATION' is missing @BroadcastBehavior
+BroadcastBehavior: android.service.euicc.EuiccService#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.speech.tts.TextToSpeech#ACTION_TTS_QUEUE_PROCESSING_COMPLETED:
+    Field 'ACTION_TTS_QUEUE_PROCESSING_COMPLETED' is missing @BroadcastBehavior
+BroadcastBehavior: android.speech.tts.TextToSpeech.Engine#ACTION_TTS_DATA_INSTALLED:
+    Field 'ACTION_TTS_DATA_INSTALLED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_DEFAULT_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_REFRESH_SUBSCRIPTION_PLANS:
+    Field 'ACTION_REFRESH_SUBSCRIPTION_PLANS' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.SubscriptionManager#ACTION_SUBSCRIPTION_PLANS_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_PLANS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE:
+    Field 'ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_PCO_VALUE:
+    Field 'ACTION_CARRIER_SIGNAL_PCO_VALUE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_REDIRECTED:
+    Field 'ACTION_CARRIER_SIGNAL_REDIRECTED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED:
+    Field 'ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_CARRIER_SIGNAL_RESET:
+    Field 'ACTION_CARRIER_SIGNAL_RESET' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_EMERGENCY_CALLBACK_MODE_CHANGED:
+    Field 'ACTION_EMERGENCY_CALLBACK_MODE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_EMERGENCY_CALL_STATE_CHANGED:
+    Field 'ACTION_EMERGENCY_CALL_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE:
+    Field 'ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SECRET_CODE:
+    Field 'ACTION_SECRET_CODE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS:
+    Field 'ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_APPLICATION_STATE_CHANGED:
+    Field 'ACTION_SIM_APPLICATION_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_CARD_STATE_CHANGED:
+    Field 'ACTION_SIM_CARD_STATE_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SIM_SLOT_STATUS_CHANGED:
+    Field 'ACTION_SIM_SLOT_STATUS_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.TelephonyManager#ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED:
+    Field 'ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.euicc.EuiccManager#ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE:
+    Field 'ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE' is missing @BroadcastBehavior
+BroadcastBehavior: android.telephony.euicc.EuiccManager#ACTION_OTA_STATUS_CHANGED:
+    Field 'ACTION_OTA_STATUS_CHANGED' is missing @BroadcastBehavior
+
+
+DeprecationMismatch: android.accounts.AccountManager#newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle):
+    Method android.accounts.AccountManager.newChooseAccountIntent(android.accounts.Account, java.util.ArrayList<android.accounts.Account>, String[], boolean, String, String, String[], android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Activity#enterPictureInPictureMode():
+    Method android.app.Activity.enterPictureInPictureMode(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Instrumentation#startAllocCounting():
+    Method android.app.Instrumentation.startAllocCounting(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Instrumentation#stopAllocCounting():
+    Method android.app.Instrumentation.stopAllocCounting(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#bigContentView:
+    Field Notification.bigContentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#contentView:
+    Field Notification.contentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#headsUpContentView:
+    Field Notification.headsUpContentView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification#tickerView:
+    Field Notification.tickerView: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.Builder#Builder(int, CharSequence, android.app.PendingIntent):
+    Constructor android.app.Notification.Action.Builder.Builder(int, CharSequence, android.app.PendingIntent): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getCancelLabel():
+    Method android.app.Notification.Action.WearableExtender.getCancelLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getConfirmLabel():
+    Method android.app.Notification.Action.WearableExtender.getConfirmLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#getInProgressLabel():
+    Method android.app.Notification.Action.WearableExtender.getInProgressLabel(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setCancelLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setCancelLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setConfirmLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setConfirmLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Action.WearableExtender#setInProgressLabel(CharSequence):
+    Method android.app.Notification.Action.WearableExtender.setInProgressLabel(CharSequence): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Builder#setContent(android.widget.RemoteViews):
+    Method android.app.Notification.Builder.setContent(android.widget.RemoteViews): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.Builder#setTicker(CharSequence, android.widget.RemoteViews):
+    Method android.app.Notification.Builder.setTicker(CharSequence, android.widget.RemoteViews): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIcon():
+    Method android.app.Notification.WearableExtender.getContentIcon(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getContentIconGravity():
+    Method android.app.Notification.WearableExtender.getContentIconGravity(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomContentHeight():
+    Method android.app.Notification.WearableExtender.getCustomContentHeight(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getCustomSizePreset():
+    Method android.app.Notification.WearableExtender.getCustomSizePreset(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getGravity():
+    Method android.app.Notification.WearableExtender.getGravity(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintAvoidBackgroundClipping():
+    Method android.app.Notification.WearableExtender.getHintAvoidBackgroundClipping(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintHideIcon():
+    Method android.app.Notification.WearableExtender.getHintHideIcon(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintScreenTimeout():
+    Method android.app.Notification.WearableExtender.getHintScreenTimeout(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#getHintShowBackgroundOnly():
+    Method android.app.Notification.WearableExtender.getHintShowBackgroundOnly(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIcon(int):
+    Method android.app.Notification.WearableExtender.setContentIcon(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setContentIconGravity(int):
+    Method android.app.Notification.WearableExtender.setContentIconGravity(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomContentHeight(int):
+    Method android.app.Notification.WearableExtender.setCustomContentHeight(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setCustomSizePreset(int):
+    Method android.app.Notification.WearableExtender.setCustomSizePreset(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setGravity(int):
+    Method android.app.Notification.WearableExtender.setGravity(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintAvoidBackgroundClipping(boolean):
+    Method android.app.Notification.WearableExtender.setHintAvoidBackgroundClipping(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintHideIcon(boolean):
+    Method android.app.Notification.WearableExtender.setHintHideIcon(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintScreenTimeout(int):
+    Method android.app.Notification.WearableExtender.setHintScreenTimeout(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.Notification.WearableExtender#setHintShowBackgroundOnly(boolean):
+    Method android.app.Notification.WearableExtender.setHintShowBackgroundOnly(boolean): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.app.backup.BackupManager#selectBackupTransport(String):
+    Method android.app.backup.BackupManager.selectBackupTransport(String): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.content.Context#BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND:
+    Field Context.BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.content.Context#POWER_WHITELIST_MANAGER:
+    Field Context.POWER_WHITELIST_MANAGER: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.content.Context#WIFI_RTT_SERVICE:
+    Field Context.WIFI_RTT_SERVICE: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.ComposeShader#ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode):
+    Constructor android.graphics.ComposeShader.ComposeShader(android.graphics.Shader, android.graphics.Shader, android.graphics.Xfermode): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#A_8:
+    Field PixelFormat.A_8: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#LA_88:
+    Field PixelFormat.LA_88: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#L_8:
+    Field PixelFormat.L_8: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_4444:
+    Field PixelFormat.RGBA_4444: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGBA_5551:
+    Field PixelFormat.RGBA_5551: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.graphics.PixelFormat#RGB_332:
+    Field PixelFormat.RGB_332: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.hardware.hdmi.HdmiControlManager#RESULT_ALREADY_IN_PROGRESS:
+    Field HdmiControlManager.RESULT_ALREADY_IN_PROGRESS: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder#setCodeRate(int):
+    Method android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder.setCodeRate(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder#setModulation(int):
+    Method android.media.tv.tuner.frontend.IsdbtFrontendSettings.Builder.setModulation(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.EGL14#eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int):
+    Method android.opengl.EGL14.eglCreatePixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, int, int[], int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.GLES20#GL_STENCIL_INDEX:
+    Field GLES20.GL_STENCIL_INDEX: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.opengl.GLSurfaceView#surfaceRedrawNeeded(android.view.SurfaceHolder):
+    Method android.opengl.GLSurfaceView.surfaceRedrawNeeded(android.view.SurfaceHolder): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle):
+    Method android.os.UserManager.setUserRestrictions(android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.os.UserManager#setUserRestrictions(android.os.Bundle, android.os.UserHandle):
+    Method android.os.UserManager.setUserRestrictions(android.os.Bundle, android.os.UserHandle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.provider.Contacts.People#markAsContacted(android.content.ContentResolver, long):
+    Method android.provider.Contacts.People.markAsContacted(android.content.ContentResolver, long): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_X:
+    Field Type.CubemapFace.POSITVE_X: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Y:
+    Field Type.CubemapFace.POSITVE_Y: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.renderscript.Type.CubemapFace#POSITVE_Z:
+    Field Type.CubemapFace.POSITVE_Z: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.speech.tts.TextToSpeech#areDefaultsEnforced():
+    Method android.speech.tts.TextToSpeech.areDefaultsEnforced(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#StatusHints(android.content.ComponentName, CharSequence, int, android.os.Bundle):
+    Constructor android.telecom.StatusHints.StatusHints(android.content.ComponentName, CharSequence, int, android.os.Bundle): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getIcon(android.content.Context):
+    Method android.telecom.StatusHints.getIcon(android.content.Context): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getIconResId():
+    Method android.telecom.StatusHints.getIconResId(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telecom.StatusHints#getPackageName():
+    Method android.telecom.StatusHints.getPackageName(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.PhoneStateListener#PhoneStateListener(java.util.concurrent.Executor):
+    Constructor android.telephony.PhoneStateListener.PhoneStateListener(java.util.concurrent.Executor): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionManager#PROFILE_CLASS_DEFAULT:
+    Field SubscriptionManager.PROFILE_CLASS_DEFAULT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringDaily(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringDaily(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringMonthly(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringMonthly(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.telephony.SubscriptionPlan.Builder#createRecurringWeekly(java.time.ZonedDateTime):
+    Method android.telephony.SubscriptionPlan.Builder.createRecurringWeekly(java.time.ZonedDateTime): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_12HOUR:
+    Field DateUtils.FORMAT_12HOUR: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_24HOUR:
+    Field DateUtils.FORMAT_24HOUR: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_AMPM:
+    Field DateUtils.FORMAT_CAP_AMPM: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_MIDNIGHT:
+    Field DateUtils.FORMAT_CAP_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON:
+    Field DateUtils.FORMAT_CAP_NOON: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_CAP_NOON_MIDNIGHT:
+    Field DateUtils.FORMAT_CAP_NOON_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.text.format.DateUtils#FORMAT_NO_NOON_MIDNIGHT:
+    Field DateUtils.FORMAT_NO_NOON_MIDNIGHT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.ViewGroup.LayoutParams#FILL_PARENT:
+    Field ViewGroup.LayoutParams.FILL_PARENT: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.Window#setTitleColor(int):
+    Method android.view.Window.setTitleColor(int): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.view.accessibility.AccessibilityEvent#MAX_TEXT_LENGTH:
+    Field AccessibilityEvent.MAX_TEXT_LENGTH: @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebSettings#getSaveFormData():
+    Method android.webkit.WebSettings.getSaveFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebView#shouldDelayChildPressedState():
+    Method android.webkit.WebView.shouldDelayChildPressedState(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebViewDatabase#clearFormData():
+    Method android.webkit.WebViewDatabase.clearFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: android.webkit.WebViewDatabase#hasFormData():
+    Method android.webkit.WebViewDatabase.hasFormData(): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+DeprecationMismatch: javax.microedition.khronos.egl.EGL10#eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]):
+    Method javax.microedition.khronos.egl.EGL10.eglCreatePixmapSurface(javax.microedition.khronos.egl.EGLDisplay, javax.microedition.khronos.egl.EGLConfig, Object, int[]): @Deprecated annotation (present) and @deprecated doc tag (not present) do not match
+
+
 KotlinKeyword: android.app.Notification#when:
     Avoid field names that are Kotlin hard keywords ("when"); see https://android.github.io/kotlin-guides/interop.html#no-hard-keywords
 
@@ -19,6 +527,1254 @@
     Protected methods not allowed; must be public: method android.view.ViewGroup.resetResolvedDrawables()}
 
 
+RequiresPermission: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
+    Method 'getAccountsByTypeAndFeatures' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
+    Method 'hasFeatures' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
+    Method 'addOnUidImportanceListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getHistoricalProcessExitReasons(String, int, int):
+    Method 'getHistoricalProcessExitReasons' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getProcessesInErrorState():
+    Method 'getProcessesInErrorState' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getUidProcessCapabilities(int):
+    Method 'getUidProcessCapabilities' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.ActivityManager#getUidProcessState(int):
+    Method 'getUidProcessState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.ActivityManager#killProcessesWhenImperceptible(int[], String):
+    Method 'killProcessesWhenImperceptible' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.ActivityManager#setDeviceLocales(android.os.LocaleList):
+    Method 'setDeviceLocales' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setAlarmClock(android.app.AlarmManager.AlarmClockInfo, android.app.PendingIntent):
+    Method 'setAlarmClock' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setExact(int, long, android.app.PendingIntent):
+    Method 'setExact' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setExactAndAllowWhileIdle(int, long, android.app.PendingIntent):
+    Method 'setExactAndAllowWhileIdle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AlarmManager#setTime(long):
+    Method 'setTime' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#isOpActive(String, int, String):
+    Method 'isOpActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#isOperationActive(int, int, String):
+    Method 'isOperationActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#startWatchingActive(String[], java.util.concurrent.Executor, android.app.AppOpsManager.OnOpActiveChangedListener):
+    Method 'startWatchingActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.AppOpsManager#startWatchingNoted(String[], java.util.concurrent.Executor, android.app.AppOpsManager.OnOpNotedListener):
+    Method 'startWatchingNoted' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setDestinationInExternalPublicDir(String, String):
+    Method 'setDestinationInExternalPublicDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setDestinationUri(android.net.Uri):
+    Method 'setDestinationUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setNotificationVisibility(int):
+    Method 'setNotificationVisibility' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.DownloadManager.Request#setShowRunningNotification(boolean):
+    Method 'setShowRunningNotification' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.GameManager#getGameMode(String):
+    Method 'getGameMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.GameManager#isAngleEnabled(String):
+    Method 'isAngleEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.GameManager#setGameMode(String, int):
+    Method 'setGameMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.GameManager#updateCustomGameModeConfiguration(String, android.app.GameModeConfiguration):
+    Method 'updateCustomGameModeConfiguration' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.LocaleManager#getApplicationLocales(String):
+    Method 'getApplicationLocales' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.Notification.Builder#setFullScreenIntent(android.app.PendingIntent, boolean):
+    Method 'setFullScreenIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.NotificationManager#canUseFullScreenIntent():
+    Method 'canUseFullScreenIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.Service#startForeground(int, android.app.Notification):
+    Method 'startForeground' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.StatusBarManager#canLaunchCaptureContentActivityForNote(android.app.Activity):
+    Method 'canLaunchCaptureContentActivityForNote' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.StatusBarManager#collapsePanels():
+    Method 'collapsePanels' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.UiModeManager#releaseProjection(int):
+    Method 'releaseProjection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.UiModeManager#requestProjection(int):
+    Method 'requestProjection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperInfo#getSettingsSliceUri():
+    Method 'getSettingsSliceUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#clear():
+    Method 'clear' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#clearWallpaper(int, int):
+    Method 'clearWallpaper' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getDrawable():
+    Method 'getDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getDrawable(int):
+    Method 'getDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getFastDrawable():
+    Method 'getFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getFastDrawable(int):
+    Method 'getFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getWallpaperFile(int):
+    Method 'getWallpaperFile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#getWallpaperInfo(int):
+    Method 'getWallpaperInfo' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekDrawable():
+    Method 'peekDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekDrawable(int):
+    Method 'peekDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekFastDrawable():
+    Method 'peekFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#peekFastDrawable(int):
+    Method 'peekFastDrawable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap):
+    Method 'setBitmap' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setBitmap(android.graphics.Bitmap, android.graphics.Rect, boolean):
+    Method 'setBitmap' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setDisplayPadding(android.graphics.Rect):
+    Method 'setDisplayPadding' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setResource(int):
+    Method 'setResource' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream):
+    Method 'setStream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setStream(java.io.InputStream, android.graphics.Rect, boolean):
+    Method 'setStream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#setWallpaperComponentWithFlags(android.content.ComponentName, int):
+    Method 'setWallpaperComponentWithFlags' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.WallpaperManager#suggestDesiredDimensions(int, int):
+    Method 'suggestDesiredDimensions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#addCrossProfileWidgetProvider(android.content.ComponentName, String):
+    Method 'addCrossProfileWidgetProvider' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName):
+    Method 'addPersistentPreferredActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#bindDeviceAdminServiceAsUser(android.content.ComponentName, android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    Method 'bindDeviceAdminServiceAsUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#clearPackagePersistentPreferredActivities(android.content.ComponentName, String):
+    Method 'clearPackagePersistentPreferredActivities' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#clearResetPasswordToken(android.content.ComponentName):
+    Method 'clearResetPasswordToken' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#createAndProvisionManagedProfile(android.app.admin.ManagedProfileProvisioningParams):
+    Method 'createAndProvisionManagedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#finalizeWorkProfileProvisioning(android.os.UserHandle, android.accounts.Account):
+    Method 'finalizeWorkProfileProvisioning' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#forceUpdateUserSetupComplete(int):
+    Method 'forceUpdateUserSetupComplete' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#generateKeyPair(android.content.ComponentName, String, android.security.keystore.KeyGenParameterSpec, int):
+    Method 'generateKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getApplicationExemptions(String):
+    Method 'getApplicationExemptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getCrossProfileWidgetProviders(android.content.ComponentName):
+    Method 'getCrossProfileWidgetProviders' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getLockTaskFeatures(android.content.ComponentName):
+    Method 'getLockTaskFeatures' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getLockTaskPackages(android.content.ComponentName):
+    Method 'getLockTaskPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getNearbyAppStreamingPolicy():
+    Method 'getNearbyAppStreamingPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getNearbyNotificationStreamingPolicy():
+    Method 'getNearbyNotificationStreamingPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getOrganizationName(android.content.ComponentName):
+    Method 'getOrganizationName' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts(android.os.UserHandle):
+    Method 'getOwnerInstalledCaCerts' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getPasswordComplexity():
+    Method 'getPasswordComplexity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getShortSupportMessage(android.content.ComponentName):
+    Method 'getShortSupportMessage' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#getUserControlDisabledPackages(android.content.ComponentName):
+    Method 'getUserControlDisabledPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#hasKeyPair(String):
+    Method 'hasKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate, String):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], String, boolean):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#installKeyPair(android.content.ComponentName, java.security.PrivateKey, java.security.cert.Certificate[], String, int):
+    Method 'installKeyPair' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isDeviceProvisioningConfigApplied():
+    Method 'isDeviceProvisioningConfigApplied' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isPackageSuspended(android.content.ComponentName, String):
+    Method 'isPackageSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#isResetPasswordTokenActive(android.content.ComponentName):
+    Method 'isResetPasswordTokenActive' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#lockNow(int):
+    Method 'lockNow' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#provisionFullyManagedDevice(android.app.admin.FullyManagedDeviceProvisioningParams):
+    Method 'provisionFullyManagedDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#removeCrossProfileWidgetProvider(android.content.ComponentName, String):
+    Method 'removeCrossProfileWidgetProvider' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#sendLostModeLocationUpdate(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
+    Method 'sendLostModeLocationUpdate' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setActiveProfileOwner(android.content.ComponentName, String):
+    Method 'setActiveProfileOwner' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setAlwaysOnVpnPackage(android.content.ComponentName, String, boolean):
+    Method 'setAlwaysOnVpnPackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setApplicationExemptions(String, java.util.Set<java.lang.Integer>):
+    Method 'setApplicationExemptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setDeviceOwner(android.content.ComponentName, int):
+    Method 'setDeviceOwner' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setDeviceProvisioningConfigApplied():
+    Method 'setDeviceProvisioningConfigApplied' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setLockTaskFeatures(android.content.ComponentName, int):
+    Method 'setLockTaskFeatures' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setLockTaskPackages(android.content.ComponentName, String[]):
+    Method 'setLockTaskPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setPermittedInputMethods(android.content.ComponentName, java.util.List<java.lang.String>):
+    Method 'setPermittedInputMethods' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setUninstallBlocked(android.content.ComponentName, String, boolean):
+    Method 'setUninstallBlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#setUserControlDisabledPackages(android.content.ComponentName, java.util.List<java.lang.String>):
+    Method 'setUserControlDisabledPackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeData(int):
+    Method 'wipeData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeData(int, CharSequence):
+    Method 'wipeData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.DevicePolicyManager#wipeDevice(int):
+    Method 'wipeDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.admin.PolicyUpdateReceiver#onPolicyChanged(android.content.Context, String, android.os.Bundle, android.app.admin.TargetUser, android.app.admin.PolicyUpdateResult):
+    Method 'onPolicyChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.admin.PolicyUpdateReceiver#onPolicySetResult(android.content.Context, String, android.os.Bundle, android.app.admin.TargetUser, android.app.admin.PolicyUpdateResult):
+    Method 'onPolicySetResult' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#dataChanged(String):
+    Method 'dataChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#requestBackup(String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int):
+    Method 'requestBackup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#setFrameworkSchedulingEnabled(boolean):
+    Method 'setFrameworkSchedulingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#updateTransportAttributes(android.content.ComponentName, String, android.content.Intent, String, android.content.Intent, CharSequence):
+    Method 'updateTransportAttributes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.BackupManager#updateTransportAttributes(android.content.ComponentName, String, android.content.Intent, String, android.content.Intent, String):
+    Method 'updateTransportAttributes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restoreAll(long, android.app.backup.RestoreObserver):
+    Method 'restoreAll' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restoreAll(long, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor):
+    Method 'restoreAll' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackage(String, android.app.backup.RestoreObserver):
+    Method 'restorePackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackage(String, android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor):
+    Method 'restorePackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackages(long, android.app.backup.RestoreObserver, java.util.Set<java.lang.String>):
+    Method 'restorePackages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.backup.RestoreSession#restorePackages(long, android.app.backup.RestoreObserver, java.util.Set<java.lang.String>, android.app.backup.BackupManagerMonitor):
+    Method 'restorePackages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setRequiredNetwork(android.net.NetworkRequest):
+    Method 'setRequiredNetwork' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setRequiredNetworkType(int):
+    Method 'setRequiredNetworkType' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobInfo.Builder#setUserInitiated(boolean):
+    Method 'setUserInitiated' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.job.JobParameters#isUserInitiatedJob():
+    Method 'isUserInitiatedJob' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.job.JobScheduler#canRunUserInitiatedJobs():
+    Method 'canRunUserInitiatedJobs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.people.PeopleManager#isConversation(String, String):
+    Method 'isConversation' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryExternalStatsForUser(java.util.UUID, android.os.UserHandle):
+    Method 'queryExternalStatsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForPackage(java.util.UUID, String, android.os.UserHandle):
+    Method 'queryStatsForPackage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUid(java.util.UUID, int):
+    Method 'queryStatsForUid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.StorageStatsManager#queryStatsForUser(java.util.UUID, android.os.UserHandle):
+    Method 'queryStatsForUser' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageEvents.Event#getTaskRootClassName():
+    Method 'getTaskRootClassName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageEvents.Event#getTaskRootPackageName():
+    Method 'getTaskRootPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#getAppStandbyBucket(String):
+    Method 'getAppStandbyBucket' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#getAppStandbyBuckets():
+    Method 'getAppStandbyBuckets' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#isAppInactive(String):
+    Method 'isAppInactive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#onCarrierPrivilegedAppsChanged():
+    Method 'onCarrierPrivilegedAppsChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryAndAggregateUsageStats(long, long):
+    Method 'queryAndAggregateUsageStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryConfigurations(int, long, long):
+    Method 'queryConfigurations' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryEventStats(int, long, long):
+    Method 'queryEventStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryEvents(long, long):
+    Method 'queryEvents' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#queryUsageStats(int, long, long):
+    Method 'queryUsageStats' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerAppUsageLimitObserver(int, String[], java.time.Duration, java.time.Duration, android.app.PendingIntent):
+    Method 'registerAppUsageLimitObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerAppUsageObserver(int, String[], long, java.util.concurrent.TimeUnit, android.app.PendingIntent):
+    Method 'registerAppUsageObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#registerUsageSessionObserver(int, String[], java.time.Duration, java.time.Duration, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'registerUsageSessionObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#reportUsageStart(android.app.Activity, String):
+    Method 'reportUsageStart' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#reportUsageStart(android.app.Activity, String, long):
+    Method 'reportUsageStart' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterAppUsageLimitObserver(int):
+    Method 'unregisterAppUsageLimitObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterAppUsageObserver(int):
+    Method 'unregisterAppUsageObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.app.usage.UsageStatsManager#unregisterUsageSessionObserver(int):
+    Method 'unregisterUsageSessionObserver' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.appwidget.AppWidgetManager#bindAppWidgetIdIfAllowed(int, android.os.UserHandle, android.content.ComponentName, android.os.Bundle):
+    Method 'bindAppWidgetIdIfAllowed' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#isDeviceAssociatedForWifiConnection(String, android.net.MacAddress, android.os.UserHandle):
+    Method 'isDeviceAssociatedForWifiConnection' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#startObservingDevicePresence(String):
+    Method 'startObservingDevicePresence' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.CompanionDeviceManager#stopObservingDevicePresence(String):
+    Method 'stopObservingDevicePresence' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.virtual.VirtualDeviceManager#createVirtualDevice(int, android.companion.virtual.VirtualDeviceParams):
+    Method 'createVirtualDevice' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.companion.virtual.VirtualDeviceParams.Builder#setLockState(int):
+    Method 'setLockState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.ContentResolver#addPeriodicSync(android.accounts.Account, String, android.os.Bundle, long):
+    Method 'addPeriodicSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#cancelSync(android.content.SyncRequest):
+    Method 'cancelSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getCurrentSync():
+    Method 'getCurrentSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getCurrentSyncs():
+    Method 'getCurrentSyncs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getIsSyncable(android.accounts.Account, String):
+    Method 'getIsSyncable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getMasterSyncAutomatically():
+    Method 'getMasterSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getPeriodicSyncs(android.accounts.Account, String):
+    Method 'getPeriodicSyncs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#getSyncAutomatically(android.accounts.Account, String):
+    Method 'getSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#isSyncActive(android.accounts.Account, String):
+    Method 'isSyncActive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#isSyncPending(android.accounts.Account, String):
+    Method 'isSyncPending' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#removePeriodicSync(android.accounts.Account, String, android.os.Bundle):
+    Method 'removePeriodicSync' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setIsSyncable(android.accounts.Account, String, int):
+    Method 'setIsSyncable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setMasterSyncAutomatically(boolean):
+    Method 'setMasterSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.ContentResolver#setSyncAutomatically(android.accounts.Account, String, boolean):
+    Method 'setSyncAutomatically' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle):
+    Method 'bindServiceAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.Context#clearWallpaper():
+    Method 'clearWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalCacheDir():
+    Method 'getExternalCacheDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalCacheDirs():
+    Method 'getExternalCacheDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalFilesDir(String):
+    Method 'getExternalFilesDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalFilesDirs(String):
+    Method 'getExternalFilesDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getExternalMediaDirs():
+    Method 'getExternalMediaDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getObbDir():
+    Method 'getObbDir' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#getObbDirs():
+    Method 'getObbDirs' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#removeStickyBroadcastAsUser(android.content.Intent, android.os.UserHandle):
+    Method 'removeStickyBroadcastAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.Context#setWallpaper(android.graphics.Bitmap):
+    Method 'setWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.Context#setWallpaper(java.io.InputStream):
+    Method 'setWallpaper' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#canRequestInteractAcrossProfiles():
+    Method 'canRequestInteractAcrossProfiles' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.ComponentName, android.os.UserHandle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.ComponentName, android.os.UserHandle, android.app.Activity, android.os.Bundle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.Intent, android.os.UserHandle, android.app.Activity):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.CrossProfileApps#startActivity(android.content.Intent, android.os.UserHandle, android.app.Activity, android.os.Bundle):
+    Method 'startActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps#getAllPackageInstallerSessions():
+    Method 'getAllPackageInstallerSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps#registerPackageInstallerSessionCallback(java.util.concurrent.Executor, android.content.pm.PackageInstaller.SessionCallback):
+    Method 'registerPackageInstallerSessionCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.LauncherApps.Callback#onPackagesSuspended(String[], android.os.UserHandle, android.os.Bundle):
+    Method 'onPackagesSuspended' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getAllSessions():
+    Method 'getAllSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getSessionInfo(int):
+    Method 'getSessionInfo' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#getStagedSessions():
+    Method 'getStagedSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller#registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback):
+    Method 'registerSessionCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.Session#requestUserPreapproval(android.content.pm.PackageInstaller.PreapprovalDetails, android.content.IntentSender):
+    Method 'requestUserPreapproval' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setInstallerPackageName(String):
+    Method 'setInstallerPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setPermissionState(String, int):
+    Method 'setPermissionState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setRequestUpdateOwnership(boolean):
+    Method 'setRequestUpdateOwnership' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageInstaller.SessionParams#setRequireUserAction(int):
+    Method 'setRequireUserAction' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#canRequestPackageInstalls():
+    Method 'canRequestPackageInstalls' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#getSuspendedPackageAppExtras():
+    Method 'getSuspendedPackageAppExtras' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#getUnsuspendablePackages(String[]):
+    Method 'getUnsuspendablePackages' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#grantRuntimePermission(String, String, android.os.UserHandle):
+    Method 'grantRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#isAutoRevokeWhitelisted(String):
+    Method 'isAutoRevokeWhitelisted' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#isPackageSuspended():
+    Method 'isPackageSuspended' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle):
+    Method 'revokeRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle, String):
+    Method 'revokeRuntimePermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setDistractingPackageRestrictions(String[], int):
+    Method 'setDistractingPackageRestrictions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, String):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, android.content.pm.SuspendDialogInfo):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#setPackagesSuspended(String[], boolean, android.os.PersistableBundle, android.os.PersistableBundle, android.content.pm.SuspendDialogInfo, int):
+    Method 'setPackagesSuspended' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.content.pm.PackageManager#verifyIntentFilter(int, int, java.util.List<java.lang.String>):
+    Method 'verifyIntentFilter' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.Sensor#getHighestDirectReportRateLevel():
+    Method 'getHighestDirectReportRateLevel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.Sensor#getMinDelay():
+    Method 'getMinDelay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraCharacteristics#getKeysNeedingPermission():
+    Method 'getKeysNeedingPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraManager.AvailabilityCallback#onCameraClosed(String):
+    Method 'onCameraClosed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.camera2.CameraManager.AvailabilityCallback#onCameraOpened(String, String):
+    Method 'onCameraOpened' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.devicestate.DeviceStateManager#cancelBaseStateOverride():
+    Method 'cancelBaseStateOverride' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.devicestate.DeviceStateManager#cancelStateRequest():
+    Method 'cancelStateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.devicestate.DeviceStateManager#requestBaseStateOverride(android.hardware.devicestate.DeviceStateRequest, java.util.concurrent.Executor, android.hardware.devicestate.DeviceStateRequest.Callback):
+    Method 'requestBaseStateOverride' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.devicestate.DeviceStateManager#requestState(android.hardware.devicestate.DeviceStateRequest, java.util.concurrent.Executor, android.hardware.devicestate.DeviceStateRequest.Callback):
+    Method 'requestState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.hdmi.HdmiControlManager#getHdmiCecVersion():
+    Method 'getHdmiCecVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.hdmi.HdmiControlManager#setHdmiCecVersion(int):
+    Method 'setHdmiCecVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.input.InputManager#addUniqueIdAssociation(String, String):
+    Method 'addUniqueIdAssociation' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.input.InputManager#removeUniqueIdAssociation(String):
+    Method 'removeUniqueIdAssociation' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback):
+    Method 'addGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#getMonitoringTypes():
+    Method 'getMonitoringTypes' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#pauseGeofence(int, int):
+    Method 'pauseGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#registerForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback):
+    Method 'registerForMonitorStateChangeCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#removeGeofence(int, int):
+    Method 'removeGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#resumeGeofence(int, int, int):
+    Method 'resumeGeofence' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.location.GeofenceHardware#unregisterForMonitorStateChangeCallback(int, android.hardware.location.GeofenceHardwareMonitorCallback):
+    Method 'unregisterForMonitorStateChangeCallback' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#grantPermission(android.hardware.usb.UsbDevice, String):
+    Method 'grantPermission' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#hasPermission(android.hardware.usb.UsbDevice):
+    Method 'hasPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.hardware.usb.UsbManager#requestPermission(android.hardware.usb.UsbDevice, android.app.PendingIntent):
+    Method 'requestPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.AudioAttributes.Builder#setHapticChannelsMuted(boolean):
+    Method 'setHapticChannelsMuted' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.AudioManager#getCallDownlinkExtractionAudioRecord(android.media.AudioFormat):
+    Method 'getCallDownlinkExtractionAudioRecord' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioManager#getCallUplinkInjectionAudioTrack(android.media.AudioFormat):
+    Method 'getCallUplinkInjectionAudioTrack' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioManager#registerAudioPolicy(android.media.audiopolicy.AudioPolicy):
+    Method 'registerAudioPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioRecord#shareAudioHistory(String, long):
+    Method 'shareAudioHistory' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.AudioRecordingConfiguration#getClientUid():
+    Method 'getClientUid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.MediaCodec#createByCodecNameForClient(String, int, int):
+    Method 'createByCodecNameForClient' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(String):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(String, java.util.Map<java.lang.String,java.lang.String>):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaExtractor#setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String,java.lang.String>):
+    Method 'setDataSource' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaPlayer#setWakeMode(android.content.Context, int):
+    Method 'setWakeMode' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.MediaRouter2#getInstance(android.content.Context, String):
+    Method 'getInstance' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.RingtoneManager#getCursor():
+    Method 'getCursor' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.RingtoneManager#getValidRingtoneUri(android.content.Context):
+    Method 'getValidRingtoneUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.audiofx.HapticGenerator#setEnabled(boolean):
+    Method 'setEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.projection.MediaProjection#createVirtualDisplay(String, int, int, int, int, android.view.Surface, android.hardware.display.VirtualDisplay.Callback, android.os.Handler):
+    Method 'createVirtualDisplay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.projection.MediaProjectionManager#getMediaProjection(int, android.content.Intent):
+    Method 'getMediaProjection' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
+    Method 'addOnActiveSessionsChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#addOnMediaKeyEventSessionChangedListener(java.util.concurrent.Executor, android.media.session.MediaSessionManager.OnMediaKeyEventSessionChangedListener):
+    Method 'addOnMediaKeyEventSessionChangedListener' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getActiveSessions(android.content.ComponentName):
+    Method 'getActiveSessions' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getMediaKeyEventSession():
+    Method 'getMediaKeyEventSession' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#getMediaKeyEventSessionPackageName():
+    Method 'getMediaKeyEventSessionPackageName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.session.MediaSessionManager#isTrustedForMediaControl(android.media.session.MediaSessionManager.RemoteUserInfo):
+    Method 'isTrustedForMediaControl' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#deleteKeyphraseSoundModel(int, java.util.Locale):
+    Method 'deleteKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#getKeyphraseSoundModel(int, java.util.Locale):
+    Method 'getKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.media.voice.KeyphraseModelManager#updateKeyphraseSoundModel(android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel):
+    Method 'updateKeyphraseSoundModel' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#clearScores():
+    Method 'clearScores' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#disableScoring():
+    Method 'disableScoring' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#getActiveScorerPackage():
+    Method 'getActiveScorerPackage' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#registerNetworkScoreCallback(int, int, java.util.concurrent.Executor, android.net.NetworkScoreManager.NetworkScoreCallback):
+    Method 'registerNetworkScoreCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#requestScores(java.util.Collection<android.net.NetworkKey>):
+    Method 'requestScores' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.NetworkScoreManager#setActiveScorer(String):
+    Method 'setActiveScorer' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.VpnService#prepareAndAuthorize(android.content.Context):
+    Method 'prepareAndAuthorize' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.sip.SipAudioCall#setSpeakerMode(boolean):
+    Method 'setSpeakerMode' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.net.sip.SipAudioCall#startAudio():
+    Method 'startAudio' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#addVcnNetworkPolicyChangeListener(java.util.concurrent.Executor, android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener):
+    Method 'addVcnNetworkPolicyChangeListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#applyVcnNetworkPolicy(android.net.NetworkCapabilities, android.net.LinkProperties):
+    Method 'applyVcnNetworkPolicy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.net.vcn.VcnManager#removeVcnNetworkPolicyChangeListener(android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener):
+    Method 'removeVcnNetworkPolicyChangeListener' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#disableForegroundDispatch(android.app.Activity):
+    Method 'disableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.NfcAdapter#enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]):
+    Method 'enableForegroundDispatch' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForAid(android.content.ComponentName, String):
+    Method 'isDefaultServiceForAid' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#isDefaultServiceForCategory(android.content.ComponentName, String):
+    Method 'isDefaultServiceForCategory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.cardemulation.CardEmulation#setOffHostForService(android.content.ComponentName, String):
+    Method 'setOffHostForService' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.IsoDep#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyA(int, byte[]):
+    Method 'authenticateSectorWithKeyA' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#authenticateSectorWithKeyB(int, byte[]):
+    Method 'authenticateSectorWithKeyB' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#decrement(int, int):
+    Method 'decrement' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#increment(int, int):
+    Method 'increment' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#readBlock(int):
+    Method 'readBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#restore(int):
+    Method 'restore' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#transfer(int):
+    Method 'transfer' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareClassic#writeBlock(int, byte[]):
+    Method 'writeBlock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#readPages(int):
+    Method 'readPages' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.MifareUltralight#writePage(int, byte[]):
+    Method 'writePage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#getNdefMessage():
+    Method 'getNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#isWritable():
+    Method 'isWritable' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#makeReadOnly():
+    Method 'makeReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.Ndef#writeNdefMessage(android.nfc.NdefMessage):
+    Method 'writeNdefMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#format(android.nfc.NdefMessage):
+    Method 'format' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NdefFormatable#formatReadOnly(android.nfc.NdefMessage):
+    Method 'formatReadOnly' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcA#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcB#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#getTimeout():
+    Method 'getTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#setTimeout(int):
+    Method 'setTimeout' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcF#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.NfcV#transceive(byte[]):
+    Method 'transceive' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#close():
+    Method 'close' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.nfc.tech.TagTechnology#connect():
+    Method 'connect' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.BugreportManager#cancelBugreport():
+    Method 'cancelBugreport' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.BugreportManager#preDumpUiData():
+    Method 'preDumpUiData' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Build#getSerial():
+    Method 'getSerial' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Debug#dumpService(String, java.io.FileDescriptor, String[]):
+    Method 'dumpService' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.DropBoxManager#getNextEntry(String, long):
+    Method 'getNextEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.Environment#getExternalStorageDirectory():
+    Method 'getExternalStorageDirectory' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Environment#isExternalStorageManager():
+    Method 'isExternalStorageManager' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.Environment#isExternalStorageManager(java.io.File):
+    Method 'isExternalStorageManager' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#dream(long):
+    Method 'dream' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#forceSuspend():
+    Method 'forceSuspend' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#getPowerSaveModeTrigger():
+    Method 'getPowerSaveModeTrigger' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#newWakeLock(int, String):
+    Method 'newWakeLock' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.PowerManager#reboot(String):
+    Method 'reboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#setBatteryDischargePrediction(java.time.Duration, boolean):
+    Method 'setBatteryDischargePrediction' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#setDynamicPowerSaveHint(boolean, int):
+    Method 'setDynamicPowerSaveHint' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.PowerManager#userActivity(long, int, int):
+    Method 'userActivity' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.RecoverySystem#rebootWipeUserData(android.content.Context):
+    Method 'rebootWipeUserData' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.StrictMode.VmPolicy.Builder#detectFileUriExposure():
+    Method 'detectFileUriExposure' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.SystemUpdateManager#retrieveSystemUpdateInfo():
+    Method 'retrieveSystemUpdateInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.SystemUpdateManager#updateSystemUpdateInfo(android.os.PersistableBundle):
+    Method 'updateSystemUpdateInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#createUser(String, String, int):
+    Method 'createUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#getUserProperties(android.os.UserHandle):
+    Method 'getUserProperties' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#getUserRestrictions(android.os.UserHandle):
+    Method 'getUserRestrictions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#hasUserRestrictionForUser(String, android.os.UserHandle):
+    Method 'hasUserRestrictionForUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isManagedProfile(int):
+    Method 'isManagedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isRestrictedProfile():
+    Method 'isRestrictedProfile' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.UserManager#isRestrictedProfile(android.os.UserHandle):
+    Method 'isRestrictedProfile' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isUserUnlocked(android.os.UserHandle):
+    Method 'isUserUnlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#isUserUnlockingOrUnlocked(android.os.UserHandle):
+    Method 'isUserUnlockingOrUnlocked' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#preCreateUser(String):
+    Method 'preCreateUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#requestQuietModeEnabled(boolean, android.os.UserHandle):
+    Method 'requestQuietModeEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.UserManager#setUserRestriction(String, boolean):
+    Method 'setUserRestriction' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshot(int):
+    Method 'takeUidSnapshot' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.health.SystemHealthManager#takeUidSnapshots(int[]):
+    Method 'takeUidSnapshots' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#getCloudMediaProvider():
+    Method 'getCloudMediaProvider' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#getManageSpaceActivityIntent(String, int):
+    Method 'getManageSpaceActivityIntent' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.os.storage.StorageManager#isAppIoBlocked(java.util.UUID, int, int, int):
+    Method 'isAppIoBlocked' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.os.storage.StorageVolume#createAccessIntent(String):
+    Method 'createAccessIntent' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForDataDelivery(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForDataDelivery' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForDataDeliveryFromDataSource(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForDataDeliveryFromDataSource' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.permission.PermissionManager#checkPermissionForStartDataDelivery(String, android.content.AttributionSource, String):
+    Method 'checkPermissionForStartDataDelivery' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.provider.Settings#canDrawOverlays(android.content.Context):
+    Method 'canDrawOverlays' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.provider.Settings.System#canWrite(android.content.Context):
+    Method 'canWrite' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.security.KeyChain#removeCredentialManagementApp(android.content.Context):
+    Method 'removeCredentialManagementApp' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.BeginCreateCredentialResponse.Builder#setRemoteCreateEntry(android.service.credentials.RemoteEntry):
+    Method 'setRemoteCreateEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.BeginGetCredentialResponse.Builder#setRemoteCredentialEntry(android.service.credentials.RemoteEntry):
+    Method 'setRemoteCredentialEntry' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.service.credentials.CallingAppInfo#getOrigin():
+    Method 'getOrigin' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.Call.Details#getContactDisplayName():
+    Method 'getContactDisplayName' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.Call.Details#getContactPhotoUri():
+    Method 'getContactPhotoUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#acceptHandover(android.net.Uri, int, android.telecom.PhoneAccountHandle):
+    Method 'acceptHandover' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    Method 'addNewIncomingCall' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#addNewIncomingConference(android.telecom.PhoneAccountHandle, android.os.Bundle):
+    Method 'addNewIncomingConference' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getCallState():
+    Method 'getCallState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getLine1Number(android.telecom.PhoneAccountHandle):
+    Method 'getLine1Number' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getOwnSelfManagedPhoneAccounts():
+    Method 'getOwnSelfManagedPhoneAccounts' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getPhoneAccount(android.telecom.PhoneAccountHandle):
+    Method 'getPhoneAccount' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#getSelfManagedPhoneAccounts():
+    Method 'getSelfManagedPhoneAccounts' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#hasManageOngoingCallsPermission():
+    Method 'hasManageOngoingCallsPermission' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#placeCall(android.net.Uri, android.os.Bundle):
+    Method 'placeCall' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#showInCallScreen(boolean):
+    Method 'showInCallScreen' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telecom.TelecomManager#silenceRinger():
+    Method 'silenceRinger' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig():
+    Method 'getConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfig(java.lang.String...):
+    Method 'getConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigByComponentForSubId(String, int):
+    Method 'getConfigByComponentForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int):
+    Method 'getConfigForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#getConfigForSubId(int, java.lang.String...):
+    Method 'getConfigForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CarrierConfigManager#notifyConfigChangedForSubId(int):
+    Method 'notifyConfigChangedForSubId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.CellLocation#requestLocationUpdate():
+    Method 'requestLocationUpdate' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.NetworkRegistrationInfo#getCellIdentity():
+    Method 'getCellIdentity' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onActiveDataSubscriptionIdChanged(int):
+    Method 'onActiveDataSubscriptionIdChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onCallAttributesChanged(android.telephony.CallAttributes):
+    Method 'onCallAttributesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onCallStateChanged(int, String):
+    Method 'onCallStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onDisplayInfoChanged(android.telephony.TelephonyDisplayInfo):
+    Method 'onDisplayInfoChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState):
+    Method 'onPreciseDataConnectionStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onRadioPowerStateChanged(int):
+    Method 'onRadioPowerStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.PhoneStateListener#onServiceStateChanged(android.telephony.ServiceState):
+    Method 'onServiceStateChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getCdmaNetworkId():
+    Method 'getCdmaNetworkId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getCdmaSystemId():
+    Method 'getCdmaSystemId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorAlphaLong():
+    Method 'getOperatorAlphaLong' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorAlphaShort():
+    Method 'getOperatorAlphaShort' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ServiceState#getOperatorNumeric():
+    Method 'getOperatorNumeric' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SignalStrengthUpdateRequest.Builder#setSystemThresholdReportingRequestedWhileIdle(boolean):
+    Method 'setSystemThresholdReportingRequestedWhileIdle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#disableCellBroadcastRange(int, int, int):
+    Method 'disableCellBroadcastRange' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#enableCellBroadcastRange(int, int, int):
+    Method 'enableCellBroadcastRange' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#getSmscAddress():
+    Method 'getSmscAddress' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#injectSmsPdu(byte[], String, android.app.PendingIntent):
+    Method 'injectSmsPdu' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendDataMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>):
+    Method 'sendMultipartTextMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>):
+    Method 'sendMultipartTextMessageWithoutPersisting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendTextMessage' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent):
+    Method 'sendTextMessageWithoutPersisting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SmsManager#setSmscAddress(String):
+    Method 'setSmscAddress' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#addSubscriptionsIntoGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    Method 'addSubscriptionsIntoGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#createSubscriptionGroup(java.util.List<java.lang.Integer>):
+    Method 'createSubscriptionGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfo(int):
+    Method 'getActiveSubscriptionInfo' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoForSimSlotIndex(int):
+    Method 'getActiveSubscriptionInfoForSimSlotIndex' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getActiveSubscriptionInfoList():
+    Method 'getActiveSubscriptionInfoList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList():
+    Method 'getAvailableSubscriptionInfoList' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getCompleteActiveSubscriptionInfoList():
+    Method 'getCompleteActiveSubscriptionInfoList' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getOpportunisticSubscriptions():
+    Method 'getOpportunisticSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getResourcesForSubId(android.content.Context, int):
+    Method 'getResourcesForSubId' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#getSubscriptionsInGroup(android.os.ParcelUuid):
+    Method 'getSubscriptionsInGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#removeSubscriptionsFromGroup(java.util.List<java.lang.Integer>, android.os.ParcelUuid):
+    Method 'removeSubscriptionsFromGroup' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh():
+    Method 'requestEmbeddedSubscriptionInfoListRefresh' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh(int):
+    Method 'requestEmbeddedSubscriptionInfoListRefresh' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#setOpportunistic(boolean, int):
+    Method 'setOpportunistic' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.SubscriptionManager#setPreferredDataSubscriptionId(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setPreferredDataSubscriptionId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener#onActiveDataSubscriptionIdChanged(int):
+    Method 'onActiveDataSubscriptionIdChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.BarringInfoListener#onBarringInfoChanged(android.telephony.BarringInfo):
+    Method 'onBarringInfoChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallAttributesListener#onCallAttributesChanged(android.telephony.CallAttributes):
+    Method 'onCallAttributesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallAttributesListener#onCallStatesChanged(java.util.List<android.telephony.CallState>):
+    Method 'onCallStatesChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.CallForwardingIndicatorListener#onCallForwardingIndicatorChanged(boolean):
+    Method 'onCallForwardingIndicatorChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.DataEnabledListener#onDataEnabledChanged(boolean, int):
+    Method 'onDataEnabledChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.EmergencyNumberListListener#onEmergencyNumberListChanged(java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>):
+    Method 'onEmergencyNumberListChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ImsCallDisconnectCauseListener#onImsCallDisconnectCauseChanged(android.telephony.ims.ImsReasonInfo):
+    Method 'onImsCallDisconnectCauseChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.MessageWaitingIndicatorListener#onMessageWaitingIndicatorChanged(boolean):
+    Method 'onMessageWaitingIndicatorChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PhysicalChannelConfigListener#onPhysicalChannelConfigChanged(java.util.List<android.telephony.PhysicalChannelConfig>):
+    Method 'onPhysicalChannelConfigChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PreciseCallStateListener#onPreciseCallStateChanged(android.telephony.PreciseCallState):
+    Method 'onPreciseCallStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.PreciseDataConnectionStateListener#onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState):
+    Method 'onPreciseDataConnectionStateChanged' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.RegistrationFailedListener#onRegistrationFailed(android.telephony.CellIdentity, String, int, int, int):
+    Method 'onRegistrationFailed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyCallback.ServiceStateListener#onServiceStateChanged(android.telephony.ServiceState):
+    Method 'onServiceStateChanged' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#bootstrapAuthenticationRequest(int, android.net.Uri, android.telephony.gba.UaSecurityProtocolIdentifier, boolean, java.util.concurrent.Executor, android.telephony.TelephonyManager.BootstrapAuthenticationCallback):
+    Method 'bootstrapAuthenticationRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#changeIccLockPin(String, String):
+    Method 'changeIccLockPin' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#clearRadioPowerOffForReason(int):
+    Method 'clearRadioPowerOffForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#clearSignalStrengthUpdateRequest(android.telephony.SignalStrengthUpdateRequest):
+    Method 'clearSignalStrengthUpdateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#doesSwitchMultiSimConfigTriggerReboot():
+    Method 'doesSwitchMultiSimConfigTriggerReboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#enableModemForSlot(int, boolean):
+    Method 'enableModemForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAidForAppType(int):
+    Method 'getAidForAppType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypes():
+    Method 'getAllowedNetworkTypes' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypesBitmask():
+    Method 'getAllowedNetworkTypesBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getAllowedNetworkTypesForReason(int):
+    Method 'getAllowedNetworkTypesForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCallState():
+    Method 'getCallState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCallStateForSubscription():
+    Method 'getCallStateForSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierConfig():
+    Method 'getCarrierConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierIdListVersion():
+    Method 'getCarrierIdListVersion' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierInfoForImsiEncryption(int):
+    Method 'getCarrierInfoForImsiEncryption' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCarrierRestrictionStatus(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getCarrierRestrictionStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCdmaRoamingMode():
+    Method 'getCdmaRoamingMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getCdmaSubscriptionMode():
+    Method 'getCdmaSubscriptionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDataActivationState():
+    Method 'getDataActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDataNetworkType():
+    Method 'getDataNetworkType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId():
+    Method 'getDeviceId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceId(int):
+    Method 'getDeviceId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getDeviceSoftwareVersion(int):
+    Method 'getDeviceSoftwareVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberDbVersion():
+    Method 'getEmergencyNumberDbVersion' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList():
+    Method 'getEmergencyNumberList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEmergencyNumberList(int):
+    Method 'getEmergencyNumberList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getEquivalentHomePlmns():
+    Method 'getEquivalentHomePlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getForbiddenPlmns():
+    Method 'getForbiddenPlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getGroupIdLevel1():
+    Method 'getGroupIdLevel1' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getImei(int):
+    Method 'getImei' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getIsimDomain():
+    Method 'getIsimDomain' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getLine1Number():
+    Method 'getLine1Number' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getManualNetworkSelectionPlmn():
+    Method 'getManualNetworkSelectionPlmn' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getMeid():
+    Method 'getMeid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getMeid(int):
+    Method 'getMeid' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNai():
+    Method 'getNai' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNetworkSelectionMode():
+    Method 'getNetworkSelectionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getNetworkSlicingConfiguration(java.util.concurrent.Executor, android.os.OutcomeReceiver<android.telephony.data.NetworkSlicingConfig,android.telephony.TelephonyManager.NetworkSlicingException>):
+    Method 'getNetworkSlicingConfiguration' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPhoneAccountHandle():
+    Method 'getPhoneAccountHandle' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPreferredNetworkTypeBitmask():
+    Method 'getPreferredNetworkTypeBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getPreferredOpportunisticDataSubscription():
+    Method 'getPreferredOpportunisticDataSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getRadioPowerOffReasons():
+    Method 'getRadioPowerOffReasons' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getRadioPowerState():
+    Method 'getRadioPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getServiceState():
+    Method 'getServiceState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getServiceState(int):
+    Method 'getServiceState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSimLocale():
+    Method 'getSimLocale' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSimSerialNumber():
+    Method 'getSimSerialNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSubscriberId():
+    Method 'getSubscriberId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSupportedRadioAccessFamily():
+    Method 'getSupportedRadioAccessFamily' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getSystemSelectionChannels():
+    Method 'getSystemSelectionChannels' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getTelephonyHistograms():
+    Method 'getTelephonyHistograms' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVisualVoicemailPackageName():
+    Method 'getVisualVoicemailPackageName' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceActivationState():
+    Method 'getVoiceActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailAlphaTag():
+    Method 'getVoiceMailAlphaTag' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceMailNumber():
+    Method 'getVoiceMailNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#getVoiceNetworkType():
+    Method 'getVoiceNetworkType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccCloseLogicalChannel(int):
+    Method 'iccCloseLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccCloseLogicalChannelBySlot(int, int):
+    Method 'iccCloseLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccExchangeSimIO(int, int, int, int, int, String):
+    Method 'iccExchangeSimIO' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String):
+    Method 'iccOpenLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannel(String, int):
+    Method 'iccOpenLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccOpenLogicalChannelBySlot(int, String, int):
+    Method 'iccOpenLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduBasicChannel(int, int, int, int, int, String):
+    Method 'iccTransmitApduBasicChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduBasicChannelBySlot(int, int, int, int, int, int, String):
+    Method 'iccTransmitApduBasicChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduLogicalChannel(int, int, int, int, int, int, String):
+    Method 'iccTransmitApduLogicalChannel' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#iccTransmitApduLogicalChannelBySlot(int, int, int, int, int, int, int, String):
+    Method 'iccTransmitApduLogicalChannelBySlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isApplicationOnUicc(int):
+    Method 'isApplicationOnUicc' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabled():
+    Method 'isDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataEnabledForReason(int):
+    Method 'isDataEnabledForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDataRoamingEnabled():
+    Method 'isDataRoamingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isDomainSelectionSupported():
+    Method 'isDomainSelectionSupported' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isEmergencyAssistanceEnabled():
+    Method 'isEmergencyAssistanceEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isIccLockEnabled():
+    Method 'isIccLockEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isManualNetworkSelectionAllowed():
+    Method 'isManualNetworkSelectionAllowed' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isModemEnabledForSlot(int):
+    Method 'isModemEnabledForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isMultiSimSupported():
+    Method 'isMultiSimSupported' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isOpportunisticNetworkEnabled():
+    Method 'isOpportunisticNetworkEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isPotentialEmergencyNumber(String):
+    Method 'isPotentialEmergencyNumber' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isPremiumCapabilityAvailableForPurchase(int):
+    Method 'isPremiumCapabilityAvailableForPurchase' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#isTetheringApnRequired():
+    Method 'isTetheringApnRequired' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#notifyOtaEmergencyNumberDbInstalled():
+    Method 'notifyOtaEmergencyNumberDbInstalled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#prepareForUnattendedReboot():
+    Method 'prepareForUnattendedReboot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#purchasePremiumCapability(int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'purchasePremiumCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#rebootModem():
+    Method 'rebootModem' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#rebootRadio():
+    Method 'rebootRadio' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#reportDefaultNetworkStatus(boolean):
+    Method 'reportDefaultNetworkStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    Method 'requestNetworkScan' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNetworkScan(int, android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback):
+    Method 'requestNetworkScan' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestNumberVerification(android.telephony.PhoneNumberRange, long, java.util.concurrent.Executor, android.telephony.NumberVerificationCallback):
+    Method 'requestNumberVerification' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#requestRadioPowerOffForReason(int):
+    Method 'requestRadioPowerOffForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetAllCarrierActions():
+    Method 'resetAllCarrierActions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetCarrierKeysForImsiEncryption():
+    Method 'resetCarrierKeysForImsiEncryption' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetOtaEmergencyNumberDbFilePath():
+    Method 'resetOtaEmergencyNumberDbFilePath' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#resetRadioConfig():
+    Method 'resetRadioConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendEnvelopeWithStatus(String):
+    Method 'sendEnvelopeWithStatus' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendThermalMitigationRequest(android.telephony.ThermalMitigationRequest):
+    Method 'sendThermalMitigationRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler):
+    Method 'sendUssdRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#sendVisualVoicemailSms(String, int, String, android.app.PendingIntent):
+    Method 'sendVisualVoicemailSms' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>):
+    Method 'setAllowedCarriers' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setAllowedNetworkTypesForReason(int, long):
+    Method 'setAllowedNetworkTypesForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCarrierDataEnabled(boolean):
+    Method 'setCarrierDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCarrierRestrictionRules(android.telephony.CarrierRestrictionRules):
+    Method 'setCarrierRestrictionRules' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String):
+    Method 'setCarrierTestOverride' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String):
+    Method 'setCarrierTestOverride' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCdmaRoamingMode(int):
+    Method 'setCdmaRoamingMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setCdmaSubscriptionMode(int):
+    Method 'setCdmaSubscriptionMode' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataActivationState(int):
+    Method 'setDataActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabled(boolean):
+    Method 'setDataEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataEnabledForReason(int, boolean):
+    Method 'setDataEnabledForReason' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setDataRoamingEnabled(boolean):
+    Method 'setDataRoamingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setForbiddenPlmns(java.util.List<java.lang.String>):
+    Method 'setForbiddenPlmns' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setIccLockEnabled(boolean, String):
+    Method 'setIccLockEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeAutomatic():
+    Method 'setNetworkSelectionModeAutomatic' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean):
+    Method 'setNetworkSelectionModeManual' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setNetworkSelectionModeManual(String, boolean, int):
+    Method 'setNetworkSelectionModeManual' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setOpportunisticNetworkState(boolean):
+    Method 'setOpportunisticNetworkState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setPreferredNetworkTypeBitmask(long):
+    Method 'setPreferredNetworkTypeBitmask' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setPreferredOpportunisticDataSubscription(int, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setPreferredOpportunisticDataSubscription' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setRadioEnabled(boolean):
+    Method 'setRadioEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSignalStrengthUpdateRequest(android.telephony.SignalStrengthUpdateRequest):
+    Method 'setSignalStrengthUpdateRequest' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerState(int):
+    Method 'setSimPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerState(int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setSimPowerState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerStateForSlot(int, int):
+    Method 'setSimPowerStateForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setSimPowerStateForSlot(int, int, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'setSimPowerStateForSlot' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoiceActivationState(int):
+    Method 'setVoiceActivationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri):
+    Method 'setVoicemailRingtoneUri' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean):
+    Method 'setVoicemailVibrationEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#supplyIccLockPin(String):
+    Method 'supplyIccLockPin' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#supplyIccLockPuk(String, String):
+    Method 'supplyIccLockPuk' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#switchMultiSimConfig(int):
+    Method 'switchMultiSimConfig' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'updateAvailableNetworks' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.TelephonyManager#updateOtaEmergencyNumberDbFilePath(android.os.ParcelFileDescriptor):
+    Method 'updateOtaEmergencyNumberDbFilePath' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.VisualVoicemailService#sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent):
+    Method 'sendVisualVoicemailSms' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.VisualVoicemailService#setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings):
+    Method 'setSmsFilterSettings' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#continueOperation(android.content.Intent, android.os.Bundle):
+    Method 'continueOperation' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#deleteSubscription(int, android.app.PendingIntent):
+    Method 'deleteSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#downloadSubscription(android.telephony.euicc.DownloadableSubscription, boolean, android.app.PendingIntent):
+    Method 'downloadSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#eraseSubscriptions(android.app.PendingIntent):
+    Method 'eraseSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#eraseSubscriptions(int, android.app.PendingIntent):
+    Method 'eraseSubscriptions' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getDefaultDownloadableSubscriptionList(android.app.PendingIntent):
+    Method 'getDefaultDownloadableSubscriptionList' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent):
+    Method 'getDownloadableSubscriptionMetadata' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getOtaStatus():
+    Method 'getOtaStatus' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getSupportedCountries():
+    Method 'getSupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#getUnsupportedCountries():
+    Method 'getUnsupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#setSupportedCountries(java.util.List<java.lang.String>):
+    Method 'setSupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#setUnsupportedCountries(java.util.List<java.lang.String>):
+    Method 'setUnsupportedCountries' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, android.app.PendingIntent):
+    Method 'switchToSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#switchToSubscription(int, int, android.app.PendingIntent):
+    Method 'switchToSubscription' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.euicc.EuiccManager#updateSubscriptionNickname(int, String, android.app.PendingIntent):
+    Method 'updateSubscriptionNickname' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#createForSubscriptionId(int):
+    Method 'createForSubscriptionId' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#getRegistrationTransportType(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationTransportType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#getVoWiFiModeSetting():
+    Method 'getVoWiFiModeSetting' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isAdvancedCallingSettingEnabled():
+    Method 'isAdvancedCallingSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isCrossSimCallingEnabled():
+    Method 'isCrossSimCallingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isTtyOverVolteEnabled():
+    Method 'isTtyOverVolteEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVoWiFiRoamingSettingEnabled():
+    Method 'isVoWiFiRoamingSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVoWiFiSettingEnabled():
+    Method 'isVoWiFiSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#isVtSettingEnabled():
+    Method 'isVtSettingEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerImsRegistrationCallback(java.util.concurrent.Executor, android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'registerImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerImsStateCallback(java.util.concurrent.Executor, android.telephony.ims.ImsStateCallback):
+    Method 'registerImsStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#registerMmTelCapabilityCallback(java.util.concurrent.Executor, android.telephony.ims.ImsMmTelManager.CapabilityCallback):
+    Method 'registerMmTelCapabilityCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#unregisterImsRegistrationCallback(android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'unregisterImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsMmTelManager#unregisterMmTelCapabilityCallback(android.telephony.ims.ImsMmTelManager.CapabilityCallback):
+    Method 'unregisterMmTelCapabilityCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#getRegistrationState(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationState' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#getRegistrationTransportType(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>):
+    Method 'getRegistrationTransportType' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#registerImsRegistrationCallback(java.util.concurrent.Executor, android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'registerImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#registerImsStateCallback(java.util.concurrent.Executor, android.telephony.ims.ImsStateCallback):
+    Method 'registerImsStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ImsRcsManager#unregisterImsRegistrationCallback(android.telephony.ims.RegistrationManager.RegistrationCallback):
+    Method 'unregisterImsRegistrationCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#getProvisioningStatusForCapability(int, int):
+    Method 'getProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#getRcsProvisioningStatusForCapability(int, int):
+    Method 'getRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isProvisioningRequiredForCapability(int, int):
+    Method 'isProvisioningRequiredForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isRcsProvisioningRequiredForCapability(int, int):
+    Method 'isRcsProvisioningRequiredForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable():
+    Method 'isRcsVolteSingleRegistrationCapable' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#notifyRcsAutoConfigurationReceived(byte[], boolean):
+    Method 'notifyRcsAutoConfigurationReceived' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerFeatureProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback):
+    Method 'registerFeatureProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerProvisioningChangedCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.Callback):
+    Method 'registerProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback(java.util.concurrent.Executor, android.telephony.ims.ProvisioningManager.RcsProvisioningCallback):
+    Method 'registerRcsProvisioningCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setProvisioningStatusForCapability(int, int, boolean):
+    Method 'setProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setRcsProvisioningStatusForCapability(int, boolean):
+    Method 'setRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#setRcsProvisioningStatusForCapability(int, int, boolean):
+    Method 'setRcsProvisioningStatusForCapability' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#unregisterProvisioningChangedCallback(android.telephony.ims.ProvisioningManager.Callback):
+    Method 'unregisterProvisioningChangedCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback(android.telephony.ims.ProvisioningManager.RcsProvisioningCallback):
+    Method 'unregisterRcsProvisioningCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.SipDelegateManager#registerSipDialogStateCallback(java.util.concurrent.Executor, android.telephony.ims.SipDialogStateCallback):
+    Method 'registerSipDialogStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.telephony.ims.SipDelegateManager#unregisterSipDialogStateCallback(android.telephony.ims.SipDialogStateCallback):
+    Method 'unregisterSipDialogStateCallback' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.WindowManager.LayoutParams#isSystemApplicationOverlay():
+    Method 'isSystemApplicationOverlay' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.view.accessibility.AccessibilityManager#registerDisplayProxy(android.view.accessibility.AccessibilityDisplayProxy):
+    Method 'registerDisplayProxy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.AccessibilityManager#unregisterDisplayProxy(android.view.accessibility.AccessibilityDisplayProxy):
+    Method 'unregisterDisplayProxy' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.CaptioningManager#setSystemAudioCaptioningEnabled(boolean):
+    Method 'setSystemAudioCaptioningEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.accessibility.CaptioningManager#setSystemAudioCaptioningUiEnabled(boolean):
+    Method 'setSystemAudioCaptioningUiEnabled' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.inputmethod.InputMethodManager#getEnabledInputMethodListAsUser(android.os.UserHandle):
+    Method 'getEnabledInputMethodListAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.inputmethod.InputMethodManager#getEnabledInputMethodSubtypeListAsUser(String, boolean, android.os.UserHandle):
+    Method 'getEnabledInputMethodSubtypeListAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.inputmethod.InputMethodManager#getInputMethodListAsUser(int):
+    Method 'getInputMethodListAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.inputmethod.InputMethodManager#isStylusHandwritingAvailableAsUser(android.os.UserHandle):
+    Method 'isStylusHandwritingAvailableAsUser' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.view.inputmethod.InputMethodManager#setCurrentInputMethodSubtype(android.view.inputmethod.InputMethodSubtype):
+    Method 'setCurrentInputMethodSubtype' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.webkit.WebSettings#setBlockNetworkLoads(boolean):
+    Method 'setBlockNetworkLoads' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.webkit.WebSettings#setGeolocationEnabled(boolean):
+    Method 'setGeolocationEnabled' documentation mentions permissions without declaring @RequiresPermission
+RequiresPermission: android.window.WindowOrganizer#applySyncTransaction(android.window.WindowContainerTransaction, android.window.WindowContainerTransactionCallback):
+    Method 'applySyncTransaction' documentation mentions permissions already declared by @RequiresPermission
+RequiresPermission: android.window.WindowOrganizer#applyTransaction(android.window.WindowContainerTransaction):
+    Method 'applyTransaction' documentation mentions permissions already declared by @RequiresPermission
+
+
 SamShouldBeLast: android.animation.ValueAnimator#ofObject(android.animation.TypeEvaluator, java.lang.Object...):
     SAM-compatible parameters (such as parameter 1, "evaluator", in android.animation.ValueAnimator.ofObject) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.Activity#convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions):
@@ -109,6 +1865,84 @@
     SAM-compatible parameters (such as parameter 1, "pw", in android.view.inputmethod.InputMethodInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 
 
+SdkConstant: android.content.Intent#ACTION_BATTERY_LEVEL_CHANGED:
+    Field 'ACTION_BATTERY_LEVEL_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_DEVICE_CUSTOMIZATION_READY:
+    Field 'ACTION_DEVICE_CUSTOMIZATION_READY' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_GLOBAL_BUTTON:
+    Field 'ACTION_GLOBAL_BUTTON' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_PRE_BOOT_COMPLETED:
+    Field 'ACTION_PRE_BOOT_COMPLETED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.Intent#ACTION_UNARCHIVE_PACKAGE:
+    Field 'ACTION_UNARCHIVE_PACKAGE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.content.pm.PackageInstaller#ACTION_CONFIRM_PRE_APPROVAL:
+    Field 'ACTION_CONFIRM_PRE_APPROVAL' is missing @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_PORT_CHANGED:
+    Field 'ACTION_USB_PORT_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_PORT_COMPLIANCE_CHANGED:
+    Field 'ACTION_USB_PORT_COMPLIANCE_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.hardware.usb.UsbManager#ACTION_USB_STATE:
+    Field 'ACTION_USB_STATE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.nfc.NfcAdapter#ACTION_REQUIRE_UNLOCK_FOR_NFC:
+    Field 'ACTION_REQUIRE_UNLOCK_FOR_NFC' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_DELETE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_DELETE_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_RENAME_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_RENAME_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.service.euicc.EuiccService#ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED:
+    Field 'ACTION_TOGGLE_SUBSCRIPTION_PRIVILEGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED:
+    Field 'ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE:
+    Field 'ACTION_REQUEST_OMADM_CONFIGURATION_UPDATE' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+SdkConstant: android.telephony.TelephonyManager#ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS:
+    Field 'ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS' is missing @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+
+
+Todo: android.Manifest.permission#DOMAIN_VERIFICATION_AGENT:
+    Documentation mentions 'TODO'
+Todo: android.Manifest.permission#INSTALL_EXISTING_PACKAGES:
+    Documentation mentions 'TODO'
+Todo: android.Manifest.permission#READ_PEOPLE_DATA:
+    Documentation mentions 'TODO'
+Todo: android.app.NotificationManager#isNotificationAssistantAccessGranted(android.content.ComponentName):
+    Documentation mentions 'TODO'
+Todo: android.hardware.camera2.params.StreamConfigurationMap:
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#getNanoAppInstanceInfo(int):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#loadNanoApp(int, android.hardware.location.NanoApp):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.ContextHubManager#unloadNanoApp(int):
+    Documentation mentions 'TODO'
+Todo: android.hardware.location.NanoAppInstanceInfo:
+    Documentation mentions 'TODO'
+Todo: android.media.tv.TvContentRatingSystemInfo#getXmlUri():
+    Documentation mentions 'TODO'
+Todo: android.media.tv.TvInputInfo#isConnectedToHdmiSwitch():
+    Documentation mentions 'TODO'
+Todo: android.os.RecoverySystem#prepareForUnattendedUpdate(android.content.Context, String, android.content.IntentSender):
+    Documentation mentions 'TODO'
+Todo: android.os.RecoverySystem#rebootAndApply(android.content.Context, String, String):
+    Documentation mentions 'TODO'
+Todo: android.os.SystemConfigManager:
+    Documentation mentions 'TODO'
+Todo: android.os.UpdateEngineCallback#onStatusUpdate(int, float):
+    Documentation mentions 'TODO'
+Todo: android.provider.ContactsContract.RawContacts#newEntityIterator(android.database.Cursor):
+    Documentation mentions 'TODO'
+Todo: android.service.voice.AlwaysOnHotwordDetector:
+    Documentation mentions 'TODO'
+Todo: android.telephony.TelephonyManager#getCurrentPhoneType():
+    Documentation mentions 'TODO'
+Todo: android.telephony.TelephonyManager#setVoiceServiceStateOverride(boolean):
+    Documentation mentions 'TODO'
+Todo: android.window.WindowContainerTransaction#setActivityWindowingMode(android.window.WindowContainerToken, int):
+    Documentation mentions 'TODO'
+
+
 UnflaggedApi: android.Manifest.permission#MANAGE_REMOTE_AUTH:
     New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_REMOTE_AUTH
 UnflaggedApi: android.Manifest.permission#START_ACTIVITIES_FROM_SDK_SANDBOX:
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index f2c0051..26f1c4b 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -16,7 +16,6 @@
 
 package android.app;
 
-import static android.Manifest.permission.CONTROL_KEYGUARD;
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -413,8 +412,9 @@
     private static final String KEY_LAUNCH_INTO_PIP_PARAMS =
             "android.activity.launchIntoPipParams";
 
-    /** See {@link #setDismissKeyguard()}. */
-    private static final String KEY_DISMISS_KEYGUARD = "android.activity.dismissKeyguard";
+    /** See {@link #setDismissKeyguardIfInsecure()}. */
+    private static final String KEY_DISMISS_KEYGUARD_IF_INSECURE =
+            "android.activity.dismissKeyguardIfInsecure";
 
     private static final String KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE =
             "android.activity.pendingIntentCreatorBackgroundActivityStartMode";
@@ -519,7 +519,7 @@
     private boolean mLaunchedFromBubble;
     private boolean mTransientLaunch;
     private PictureInPictureParams mLaunchIntoPipParams;
-    private boolean mDismissKeyguard;
+    private boolean mDismissKeyguardIfInsecure;
     @BackgroundActivityStartMode
     private int mPendingIntentCreatorBackgroundActivityStartMode =
             MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED;
@@ -1333,7 +1333,7 @@
         mLaunchIntoPipParams = opts.getParcelable(KEY_LAUNCH_INTO_PIP_PARAMS, android.app.PictureInPictureParams.class);
         mIsEligibleForLegacyPermissionPrompt =
                 opts.getBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE);
-        mDismissKeyguard = opts.getBoolean(KEY_DISMISS_KEYGUARD);
+        mDismissKeyguardIfInsecure = opts.getBoolean(KEY_DISMISS_KEYGUARD_IF_INSECURE);
         mPendingIntentCreatorBackgroundActivityStartMode = opts.getInt(
                 KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE,
                 MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED);
@@ -2036,24 +2036,24 @@
     }
 
     /**
-     * Sets whether the keyguard should go away when this activity launches.
+     * Sets whether the insecure keyguard should go away when this activity launches. In case the
+     * keyguard is secure, this option will be ignored.
      *
      * @see Activity#setShowWhenLocked(boolean)
      * @see android.R.attr#showWhenLocked
      * @hide
      */
-    @RequiresPermission(CONTROL_KEYGUARD)
-    public void setDismissKeyguard() {
-        mDismissKeyguard = true;
+    public void setDismissKeyguardIfInsecure() {
+        mDismissKeyguardIfInsecure = true;
     }
 
     /**
-     * @see #setDismissKeyguard()
+     * @see #setDismissKeyguardIfInsecure()
      * @return whether the insecure keyguard should go away when the activity launches.
      * @hide
      */
-    public boolean getDismissKeyguard() {
-        return mDismissKeyguard;
+    public boolean getDismissKeyguardIfInsecure() {
+        return mDismissKeyguardIfInsecure;
     }
 
     /**
@@ -2367,8 +2367,8 @@
             b.putBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE,
                     mIsEligibleForLegacyPermissionPrompt);
         }
-        if (mDismissKeyguard) {
-            b.putBoolean(KEY_DISMISS_KEYGUARD, mDismissKeyguard);
+        if (mDismissKeyguardIfInsecure) {
+            b.putBoolean(KEY_DISMISS_KEYGUARD_IF_INSECURE, mDismissKeyguardIfInsecure);
         }
         if (mPendingIntentCreatorBackgroundActivityStartMode
                 != MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3b6ea14..dfb416a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -56,7 +56,7 @@
 import android.app.backup.BackupAnnotations.OperationType;
 import android.app.compat.CompatChanges;
 import android.app.sdksandbox.sandboxactivity.ActivityContextInfo;
-import android.app.sdksandbox.sandboxactivity.ActivityContextInfoProvider;
+import android.app.sdksandbox.sandboxactivity.SdkSandboxActivityAuthority;
 import android.app.servertransaction.ActivityLifecycleItem;
 import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
 import android.app.servertransaction.ActivityRelaunchItem;
@@ -2272,7 +2272,8 @@
                     case DUMP_HEAP: return "DUMP_HEAP";
                     case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
                     case SET_CORE_SETTINGS: return "SET_CORE_SETTINGS";
-                    case UPDATE_PACKAGE_COMPATIBILITY_INFO: return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
+                    case UPDATE_PACKAGE_COMPATIBILITY_INFO:
+                        return "UPDATE_PACKAGE_COMPATIBILITY_INFO";
                     case DUMP_PROVIDER: return "DUMP_PROVIDER";
                     case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
                     case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS";
@@ -3776,8 +3777,10 @@
                     r.activityInfo.targetActivity);
         }
 
-        boolean isSandboxActivityContext = sandboxActivitySdkBasedContext()
-                && r.intent.isSandboxActivity(mSystemContext);
+        boolean isSandboxActivityContext =
+                sandboxActivitySdkBasedContext()
+                        && SdkSandboxActivityAuthority.isSdkSandboxActivity(
+                                mSystemContext, r.intent);
         boolean isSandboxedSdkContextUsed = false;
         ContextImpl activityBaseContext;
         if (isSandboxActivityContext) {
@@ -4022,11 +4025,12 @@
      */
     @Nullable
     private ContextImpl createBaseContextForSandboxActivity(@NonNull ActivityClientRecord r) {
-        ActivityContextInfoProvider contextInfoProvider = ActivityContextInfoProvider.getInstance();
+        SdkSandboxActivityAuthority sdkSandboxActivityAuthority =
+                SdkSandboxActivityAuthority.getInstance();
 
         ActivityContextInfo contextInfo;
         try {
-            contextInfo = contextInfoProvider.getActivityContextInfo(r.intent);
+            contextInfo = sdkSandboxActivityAuthority.getActivityContextInfo(r.intent);
         } catch (IllegalArgumentException e) {
             Log.e(TAG, "Passed intent does not match an expected sandbox activity", e);
             return null;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 367e92b..ca6d8df 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -2586,6 +2586,16 @@
     }
 
     @Override
+    public boolean isAppArchivable(String packageName) throws NameNotFoundException {
+        try {
+            Objects.requireNonNull(packageName);
+            return mPM.isAppArchivable(packageName, new UserHandle(getUserId()));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     public int getMoveStatus(int moveId) {
         try {
             return mPM.getMoveStatus(moveId);
diff --git a/core/java/android/app/BackgroundStartPrivileges.java b/core/java/android/app/BackgroundStartPrivileges.java
index 76c0ccf..20278ea 100644
--- a/core/java/android/app/BackgroundStartPrivileges.java
+++ b/core/java/android/app/BackgroundStartPrivileges.java
@@ -174,6 +174,15 @@
 
     @Override
     public String toString() {
+        if (this == ALLOW_BAL) {
+            return "BSP.ALLOW_BAL";
+        }
+        if (this == ALLOW_FGS) {
+            return "BSP.ALLOW_FGS";
+        }
+        if (this == NONE) {
+            return "BSP.NONE";
+        }
         return "BackgroundStartPrivileges["
                 + "allowsBackgroundActivityStarts=" + mAllowsBackgroundActivityStarts
                 + ", allowsBackgroundForegroundServiceStarts="
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 2c428ef..1f8784b 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -259,12 +259,10 @@
      * @param taskId the id of the task to retrieve the sAutoapshots for
      * @param isLowResolution if set, if the snapshot needs to be loaded from disk, this will load
      *                          a reduced resolution of it, which is much faster
-     * @param takeSnapshotIfNeeded if set, call {@link #takeTaskSnapshot} to trigger the snapshot
-                                   if no cache exists.
      * @return a graphic buffer representing a screenshot of a task
      */
     android.window.TaskSnapshot getTaskSnapshot(
-            int taskId, boolean isLowResolution, boolean takeSnapshotIfNeeded);
+            int taskId, boolean isLowResolution);
 
     /**
      * Requests for a new snapshot to be taken for the task with the given id, storing it in the
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 10747bb..357ee0a 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -66,6 +66,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -1890,6 +1891,7 @@
     public ActivityResult execStartActivity(
             Context who, IBinder contextThread, IBinder token, Activity target,
             Intent intent, int requestCode, Bundle options) {
+        Objects.requireNonNull(intent);
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         Uri referrer = target != null ? target.onProvideReferrer() : null;
         if (referrer != null) {
@@ -1969,6 +1971,10 @@
     public int execStartActivitiesAsUser(Context who, IBinder contextThread,
             IBinder token, Activity target, Intent[] intents, Bundle options,
             int userId) {
+        Objects.requireNonNull(intents);
+        for (int i = intents.length - 1; i >= 0; i--) {
+            Objects.requireNonNull(intents[i]);
+        }
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (isSdkSandboxAllowedToStartActivities()) {
             for (Intent intent : intents) {
@@ -2022,33 +2028,34 @@
      * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
      * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
      * but for calls from a {@link Fragment}.
-     * 
+     *
      * @param who The Context from which the activity is being started.
      * @param contextThread The main thread of the Context from which the activity
      *                      is being started.
-     * @param token Internal token identifying to the system who is starting 
+     * @param token Internal token identifying to the system who is starting
      *              the activity; may be null.
-     * @param target Which element is performing the start (and thus receiving 
+     * @param target Which element is performing the start (and thus receiving
      *               any result).
      * @param intent The actual Intent to start.
-     * @param requestCode Identifier for this request's result; less than zero 
+     * @param requestCode Identifier for this request's result; less than zero
      *                    if the caller is not expecting a result.
-     * 
-     * @return To force the return of a particular result, return an 
+     *
+     * @return To force the return of a particular result, return an
      *         ActivityResult object containing the desired data; otherwise
      *         return null.  The default implementation always returns null.
-     *  
+     *
      * @throws android.content.ActivityNotFoundException
-     * 
+     *
      * @see Activity#startActivity(Intent)
      * @see Activity#startActivityForResult(Intent, int)
-     * 
+     *
      * {@hide}
      */
     @UnsupportedAppUsage
     public ActivityResult execStartActivity(
         Context who, IBinder contextThread, IBinder token, String target,
         Intent intent, int requestCode, Bundle options) {
+        Objects.requireNonNull(intent);
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (isSdkSandboxAllowedToStartActivities()) {
             adjustIntentForCtsInSdkSandboxInstrumentation(intent);
@@ -2123,6 +2130,7 @@
     public ActivityResult execStartActivity(
             Context who, IBinder contextThread, IBinder token, String resultWho,
             Intent intent, int requestCode, Bundle options, UserHandle user) {
+        Objects.requireNonNull(intent);
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (isSdkSandboxAllowedToStartActivities()) {
             adjustIntentForCtsInSdkSandboxInstrumentation(intent);
@@ -2176,6 +2184,7 @@
             Context who, IBinder contextThread, IBinder token, Activity target,
             Intent intent, int requestCode, Bundle options,
             boolean ignoreTargetSecurity, int userId) {
+        Objects.requireNonNull(intent);
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (isSdkSandboxAllowedToStartActivities()) {
             adjustIntentForCtsInSdkSandboxInstrumentation(intent);
@@ -2230,6 +2239,7 @@
     public void execStartActivityFromAppTask(
             Context who, IBinder contextThread, IAppTask appTask,
             Intent intent, Bundle options) {
+        Objects.requireNonNull(intent);
         IApplicationThread whoThread = (IApplicationThread) contextThread;
         if (isSdkSandboxAllowedToStartActivities()) {
             adjustIntentForCtsInSdkSandboxInstrumentation(intent);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index bbc843b..2d80b1f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -31,6 +31,7 @@
 import android.annotation.DimenRes;
 import android.annotation.Dimension;
 import android.annotation.DrawableRes;
+import android.annotation.FlaggedApi;
 import android.annotation.IdRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -12242,6 +12243,7 @@
      * {@code TvExtender(Notification)} constructor, and then using the {@code get} methods
      * to access values.
      */
+    @FlaggedApi(Flags.FLAG_API_TVEXTENDER)
     public static final class TvExtender implements Extender {
         private static final String TAG = "TvExtender";
 
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7704486..4c70c91 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -49,6 +49,7 @@
 import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
 import static android.Manifest.permission.SET_TIME;
 import static android.Manifest.permission.SET_TIME_ZONE;
+import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
 import static android.content.Intent.LOCAL_FLAG_FROM_SYSTEM;
 import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
 import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
@@ -17047,23 +17048,6 @@
     }
 
     /**
-     * Overrides the effective cached value of enable_keep_profiles_running for testing purposes.
-     *
-     * @hide
-     */
-    @TestApi
-    @RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
-    public void setOverrideKeepProfilesRunning(boolean enabled) {
-        if (mService != null) {
-            try {
-                mService.setOverrideKeepProfilesRunning(enabled);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-    }
-
-    /**
      * Triggers the data migration of device policies for existing DPCs to the Device Policy Engine.
      * If {@code forceMigration} is set to {@code true} it skips the prerequisite checks before
      * triggering the migration.
@@ -17136,4 +17120,14 @@
         }
         return null;
     }
-}
+
+    // TODO(b/308755220): Remove once the build is finalised.
+    /**
+     * Returns true if the flag for the onboarding bugreport V2 is enabled.
+     *
+     * @hide
+     */
+    public boolean isOnboardingBugreportV2FlagEnabled() {
+        return onboardingBugreportV2Enabled();
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 8dd50f0..304359b 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -312,21 +312,11 @@
             int targetUserId);
 
     /**
-     * Returns whether new "turn off work" behavior is enabled via feature flag.
-     */
-    public abstract boolean isKeepProfilesRunningEnabled();
-
-    /**
      * True if either the entire device or the user is organization managed.
      */
     public abstract boolean isUserOrganizationManaged(@UserIdInt int userId);
 
     /**
-     * Returns the list of packages suspended by admin on a given user.
-     */
-    public abstract Set<String> getPackagesSuspendedByAdmin(@UserIdInt int userId);
-
-    /**
      * Returns whether the application exemptions feature flag is enabled.
      */
     public abstract boolean isApplicationExemptionsFlagEnabled();
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 58f9d57..6fe40be 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -603,8 +603,6 @@
 
     DevicePolicyState getDevicePolicyState();
 
-    void setOverrideKeepProfilesRunning(boolean enabled);
-
     boolean triggerDevicePolicyEngineMigration(boolean forceMigration);
 
     boolean isDeviceFinanced(String callerPackageName);
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index cd1d8ce..d9b521f 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -5,4 +5,13 @@
   namespace: "systemui"
   description: "This flag controls new and updated DND apis"
   bug: "300477976"
-}
\ No newline at end of file
+}
+
+flag {
+  name: "api_tvextender"
+  namespace: "systemui"
+  description: "Guards new android.app.Notification.TvExtender api"
+  bug: "308164892"
+  is_fixed_read_only: true
+}
+
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 49543a1..ebd5d64 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -20,10 +20,9 @@
 import android.app.usage.BroadcastResponseStats;
 import android.app.usage.BroadcastResponseStatsList;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageEventsQuery;
 import android.content.pm.ParceledListSlice;
 
-import java.util.Map;
-
 /**
  * System private API for talking with the UsageStatsManagerService.
  *
@@ -42,6 +41,8 @@
     UsageEvents queryEventsForPackage(long beginTime, long endTime, String callingPackage);
     UsageEvents queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage);
     UsageEvents queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage);
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)")
+    UsageEvents queryEventsWithFilter(in UsageEventsQuery query, String callingPackage);
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     void setAppInactive(String packageName, boolean inactive, int userId);
     boolean isAppStandbyEnabled();
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index c188686..1eb452c 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -349,6 +349,47 @@
          */
         public static final int MAX_EVENT_TYPE = 31;
 
+        /**
+         * Keep in sync with the event types defined above.
+         * @hide
+         */
+        @IntDef(flag = false, value = {
+                NONE,
+                ACTIVITY_RESUMED,
+                ACTIVITY_PAUSED,
+                END_OF_DAY,
+                CONTINUE_PREVIOUS_DAY,
+                CONFIGURATION_CHANGE,
+                SYSTEM_INTERACTION,
+                USER_INTERACTION,
+                SHORTCUT_INVOCATION,
+                CHOOSER_ACTION,
+                NOTIFICATION_SEEN,
+                STANDBY_BUCKET_CHANGED,
+                NOTIFICATION_INTERRUPTION,
+                SLICE_PINNED_PRIV,
+                SLICE_PINNED,
+                SCREEN_INTERACTIVE,
+                SCREEN_NON_INTERACTIVE,
+                KEYGUARD_SHOWN,
+                KEYGUARD_HIDDEN,
+                FOREGROUND_SERVICE_START,
+                FOREGROUND_SERVICE_STOP,
+                CONTINUING_FOREGROUND_SERVICE,
+                ROLLOVER_FOREGROUND_SERVICE,
+                ACTIVITY_STOPPED,
+                ACTIVITY_DESTROYED,
+                FLUSH_TO_DISK,
+                DEVICE_SHUTDOWN,
+                DEVICE_STARTUP,
+                USER_UNLOCKED,
+                USER_STOPPED,
+                LOCUS_ID_SET,
+                APP_COMPONENT_USED,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface EventType {}
+
         /** @hide */
         public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0;
 
diff --git a/core/java/android/app/usage/UsageEventsQuery.aidl b/core/java/android/app/usage/UsageEventsQuery.aidl
new file mode 100644
index 0000000..5ed370d
--- /dev/null
+++ b/core/java/android/app/usage/UsageEventsQuery.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.usage;
+
+parcelable UsageEventsQuery;
\ No newline at end of file
diff --git a/core/java/android/app/usage/UsageEventsQuery.java b/core/java/android/app/usage/UsageEventsQuery.java
new file mode 100644
index 0000000..8c63d18
--- /dev/null
+++ b/core/java/android/app/usage/UsageEventsQuery.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.usage;
+
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.app.usage.UsageEvents.Event;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An Object-Oriented representation for a {@link UsageEvents} query.
+ * Used by {@link UsageStatsManager#queryEvents(UsageEventsQuery)} call.
+ */
+@FlaggedApi(Flags.FLAG_FILTER_BASED_EVENT_QUERY_API)
+public final class UsageEventsQuery implements Parcelable {
+    private final @CurrentTimeMillisLong long mBeginTimeMillis;
+    private final @CurrentTimeMillisLong long mEndTimeMillis;
+    private final @Event.EventType int[] mEventTypes;
+
+    private UsageEventsQuery(@NonNull Builder builder) {
+        mBeginTimeMillis = builder.mBeginTimeMillis;
+        mEndTimeMillis = builder.mEndTimeMillis;
+        mEventTypes = ArrayUtils.convertToIntArray(builder.mEventTypes);
+    }
+
+    private UsageEventsQuery(Parcel in) {
+        mBeginTimeMillis = in.readLong();
+        mEndTimeMillis = in.readLong();
+        int eventTypesLength = in.readInt();
+        mEventTypes = new int[eventTypesLength];
+        in.readIntArray(mEventTypes);
+    }
+
+    /**
+     * Returns the inclusive timestamp to indicate the beginning of the range of events.
+     * Defined in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}.
+     */
+    public @CurrentTimeMillisLong long getBeginTimeMillis() {
+        return mBeginTimeMillis;
+    }
+
+    /**
+     * Returns the exclusive timpstamp to indicate the end of the range of events.
+     * Defined in terms of "Unix time", see {@link java.lang.System#currentTimeMillis}.
+     */
+    public @CurrentTimeMillisLong long getEndTimeMillis() {
+        return mEndTimeMillis;
+    }
+
+    /**
+     * Returns the set of usage event types for the query.
+     * <em>Note: An empty set indicates query for all usage events. </em>
+     */
+    public @NonNull Set<Integer> getEventTypes() {
+        if (ArrayUtils.isEmpty(mEventTypes)) {
+            return Collections.emptySet();
+        }
+
+        HashSet<Integer> eventTypeSet = new HashSet<>();
+        for (int eventType : mEventTypes) {
+            eventTypeSet.add(eventType);
+        }
+        return eventTypeSet;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeLong(mBeginTimeMillis);
+        dest.writeLong(mEndTimeMillis);
+        dest.writeInt(mEventTypes.length);
+        dest.writeIntArray(mEventTypes);
+    }
+
+    @NonNull
+    public static final Creator<UsageEventsQuery> CREATOR =
+            new Creator<UsageEventsQuery>() {
+                @Override
+                public UsageEventsQuery createFromParcel(Parcel in) {
+                    return new UsageEventsQuery(in);
+                }
+
+                @Override
+                public UsageEventsQuery[] newArray(int size) {
+                    return new UsageEventsQuery[size];
+                }
+            };
+
+    /** @hide */
+    public int[] getEventTypeFilter() {
+        return Arrays.copyOf(mEventTypes, mEventTypes.length);
+    }
+
+    /**
+     * Builder for UsageEventsQuery.
+     */
+    public static final class Builder {
+        private final @CurrentTimeMillisLong long mBeginTimeMillis;
+        private final @CurrentTimeMillisLong long mEndTimeMillis;
+        private final ArraySet<Integer> mEventTypes = new ArraySet<>();
+
+        /**
+         * Constructor that specifies the period for which to return events.
+         * @param beginTimeMillis Inclusive beginning timestamp, as per
+         *                        {@link java.lang.System#currentTimeMillis()}
+         * @param endTimeMillis Exclusive ending timestamp, as per
+         *                        {@link java.lang.System#currentTimeMillis()}
+         *
+         * @throws IllegalArgumentException if {@code beginTimeMillis} &lt;
+         *                                  {@code endTimeMillis}
+         */
+        public Builder(@CurrentTimeMillisLong long beginTimeMillis,
+                @CurrentTimeMillisLong long endTimeMillis) {
+            if (beginTimeMillis < 0 || endTimeMillis < beginTimeMillis) {
+                throw new IllegalArgumentException("Invalid period");
+            }
+            mBeginTimeMillis = beginTimeMillis;
+            mEndTimeMillis = endTimeMillis;
+        }
+
+        /**
+         * Builds a read-only UsageEventsQuery object.
+         */
+        public @NonNull UsageEventsQuery build() {
+            return new UsageEventsQuery(this);
+        }
+
+        /**
+         * Specifies the list of usage event types to be included in the query.
+         * @param eventTypes List of the usage event types. See {@link UsageEvents.Event}
+         *
+         * @throws llegalArgumentException if the event type is not valid.
+         */
+        public @NonNull Builder addEventTypes(@NonNull @Event.EventType int... eventTypes) {
+            for (int i = 0; i < eventTypes.length; i++) {
+                final int eventType = eventTypes[i];
+                if (eventType < Event.NONE || eventType > Event.MAX_EVENT_TYPE) {
+                    throw new IllegalArgumentException("Invalid usage event type: " + eventType);
+                }
+                mEventTypes.add(eventType);
+            }
+            return this;
+        }
+    }
+}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 2a10ed1..4f1c993 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.annotation.CurrentTimeMillisLong;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -581,6 +582,29 @@
     }
 
     /**
+     * Query for events with specific UsageEventsQuery object.
+     * <em>Note: if the user's device is not in an unlocked state (as defined by
+     * {@link UserManager#isUserUnlocked()}), then {@code null} will be returned.</em>
+     *
+     * @param query The query object used to specify the query parameters.
+     * @return A {@link UsageEvents}.
+     */
+    @FlaggedApi(Flags.FLAG_FILTER_BASED_EVENT_QUERY_API)
+    @NonNull
+    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
+    public UsageEvents queryEvents(@NonNull UsageEventsQuery query) {
+        try {
+            UsageEvents iter = mService.queryEventsWithFilter(query, mContext.getOpPackageName());
+            if (iter != null) {
+                return iter;
+            }
+        } catch (RemoteException e) {
+            // fallthrough and return empty result.
+        }
+        return sEmptyResults;
+    }
+
+    /**
      * Like {@link #queryEvents(long, long)}, but only returns events for the calling package.
      * <em>Note: Starting from {@link android.os.Build.VERSION_CODES#R Android R}, if the user's
      * device is not in an unlocked state (as defined by {@link UserManager#isUserUnlocked()}),
diff --git a/core/java/android/app/usage/flags.aconfig b/core/java/android/app/usage/flags.aconfig
index 0b8e29f..a611255 100644
--- a/core/java/android/app/usage/flags.aconfig
+++ b/core/java/android/app/usage/flags.aconfig
@@ -28,3 +28,10 @@
     description: "Flag for parcelable usage event list"
     bug: "301254110"
 }
+
+flag {
+    name: "filter_based_event_query_api"
+    namespace: "backstage_power"
+    description: " Feature flag to support filter based event query API"
+    bug: "194321117"
+}
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index 0975cbb..97a7aa4 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -169,7 +169,8 @@
      * @see VirtualDeviceManager.VirtualDevice#setDevicePolicy
      * @hide
      */
-    @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY})
+    @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY,
+            POLICY_TYPE_CLIPBOARD})
     @Retention(RetentionPolicy.SOURCE)
     @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
     public @interface DynamicPolicyType {}
@@ -230,6 +231,20 @@
     @FlaggedApi(Flags.FLAG_DYNAMIC_POLICY)
     public static final int POLICY_TYPE_ACTIVITY = 3;
 
+    /**
+     * Tells the clipboard manager whether this device's clipboard should be shared or not.
+     *
+     * <ul>
+     *     <li>{@link #DEVICE_POLICY_DEFAULT}: By default the device's clipboard is its own and is
+     *     not shared with other devices' clipboards, including the clipboard of the default device.
+     *     <li>{@link #DEVICE_POLICY_CUSTOM}: The device's clipboard is shared with the default
+     *     device's clipboard. Any clipboard operation on the virtual device is as if it was done on
+     *     the default device.
+     * </ul>
+     */
+    @FlaggedApi(Flags.FLAG_CROSS_DEVICE_CLIPBOARD)
+    public static final int POLICY_TYPE_CLIPBOARD = 4;
+
     private final int mLockState;
     @NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts;
     @NavigationPolicy
@@ -1086,6 +1101,10 @@
                 }
             }
 
+            if (!Flags.crossDeviceClipboard()) {
+                mDevicePolicies.delete(POLICY_TYPE_CLIPBOARD);
+            }
+
             if ((mAudioPlaybackSessionId != AUDIO_SESSION_ID_GENERATE
                     || mAudioRecordingSessionId != AUDIO_SESSION_ID_GENERATE)
                     && mDevicePolicies.get(POLICY_TYPE_AUDIO, DEVICE_POLICY_DEFAULT)
diff --git a/core/java/android/companion/virtual/flags.aconfig b/core/java/android/companion/virtual/flags.aconfig
index 3cadb7c..cfab9eb 100644
--- a/core/java/android/companion/virtual/flags.aconfig
+++ b/core/java/android/companion/virtual/flags.aconfig
@@ -16,6 +16,13 @@
 }
 
 flag {
+  name: "cross_device_clipboard"
+  namespace: "virtual_devices"
+  description: "Enable cross-device clipboard API"
+  bug: "306622082"
+}
+
+flag {
   name: "vdm_custom_home"
   namespace: "virtual_devices"
   description: "Enable custom home API"
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ea54c91..02e0cf6 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -12587,8 +12587,12 @@
         return (mFlags & FLAG_ACTIVITY_NEW_DOCUMENT) == FLAG_ACTIVITY_NEW_DOCUMENT;
     }
 
-    // TODO(b/299109198): Refactor into the {@link SdkSandboxManagerLocal}
-    /** @hide */
+    /**
+     * @deprecated Use {@link SdkSandboxActivityAuthority#isSdkSandboxActivity} instead.
+     * Once the other API is finalized this method will be removed.
+     * @hide
+     */
+    @Deprecated
     public boolean isSandboxActivity(@NonNull Context context) {
         if (mAction != null && mAction.equals(ACTION_START_SANDBOXED_ACTIVITY)) {
             return true;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 9926415..babfba1 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -838,4 +838,6 @@
     ArchivedPackageParcel getArchivedPackage(in String packageName, int userId);
 
     Bitmap getArchivedAppIcon(String packageName, in UserHandle user);
+
+    boolean isAppArchivable(String packageName, in UserHandle user);
 }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 1114b35..6681e54 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -3832,6 +3832,7 @@
          */
         @SystemApi
         @RequiresPermission(Manifest.permission.READ_INSTALLED_SESSION_PATHS)
+        @FlaggedApi(Flags.FLAG_GET_RESOLVED_APK_PATH)
         public @Nullable String getResolvedBaseApkPath() {
             return resolvedBaseCodePath;
         }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index dea4a12..e2a5747 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1480,6 +1480,7 @@
             INSTALL_ALLOW_DOWNGRADE,
             INSTALL_STAGED,
             INSTALL_REQUEST_UPDATE_OWNERSHIP,
+            INSTALL_IGNORE_DEXOPT_PROFILE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface InstallFlags {}
@@ -1712,6 +1713,18 @@
     public static final int INSTALL_ARCHIVED = 1 << 27;
 
     /**
+     * If set, all dexopt profiles are ignored by dexopt during the installation, including the
+     * profile in the DM file and the profile embedded in the APK file. If an invalid profile is
+     * provided during installation, no warning will be reported by {@code adb install}.
+     *
+     * This option does not affect later dexopt operations (e.g., background dexopt and manual `pm
+     * compile` invocations).
+     *
+     * @hide
+     */
+    public static final int INSTALL_IGNORE_DEXOPT_PROFILE = 1 << 28;
+
+    /**
      * Flag parameter for {@link #installPackage} to force a non-staged update of an APEX. This is
      * a development-only feature and should not be used on end user devices.
      *
@@ -8910,6 +8923,20 @@
     }
 
     /**
+     * Returns true if an app is archivable.
+     *
+     * @throws NameNotFoundException if the given package name is not available to the caller.
+     * @see PackageInstaller#requestArchive(String, IntentSender)
+     *
+     * @hide
+     */
+    @SystemApi
+    @FlaggedApi(android.content.pm.Flags.FLAG_ARCHIVING)
+    public boolean isAppArchivable(@NonNull String packageName) throws NameNotFoundException {
+        throw new UnsupportedOperationException("isAppArchivable not implemented");
+    }
+
+    /**
      * Attempts to clear the user data directory of an application.
      * Since this may take a little while, the result will
      * be posted back to the given observer.  A deletion will fail if the
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index cdda12e..012b6c4 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -273,6 +273,9 @@
      * to the <code>retailDemo</code> value of
      * {@link android.R.attr#protectionLevel}.
      *
+     * @deprecated This flag has been replaced by the retail demo role and is a no-op since Android
+     *             V.
+     *
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index a8fe21e..814eae6 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -60,7 +60,6 @@
 }
 
 flag {
-
     name: "rollback_lifetime"
     namespace: "package_manager_service"
     description: "Feature flag to enable custom rollback lifetime during install."
@@ -74,3 +73,10 @@
     description: "Feature flag to improve install freeze time."
     bug: "307561242"
 }
+
+flag {
+    name: "get_resolved_apk_path"
+    namespace: "package_manager_service"
+    description: "Feature flag to retrieve resolved path of the base APK during an app install."
+    bug: "269728874"
+}
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 943eee4..61d8702 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -18,6 +18,7 @@
 
 import static android.hardware.biometrics.BiometricManager.Authenticators;
 
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
@@ -296,4 +297,15 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({BIOMETRIC_LOCKOUT_NONE, BIOMETRIC_LOCKOUT_TIMED, BIOMETRIC_LOCKOUT_PERMANENT})
     @interface LockoutMode {}
+
+    //
+    // Other miscellaneous constants
+    //
+
+    /**
+     * Returned from {@link BiometricManager#getLastAuthenticationTime(int)} when there has
+     * been no successful authentication for the given authenticator since boot.
+     */
+    @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
+    long BIOMETRIC_NO_AUTHENTICATION = -1;
 }
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 82694ee..90bbca8 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -23,6 +23,8 @@
 
 import static com.android.internal.util.FrameworkStatsLog.AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_BIOMETRIC_MANAGER_CAN_AUTHENTICATE;
 
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -30,6 +32,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.app.KeyguardManager;
 import android.content.Context;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -86,6 +89,17 @@
             BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
 
     /**
+     * Returned from {@link BiometricManager#getLastAuthenticationTime(int)} when no matching
+     * successful authentication has been performed since boot.
+     */
+    @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
+    public static final long BIOMETRIC_NO_AUTHENTICATION =
+            BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
+
+    private static final int GET_LAST_AUTH_TIME_ALLOWED_AUTHENTICATORS =
+            Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG;
+
+    /**
      * @hide
      */
     @IntDef({BIOMETRIC_SUCCESS,
@@ -637,5 +651,58 @@
         }
 
     }
+
+    /**
+     * Gets the last time the user successfully authenticated using one of the given authenticators.
+     * The returned value is time in
+     * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()} (time since
+     * boot, including sleep).
+     * <p>
+     * {@link BiometricManager#BIOMETRIC_NO_AUTHENTICATION} is returned in the case where there
+     * has been no successful authentication using any of the given authenticators since boot.
+     * <p>
+     * Currently, only {@link Authenticators#DEVICE_CREDENTIAL} and
+     * {@link Authenticators#BIOMETRIC_STRONG} are accepted. {@link IllegalArgumentException} will
+     * be thrown if {@code authenticators} contains other authenticator types.
+     * <p>
+     * Note that this may return successful authentication times even if the device is currently
+     * locked. You may use {@link KeyguardManager#isDeviceLocked()} to determine if the device
+     * is unlocked or not. Additionally, this method may return valid times for an authentication
+     * method that is no longer available. For instance, if the user unlocked the device with a
+     * {@link Authenticators#BIOMETRIC_STRONG} authenticator but then deleted that authenticator
+     * (e.g., fingerprint data), this method will still return the time of that unlock for
+     * {@link Authenticators#BIOMETRIC_STRONG} if it is the most recent successful event. The caveat
+     * is that {@link BiometricManager#BIOMETRIC_NO_AUTHENTICATION} will be returned if the device
+     * no longer has a secure lock screen at all, even if there were successful authentications
+     * performed before the lock screen was made insecure.
+     *
+     * @param authenticators bit field consisting of constants defined in {@link Authenticators}.
+     * @return the time of last authentication or
+     * {@link BiometricManager#BIOMETRIC_NO_AUTHENTICATION}
+     * @throws IllegalArgumentException if {@code authenticators} contains values other than
+     * {@link Authenticators#DEVICE_CREDENTIAL} and {@link Authenticators#BIOMETRIC_STRONG} or is
+     * 0.
+     */
+    @RequiresPermission(USE_BIOMETRIC)
+    @ElapsedRealtimeLong
+    @FlaggedApi(Flags.FLAG_LAST_AUTHENTICATION_TIME)
+    public long getLastAuthenticationTime(
+            @BiometricManager.Authenticators.Types int authenticators) {
+        if (authenticators == 0
+                || (GET_LAST_AUTH_TIME_ALLOWED_AUTHENTICATORS & authenticators) != authenticators) {
+            throw new IllegalArgumentException(
+                    "Only BIOMETRIC_STRONG and DEVICE_CREDENTIAL authenticators may be used.");
+        }
+
+        if (mService != null) {
+            try {
+                return mService.getLastAuthenticationTime(UserHandle.myUserId(), authenticators);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        } else {
+            return BIOMETRIC_NO_AUTHENTICATION;
+        }
+    }
 }
 
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 7a43286..97bbfbb 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -21,6 +21,7 @@
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 import static android.hardware.biometrics.BiometricManager.Authenticators;
 import static android.hardware.biometrics.Flags.FLAG_ADD_KEY_AGREEMENT_CRYPTO_OBJECT;
+import static android.hardware.biometrics.Flags.FLAG_GET_OP_ID_CRYPTO_OBJECT;
 
 import android.annotation.CallbackExecutor;
 import android.annotation.FlaggedApi;
@@ -851,6 +852,14 @@
         public @Nullable KeyAgreement getKeyAgreement() {
             return super.getKeyAgreement();
         }
+
+        /**
+         * Get the operation handle associated with this object or 0 if none.
+         */
+        @FlaggedApi(FLAG_GET_OP_ID_CRYPTO_OBJECT)
+        public long getOpId() {
+            return super.getOpId();
+        }
     }
 
     /**
diff --git a/core/java/android/hardware/biometrics/CryptoObject.java b/core/java/android/hardware/biometrics/CryptoObject.java
index 39fbe83..8d3ea3f 100644
--- a/core/java/android/hardware/biometrics/CryptoObject.java
+++ b/core/java/android/hardware/biometrics/CryptoObject.java
@@ -154,7 +154,7 @@
      * @hide
      * @return the opId associated with this object or 0 if none
      */
-    public final long getOpId() {
+    public long getOpId() {
         if (mCrypto == null) {
             return 0;
         } else if (mCrypto instanceof IdentityCredential) {
diff --git a/core/java/android/hardware/biometrics/IAuthService.aidl b/core/java/android/hardware/biometrics/IAuthService.aidl
index c2e5c0b..5bdbe2b5 100644
--- a/core/java/android/hardware/biometrics/IAuthService.aidl
+++ b/core/java/android/hardware/biometrics/IAuthService.aidl
@@ -57,6 +57,9 @@
     // Checks if biometrics can be used.
     int canAuthenticate(String opPackageName, int userId, int authenticators);
 
+    // Gets the time of last authentication for the given user and authenticators.
+    long getLastAuthenticationTime(int userId, int authenticators);
+
     // Checks if any biometrics are enrolled.
     boolean hasEnrolledBiometrics(int userId, String opPackageName);
 
diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl
index 18c8d1b..058f302 100644
--- a/core/java/android/hardware/biometrics/IBiometricService.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricService.aidl
@@ -53,6 +53,10 @@
     @EnforcePermission("USE_BIOMETRIC_INTERNAL")
     int canAuthenticate(String opPackageName, int userId, int callingUserId, int authenticators);
 
+    // Gets the time of last authentication for the given user and authenticators.
+    @EnforcePermission("USE_BIOMETRIC_INTERNAL")
+    long getLastAuthenticationTime(int userId, int authenticators);
+
     // Checks if any biometrics are enrolled.
     @EnforcePermission("USE_BIOMETRIC_INTERNAL")
     boolean hasEnrolledBiometrics(int userId, String opPackageName);
diff --git a/core/java/android/hardware/biometrics/flags.aconfig b/core/java/android/hardware/biometrics/flags.aconfig
index 66429e5..56ec763 100644
--- a/core/java/android/hardware/biometrics/flags.aconfig
+++ b/core/java/android/hardware/biometrics/flags.aconfig
@@ -1,9 +1,23 @@
 package: "android.hardware.biometrics"
 
 flag {
+    name: "last_authentication_time"
+    namespace: "wallet_integration"
+    description: "Feature flag for adding getLastAuthenticationTime API to BiometricManager"
+    bug: "301979982"
+}
+
+flag {
   name: "add_key_agreement_crypto_object"
   namespace: "biometrics"
   description: "Feature flag for adding KeyAgreement api to CryptoObject."
   bug: "282058146"
 }
 
+flag {
+  name: "get_op_id_crypto_object"
+  namespace: "biometrics"
+  description: "Feature flag for adding a get operation id api to CryptoObject."
+  bug: "307601768"
+}
+
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 779a8db..6f11d3a 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -493,7 +493,7 @@
     /**
      * Check whether safe mode is enabled
      *
-     * @see Builder#enableSafeMode(boolean)
+     * @see Builder#setSafeModeEnabled(boolean)
      */
     @FlaggedApi(FLAG_SAFE_MODE_CONFIG)
     public boolean isSafeModeEnabled() {
@@ -815,8 +815,8 @@
          *
          * <p>If a VCN fails to provide connectivity within a system-provided timeout, it will enter
          * safe mode. In safe mode, the VCN Network will be torn down and the system will restore
-         * connectivity by allowing underlying cellular networks to be used as default. At the same
-         * time, VCN will continue to retry until it succeeds.
+         * connectivity by allowing underlying cellular or WiFi networks to be used as default. At
+         * the same time, VCN will continue to retry until it succeeds.
          *
          * <p>When safe mode is disabled and VCN connection fails to provide connectivity, end users
          * might not have connectivity, and may not have access to carrier-owned underlying
@@ -826,7 +826,7 @@
          */
         @FlaggedApi(FLAG_SAFE_MODE_CONFIG)
         @NonNull
-        public Builder enableSafeMode(boolean enabled) {
+        public Builder setSafeModeEnabled(boolean enabled) {
             mIsSafeModeDisabled = !enabled;
             return this;
         }
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index a07735e..8fcff78 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -117,8 +117,6 @@
     private static final String ANGLE_GL_DRIVER_CHOICE_NATIVE = "native";
     private static final String SYSTEM_ANGLE_STRING = "system";
 
-    private static final String PROPERTY_RO_ANGLE_SUPPORTED = "ro.gfx.angle.supported";
-
     private ClassLoader mClassLoader;
     private String mLibrarySearchPaths;
     private String mLibraryPermittedPaths;
@@ -620,8 +618,7 @@
     }
 
     /**
-     * Attempt to set up ANGLE from system, if the apk can be found, pass ANGLE details to
-     * the C++ GraphicsEnv class.
+     * Set up ANGLE from system.
      *
      * @param context - Context of the application.
      * @param bundle - Bundle of the application.
@@ -630,14 +627,8 @@
      *         false: can not set up to use system ANGLE because it doesn't exist.
      */
     private boolean setupAngleFromSystem(Context context, Bundle bundle, String packageName) {
-        final boolean systemAngleSupported = SystemProperties
-                                             .getBoolean(PROPERTY_RO_ANGLE_SUPPORTED, false);
-        if (!systemAngleSupported) {
-            return false;
-        }
-
-        // If we make it to here, system ANGLE will be used.  Call nativeSetAngleInfo() with
-        // the application package name and ANGLE features to use.
+        // System ANGLE always exists, call nativeSetAngleInfo() with the application package
+        // name and ANGLE features to use.
         final String[] features = getAngleEglFeatures(context, bundle);
         nativeSetAngleInfo(SYSTEM_ANGLE_STRING, false, packageName, features);
         return true;
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index a3b836a..d4688f8 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -933,6 +933,12 @@
         rebootWipeUserData(context, shutdown, reason, force, false /* wipeEuicc */);
     }
 
+    /** {@hide} */
+    public static void rebootWipeUserData(Context context, boolean shutdown, String reason,
+            boolean force, boolean wipeEuicc) throws IOException {
+        rebootWipeUserData(context, shutdown, reason, force, wipeEuicc, false /* keepMemtagMode */);
+    }
+
     /**
      * Reboots the device and wipes the user data and cache
      * partitions.  This is sometimes called a "factory reset", which
@@ -948,6 +954,7 @@
      * @param force     whether the {@link UserManager.DISALLOW_FACTORY_RESET} user restriction
      *                  should be ignored
      * @param wipeEuicc whether wipe the euicc data
+     * @param keepMemtagMode whether to tell recovery to keep currently configured memtag mode
      *
      * @throws IOException  if writing the recovery command file
      * fails, or if the reboot itself fails.
@@ -956,7 +963,7 @@
      * @hide
      */
     public static void rebootWipeUserData(Context context, boolean shutdown, String reason,
-            boolean force, boolean wipeEuicc) throws IOException {
+            boolean force, boolean wipeEuicc, boolean keepMemtagMode) throws IOException {
         UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
         if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
             throw new SecurityException("Wiping data is not allowed for this user.");
@@ -996,8 +1003,13 @@
             reasonArg = "--reason=" + sanitizeArg(reason + "," + timeStamp);
         }
 
+        String memtagArg = null;
+        if (keepMemtagMode) {
+            memtagArg = "--keep_memtag_mode";
+        }
+
         final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() ;
-        bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg);
+        bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg, memtagArg);
     }
 
     /**
diff --git a/core/java/android/preference/OWNERS b/core/java/android/preference/OWNERS
index 827134e..b4cb9ec 100644
--- a/core/java/android/preference/OWNERS
+++ b/core/java/android/preference/OWNERS
@@ -1,3 +1,5 @@
 lpf@google.com
 pavlis@google.com
 clarabayarri@google.com
+
+per-file SeekBarVolumizer.java = jmtrivi@google.com
\ No newline at end of file
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 3f40139..cda3e4e 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -407,6 +407,7 @@
                         mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
                                 .getAudioAttributes())
                                 .setFlags(AudioAttributes.FLAG_BYPASS_MUTE)
+                                .addTag("VX_AOSP_SAMPLESOUND")
                                 .build());
                         mRingtone.play();
                     } catch (Throwable e) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index c282c96..c012ff3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5914,6 +5914,7 @@
          *
          * @hide
          */
+        @Readable
         public static final String TOUCHPAD_NATURAL_SCROLLING = "touchpad_natural_scrolling";
 
         /**
@@ -10308,6 +10309,13 @@
         @Readable
         public static final String SHOW_NOTIFICATION_SNOOZE = "show_notification_snooze";
 
+       /**
+         * 1 if it is allowed to remove the primary GAIA account. 0 by default.
+         * @hide
+         */
+        public static final String ALLOW_PRIMARY_GAIA_ACCOUNT_REMOVAL_FOR_TESTS =
+                "allow_primary_gaia_account_removal_for_tests";
+
         /**
          * List of TV inputs that are currently hidden. This is a string
          * containing the IDs of all hidden TV inputs. Each ID is encoded by
@@ -15271,6 +15279,7 @@
          * max_history_files (int)
          * max_history_buffer_kb (int)
          * battery_charged_delay_ms (int)
+         * battery_charging_enforce_level (int)
          * </pre>
          *
          * <p>
@@ -18298,8 +18307,11 @@
 
         /**
          * Delay for sending ACTION_CHARGING after device is plugged in.
-         * This is used as an override for constants defined in BatteryStatsImpl for
-         * ease of experimentation.
+         * This is used as an override for constants defined in BatteryStatsImpl. Its purposes are:
+         * <ol>
+         *     <li>Ease of experimentation</li>
+         *     <li>Customization of different device</li>
+         * </ol>
          *
          * @see com.android.internal.os.BatteryStatsImpl.Constants.KEY_BATTERY_CHARGED_DELAY_MS
          * @hide
@@ -18309,6 +18321,22 @@
                 "battery_charging_state_update_delay";
 
         /**
+         * Threshold battery level to enforce battery state as charging. That means when battery
+         * level is equal to or higher than this threshold, it is always considered charging, even
+         * if battery level lowered.
+         * This is used as an override for constants defined in BatteryStatsImpl. Its purposes are:
+         * <ol>
+         *     <li>Ease of experimentation</li>
+         *     <li>Customization of different device</li>
+         * </ol>
+         *
+         * @hide
+         * @see com.android.internal.os.BatteryStatsImpl.Constants.BATTERY_CHARGING_ENFORCE_LEVEL
+         */
+        public static final String BATTERY_CHARGING_STATE_ENFORCE_LEVEL =
+                "battery_charging_state_enforce_level";
+
+        /**
          * A serialized string of params that will be loaded into a text classifier action model.
          *
          * @hide
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 27ad45d..bcda25a 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -3206,6 +3206,15 @@
         public static final String INFRASTRUCTURE_BITMASK = "infrastructure_bitmask";
 
         /**
+         * Indicating if the APN is used for eSIM bootsrap provisioning. The default value is 0 (Not
+         * used for eSIM bootstrap provisioning).
+         *
+         * <P>Type: INTEGER</P>
+         * @hide
+         */
+        public static final String ESIM_BOOTSTRAP_PROVISIONING = "esim_bootstrap_provisioning";
+
+        /**
          * MVNO type:
          * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
          * <P>Type: TEXT</P>
diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS
index 96c0be7..33a67ae 100644
--- a/core/java/android/security/OWNERS
+++ b/core/java/android/security/OWNERS
@@ -8,3 +8,4 @@
 per-file Confirmation*.java = file:/keystore/OWNERS
 per-file FileIntegrityManager.java = file:platform/system/security:/fsverity/OWNERS
 per-file IFileIntegrityService.aidl = file:platform/system/security:/fsverity/OWNERS
+per-file *.aconfig = victorhsieh@google.com
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 94eca3d..0133bd8 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -29,3 +29,10 @@
     bug: "277916185"
     is_fixed_read_only: true
 }
+
+flag {
+    name: "binary_transparency_sepolicy_hash"
+    namespace: "hardware_backed_security"
+    description: "Collect sepolicy hash from sysfs"
+    bug: "308471499"
+}
diff --git a/core/java/android/service/notification/flags.aconfig b/core/java/android/service/notification/flags.aconfig
index 52d4d47..2a05c84 100644
--- a/core/java/android/service/notification/flags.aconfig
+++ b/core/java/android/service/notification/flags.aconfig
@@ -4,7 +4,7 @@
   name: "ranking_update_ashmem"
   namespace: "systemui"
   description: "This flag controls moving ranking update contents into ashmem"
-  bug: "284297289"
+  bug: "249848655"
 }
 
 flag {
diff --git a/core/java/android/speech/tts/BlockingAudioTrack.java b/core/java/android/speech/tts/BlockingAudioTrack.java
index be5851c..d84cc2c 100644
--- a/core/java/android/speech/tts/BlockingAudioTrack.java
+++ b/core/java/android/speech/tts/BlockingAudioTrack.java
@@ -194,17 +194,22 @@
             audioTrack.play();
         }
 
-        int count = 0;
-        while (count < bytes.length) {
-            // Note that we don't take bufferCopy.mOffset into account because
-            // it is guaranteed to be 0.
-            int written = audioTrack.write(bytes, count, bytes.length);
+        int offset = 0;
+        while (offset < bytes.length) {
+            // Although it requests to write the entire bytes at once, it might fail when the track
+            // got stopped or the thread is interrupted. In that case, it needs to carry on from
+            // last offset.
+            int sizeToWrite = bytes.length - offset;
+            int written = audioTrack.write(bytes, offset, sizeToWrite);
             if (written <= 0) {
+                if (written < 0) {
+                    Log.e(TAG, "An error occurred while writing to audio track: " + written);
+                }
                 break;
             }
-            count += written;
+            offset += written;
         }
-        return count;
+        return offset;
     }
 
     private AudioTrack createStreamingAudioTrack() {
diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig
index 43c38f3..a1885ae 100644
--- a/core/java/android/text/flags/flags.aconfig
+++ b/core/java/android/text/flags/flags.aconfig
@@ -75,3 +75,10 @@
   description: "A feature flag that implements line break word style auto."
   bug: "280005585"
 }
+
+flag {
+  name: "inter_character_justification"
+  namespace: "text"
+  description: "A feature flag that implement inter character justification."
+  bug: "283193133"
+}
diff --git a/core/java/android/view/AttachedSurfaceControl.java b/core/java/android/view/AttachedSurfaceControl.java
index d545751..fd5517d 100644
--- a/core/java/android/view/AttachedSurfaceControl.java
+++ b/core/java/android/view/AttachedSurfaceControl.java
@@ -231,4 +231,19 @@
     default void removeTrustedPresentationCallback(@NonNull SurfaceControl.Transaction t,
             @NonNull Consumer<Boolean> listener) {
     }
+
+    /**
+     * Transfer the currently in progress touch gesture from the host to the requested
+     * {@link SurfaceControlViewHost.SurfacePackage}. This requires that the
+     * SurfaceControlViewHost was created with the current host's inputToken.
+     *
+     * @param surfacePackage The SurfacePackage to transfer the gesture to.
+     * @return Whether the touch stream was transferred.
+     */
+    @FlaggedApi(Flags.FLAG_TRANSFER_GESTURE_TO_EMBEDDED)
+    default boolean transferHostTouchGestureToEmbedded(
+            @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
+        throw new UnsupportedOperationException(
+                "transferHostTouchGestureToEmbedded is unimplemented");
+    }
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 7acf2f8..02e97da 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -357,4 +357,6 @@
     boolean cancelDraw(IWindow window);
 
     boolean transferEmbeddedTouchFocusToHost(IWindow embeddedWindow);
+
+    boolean transferHostTouchGestureToEmbedded(IWindow hostWindow, IBinder transferTouchToken);
 }
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 9d88af9..451a71b 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -2671,7 +2671,7 @@
          *
          * @param minAlpha               The min alpha the {@link SurfaceControl} is required to
          *                               have to be considered inside the threshold.
-         * @param minFractionRendered    The min fraction of the SurfaceControl that was resented
+         * @param minFractionRendered    The min fraction of the SurfaceControl that was presented
          *                               to the user to be considered inside the threshold.
          * @param stabilityRequirementMs The time in milliseconds required for the
          *                               {@link SurfaceControl} to be in the threshold.
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 57b19a8..4056531 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -287,7 +287,8 @@
         }
 
         /**
-         * Returns an input token used which can be used to request focus on the embedded surface.
+         * Returns an input token used which can be used to request focus on the embedded surface
+         * or to transfer touch gesture to the embedded surface.
          *
          * @hide
          */
@@ -526,7 +527,8 @@
     }
 
     /**
-     * Returns an input token used which can be used to request focus on the embedded surface.
+     * Returns an input token used which can be used to request focus on the embedded surface
+     * or to transfer touch gesture to the embedded surface.
      *
      * @hide
      */
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 5b69d7f..0ae14a2 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -43,6 +43,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -51,6 +52,7 @@
 import android.view.accessibility.IAccessibilityEmbeddedConnection;
 import android.window.SurfaceSyncGroup;
 
+import com.android.graphics.hwui.flags.Flags;
 import com.android.internal.view.SurfaceCallbackHelper;
 
 import java.lang.annotation.Retention;
@@ -326,6 +328,8 @@
         }
     };
 
+    private final boolean mRtDrivenClipping = Flags.clipSurfaceviews();
+
     public SurfaceView(Context context) {
         this(context, null);
     }
@@ -572,6 +576,10 @@
     public void setClipBounds(Rect clipBounds) {
         super.setClipBounds(clipBounds);
 
+        if (mRtDrivenClipping && isHardwareAccelerated()) {
+            return;
+        }
+
         if (!mClipSurfaceToBounds || mSurfaceControl == null) {
             return;
         }
@@ -915,15 +923,17 @@
             }
             if (sizeChanged || creating || !isHardwareAccelerated()) {
 
-                // Set a window crop when creating the surface or changing its size to
-                // crop the buffer to the surface size since the buffer producer may
-                // use SCALING_MODE_SCALE and submit a larger size than the surface
-                // size.
-                if (mClipSurfaceToBounds && mClipBounds != null) {
-                    surfaceUpdateTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
-                } else {
-                    surfaceUpdateTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
-                            mSurfaceHeight);
+                if (!mRtDrivenClipping || !isHardwareAccelerated()) {
+                    // Set a window crop when creating the surface or changing its size to
+                    // crop the buffer to the surface size since the buffer producer may
+                    // use SCALING_MODE_SCALE and submit a larger size than the surface
+                    // size.
+                    if (mClipSurfaceToBounds && mClipBounds != null) {
+                        surfaceUpdateTransaction.setWindowCrop(mSurfaceControl, mClipBounds);
+                    } else {
+                        surfaceUpdateTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
+                                mSurfaceHeight);
+                    }
                 }
 
                 surfaceUpdateTransaction.setDesintationFrame(mBlastSurfaceControl, mSurfaceWidth,
@@ -941,7 +951,7 @@
                             mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/);
                 }
                 if (DEBUG_POSITION) {
-                    Log.d(TAG, String.format(
+                    Log.d(TAG, TextUtils.formatSimple(
                             "%d performSurfaceTransaction %s "
                                 + "position = [%d, %d, %d, %d] surfaceSize = %dx%d",
                             System.identityHashCode(this),
@@ -1453,6 +1463,7 @@
     }
 
     private final Rect mRTLastReportedPosition = new Rect();
+    private final Rect mRTLastSetCrop = new Rect();
 
     private class SurfaceViewPositionUpdateListener implements RenderNode.PositionUpdateListener {
         private final int mRtSurfaceWidth;
@@ -1496,6 +1507,45 @@
         }
 
         @Override
+        public void positionChanged(long frameNumber, int left, int top, int right, int bottom,
+                int clipLeft, int clipTop, int clipRight, int clipBottom) {
+            try {
+                if (DEBUG_POSITION) {
+                    Log.d(TAG, String.format(
+                            "%d updateSurfacePosition RenderWorker, frameNr = %d, "
+                                    + "position = [%d, %d, %d, %d] clip = [%d, %d, %d, %d] "
+                                    + "surfaceSize = %dx%d",
+                            System.identityHashCode(SurfaceView.this), frameNumber,
+                            left, top, right, bottom, clipLeft, clipTop, clipRight, clipBottom,
+                            mRtSurfaceWidth, mRtSurfaceHeight));
+                }
+                synchronized (mSurfaceControlLock) {
+                    if (mSurfaceControl == null) return;
+
+                    mRTLastReportedPosition.set(left, top, right, bottom);
+                    onSetSurfacePositionAndScale(mPositionChangedTransaction, mSurfaceControl,
+                            mRTLastReportedPosition.left /*positionLeft*/,
+                            mRTLastReportedPosition.top /*positionTop*/,
+                            mRTLastReportedPosition.width()
+                                    / (float) mRtSurfaceWidth /*postScaleX*/,
+                            mRTLastReportedPosition.height()
+                                    / (float) mRtSurfaceHeight /*postScaleY*/);
+
+                    mRTLastSetCrop.set(clipLeft, clipTop, clipRight, clipBottom);
+                    mPositionChangedTransaction.setCrop(mSurfaceControl, mRTLastSetCrop);
+                    if (mRTLastSetCrop.isEmpty()) {
+                        mPositionChangedTransaction.hide(mSurfaceControl);
+                    } else {
+                        mPositionChangedTransaction.show(mSurfaceControl);
+                    }
+                }
+                applyOrMergeTransaction(mPositionChangedTransaction, frameNumber);
+            } catch (Exception ex) {
+                Log.e(TAG, "Exception from repositionChild", ex);
+            }
+        }
+
+        @Override
         public void applyStretch(long frameNumber, float width, float height,
                 float vecX, float vecY, float maxStretchX, float maxStretchY,
                 float childRelativeLeft, float childRelativeTop, float childRelativeRight,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 5720fc0..287c7b2 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3752,15 +3752,7 @@
                         && !child.isActivityDeniedForAutofillForUnimportantView())
                     || (shouldIncludeAllChildrenViewWithAutofillTypeNotNone(afm)
                         && child.getAutofillType() != AUTOFILL_TYPE_NONE)
-                    || shouldIncludeAllChildrenViews(afm)
-                    || (child instanceof ViewGroup && child.getVisibility() != View.VISIBLE)) {
-                // If the child is a ViewGroup object and its visibility is not visible, include
-                // it as part of the assist structure. The children of these invisible ViewGroup
-                // objects are parsed and included in the assist structure. When the Autofill
-                // Provider determines the visibility of these children, it looks at their
-                // visibility as well as their parent's visibility. Omitting invisible parents
-                // will lead to the Autofill Provider incorrectly assuming that these children
-                // of invisible parents are actually visible.
+                    || shouldIncludeAllChildrenViews(afm)){
                 list.add(child);
             } else if (child instanceof ViewGroup) {
                 ((ViewGroup) child).populateChildrenForAutofill(list, flags);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2422369..1ee303c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -11893,4 +11893,17 @@
         }
         Log.d(mTag, msg);
     }
+
+    @Override
+    public boolean transferHostTouchGestureToEmbedded(
+            @NonNull SurfaceControlViewHost.SurfacePackage surfacePackage) {
+        final IWindowSession realWm = WindowManagerGlobal.getWindowSession();
+        try {
+            return realWm.transferHostTouchGestureToEmbedded(mWindow,
+                    surfacePackage.getInputToken());
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+        return false;
+    }
 }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 4f03ce9..cfec081 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -90,6 +90,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
@@ -5872,7 +5873,7 @@
      *
      * @hide
      */
-    @FlaggedApi("REPLACE_CONTENT_WITH_MIRROR")
+    @SuppressLint("UnflaggedApi") // The API is only used for tests.
     @TestApi
     @RequiresPermission(permission.ACCESS_SURFACE_FLINGER)
     default boolean replaceContentOnDisplayWithMirror(int displayId, @NonNull Window window) {
@@ -5888,7 +5889,7 @@
      *
      * @hide
      */
-    @FlaggedApi("REPLACE_CONTENT_WITH_MIRROR")
+    @SuppressLint("UnflaggedApi") // The API is only used for tests.
     @TestApi
     @RequiresPermission(permission.ACCESS_SURFACE_FLINGER)
     default boolean replaceContentOnDisplayWithSc(int displayId, @NonNull SurfaceControl sc) {
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 7c3b6ae..652fe24 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -656,6 +656,14 @@
         return false;
     }
 
+    @Override
+    public boolean transferHostTouchGestureToEmbedded(IWindow hostWindow,
+            IBinder embeddedInputToken) {
+        Log.e(TAG, "Received request to transferHostTouchGestureToEmbedded on"
+                + " WindowlessWindowManager. We shouldn't get here!");
+        return false;
+    }
+
     void setParentInterface(@Nullable ISurfaceControlViewHostParent parentInterface) {
         IBinder oldInterface = mParentInterface == null ? null : mParentInterface.asBinder();
         IBinder newInterface = parentInterface == null ? null : parentInterface.asBinder();
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 451acbe..260d9a8 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -165,6 +165,13 @@
     public static final int TYPE_PARAMETER_WINDOWLESS = 0x00000100;
 
     /**
+     * Application has set Window_windowSplashScreenBehavior to
+     * SPLASH_SCREEN_BEHAVIOR_ICON_PREFERRED.
+     * @hide
+     */
+    public static final int TYPE_PARAMETER_APP_PREFERS_ICON = 0x00000200;
+
+    /**
      * Application is allowed to use the legacy splash screen
      * @hide
      */
diff --git a/core/java/android/window/flags/window_surfaces.aconfig b/core/java/android/window/flags/window_surfaces.aconfig
index 5ad5c79..68eddff 100644
--- a/core/java/android/window/flags/window_surfaces.aconfig
+++ b/core/java/android/window/flags/window_surfaces.aconfig
@@ -25,3 +25,10 @@
     is_fixed_read_only: true
     bug: "304508760"
 }
+
+flag {
+    namespace: "window_surfaces"
+    name: "transfer_gesture_to_embedded"
+    description: "Enable public API for Window Surfaces"
+    bug: "287076178"
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c75f996..ec302e7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2358,6 +2358,15 @@
     <permission android:name="android.permission.SUSPEND_APPS"
         android:protectionLevel="signature|role" />
 
+    <!-- @SystemApi
+         @hide
+         @FlaggedApi("android.content.pm.quarantined_enabled")
+         Allows an application to quarantine other apps, which will prevent
+         them from running without explicit user action.
+    -->
+    <permission android:name="android.permission.QUARANTINE_APPS"
+        android:protectionLevel="internal|verifier" />
+
     <!-- Allows applications to discover and pair bluetooth devices.
          <p>Protection level: normal
     -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 95f1493..9f99dc9 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -301,7 +301,9 @@
             granted to the system companion device manager service -->
         <flag name="companion" value="0x800000" />
         <!-- Additional flag from base permission type: this permission will be granted to the
-             retail demo app, as defined by the OEM. -->
+             retail demo app, as defined by the OEM.
+             This flag has been replaced by the retail demo role and is a no-op since Android V.
+          -->
         <flag name="retailDemo" value="0x1000000" />
         <!-- Additional flag from base permission type: this permission will be granted to the
              recents app. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ab71b41..862e537 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2213,7 +2213,10 @@
     <bool name="config_single_volume">false</bool>
 
     <!-- Volume policy -->
+    <!-- Strongly consider keeping these 2 values in sync - otherwise vol up/vol down have confusing
+    asymmetric behavior, as in b/279645379 -->
     <bool name="config_volume_down_to_enter_silent">false</bool>
+    <bool name="config_volume_up_to_exit_silent">false</bool>
 
     <!-- The number of volume steps for the notification stream -->
     <integer name="config_audio_notif_vol_steps">7</integer>
@@ -4174,6 +4177,10 @@
     <!-- Inactivity threshold (in milliseconds) used in JobScheduler. JobScheduler will consider
          the device to be "idle" after being inactive for this long. -->
     <integer name="config_jobSchedulerInactivityIdleThreshold">1860000</integer>
+    <!-- Inactivity threshold (in milliseconds) used in JobScheduler. JobScheduler will consider
+         the device to be "idle" after being inactive for this long if the device is on stable
+         power. Stable power is defined as "charging + battery not low". -->
+    <integer name="config_jobSchedulerInactivityIdleThresholdOnStablePower">1860000</integer>
     <!-- The alarm window (in milliseconds) that JobScheduler uses to enter the idle state -->
     <integer name="config_jobSchedulerIdleWindowSlop">300000</integer>
 
@@ -4369,6 +4376,15 @@
          UI is handled by ActivityManagerService -->
     <bool name="config_customUserSwitchUi">false</bool>
 
+    <!-- Flag specifying whether the first account added can be removed or renamed. By default,
+    this ability is enabled. When false, user will not be able to remove the first account. -->
+    <bool name="config_canRemoveFirstAccount">true</bool>
+
+    <!-- Used together with config_canRemoveOrRenameFirstAccount when set to false. By default, this
+    is blank. Check if the first account is of this account type. If it is, then disable
+    remove/rename. -->
+    <string name="config_accountTypeToKeepFirstAccount"></string>
+
     <!-- A array of regex to treat a SMS as VVM SMS if the message body matches.
          Each item represents an entry, which consists of two parts:
          a comma (,) separated list of MCCMNC the regex applies to, followed by a semicolon (;), and
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1aa1fea..e646548 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -328,6 +328,7 @@
   <java-symbol type="integer" name="config_phonenumber_compare_min_match" />
   <java-symbol type="bool" name="config_single_volume" />
   <java-symbol type="bool" name="config_volume_down_to_enter_silent" />
+  <java-symbol type="bool" name="config_volume_up_to_exit_silent" />
   <java-symbol type="bool" name="config_voice_capable" />
   <java-symbol type="bool" name="config_requireCallCapableAccountForHandle" />
   <java-symbol type="bool" name="config_user_notification_of_restrictied_mobile_access" />
@@ -1722,6 +1723,8 @@
   <java-symbol type="bool" name="config_startDreamImmediatelyOnDock" />
   <java-symbol type="bool" name="config_carDockEnablesAccelerometer" />
   <java-symbol type="bool" name="config_customUserSwitchUi" />
+  <java-symbol type="bool" name="config_canRemoveFirstAccount" />
+  <java-symbol type="string" name="config_accountTypeToKeepFirstAccount" />
   <java-symbol type="bool" name="config_deskDockEnablesAccelerometer" />
   <java-symbol type="bool" name="config_disableMenuKeyInLockScreen" />
   <java-symbol type="bool" name="config_enableCarDockHomeLaunch" />
@@ -2879,6 +2882,7 @@
   <java-symbol type="integer" name="config_defaultNightMode" />
 
   <java-symbol type="integer" name="config_jobSchedulerInactivityIdleThreshold" />
+  <java-symbol type="integer" name="config_jobSchedulerInactivityIdleThresholdOnStablePower" />
   <java-symbol type="integer" name="config_jobSchedulerIdleWindowSlop" />
   <java-symbol type="bool" name="config_jobSchedulerRestrictBackgroundUser" />
   <java-symbol type="integer" name="config_jobSchedulerUserGracePeriod" />
diff --git a/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java b/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java
new file mode 100644
index 0000000..839b645
--- /dev/null
+++ b/core/tests/coretests/src/android/app/usage/UsageEventsQueryTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app.usage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.app.usage.UsageEvents.Event;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class UsageEventsQueryTest {
+    @Test
+    public void testQueryDuration() {
+        // Test with negative beginTimeMillis.
+        long beginTimeMillis = -100;
+        long endTimeMillis = 100;
+        try {
+            UsageEventsQuery query = new UsageEventsQuery.Builder(beginTimeMillis, endTimeMillis)
+                    .build();
+            fail("beginTimeMillis should be a non-negative timestamp measured as the number of"
+                    + " milliseconds since 1970-01-01T00:00:00Z.");
+        } catch (IllegalArgumentException e) {
+            // Expected, fall through;
+        }
+
+        // Test with negative endTimeMillis.
+        beginTimeMillis = 1001;
+        endTimeMillis = -1;
+        try {
+            UsageEventsQuery query = new UsageEventsQuery.Builder(beginTimeMillis, endTimeMillis)
+                    .build();
+            fail("endTimeMillis should be a non-negative timestamp measured as the number of"
+                    + " milliseconds since 1970-01-01T00:00:00Z.");
+        } catch (IllegalArgumentException e) {
+            // Expected, fall through;
+        }
+
+        // Test with beginTimeMillis < endTimeMillis;
+        beginTimeMillis = 2001;
+        endTimeMillis = 1000;
+        try {
+            UsageEventsQuery query = new UsageEventsQuery.Builder(beginTimeMillis, endTimeMillis)
+                    .build();
+            fail("beginTimeMillis should be smaller than endTimeMillis");
+        } catch (IllegalArgumentException e) {
+            // Expected, fall through;
+        }
+
+        // Test with beginTimeMillis == endTimeMillis, valid.
+        beginTimeMillis = 1001;
+        endTimeMillis = 1001;
+        try {
+            UsageEventsQuery query = new UsageEventsQuery.Builder(beginTimeMillis, endTimeMillis)
+                    .build();
+            assertEquals(query.getBeginTimeMillis(), query.getEndTimeMillis());
+        } catch (IllegalArgumentException e) {
+            // Not expected for valid duration.
+            fail("Valid duration for beginTimeMillis=" + beginTimeMillis
+                    + ", endTimeMillis=" + endTimeMillis);
+        }
+
+        beginTimeMillis = 2001;
+        endTimeMillis = 3001;
+        try {
+            UsageEventsQuery query = new UsageEventsQuery.Builder(beginTimeMillis, endTimeMillis)
+                    .build();
+            assertEquals(query.getBeginTimeMillis(), 2001);
+            assertEquals(query.getEndTimeMillis(), 3001);
+        } catch (IllegalArgumentException e) {
+            // Not expected for valid duration.
+            fail("Valid duration for beginTimeMillis=" + beginTimeMillis
+                    + ", endTimeMillis=" + endTimeMillis);
+        }
+    }
+
+    @Test
+    public void testQueryEventTypes() {
+        Random rnd = new Random();
+        UsageEventsQuery.Builder queryBuilder = new UsageEventsQuery.Builder(1000, 2000);
+
+        // Test with invalid event type.
+        int eventType = Event.NONE - 1;
+        try {
+            queryBuilder.addEventTypes(eventType);
+            fail("Invalid event type: " + eventType);
+        } catch (IllegalArgumentException e) {
+            // Expected, fall through.
+        }
+
+        eventType = Event.MAX_EVENT_TYPE + 1;
+        try {
+            queryBuilder.addEventTypes(eventType);
+            fail("Invalid event type: " + eventType);
+        } catch (IllegalArgumentException e) {
+            // Expected, fall through.
+        }
+
+        // Test with valid and duplicate event types.
+        eventType = rnd.nextInt(Event.MAX_EVENT_TYPE + 1);
+        try {
+            UsageEventsQuery query = queryBuilder.addEventTypes(eventType, eventType, eventType)
+                    .build();
+            Set<Integer> eventTypeSet = query.getEventTypes();
+            assertEquals(eventTypeSet.size(), 1);
+            int type = eventTypeSet.iterator().next();
+            assertEquals(type, eventType);
+        } catch (IllegalArgumentException e) {
+            fail("Valid event type: " + eventType);
+        }
+    }
+}
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 15d26eb..2732569 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -272,6 +272,17 @@
         void positionChanged(long frameNumber, int left, int top, int right, int bottom);
 
         /**
+         * Called by native by a Rendering Worker thread to update window position; includes
+         * the local rect that represents the clipped area of the RenderNode's bounds.
+         *
+         * @hide
+         */
+        default void positionChanged(long frameNumber, int left, int top, int right, int bottom,
+                int clipLeft, int clipTop, int clipRight, int clipBottom) {
+            positionChanged(frameNumber, left, top, right, bottom);
+        }
+
+        /**
          * Called by JNI
          *
          * @hide */
@@ -287,6 +298,23 @@
         }
 
         /**
+         * Called by JNI
+         *
+         * @hide */
+        static boolean callPositionChanged2(WeakReference<PositionUpdateListener> weakListener,
+                long frameNumber, int left, int top, int right, int bottom,
+                int clipLeft, int clipTop, int clipRight, int clipBottom) {
+            final PositionUpdateListener listener = weakListener.get();
+            if (listener != null) {
+                listener.positionChanged(frameNumber, left, top, right, bottom, clipLeft,
+                        clipTop, clipRight, clipBottom);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        /**
          * Call to apply a stretch effect to any child SurfaceControl layers
          *
          * TODO: Fold this into positionChanged & have HWUI do the ASurfaceControl calls?
@@ -371,6 +399,15 @@
         }
 
         @Override
+        public void positionChanged(long frameNumber, int left, int top, int right, int bottom,
+                int clipLeft, int clipTop, int clipRight, int clipBottom) {
+            for (PositionUpdateListener pul : mListeners) {
+                pul.positionChanged(frameNumber, left, top, right, bottom, clipLeft, clipTop,
+                        clipRight, clipBottom);
+            }
+        }
+
+        @Override
         public void positionLost(long frameNumber) {
             for (PositionUpdateListener pul : mListeners) {
                 pul.positionLost(frameNumber);
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java
index 2d2dd24..b4b3e92 100644
--- a/keystore/java/android/security/Authorization.java
+++ b/keystore/java/android/security/Authorization.java
@@ -18,7 +18,9 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.hardware.biometrics.BiometricConstants;
 import android.hardware.security.keymint.HardwareAuthToken;
+import android.hardware.security.keymint.HardwareAuthenticatorType;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.ServiceSpecificException;
@@ -37,7 +39,10 @@
 
     public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
 
-    private static IKeystoreAuthorization getService() {
+    /**
+     * @return an instance of IKeystoreAuthorization
+     */
+    public static IKeystoreAuthorization getService() {
         return IKeystoreAuthorization.Stub.asInterface(
                     ServiceManager.checkService("android.security.authorization"));
     }
@@ -100,4 +105,24 @@
         }
     }
 
+    /**
+     * Gets the last authentication time of the given user and authenticators.
+     *
+     * @param userId user id
+     * @param authenticatorTypes an array of {@link HardwareAuthenticatorType}.
+     * @return the last authentication time or
+     * {@link BiometricConstants#BIOMETRIC_NO_AUTHENTICATION}.
+     */
+    public static long getLastAuthenticationTime(
+            long userId, @HardwareAuthenticatorType int[] authenticatorTypes) {
+        try {
+            return getService().getLastAuthTime(userId, authenticatorTypes);
+        } catch (RemoteException | NullPointerException e) {
+            Log.w(TAG, "Can not connect to keystore", e);
+            return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
+        } catch (ServiceSpecificException e) {
+            return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
+        }
+    }
+
 }
diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java
index af188a9..464714f 100644
--- a/keystore/java/android/security/GateKeeper.java
+++ b/keystore/java/android/security/GateKeeper.java
@@ -45,8 +45,19 @@
 
     @UnsupportedAppUsage
     public static long getSecureUserId() throws IllegalStateException {
+        return getSecureUserId(UserHandle.myUserId());
+    }
+
+    /**
+     * Return the secure user id for a given user id
+     * @param userId the user id, e.g. 0
+     * @return the secure user id or {@link GateKeeper#INVALID_SECURE_USER_ID} if no such mapping
+     * for the given user id is found.
+     * @throws IllegalStateException if there is an error retrieving the secure user id
+     */
+    public static long getSecureUserId(int userId) throws IllegalStateException {
         try {
-            return getService().getSecureUserId(UserHandle.myUserId());
+            return getService().getSecureUserId(userId);
         } catch (RemoteException e) {
             throw new IllegalStateException(
                     "Failed to obtain secure user ID from gatekeeper", e);
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 1ba41b1..b714035 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -1596,6 +1596,8 @@
          * {@link #getAttestationChallenge()} returns non-null and the spec is used to generate a
          * symmetric (AES or HMAC) key, {@link javax.crypto.KeyGenerator#generateKey()} will throw
          * {@link java.security.InvalidAlgorithmParameterException}.
+         *
+         * <p>The challenge may be up to 128 bytes.
          */
         @NonNull
         public Builder setAttestationChallenge(byte[] attestationChallenge) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
index a663f9f..ed99501 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/WindowExtensionsImpl.java
@@ -20,6 +20,7 @@
 import android.app.ActivityThread;
 import android.app.Application;
 import android.content.Context;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -40,12 +41,17 @@
  */
 public class WindowExtensionsImpl implements WindowExtensions {
 
+    private static final String TAG = "WindowExtensionsImpl";
     private final Object mLock = new Object();
     private volatile DeviceStateManagerFoldingFeatureProducer mFoldingFeatureProducer;
     private volatile WindowLayoutComponentImpl mWindowLayoutComponent;
     private volatile SplitController mSplitController;
     private volatile WindowAreaComponent mWindowAreaComponent;
 
+    public WindowExtensionsImpl() {
+        Log.i(TAG, "Initializing Window Extensions.");
+    }
+
     // TODO(b/241126279) Introduce constants to better version functionality
     @Override
     public int getVendorApiLevel() {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 76f0b67..4973a4d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -156,6 +156,7 @@
 
     public SplitController(@NonNull WindowLayoutComponentImpl windowLayoutComponent,
             @NonNull DeviceStateManagerFoldingFeatureProducer foldingFeatureProducer) {
+        Log.i(TAG, "Initializing Activity Embedding Controller.");
         final MainThreadExecutor executor = new MainThreadExecutor();
         mHandler = executor.mHandler;
         mPresenter = new SplitPresenter(executor, windowLayoutComponent, this);
@@ -208,6 +209,7 @@
     @Override
     public void setEmbeddingRules(@NonNull Set<EmbeddingRule> rules) {
         synchronized (mLock) {
+            Log.i(TAG, "Setting embedding rules. Size: " + rules.size());
             mSplitRules.clear();
             mSplitRules.addAll(rules);
         }
@@ -216,6 +218,7 @@
     @Override
     public boolean pinTopActivityStack(int taskId, @NonNull SplitPinRule splitPinRule) {
         synchronized (mLock) {
+            Log.i(TAG, "Request to pin top activity stack.");
             final TaskContainer task = getTaskContainer(taskId);
             if (task == null) {
                 Log.e(TAG, "Cannot find the task for id: " + taskId);
@@ -272,6 +275,7 @@
     @Override
     public void unpinTopActivityStack(int taskId){
         synchronized (mLock) {
+            Log.i(TAG, "Request to unpin top activity stack.");
             final TaskContainer task = getTaskContainer(taskId);
             if (task == null) {
                 Log.e(TAG, "Cannot find the task to unpin, id: " + taskId);
diff --git a/libs/WindowManager/Shell/res/values-television/config.xml b/libs/WindowManager/Shell/res/values-television/config.xml
index 8d2e28b..464e132 100644
--- a/libs/WindowManager/Shell/res/values-television/config.xml
+++ b/libs/WindowManager/Shell/res/values-television/config.xml
@@ -57,4 +57,9 @@
           - 0 for radial vanish + slide up
           - 1 for fade out -->
     <integer name="starting_window_exit_animation_type">1</integer>
+
+    <!-- Whether this device allows to use the appIcon as a fallback icon for the splash screen
+        window. If false, the splash screen will be a solid color splash screen whenever the
+        app has not provided a windowSplashScreenAnimatedIcon. -->
+    <bool name="config_canUseAppIconForSplashScreen">false</bool>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 7436400..6a6f2b0 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -136,4 +136,9 @@
 
     <!-- Whether DragAndDrop capability is enabled -->
     <bool name="config_enableShellDragDrop">true</bool>
+
+    <!-- Whether this device allows to use the appIcon as a fallback icon for the splash screen
+        window. If false, the splash screen will be a solid color splash screen whenever the
+        app has not provided a windowSplashScreenAnimatedIcon. -->
+    <bool name="config_canUseAppIconForSplashScreen">true</bool>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index c4be384..55a9132 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -476,4 +476,11 @@
     <item type="dimen" format="float" name="splash_icon_enlarge_foreground_threshold">0.44</item>
     <!-- Scaling factor applied to splash icons without provided background i.e. (192 / 160) -->
     <item type="dimen" format="float" name="splash_icon_no_background_scale_factor">1.2</item>
+
+    <!-- The margin between the entering window and the exiting window during cross task back -->
+    <dimen name="cross_task_back_inter_window_margin">14dp</dimen>
+    <!-- The vertical margin that needs to be preserved between the scaled window bounds and the
+    original window bounds (once the surface is scaled enough to do so) -->
+    <dimen name="cross_task_back_vertical_margin">8dp</dimen>
+
 </resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
index 4d87c95..ac75c73 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
@@ -255,8 +255,13 @@
         int offsetLayer = TYPE_LAYER_OFFSET;
         final List<ActivityEmbeddingAnimationAdapter> adapters = new ArrayList<>();
         for (TransitionInfo.Change change : openingChanges) {
+            final Animation animation =
+                    animationProvider.get(info, change, openingWholeScreenBounds);
+            if (animation.getDuration() == 0) {
+                continue;
+            }
             final ActivityEmbeddingAnimationAdapter adapter = createOpenCloseAnimationAdapter(
-                    info, change, animationProvider, openingWholeScreenBounds);
+                    info, change, animation, openingWholeScreenBounds);
             if (isOpening) {
                 adapter.overrideLayer(offsetLayer++);
             }
@@ -275,8 +280,13 @@
                     adapters.add(snapshotAdapter);
                 }
             }
+            final Animation animation =
+                    animationProvider.get(info, change, closingWholeScreenBounds);
+            if (animation.getDuration() == 0) {
+                continue;
+            }
             final ActivityEmbeddingAnimationAdapter adapter = createOpenCloseAnimationAdapter(
-                    info, change, animationProvider, closingWholeScreenBounds);
+                    info, change, animation, closingWholeScreenBounds);
             if (!isOpening) {
                 adapter.overrideLayer(offsetLayer++);
             }
@@ -353,8 +363,7 @@
     @NonNull
     private ActivityEmbeddingAnimationAdapter createOpenCloseAnimationAdapter(
             @NonNull TransitionInfo info, @NonNull TransitionInfo.Change change,
-            @NonNull AnimationProvider animationProvider, @NonNull Rect wholeAnimationBounds) {
-        final Animation animation = animationProvider.get(info, change, wholeAnimationBounds);
+            @NonNull Animation animation, @NonNull Rect wholeAnimationBounds) {
         return new ActivityEmbeddingAnimationAdapter(animation, change, change.getLeash(),
                 wholeAnimationBounds, TransitionUtil.getRootFor(change, info));
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
index cc9c2be..6cd1324 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
@@ -22,6 +22,8 @@
 import static com.android.internal.policy.TransitionAnimation.WALLPAPER_TRANSITION_NONE;
 import static com.android.wm.shell.transition.TransitionAnimationHelper.loadAttributeAnimation;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Rect;
 import android.view.animation.AlphaAnimation;
@@ -34,8 +36,6 @@
 import android.view.animation.TranslateAnimation;
 import android.window.TransitionInfo;
 
-import androidx.annotation.NonNull;
-
 import com.android.internal.policy.TransitionAnimation;
 import com.android.wm.shell.util.TransitionUtil;
 
@@ -201,11 +201,10 @@
     Animation loadOpenAnimation(@NonNull TransitionInfo info,
             @NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) {
         final boolean isEnter = TransitionUtil.isOpeningType(change.getMode());
-        final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
+        final Animation customAnimation = loadCustomAnimation(info, isEnter);
         final Animation animation;
-        if (options != null && options.getType() == ANIM_CUSTOM) {
-            animation = mTransitionAnimation.loadAnimationRes(options.getPackageName(),
-                    isEnter ? options.getEnterResId() : options.getExitResId());
+        if (customAnimation != null) {
+            animation = customAnimation;
         } else if (shouldShowBackdrop(info, change)) {
             animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
                     ? com.android.internal.R.anim.task_fragment_clear_top_open_enter
@@ -229,11 +228,10 @@
     Animation loadCloseAnimation(@NonNull TransitionInfo info,
             @NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) {
         final boolean isEnter = TransitionUtil.isOpeningType(change.getMode());
-        final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
+        final Animation customAnimation = loadCustomAnimation(info, isEnter);
         final Animation animation;
-        if (options != null && options.getType() == ANIM_CUSTOM) {
-            animation = mTransitionAnimation.loadAnimationRes(options.getPackageName(),
-                    isEnter ? options.getEnterResId() : options.getExitResId());
+        if (customAnimation != null) {
+            animation = customAnimation;
         } else if (shouldShowBackdrop(info, change)) {
             animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
                     ? com.android.internal.R.anim.task_fragment_clear_top_close_enter
@@ -259,4 +257,21 @@
                 mTransitionAnimation, false);
         return a != null && a.getShowBackdrop();
     }
+
+    @Nullable
+    private Animation loadCustomAnimation(@NonNull TransitionInfo info, boolean isEnter) {
+        final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
+        if (options == null || options.getType() != ANIM_CUSTOM) {
+            return null;
+        }
+        final Animation anim = mTransitionAnimation.loadAnimationRes(options.getPackageName(),
+                isEnter ? options.getEnterResId() : options.getExitResId());
+        if (anim != null) {
+            return anim;
+        }
+        // The app may be intentional to use an invalid resource as a no-op animation.
+        // ActivityEmbeddingAnimationRunner#createOpenCloseAnimationAdapters will skip the
+        // animation with duration 0. Then it will use prepareForJumpCut for empty adapters.
+        return new AlphaAnimation(1f, 1f);
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
index 2ec9e8b..880579d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/Interpolators.java
@@ -88,6 +88,8 @@
     public static final PathInterpolator DIM_INTERPOLATOR =
             new PathInterpolator(.23f, .87f, .52f, -0.11f);
 
+    public static final Interpolator DECELERATE = new PathInterpolator(0f, 0f, 0.5f, 1f);
+
     // Create the default emphasized interpolator
     private static PathInterpolator createEmphasizedInterpolator() {
         Path path = new Path();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
index fc5ff01..8ec297e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossTaskBackAnimation.java
@@ -18,7 +18,6 @@
 
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.window.BackEvent.EDGE_RIGHT;
 
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_PREDICTIVE_BACK_CROSS_TASK;
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
@@ -37,7 +36,7 @@
 import android.view.IRemoteAnimationRunner;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
-import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.window.BackEvent;
 import android.window.BackMotionEvent;
@@ -46,6 +45,8 @@
 
 import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.Interpolators;
 import com.android.wm.shell.common.annotations.ShellMainThread;
 
 import javax.inject.Inject;
@@ -68,32 +69,18 @@
     private static final int BACKGROUNDCOLOR = 0x43433A;
 
     /**
-     * Minimum scale of the entering window.
+     * Minimum scale of the entering and closing window.
      */
-    private static final float ENTERING_MIN_WINDOW_SCALE = 0.85f;
+    private static final float MIN_WINDOW_SCALE = 0.8f;
 
-    /**
-     * Minimum scale of the closing window.
-     */
-    private static final float CLOSING_MIN_WINDOW_SCALE = 0.75f;
-
-    /**
-     * Minimum color scale of the closing window.
-     */
-    private static final float CLOSING_MIN_WINDOW_COLOR_SCALE = 0.1f;
-
-    /**
-     * The margin between the entering window and the closing window
-     */
-    private static final int WINDOW_MARGIN = 35;
-
-    /** Max window translation in the Y axis. */
-    private static final int WINDOW_MAX_DELTA_Y = 160;
+    /** Duration of post animation after gesture committed. */
+    private static final int POST_ANIMATION_DURATION_MS = 500;
 
     private final Rect mStartTaskRect = new Rect();
     private final float mCornerRadius;
 
     // The closing window properties.
+    private final Rect mClosingStartRect = new Rect();
     private final RectF mClosingCurrentRect = new RectF();
 
     // The entering window properties.
@@ -101,44 +88,32 @@
     private final RectF mEnteringCurrentRect = new RectF();
 
     private final PointF mInitialTouchPos = new PointF();
-    private final Interpolator mInterpolator = new AccelerateDecelerateInterpolator();
-
+    private final Interpolator mPostAnimationInterpolator = Interpolators.EMPHASIZED;
+    private final Interpolator mYMovementInterpolator = Interpolators.DECELERATE;
+    private final Interpolator mProgressInterpolator = new DecelerateInterpolator();
     private final Matrix mTransformMatrix = new Matrix();
 
     private final float[] mTmpFloat9 = new float[9];
-    private final float[] mTmpTranslate = {0, 0, 0};
     private final BackAnimationRunner mBackAnimationRunner;
     private final BackAnimationBackground mBackground;
     private final Context mContext;
     private RemoteAnimationTarget mEnteringTarget;
     private RemoteAnimationTarget mClosingTarget;
-    private SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+    private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
     private boolean mBackInProgress = false;
-    private boolean mIsRightEdge;
-    private float mProgress = 0;
-    private PointF mTouchPos = new PointF();
+    private final PointF mTouchPos = new PointF();
     private IRemoteAnimationFinishedCallback mFinishCallback;
-    private BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
+    private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
+    private float mInterWindowMargin;
+    private float mVerticalMargin;
 
     @Inject
     public CrossTaskBackAnimation(Context context, BackAnimationBackground background) {
-        mContext = context;
         mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
         mBackAnimationRunner = new BackAnimationRunner(
                 new Callback(), new Runner(), context, CUJ_PREDICTIVE_BACK_CROSS_TASK);
         mBackground = background;
-    }
-
-    private static void computeScaleTransformMatrix(float scale, float[] matrix) {
-        matrix[0] = scale;
-        matrix[1] = 0;
-        matrix[2] = 0;
-        matrix[3] = 0;
-        matrix[4] = scale;
-        matrix[5] = 0;
-        matrix[6] = 0;
-        matrix[7] = 0;
-        matrix[8] = scale;
+        mContext = context;
     }
 
     private static float mapRange(float value, float min, float max) {
@@ -146,7 +121,7 @@
     }
 
     private float getInterpolatedProgress(float backProgress) {
-        return 1 - (1 - backProgress) * (1 - backProgress) * (1 - backProgress);
+        return mProgressInterpolator.getInterpolation(backProgress);
     }
 
     private void startBackAnimation() {
@@ -162,6 +137,10 @@
         // Draw background.
         mBackground.ensureBackground(mClosingTarget.windowConfiguration.getBounds(),
                 BACKGROUNDCOLOR, mTransaction);
+        mInterWindowMargin = mContext.getResources()
+                .getDimension(R.dimen.cross_task_back_inter_window_margin);
+        mVerticalMargin = mContext.getResources()
+                .getDimension(R.dimen.cross_task_back_vertical_margin);
     }
 
     private void updateGestureBackProgress(float progress, BackEvent event) {
@@ -169,44 +148,38 @@
             return;
         }
 
-        float touchX = event.getTouchX();
         float touchY = event.getTouchY();
-        float dX = Math.abs(touchX - mInitialTouchPos.x);
 
         // The 'follow width' is the width of the window if it completely matches
         // the gesture displacement.
         final int width = mStartTaskRect.width();
         final int height = mStartTaskRect.height();
 
-        // The 'progress width' is the width of the window if it strictly linearly interpolates
-        // to minimum scale base on progress.
-        float enteringScale = mapRange(progress, 1, ENTERING_MIN_WINDOW_SCALE);
-        float closingScale = mapRange(progress, 1, CLOSING_MIN_WINDOW_SCALE);
-        float closingColorScale = mapRange(progress, 1, CLOSING_MIN_WINDOW_COLOR_SCALE);
+        float scale = mapRange(progress, 1, MIN_WINDOW_SCALE);
+        float scaledWidth = scale * width;
+        float scaledHeight = scale * height;
 
-        // The final width is derived from interpolating between the follow with and progress width
-        // using gesture progress.
-        float enteringWidth = enteringScale * width;
-        float closingWidth = closingScale * width;
-        float enteringHeight = (float) height / width * enteringWidth;
-        float closingHeight = (float) height / width * closingWidth;
-
-        float deltaYRatio = (touchY - mInitialTouchPos.y) / height;
         // Base the window movement in the Y axis on the touch movement in the Y axis.
-        float deltaY = (float) Math.sin(deltaYRatio * Math.PI * 0.5f) * WINDOW_MAX_DELTA_Y;
-        // Move the window along the Y axis.
-        float closingTop = (height - closingHeight) * 0.5f + deltaY;
-        float enteringTop = (height - enteringHeight) * 0.5f + deltaY;
-        // Move the window along the X axis.
-        float right = width - (progress * WINDOW_MARGIN);
-        float left = right - closingWidth;
+        float rawYDelta = touchY - mInitialTouchPos.y;
+        float yDirection = rawYDelta < 0 ? -1 : 1;
+        // limit yDelta interpretation to 1/2 of screen height in either direction
+        float deltaYRatio = Math.min(height / 2f, Math.abs(rawYDelta)) / (height / 2f);
+        float interpolatedYRatio = mYMovementInterpolator.getInterpolation(deltaYRatio);
+        // limit y-shift so surface never passes 8dp screen margin
+        float deltaY = yDirection * interpolatedYRatio * Math.max(0f,
+                (height - scaledHeight) / 2f - mVerticalMargin);
 
-        mClosingCurrentRect.set(left, closingTop, right, closingTop + closingHeight);
-        mEnteringCurrentRect.set(left - enteringWidth - WINDOW_MARGIN, enteringTop,
-                left - WINDOW_MARGIN, enteringTop + enteringHeight);
+        // Move the window along the Y axis.
+        float scaledTop = (height - scaledHeight) * 0.5f + deltaY;
+        // Move the window along the X axis.
+        float right = width - (progress * mVerticalMargin);
+        float left = right - scaledWidth;
+
+        mClosingCurrentRect.set(left, scaledTop, right, scaledTop + scaledHeight);
+        mEnteringCurrentRect.set(left - scaledWidth - mInterWindowMargin, scaledTop,
+                left - mInterWindowMargin, scaledTop + scaledHeight);
 
         applyTransform(mClosingTarget.leash, mClosingCurrentRect, mCornerRadius);
-        applyColorTransform(mClosingTarget.leash, closingColorScale);
         applyTransform(mEnteringTarget.leash, mEnteringCurrentRect, mCornerRadius);
         mTransaction.apply();
 
@@ -214,9 +187,21 @@
     }
 
     private void updatePostCommitClosingAnimation(float progress) {
+        float targetLeft =
+                mStartTaskRect.left + (1 - MIN_WINDOW_SCALE) * mStartTaskRect.width() / 2;
+        float targetTop =
+                mStartTaskRect.top + (1 - MIN_WINDOW_SCALE) * mStartTaskRect.height() / 2;
+        float targetWidth = mStartTaskRect.width() * MIN_WINDOW_SCALE;
+        float targetHeight = mStartTaskRect.height() * MIN_WINDOW_SCALE;
+
+        float left = mapRange(progress, mClosingStartRect.left, targetLeft);
+        float top = mapRange(progress, mClosingStartRect.top, targetTop);
+        float width = mapRange(progress, mClosingStartRect.width(), targetWidth);
+        float height = mapRange(progress, mClosingStartRect.height(), targetHeight);
         mTransaction.setLayer(mClosingTarget.leash, 0);
-        float alpha = mapRange(progress, 1, 0);
-        mTransaction.setAlpha(mClosingTarget.leash, alpha);
+
+        mClosingCurrentRect.set(left, top, left + width, top + height);
+        applyTransform(mClosingTarget.leash, mClosingCurrentRect, mCornerRadius);
     }
 
     private void updatePostCommitEnteringAnimation(float progress) {
@@ -244,14 +229,6 @@
                 .setCornerRadius(leash, cornerRadius);
     }
 
-    private void applyColorTransform(SurfaceControl leash, float colorScale) {
-        if (leash == null) {
-            return;
-        }
-        computeScaleTransformMatrix(colorScale, mTmpFloat9);
-        mTransaction.setColorTransform(leash, mTmpFloat9, mTmpTranslate);
-    }
-
     private void finishAnimation() {
         if (mEnteringTarget != null) {
             mEnteringTarget.leash.release();
@@ -276,7 +253,8 @@
             try {
                 mFinishCallback.onAnimationFinished();
             } catch (RemoteException e) {
-                e.printStackTrace();
+                ProtoLog.e(WM_SHELL_BACK_PREVIEW,
+                        "RemoteException when invoking onAnimationFinished callback");
             }
             mFinishCallback = null;
         }
@@ -285,12 +263,11 @@
     private void onGestureProgress(@NonNull BackEvent backEvent) {
         if (!mBackInProgress) {
             mInitialTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY());
-            mIsRightEdge = backEvent.getSwipeEdge() == EDGE_RIGHT;
             mBackInProgress = true;
         }
-        mProgress = backEvent.getProgress();
+        float progress = backEvent.getProgress();
         mTouchPos.set(backEvent.getTouchX(), backEvent.getTouchY());
-        updateGestureBackProgress(getInterpolatedProgress(mProgress), backEvent);
+        updateGestureBackProgress(getInterpolatedProgress(progress), backEvent);
     }
 
     private void onGestureCommitted() {
@@ -302,9 +279,11 @@
         // We enter phase 2 of the animation, the starting coordinates for phase 2 are the current
         // coordinate of the gesture driven phase.
         mEnteringCurrentRect.round(mEnteringStartRect);
+        mClosingCurrentRect.round(mClosingStartRect);
 
-        ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(300);
-        valueAnimator.setInterpolator(mInterpolator);
+        ValueAnimator valueAnimator =
+                ValueAnimator.ofFloat(1f, 0f).setDuration(POST_ANIMATION_DURATION_MS);
+        valueAnimator.setInterpolator(mPostAnimationInterpolator);
         valueAnimator.addUpdateListener(animation -> {
             float progress = animation.getAnimatedFraction();
             updatePostCommitEnteringAnimation(progress);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
index 84feb03..108aa82 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
@@ -129,9 +129,7 @@
     @JvmStatic
     fun getTaskSnapshot(taskId: Int, isLowResolution: Boolean): TaskSnapshot? {
         return if (taskId <= 0) null else try {
-            ActivityTaskManager.getService().getTaskSnapshot(
-                taskId, isLowResolution, false /* takeSnapshotIfNeeded */
-            )
+            ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution)
         } catch (e: RemoteException) {
             Log.e(TAG, "Failed to get task snapshot, taskId=$taskId", e)
             null
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index ea7b2e9..64294c9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -103,6 +103,7 @@
 import com.android.wm.shell.taskview.TaskViewFactory;
 import com.android.wm.shell.taskview.TaskViewFactoryController;
 import com.android.wm.shell.taskview.TaskViewTransitions;
+import com.android.wm.shell.transition.HomeTransitionObserver;
 import com.android.wm.shell.transition.ShellTransitions;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
@@ -613,14 +614,22 @@
             @ShellMainThread ShellExecutor mainExecutor,
             @ShellMainThread Handler mainHandler,
             @ShellAnimationThread ShellExecutor animExecutor,
-            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
+            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
+            HomeTransitionObserver homeTransitionObserver) {
         if (!context.getResources().getBoolean(R.bool.config_registerShellTransitionsOnInit)) {
             // TODO(b/238217847): Force override shell init if registration is disabled
             shellInit = new ShellInit(mainExecutor);
         }
         return new Transitions(context, shellInit, shellCommandHandler, shellController, organizer,
                 pool, displayController, mainExecutor, mainHandler, animExecutor,
-                rootTaskDisplayAreaOrganizer);
+                rootTaskDisplayAreaOrganizer, homeTransitionObserver);
+    }
+
+    @WMSingleton
+    @Provides
+    static HomeTransitionObserver provideHomeTransitionObserver(Context context,
+            @ShellMainThread ShellExecutor mainExecutor) {
+        return new HomeTransitionObserver(context, mainExecutor);
     }
 
     @WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index a533ca5..47769a8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -78,6 +78,7 @@
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.taskview.TaskViewTransitions;
 import com.android.wm.shell.transition.DefaultMixedHandler;
+import com.android.wm.shell.transition.HomeTransitionObserver;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
 import com.android.wm.shell.unfold.UnfoldAnimationController;
@@ -380,9 +381,10 @@
     static RecentsTransitionHandler provideRecentsTransitionHandler(
             ShellInit shellInit,
             Transitions transitions,
-            Optional<RecentTasksController> recentTasksController) {
+            Optional<RecentTasksController> recentTasksController,
+            HomeTransitionObserver homeTransitionObserver) {
         return new RecentsTransitionHandler(shellInit, transitions,
-                recentTasksController.orElse(null));
+                recentTasksController.orElse(null), homeTransitionObserver);
     }
 
     //
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
index 1898ea7..3b48c67 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/pip/Pip2Module.java
@@ -22,6 +22,8 @@
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.common.pip.PipBoundsAlgorithm;
 import com.android.wm.shell.common.pip.PipBoundsState;
 import com.android.wm.shell.common.pip.PipDisplayLayoutState;
@@ -29,6 +31,7 @@
 import com.android.wm.shell.dagger.WMShellBaseModule;
 import com.android.wm.shell.dagger.WMSingleton;
 import com.android.wm.shell.pip2.phone.PipController;
+import com.android.wm.shell.pip2.phone.PipScheduler;
 import com.android.wm.shell.pip2.phone.PipTransition;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
@@ -52,9 +55,10 @@
             @NonNull Transitions transitions,
             PipBoundsState pipBoundsState,
             PipBoundsAlgorithm pipBoundsAlgorithm,
-            Optional<PipController> pipController) {
+            Optional<PipController> pipController,
+            @NonNull PipScheduler pipScheduler) {
         return new PipTransition(shellInit, shellTaskOrganizer, transitions, pipBoundsState, null,
-                pipBoundsAlgorithm);
+                pipBoundsAlgorithm, pipScheduler);
     }
 
     @WMSingleton
@@ -73,4 +77,12 @@
                     pipDisplayLayoutState));
         }
     }
+
+    @WMSingleton
+    @Provides
+    static PipScheduler providePipScheduler(Context context,
+            PipBoundsState pipBoundsState,
+            @ShellMainThread ShellExecutor mainExecutor) {
+        return new PipScheduler(context, pipBoundsState, mainExecutor);
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index 412a5b5..8e12991 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -343,9 +343,8 @@
             task.taskId
         )
         val wct = WindowContainerTransaction()
-        wct.setWindowingMode(task.token, WINDOWING_MODE_MULTI_WINDOW)
         wct.setBounds(task.token, Rect())
-        wct.setDensityDpi(task.token, getDefaultDensityDpi())
+        addMoveToSplitChanges(wct, task)
         if (Transitions.ENABLE_SHELL_TRANSITIONS) {
             transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */)
         } else {
@@ -827,7 +826,9 @@
         wct: WindowContainerTransaction,
         taskInfo: RunningTaskInfo
     ) {
-        wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_MULTI_WINDOW)
+        // Explicitly setting multi-window at task level interferes with animations.
+        // Let task inherit windowing mode once transition is complete instead.
+        wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED)
         // The task's density may have been overridden in freeform; revert it here as we don't
         // want it overridden in multi-window.
         wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi())
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
new file mode 100644
index 0000000..9bb383f
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipScheduler.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.pip2.phone;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
+import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.view.SurfaceControl;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.Nullable;
+import androidx.core.content.ContextCompat;
+
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.pip.PipBoundsState;
+import com.android.wm.shell.common.pip.PipUtils;
+import com.android.wm.shell.pip.PipTransitionController;
+
+/**
+ * Scheduler for Shell initiated PiP transitions and animations.
+ */
+public class PipScheduler {
+    private static final String TAG = PipScheduler.class.getSimpleName();
+    private static final String BROADCAST_FILTER = PipScheduler.class.getCanonicalName();
+
+    private final Context mContext;
+    private final PipBoundsState mPipBoundsState;
+    private final ShellExecutor mMainExecutor;
+    private PipSchedulerReceiver mSchedulerReceiver;
+    private PipTransitionController mPipTransitionController;
+
+    // pinned PiP task's WC token
+    @Nullable
+    private WindowContainerToken mPipTaskToken;
+
+    // pinned PiP task's leash
+    @Nullable
+    private SurfaceControl mPinnedTaskLeash;
+
+    // the leash of the original task of the PiP activity;
+    // used to synchronize app drawings in the multi-activity case
+    @Nullable
+    private SurfaceControl mOriginalTaskLeash;
+
+    /**
+     * A temporary broadcast receiver to initiate exit PiP via expand.
+     * This will later be modified to be triggered by the PiP menu.
+     */
+    private class PipSchedulerReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            scheduleExitPipViaExpand();
+        }
+    }
+
+    public PipScheduler(Context context, PipBoundsState pipBoundsState,
+            ShellExecutor mainExecutor) {
+        mContext = context;
+        mPipBoundsState = pipBoundsState;
+        mMainExecutor = mainExecutor;
+
+        if (PipUtils.isPip2ExperimentEnabled()) {
+            // temporary broadcast receiver to initiate exit PiP via expand
+            mSchedulerReceiver = new PipSchedulerReceiver();
+            ContextCompat.registerReceiver(mContext, mSchedulerReceiver,
+                    new IntentFilter(BROADCAST_FILTER), ContextCompat.RECEIVER_EXPORTED);
+        }
+    }
+
+    void setPipTransitionController(PipTransitionController pipTransitionController) {
+        mPipTransitionController = pipTransitionController;
+    }
+
+    void setPinnedTaskLeash(SurfaceControl pinnedTaskLeash) {
+        mPinnedTaskLeash = pinnedTaskLeash;
+    }
+
+    void setOriginalTaskLeash(SurfaceControl originalTaskLeash) {
+        mOriginalTaskLeash = originalTaskLeash;
+    }
+
+    void setPipTaskToken(@Nullable WindowContainerToken pipTaskToken) {
+        mPipTaskToken = pipTaskToken;
+    }
+
+    @Nullable
+    private WindowContainerTransaction getExitPipViaExpandTransaction() {
+        if (mPipTaskToken == null || mPinnedTaskLeash == null) {
+            return null;
+        }
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        // final expanded bounds to be inherited from the parent
+        wct.setBounds(mPipTaskToken, null);
+        // if we are hitting a multi-activity case
+        // windowing mode change will reparent to original host task
+        wct.setWindowingMode(mPipTaskToken, WINDOWING_MODE_UNDEFINED);
+        return wct;
+    }
+
+    /**
+     * Schedules exit PiP via expand transition.
+     */
+    public void scheduleExitPipViaExpand() {
+        WindowContainerTransaction wct = getExitPipViaExpandTransaction();
+        if (wct != null) {
+            mMainExecutor.execute(() -> {
+                mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct,
+                        null /* destinationBounds */);
+            });
+        }
+    }
+
+    void onExitPip() {
+        mPipTaskToken = null;
+        mPinnedTaskLeash = null;
+        mOriginalTaskLeash = null;
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
index d704b09..7d3bd65 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java
@@ -16,8 +16,12 @@
 
 package com.android.wm.shell.pip2.phone;
 
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.view.WindowManager.TRANSIT_OPEN;
 
+import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
+
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.PictureInPictureParams;
@@ -26,6 +30,7 @@
 import android.view.SurfaceControl;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
+import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.Nullable;
@@ -43,8 +48,15 @@
  * Implementation of transitions for PiP on phone.
  */
 public class PipTransition extends PipTransitionController {
+    private static final String TAG = PipTransition.class.getSimpleName();
+
+    private PipScheduler mPipScheduler;
+    @Nullable
+    private WindowContainerToken mPipTaskToken;
     @Nullable
     private IBinder mAutoEnterButtonNavTransition;
+    @Nullable
+    private IBinder mExitViaExpandTransition;
 
     public PipTransition(
             @NonNull ShellInit shellInit,
@@ -52,9 +64,13 @@
             @NonNull Transitions transitions,
             PipBoundsState pipBoundsState,
             PipMenuController pipMenuController,
-            PipBoundsAlgorithm pipBoundsAlgorithm) {
+            PipBoundsAlgorithm pipBoundsAlgorithm,
+            PipScheduler pipScheduler) {
         super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController,
                 pipBoundsAlgorithm);
+
+        mPipScheduler = pipScheduler;
+        mPipScheduler.setPipTransitionController(this);
     }
 
     @Override
@@ -64,6 +80,18 @@
         }
     }
 
+    @Override
+    public void startExitTransition(int type, WindowContainerTransaction out,
+            @android.annotation.Nullable Rect destinationBounds) {
+        if (out == null) {
+            return;
+        }
+        IBinder transition = mTransitions.startTransition(type, out, this);
+        if (type == TRANSIT_EXIT_PIP) {
+            mExitViaExpandTransition = transition;
+        }
+    }
+
     @Nullable
     @Override
     public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@@ -84,8 +112,18 @@
         }
     }
 
+    @Override
+    public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
+            @NonNull Transitions.TransitionFinishCallback finishCallback) {}
+
+    @Override
+    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+            @Nullable SurfaceControl.Transaction finishT) {}
+
     private WindowContainerTransaction getEnterPipTransaction(@NonNull IBinder transition,
             @NonNull TransitionRequestInfo request) {
+        // cache the original task token to check for multi-activity case later
         final ActivityManager.RunningTaskInfo pipTask = request.getPipTask();
         PictureInPictureParams pipParams = pipTask.pictureInPictureParams;
         mPipBoundsState.setBoundsStateForEntry(pipTask.topActivity, pipTask.topActivityInfo,
@@ -93,6 +131,8 @@
 
         // calculate the entry bounds and notify core to move task to pinned with final bounds
         final Rect entryBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
+        mPipBoundsState.setBounds(entryBounds);
+
         WindowContainerTransaction wct = new WindowContainerTransaction();
         wct.movePipActivityToPinnedRootTask(pipTask.token, entryBounds);
         return wct;
@@ -121,19 +161,59 @@
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
         if (transition == mAutoEnterButtonNavTransition) {
+            mAutoEnterButtonNavTransition = null;
+            TransitionInfo.Change pipChange = getPipChange(info);
+            if (pipChange == null) {
+                return false;
+            }
+            mPipTaskToken = pipChange.getContainer();
+
+            // cache the PiP task token and the relevant leashes
+            mPipScheduler.setPipTaskToken(mPipTaskToken);
+            mPipScheduler.setPinnedTaskLeash(pipChange.getLeash());
+            // check if we entered PiP from a multi-activity task and set the original task leash
+            final int lastParentTaskId = pipChange.getTaskInfo().lastParentTaskIdBeforePip;
+            final boolean isSingleActivity = lastParentTaskId == INVALID_TASK_ID;
+            mPipScheduler.setOriginalTaskLeash(isSingleActivity ? null :
+                    findChangeByTaskId(info, lastParentTaskId).getLeash());
+
             startTransaction.apply();
             finishCallback.onTransitionFinished(null);
             return true;
+        } else if (transition == mExitViaExpandTransition) {
+            mExitViaExpandTransition = null;
+            startTransaction.apply();
+            finishCallback.onTransitionFinished(null);
+            onExitPip();
+            return true;
         }
         return false;
     }
 
-    @Override
-    public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
-            @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
-            @NonNull Transitions.TransitionFinishCallback finishCallback) {}
+    @Nullable
+    private TransitionInfo.Change getPipChange(TransitionInfo info) {
+        for (TransitionInfo.Change change : info.getChanges()) {
+            if (change.getTaskInfo() != null
+                    && change.getTaskInfo().getWindowingMode() == WINDOWING_MODE_PINNED) {
+                return change;
+            }
+        }
+        return null;
+    }
 
-    @Override
-    public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
-            @Nullable SurfaceControl.Transaction finishT) {}
+    @Nullable
+    private TransitionInfo.Change findChangeByTaskId(TransitionInfo info, int taskId) {
+        for (TransitionInfo.Change change : info.getChanges()) {
+            if (change.getTaskInfo() != null
+                    && change.getTaskInfo().taskId == taskId) {
+                return change;
+            }
+        }
+        return null;
+    }
+
+    private void onExitPip() {
+        mPipTaskToken = null;
+        mPipScheduler.onExitPip();
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index d277eef..c20d23e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -59,6 +59,7 @@
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.HomeTransitionObserver;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.util.TransitionUtil;
 
@@ -85,11 +86,15 @@
      */
     private final ArrayList<RecentsMixedHandler> mMixers = new ArrayList<>();
 
+    private final HomeTransitionObserver mHomeTransitionObserver;
+
     public RecentsTransitionHandler(ShellInit shellInit, Transitions transitions,
-            @Nullable RecentTasksController recentTasksController) {
+            @Nullable RecentTasksController recentTasksController,
+            HomeTransitionObserver homeTransitionObserver) {
         mTransitions = transitions;
         mExecutor = transitions.getMainExecutor();
         mRecentTasksController = recentTasksController;
+        mHomeTransitionObserver = homeTransitionObserver;
         if (!Transitions.ENABLE_SHELL_TRANSITIONS) return;
         if (recentTasksController == null) return;
         shellInit.addInitCallback(() -> {
@@ -911,6 +916,11 @@
                 Slog.e(TAG, "Duplicate call to finish");
                 return;
             }
+            if (!toHome) {
+                // For some transitions, we may have notified home activity that it became visible.
+                // We need to notify the observer that we are no longer going home.
+                mHomeTransitionObserver.notifyHomeVisibilityChanged(false);
+            }
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                     "[%d] RecentsController.finishInner: toHome=%b userLeave=%b "
                             + "willFinishToHome=%b state=%d",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 0c6adc9..43ae5f4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -23,6 +23,7 @@
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_APP_PREFERS_ICON;
 
 import android.annotation.ColorInt;
 import android.annotation.IntDef;
@@ -125,6 +126,7 @@
     private final TransactionPool mTransactionPool;
     private final SplashScreenWindowAttrs mTmpAttrs = new SplashScreenWindowAttrs();
     private final Handler mSplashscreenWorkerHandler;
+    private final boolean mCanUseAppIconForSplashScreen;
     @VisibleForTesting
     final ColorCache mColorCache;
 
@@ -141,6 +143,8 @@
         shellSplashscreenWorkerThread.start();
         mSplashscreenWorkerHandler = shellSplashscreenWorkerThread.getThreadHandler();
         mColorCache = new ColorCache(mContext, mSplashscreenWorkerHandler);
+        mCanUseAppIconForSplashScreen = context.getResources().getBoolean(
+                com.android.wm.shell.R.bool.config_canUseAppIconForSplashScreen);
     }
 
     /**
@@ -427,7 +431,10 @@
         getWindowAttrs(context, mTmpAttrs);
         mLastPackageContextConfigHash = context.getResources().getConfiguration().hashCode();
 
-        final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
+        final @StartingWindowType int splashType =
+                suggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN && !canUseIcon(info)
+                ? STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN : suggestType;
+        final Drawable legacyDrawable = splashType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
                 ? peekLegacySplashscreenContent(context, mTmpAttrs) : null;
         final ActivityInfo ai = info.targetActivityInfo != null
                 ? info.targetActivityInfo
@@ -439,12 +446,17 @@
         return new SplashViewBuilder(context, ai)
                 .setWindowBGColor(themeBGColor)
                 .overlayDrawable(legacyDrawable)
-                .chooseStyle(suggestType)
+                .chooseStyle(splashType)
                 .setUiThreadInitConsumer(uiThreadInitConsumer)
                 .setAllowHandleSolidColor(info.allowHandleSolidColorSplashScreen())
                 .build();
     }
 
+    private boolean canUseIcon(StartingWindowInfo info) {
+        return mCanUseAppIconForSplashScreen || mTmpAttrs.mSplashScreenIcon != null
+             || (info.startingWindowTypeParameter & TYPE_PARAMETER_APP_PREFERS_ICON) != 0;
+    }
+
     private int getBGColorFromCache(ActivityInfo ai, IntSupplier windowBgColorSupplier) {
         return mColorCache.getWindowColor(ai.packageName, mLastPackageContextConfigHash,
                 mTmpAttrs.mWindowBgColor, mTmpAttrs.mWindowBgResId, windowBgColorSupplier).mBgColor;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
index f561aa5..b528089d15 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
@@ -38,24 +38,15 @@
  */
 public class HomeTransitionObserver implements TransitionObserver,
         RemoteCallable<HomeTransitionObserver> {
-    private final SingleInstanceRemoteListener<HomeTransitionObserver, IHomeTransitionListener>
+    private SingleInstanceRemoteListener<HomeTransitionObserver, IHomeTransitionListener>
             mListener;
 
     private @NonNull final Context mContext;
     private @NonNull final ShellExecutor mMainExecutor;
-    private @NonNull final Transitions mTransitions;
-
     public HomeTransitionObserver(@NonNull Context context,
-            @NonNull ShellExecutor mainExecutor,
-            @NonNull Transitions transitions) {
+            @NonNull ShellExecutor mainExecutor) {
         mContext = context;
         mMainExecutor = mainExecutor;
-        mTransitions = transitions;
-
-        mListener = new SingleInstanceRemoteListener<>(this,
-                c -> mTransitions.registerObserver(this),
-                c -> mTransitions.unregisterObserver(this));
-
     }
 
     @Override
@@ -72,7 +63,7 @@
             final int mode = change.getMode();
             if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME
                     && TransitionUtil.isOpenOrCloseMode(mode)) {
-                mListener.call(l -> l.onHomeVisibilityChanged(TransitionUtil.isOpeningType(mode)));
+                notifyHomeVisibilityChanged(TransitionUtil.isOpeningType(mode));
             }
         }
     }
@@ -92,7 +83,14 @@
      * Sets the home transition listener that receives any transitions resulting in a change of
      *
      */
-    public void setHomeTransitionListener(IHomeTransitionListener listener) {
+    public void setHomeTransitionListener(Transitions transitions,
+            IHomeTransitionListener listener) {
+        if (mListener == null) {
+            mListener = new SingleInstanceRemoteListener<>(this,
+                    c -> transitions.registerObserver(this),
+                    c -> transitions.unregisterObserver(this));
+        }
+
         if (listener != null) {
             mListener.register(listener);
         } else {
@@ -100,6 +98,16 @@
         }
     }
 
+    /**
+     * Notifies the listener that the home visibility has changed.
+     * @param isVisible true when home activity is visible, false otherwise.
+     */
+    public void notifyHomeVisibilityChanged(boolean isVisible) {
+        if (mListener != null) {
+            mListener.call(l -> l.onHomeVisibilityChanged(isVisible));
+        }
+    }
+
     @Override
     public Context getContext() {
         return mContext;
@@ -113,7 +121,7 @@
     /**
      * Invalidates this controller, preventing future calls to send updates.
      */
-    public void invalidate() {
-        mTransitions.unregisterObserver(this);
+    public void invalidate(Transitions transitions) {
+        transitions.unregisterObserver(this);
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index c34a14e..ab5c063 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -192,6 +192,8 @@
 
     private final ArrayList<TransitionObserver> mObservers = new ArrayList<>();
 
+    private HomeTransitionObserver mHomeTransitionObserver;
+
     /** List of {@link Runnable} instances to run when the last active transition has finished.  */
     private final ArrayList<Runnable> mRunWhenIdleQueue = new ArrayList<>();
 
@@ -205,12 +207,6 @@
      */
     private static final int SYNC_ALLOWANCE_MS = 120;
 
-    /**
-     * Keyguard gets a more generous timeout to finish its animations, because we are always holding
-     * a sleep token during occlude/unocclude transitions and we want them to finish playing cleanly
-     */
-    private static final int SYNC_ALLOWANCE_KEYGUARD_MS = 2000;
-
     /** For testing only. Disables the force-finish timeout on sync. */
     private boolean mDisableForceSync = false;
 
@@ -273,10 +269,11 @@
             @NonNull DisplayController displayController,
             @NonNull ShellExecutor mainExecutor,
             @NonNull Handler mainHandler,
-            @NonNull ShellExecutor animExecutor) {
+            @NonNull ShellExecutor animExecutor,
+            @NonNull HomeTransitionObserver observer) {
         this(context, shellInit, new ShellCommandHandler(), shellController, organizer, pool,
                 displayController, mainExecutor, mainHandler, animExecutor,
-                new RootTaskDisplayAreaOrganizer(mainExecutor, context, shellInit));
+                new RootTaskDisplayAreaOrganizer(mainExecutor, context, shellInit), observer);
     }
 
     public Transitions(@NonNull Context context,
@@ -289,7 +286,8 @@
             @NonNull ShellExecutor mainExecutor,
             @NonNull Handler mainHandler,
             @NonNull ShellExecutor animExecutor,
-            @NonNull RootTaskDisplayAreaOrganizer rootTDAOrganizer) {
+            @NonNull RootTaskDisplayAreaOrganizer rootTDAOrganizer,
+            @NonNull HomeTransitionObserver observer) {
         mOrganizer = organizer;
         mContext = context;
         mMainExecutor = mainExecutor;
@@ -308,6 +306,7 @@
         mHandlers.add(mRemoteTransitionHandler);
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "addHandler: Remote");
         shellInit.addInitCallback(this::onInit, this);
+        mHomeTransitionObserver = observer;
     }
 
     private void onInit() {
@@ -357,7 +356,7 @@
     }
 
     private ExternalInterfaceBinder createExternalInterface() {
-        return new IShellTransitionsImpl(mContext, getMainExecutor(), this);
+        return new IShellTransitionsImpl(this);
     }
 
     @Override
@@ -1209,11 +1208,8 @@
             if (track.mActiveTransition == playing) {
                 if (!mDisableForceSync) {
                     // Give it a short amount of time to process it before forcing.
-                    final int tolerance = KeyguardTransitionHandler.handles(playing.mInfo)
-                            ? SYNC_ALLOWANCE_KEYGUARD_MS
-                            : SYNC_ALLOWANCE_MS;
                     mMainExecutor.executeDelayed(
-                            () -> finishForSync(reason, trackIdx, playing), tolerance);
+                            () -> finishForSync(reason, trackIdx, playing), SYNC_ALLOWANCE_MS);
                 }
                 break;
             }
@@ -1406,12 +1402,9 @@
     private static class IShellTransitionsImpl extends IShellTransitions.Stub
             implements ExternalInterfaceBinder {
         private Transitions mTransitions;
-        private final HomeTransitionObserver mHomeTransitionObserver;
 
-        IShellTransitionsImpl(Context context, ShellExecutor executor, Transitions transitions) {
+        IShellTransitionsImpl(Transitions transitions) {
             mTransitions = transitions;
-            mHomeTransitionObserver = new HomeTransitionObserver(context, executor,
-                    mTransitions);
         }
 
         /**
@@ -1419,7 +1412,7 @@
          */
         @Override
         public void invalidate() {
-            mHomeTransitionObserver.invalidate();
+            mTransitions.mHomeTransitionObserver.invalidate(mTransitions);
             mTransitions = null;
         }
 
@@ -1449,7 +1442,8 @@
         public void setHomeTransitionListener(IHomeTransitionListener listener) {
             executeRemoteCallWithTaskPermission(mTransitions, "setHomeTransitionListener",
                     (transitions) -> {
-                        mHomeTransitionObserver.setHomeTransitionListener(listener);
+                        transitions.mHomeTransitionObserver.setHomeTransitionListener(mTransitions,
+                                listener);
                     });
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 716f8b8..e206039 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -82,6 +82,7 @@
 import com.android.wm.shell.recents.RecentsTransitionHandler;
 import com.android.wm.shell.recents.RecentsTransitionStateListener;
 import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.splitscreen.SplitScreen.StageType;
 import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.sysui.KeyguardChangeListener;
 import com.android.wm.shell.sysui.ShellCommandHandler;
@@ -238,7 +239,7 @@
         mSplitScreenController = splitScreenController;
         mSplitScreenController.registerSplitScreenListener(new SplitScreen.SplitScreenListener() {
             @Override
-            public void onTaskStageChanged(int taskId, int stage, boolean visible) {
+            public void onTaskStageChanged(int taskId, @StageType int stage, boolean visible) {
                 if (visible) {
                     DesktopModeWindowDecoration decor = mWindowDecorByTaskId.get(taskId);
                     if (decor != null && DesktopModeStatus.isEnabled()
@@ -391,10 +392,10 @@
             final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
             final int id = v.getId();
             if (id == R.id.close_window) {
-                mTaskOperations.closeTask(mTaskToken);
                 if (isTaskInSplitScreen(mTaskId)) {
-                    RunningTaskInfo remainingTask = getOtherSplitTask(mTaskId);
-                    mSplitScreenController.moveTaskToFullscreen(remainingTask.taskId);
+                    mSplitScreenController.moveTaskToFullscreen(getOtherSplitTask(mTaskId).taskId);
+                } else {
+                    mTaskOperations.closeTask(mTaskToken);
                 }
             } else if (id == R.id.back_button) {
                 mTaskOperations.injectBackKey();
@@ -417,8 +418,12 @@
                 }
                 decoration.closeHandleMenu();
             } else if (id == R.id.fullscreen_button) {
-                mDesktopTasksController.ifPresent(c -> c.moveToFullscreen(mTaskId));
                 decoration.closeHandleMenu();
+                if (isTaskInSplitScreen(mTaskId)) {
+                    mSplitScreenController.moveTaskToFullscreen(mTaskId);
+                } else {
+                    mDesktopTasksController.ifPresent(c -> c.moveToFullscreen(mTaskId));
+                }
             } else if (id == R.id.split_screen_button) {
                 decoration.closeHandleMenu();
                 mDesktopTasksController.ifPresent(c -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
index 9dc86db..b1fb0f1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/DesktopModeFocusedWindowDecorationViewHolder.kt
@@ -42,11 +42,11 @@
     }
 
     override fun onHandleMenuOpened() {
-        animateCaptionHandleAlpha(startValue = 0f, endValue = 1f)
+        animateCaptionHandleAlpha(startValue = 1f, endValue = 0f)
     }
 
     override fun onHandleMenuClosed() {
-        animateCaptionHandleAlpha(startValue = 1f, endValue = 0f)
+        animateCaptionHandleAlpha(startValue = 0f, endValue = 1f)
     }
 
     private fun getCaptionHandleBarColor(taskInfo: RunningTaskInfo): Int {
diff --git a/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
index 1df1136..5b2ffec 100644
--- a/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/appcompat/AndroidTestTemplate.xml
@@ -95,14 +95,6 @@
         <option name="pull-pattern-keys" value="perfetto_file_path"/>
         <option name="directory-keys"
                 value="/data/user/0/com.android.wm.shell.flicker/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.pip/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.service/files"/>
         <option name="collect-on-run-ended-only" value="true"/>
         <option name="clean-up" value="true"/>
     </metrics_collector>
diff --git a/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
index 1df1136..9f7d9fc 100644
--- a/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/bubble/AndroidTestTemplate.xml
@@ -94,15 +94,7 @@
     <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
         <option name="pull-pattern-keys" value="perfetto_file_path"/>
         <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker/files"/>
-        <option name="directory-keys"
                 value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.pip/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.service/files"/>
         <option name="collect-on-run-ended-only" value="true"/>
         <option name="clean-up" value="true"/>
     </metrics_collector>
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
index 1df1136..882b200 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/pip/AndroidTestTemplate.xml
@@ -94,15 +94,9 @@
     <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
         <option name="pull-pattern-keys" value="perfetto_file_path"/>
         <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/>
-        <option name="directory-keys"
                 value="/data/user/0/com.android.wm.shell.flicker.pip/files"/>
         <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.service/files"/>
+                value="/data/user/0/com.android.wm.shell.flicker.pip.apps/files"/>
         <option name="collect-on-run-ended-only" value="true"/>
         <option name="clean-up" value="true"/>
     </metrics_collector>
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
index ca182fa..6df6539 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/pip/csuiteDefaultTemplate.xml
@@ -57,6 +57,17 @@
         <option name="test-file-name" value="WMShellFlickerTestsPipAppsCSuite.apk"/>
         <option name="test-file-name" value="FlickerTestApp.apk"/>
     </target_preparer>
+
+    <!-- Needed for installing apk's from Play Store -->
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="aapt-version" value="AAPT2"/>
+        <option name="throw-if-not-found" value="false"/>
+        <option name="install-arg" value="-d"/>
+        <option name="install-arg" value="-g"/>
+        <option name="install-arg" value="-r"/>
+        <option name="test-file-name" value="pstash://com.netflix.mediaclient"/>
+    </target_preparer>
+
     <!-- Enable mocking GPS location by the test app -->
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command"
@@ -94,28 +105,8 @@
     <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
         <option name="pull-pattern-keys" value="perfetto_file_path"/>
         <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.pip/files"/>
-        <option name="directory-keys"
                 value="/data/user/0/com.android.wm.shell.flicker.pip.apps/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.service/files"/>
         <option name="collect-on-run-ended-only" value="true"/>
         <option name="clean-up" value="true"/>
     </metrics_collector>
-
-    <!-- Needed for installing apk's from Play Store -->
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="aapt-version" value="AAPT2"/>
-        <option name="throw-if-not-found" value="false"/>
-        <option name="install-arg" value="-d"/>
-        <option name="install-arg" value="-g"/>
-        <option name="install-arg" value="-r"/>
-        <option name="test-file-name" value="pstash://com.netflix.mediaclient"/>
-    </target_preparer>
 </configuration>
diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt
index be5a27a..bd8b005 100644
--- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/apps/AppsEnterPipTransition.kt
@@ -20,6 +20,8 @@
 import android.tools.common.Rotation
 import android.tools.common.traces.component.ComponentNameMatcher
 import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.junit.FlickerBuilderProvider
+import android.tools.device.flicker.legacy.FlickerBuilder
 import android.tools.device.flicker.legacy.LegacyFlickerTest
 import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
 import com.android.wm.shell.flicker.pip.common.EnterPipTransition
@@ -29,6 +31,15 @@
 abstract class AppsEnterPipTransition(flicker: LegacyFlickerTest) : EnterPipTransition(flicker) {
     protected abstract val standardAppHelper: StandardAppHelper
 
+    @FlickerBuilderProvider
+    override fun buildFlicker(): FlickerBuilder {
+        return FlickerBuilder(instrumentation).apply {
+            withoutScreenRecorder()
+            setup { flicker.scenario.setIsTablet(tapl.isTablet) }
+            transition()
+        }
+    }
+
     /** Checks [standardAppHelper] window remains visible throughout the animation */
     @Postsubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
index 1df1136..51a55e35 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/service/AndroidTestTemplate.xml
@@ -94,14 +94,6 @@
     <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
         <option name="pull-pattern-keys" value="perfetto_file_path"/>
         <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.pip/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/>
-        <option name="directory-keys"
                 value="/data/user/0/com.android.wm.shell.flicker.service/files"/>
         <option name="collect-on-run-ended-only" value="true"/>
         <option name="clean-up" value="true"/>
diff --git a/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml b/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
index 1df1136..fdda597 100644
--- a/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
+++ b/libs/WindowManager/Shell/tests/flicker/splitscreen/AndroidTestTemplate.xml
@@ -94,15 +94,7 @@
     <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
         <option name="pull-pattern-keys" value="perfetto_file_path"/>
         <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.bubbles/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.pip/files"/>
-        <option name="directory-keys"
                 value="/data/user/0/com.android.wm.shell.flicker.splitscreen/files"/>
-        <option name="directory-keys"
-                value="/data/user/0/com.android.wm.shell.flicker.service/files"/>
         <option name="collect-on-run-ended-only" value="true"/>
         <option name="clean-up" value="true"/>
     </metrics_collector>
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt
index 0f3e0f5..e9363f7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseBenchmarkTest.kt
@@ -38,7 +38,7 @@
      * executions
      */
     @FlickerBuilderProvider
-    fun buildFlicker(): FlickerBuilder {
+    open fun buildFlicker(): FlickerBuilder {
         return FlickerBuilder(instrumentation).apply {
             setup { flicker.scenario.setIsTablet(tapl.isTablet) }
             transition()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt
index c31b9e2..3244ebc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/SplitScreenUtils.kt
@@ -135,19 +135,29 @@
             // second task to split.
             val home = tapl.workspace.switchToOverview()
             ChangeDisplayOrientationRule.setRotation(rotation)
-            home.overviewActions.clickSplit()
+            val isGridOnlyOverviewEnabled = tapl.isGridOnlyOverviewEnabled
+            if (isGridOnlyOverviewEnabled) {
+                home.currentTask.tapMenu().tapSplitMenuItem()
+            } else {
+                home.overviewActions.clickSplit()
+            }
             val snapshots = device.wait(Until.findObjects(overviewSnapshotSelector), TIMEOUT_MS)
             if (snapshots == null || snapshots.size < 1) {
                 error("Fail to find a overview snapshot to split.")
             }
 
-            // Find the second task in the upper right corner in split select mode by sorting
-            // 'left' in descending order and 'top' in ascending order.
+            // Find the second task in the upper (or bottom for grid only Overview) right corner in
+            // split select mode by sorting 'left' in descending order and 'top' in ascending (or
+            // descending for grid only Overview) order.
             snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
                 t2.getVisibleBounds().left - t1.getVisibleBounds().left
             }
             snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
-                t1.getVisibleBounds().top - t2.getVisibleBounds().top
+                if (isGridOnlyOverviewEnabled) {
+                    t2.getVisibleBounds().top - t1.getVisibleBounds().top
+                } else {
+                    t1.getVisibleBounds().top - t2.getVisibleBounds().top
+                }
             }
             snapshots[0].click()
         } else {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
index 02c9d30..2ac72af 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java
@@ -98,4 +98,21 @@
         // The animation should be empty when it is behind starting window.
         assertEquals(0, animator.getDuration());
     }
+
+    @Test
+    public void testInvalidCustomAnimation() {
+        final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
+                .addChange(createChange(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY))
+                .build();
+        info.setAnimationOptions(TransitionInfo.AnimationOptions
+                .makeCustomAnimOptions("packageName", 0 /* enterResId */, 0 /* exitResId */,
+                        0 /* backgroundColor */, false /* overrideTaskTransition */));
+        final Animator animator = mAnimRunner.createAnimator(
+                info, mStartTransaction, mFinishTransaction,
+                () -> mFinishCallback.onTransitionFinished(null /* wct */),
+                new ArrayList<>());
+
+        // An invalid custom animation is equivalent to jump-cut.
+        assertEquals(0, animator.getDuration());
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index cc4db22..fff65f3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -74,6 +74,7 @@
 import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.transition.HomeTransitionObserver;
 import com.android.wm.shell.transition.Transitions;
 
 import org.junit.Before;
@@ -373,7 +374,7 @@
         ShellInit shellInit = new ShellInit(mMainExecutor);
         final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class),
                 mTaskOrganizer, mTransactionPool, mock(DisplayController.class), mMainExecutor,
-                mMainHandler, mAnimExecutor);
+                mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class));
         shellInit.init();
         return t;
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java
index a9082a6..012c4081 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingWindowControllerTests.java
@@ -80,6 +80,7 @@
         MockitoAnnotations.initMocks(this);
         doReturn(mock(Display.class)).when(mDisplayManager).getDisplay(anyInt());
         doReturn(mDisplayManager).when(mContext).getSystemService(eq(DisplayManager.class));
+        doReturn(super.mContext.getResources()).when(mContext).getResources();
         mShellInit = spy(new ShellInit(mMainExecutor));
         mShellController = spy(new ShellController(mContext, mShellInit, mShellCommandHandler,
                 mMainExecutor));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
index 7a8a2a9..ea7c0d9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
@@ -75,24 +75,24 @@
     private final Handler mMainHandler = new Handler(Looper.getMainLooper());
     private final DisplayController mDisplayController = mock(DisplayController.class);
 
+    private IHomeTransitionListener mListener;
     private Transitions mTransition;
+    private HomeTransitionObserver mHomeTransitionObserver;
 
     @Before
     public void setUp() {
+        mListener = mock(IHomeTransitionListener.class);
+        when(mListener.asBinder()).thenReturn(mock(IBinder.class));
+
+        mHomeTransitionObserver = new HomeTransitionObserver(mContext, mMainExecutor);
         mTransition = new Transitions(mContext, mock(ShellInit.class), mock(ShellController.class),
                 mOrganizer, mTransactionPool, mDisplayController, mMainExecutor,
-                mMainHandler, mAnimExecutor);
+                mMainHandler, mAnimExecutor, mHomeTransitionObserver);
+        mHomeTransitionObserver.setHomeTransitionListener(mTransition, mListener);
     }
 
     @Test
     public void testHomeActivityWithOpenModeNotifiesHomeIsVisible() throws RemoteException {
-        IHomeTransitionListener listener = mock(IHomeTransitionListener.class);
-        when(listener.asBinder()).thenReturn(mock(IBinder.class));
-
-        HomeTransitionObserver observer = new HomeTransitionObserver(mContext, mMainExecutor,
-                mTransition);
-        observer.setHomeTransitionListener(listener);
-
         TransitionInfo info = mock(TransitionInfo.class);
         TransitionInfo.Change change = mock(TransitionInfo.Change.class);
         ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
@@ -101,23 +101,16 @@
 
         setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_OPEN);
 
-        observer.onTransitionReady(mock(IBinder.class),
+        mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
                 info,
                 mock(SurfaceControl.Transaction.class),
                 mock(SurfaceControl.Transaction.class));
 
-        verify(listener, times(1)).onHomeVisibilityChanged(true);
+        verify(mListener, times(1)).onHomeVisibilityChanged(true);
     }
 
     @Test
     public void testHomeActivityWithCloseModeNotifiesHomeIsNotVisible() throws RemoteException {
-        IHomeTransitionListener listener = mock(IHomeTransitionListener.class);
-        when(listener.asBinder()).thenReturn(mock(IBinder.class));
-
-        HomeTransitionObserver observer = new HomeTransitionObserver(mContext, mMainExecutor,
-                mTransition);
-        observer.setHomeTransitionListener(listener);
-
         TransitionInfo info = mock(TransitionInfo.class);
         TransitionInfo.Change change = mock(TransitionInfo.Change.class);
         ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
@@ -126,38 +119,30 @@
 
         setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_HOME, TRANSIT_TO_BACK);
 
-        observer.onTransitionReady(mock(IBinder.class),
+        mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
                 info,
                 mock(SurfaceControl.Transaction.class),
                 mock(SurfaceControl.Transaction.class));
 
-        verify(listener, times(1)).onHomeVisibilityChanged(false);
+        verify(mListener, times(1)).onHomeVisibilityChanged(false);
     }
 
     @Test
     public void testNonHomeActivityDoesNotTriggerCallback() throws RemoteException {
-        IHomeTransitionListener listener = mock(IHomeTransitionListener.class);
-        when(listener.asBinder()).thenReturn(mock(IBinder.class));
-
-        HomeTransitionObserver observer = new HomeTransitionObserver(mContext, mMainExecutor,
-                mTransition);
-        observer.setHomeTransitionListener(listener);
-
         TransitionInfo info = mock(TransitionInfo.class);
         TransitionInfo.Change change = mock(TransitionInfo.Change.class);
         ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
         when(change.getTaskInfo()).thenReturn(taskInfo);
         when(info.getChanges()).thenReturn(new ArrayList<>(List.of(change)));
 
-
         setupTransitionInfo(taskInfo, change, ACTIVITY_TYPE_UNDEFINED, TRANSIT_TO_BACK);
 
-        observer.onTransitionReady(mock(IBinder.class),
+        mHomeTransitionObserver.onTransitionReady(mock(IBinder.class),
                 info,
                 mock(SurfaceControl.Transaction.class),
                 mock(SurfaceControl.Transaction.class));
 
-        verify(listener, times(0)).onHomeVisibilityChanged(anyBoolean());
+        verify(mListener, times(0)).onHomeVisibilityChanged(anyBoolean());
     }
 
     /**
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index da83d4c0..4e300d9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -146,7 +146,7 @@
         ShellInit shellInit = mock(ShellInit.class);
         final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class),
                 mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor,
-                mMainHandler, mAnimExecutor);
+                mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class));
         // One from Transitions, one from RootTaskDisplayAreaOrganizer
         verify(shellInit).addInitCallback(any(), eq(t));
         verify(shellInit).addInitCallback(any(), isA(RootTaskDisplayAreaOrganizer.class));
@@ -158,7 +158,7 @@
         ShellController shellController = mock(ShellController.class);
         final Transitions t = new Transitions(mContext, shellInit, shellController,
                 mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor,
-                mMainHandler, mAnimExecutor);
+                mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class));
         shellInit.init();
         verify(shellController, times(1)).addExternalInterface(
                 eq(ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS), any(), any());
@@ -1075,10 +1075,10 @@
         final Transitions transitions =
                 new Transitions(mContext, shellInit, mock(ShellController.class), mOrganizer,
                         mTransactionPool, createTestDisplayController(), mMainExecutor,
-                        mMainHandler, mAnimExecutor);
+                        mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class));
         final RecentsTransitionHandler recentsHandler =
                 new RecentsTransitionHandler(shellInit, transitions,
-                        mock(RecentTasksController.class));
+                        mock(RecentTasksController.class), mock(HomeTransitionObserver.class));
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
         shellInit.init();
 
@@ -1623,7 +1623,7 @@
         ShellInit shellInit = new ShellInit(mMainExecutor);
         final Transitions t = new Transitions(mContext, shellInit, mock(ShellController.class),
                 mOrganizer, mTransactionPool, createTestDisplayController(), mMainExecutor,
-                mMainHandler, mAnimExecutor);
+                mMainHandler, mAnimExecutor, mock(HomeTransitionObserver.class));
         shellInit.init();
         return t;
     }
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index ff1eedb..da728f9 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -144,6 +144,7 @@
                 "libsync",
                 "libui",
                 "aconfig_text_flags_c_lib",
+                "server_configurable_flags",
             ],
             static_libs: [
                 "libEGL_blobCache",
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index a8d170d..fd27641 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -242,6 +242,47 @@
     }
 }
 
+SkRect DamageAccumulator::computeClipAndTransform(const SkRect& bounds, Matrix4* outMatrix) const {
+    const DirtyStack* frame = mHead;
+    Matrix4 transform;
+    SkRect pretransformResult = bounds;
+    while (true) {
+        SkRect currentBounds = pretransformResult;
+        pretransformResult.setEmpty();
+        switch (frame->type) {
+            case TransformRenderNode: {
+                const RenderProperties& props = frame->renderNode->properties();
+                // Perform clipping
+                if (props.getClipDamageToBounds() && !currentBounds.isEmpty()) {
+                    if (!currentBounds.intersect(
+                                SkRect::MakeIWH(props.getWidth(), props.getHeight()))) {
+                        currentBounds.setEmpty();
+                    }
+                }
+
+                // apply all transforms
+                mapRect(props, currentBounds, &pretransformResult);
+                frame->renderNode->applyViewPropertyTransforms(transform);
+            } break;
+            case TransformMatrix4:
+                mapRect(frame->matrix4, currentBounds, &pretransformResult);
+                transform.multiply(*frame->matrix4);
+                break;
+            default:
+                pretransformResult = currentBounds;
+                break;
+        }
+        if (frame->prev == frame) break;
+        frame = frame->prev;
+    }
+    SkRect result;
+    Matrix4 globalToLocal;
+    globalToLocal.loadInverse(transform);
+    mapRect(&globalToLocal, pretransformResult, &result);
+    *outMatrix = transform;
+    return result;
+}
+
 void DamageAccumulator::dirty(float left, float top, float right, float bottom) {
     mHead->pendingDirty.join({left, top, right, bottom});
 }
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index c4249af..30bf706 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -61,6 +61,8 @@
 
     void computeCurrentTransform(Matrix4* outMatrix) const;
 
+    SkRect computeClipAndTransform(const SkRect& bounds, Matrix4* outMatrix) const;
+
     void finish(SkRect* totalDirty);
 
     struct StretchResult {
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 5e5eb4a..ad600d0 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -20,15 +20,26 @@
 #ifdef __ANDROID__
 #include "HWUIProperties.sysprop.h"
 #endif
-#include "src/core/SkTraceEventCommon.h"
+#include <android-base/properties.h>
+#include <cutils/compiler.h>
+#include <log/log.h>
 
 #include <algorithm>
 #include <cstdlib>
 #include <optional>
 
-#include <android-base/properties.h>
-#include <cutils/compiler.h>
-#include <log/log.h>
+#include "src/core/SkTraceEventCommon.h"
+
+#ifdef __ANDROID__
+#include <com_android_graphics_hwui_flags.h>
+namespace hwui_flags = com::android::graphics::hwui::flags;
+#else
+namespace hwui_flags {
+constexpr bool clip_surfaceviews() {
+    return false;
+}
+}  // namespace hwui_flags
+#endif
 
 namespace android {
 namespace uirenderer {
@@ -92,6 +103,8 @@
 
 float Properties::maxHdrHeadroomOn8bit = 5.f;  // TODO: Refine this number
 
+bool Properties::clipSurfaceViews = false;
+
 StretchEffectBehavior Properties::stretchEffectBehavior = StretchEffectBehavior::ShaderHWUI;
 
 DrawingEnabled Properties::drawingEnabled = DrawingEnabled::NotInitialized;
@@ -159,6 +172,9 @@
     // call isDrawingEnabled to force loading of the property
     isDrawingEnabled();
 
+    clipSurfaceViews =
+            base::GetBoolProperty("debug.hwui.clip_surfaceviews", hwui_flags::clip_surfaceviews());
+
     return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
 }
 
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index bb47744..bca57e9 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -325,6 +325,8 @@
 
     static float maxHdrHeadroomOn8bit;
 
+    static bool clipSurfaceViews;
+
     static StretchEffectBehavior getStretchEffectBehavior() {
         return stretchEffectBehavior;
     }
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index caffdfc..ef4dce5 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -17,18 +17,18 @@
 #ifndef ANDROID_GRAPHICS_PAINT_H_
 #define ANDROID_GRAPHICS_PAINT_H_
 
-#include "Typeface.h"
-
-#include <cutils/compiler.h>
-
 #include <SkFont.h>
 #include <SkPaint.h>
 #include <SkSamplingOptions.h>
+#include <cutils/compiler.h>
+#include <minikin/FamilyVariant.h>
+#include <minikin/FontFamily.h>
+#include <minikin/FontFeature.h>
+#include <minikin/Hyphenator.h>
+
 #include <string>
 
-#include <minikin/FontFamily.h>
-#include <minikin/FamilyVariant.h>
-#include <minikin/Hyphenator.h>
+#include "Typeface.h"
 
 namespace android {
 
@@ -82,11 +82,15 @@
 
     float getWordSpacing() const { return mWordSpacing; }
 
-    void setFontFeatureSettings(const std::string& fontFeatureSettings) {
-        mFontFeatureSettings = fontFeatureSettings;
+    void setFontFeatureSettings(std::string_view fontFeatures) {
+        mFontFeatureSettings = minikin::FontFeature::parse(fontFeatures);
     }
 
-    std::string getFontFeatureSettings() const { return mFontFeatureSettings; }
+    void resetFontFeatures() { mFontFeatureSettings.clear(); }
+
+    const std::vector<minikin::FontFeature>& getFontFeatureSettings() const {
+        return mFontFeatureSettings;
+    }
 
     void setMinikinLocaleListId(uint32_t minikinLocaleListId) {
         mMinikinLocaleListId = minikinLocaleListId;
@@ -170,7 +174,7 @@
 
     float mLetterSpacing = 0;
     float mWordSpacing = 0;
-    std::string mFontFeatureSettings;
+    std::vector<minikin::FontFeature> mFontFeatureSettings;
     uint32_t mMinikinLocaleListId;
     std::optional<minikin::FamilyVariant> mFamilyVariant;
     uint32_t mHyphenEdit = 0;
diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp
index 8c71d6f..d84b73d 100644
--- a/libs/hwui/jni/Paint.cpp
+++ b/libs/hwui/jni/Paint.cpp
@@ -33,6 +33,7 @@
 #include <cassert>
 #include <cstring>
 #include <memory>
+#include <string_view>
 #include <vector>
 
 #include "ColorFilter.h"
@@ -690,10 +691,11 @@
                                        jstring settings) {
         Paint* paint = reinterpret_cast<Paint*>(paintHandle);
         if (!settings) {
-            paint->setFontFeatureSettings(std::string());
+            paint->resetFontFeatures();
         } else {
             ScopedUtfChars settingsChars(env, settings);
-            paint->setFontFeatureSettings(std::string(settingsChars.c_str(), settingsChars.size()));
+            paint->setFontFeatureSettings(
+                    std::string_view(settingsChars.c_str(), settingsChars.size()));
         }
     }
 
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index 2a218a2..a1b05c1 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -568,6 +568,7 @@
 struct {
     jclass clazz;
     jmethodID callPositionChanged;
+    jmethodID callPositionChanged2;
     jmethodID callApplyStretch;
     jmethodID callPositionLost;
 } gPositionListener;
@@ -589,14 +590,25 @@
         virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) override {
             if (CC_UNLIKELY(!mListener || !info.updateWindowPositions)) return;
 
-            Matrix4 transform;
-            info.damageAccumulator->computeCurrentTransform(&transform);
             const RenderProperties& props = node.properties();
+            const bool enableClip = Properties::clipSurfaceViews;
 
-            uirenderer::Rect bounds(props.getWidth(), props.getHeight());
+            Matrix4 transform;
+            SkIRect clipBounds;
+            if (enableClip) {
+                uirenderer::Rect initialClipBounds;
+                props.getClippingRectForFlags(props.getClippingFlags(), &initialClipBounds);
+                clipBounds =
+                        info.damageAccumulator
+                                ->computeClipAndTransform(initialClipBounds.toSkRect(), &transform)
+                                .roundOut();
+            } else {
+                info.damageAccumulator->computeCurrentTransform(&transform);
+            }
             bool useStretchShader =
                     Properties::getStretchEffectBehavior() != StretchEffectBehavior::UniformScale;
             // Compute the transform bounds first before calculating the stretch
+            uirenderer::Rect bounds(props.getWidth(), props.getHeight());
             transform.mapRect(bounds);
 
             bool hasStretch = useStretchShader && info.stretchEffectCount;
@@ -614,10 +626,11 @@
                 bounds.roundOut();
             }
 
-            if (mPreviousPosition == bounds) {
+            if (mPreviousPosition == bounds && mPreviousClip == clipBounds) {
                 return;
             }
             mPreviousPosition = bounds;
+            mPreviousClip = clipBounds;
 
             ATRACE_NAME("Update SurfaceView position");
 
@@ -629,11 +642,23 @@
             // In particular if the app removes a view from the view tree before
             // this callback is dispatched, then we lose the position
             // information for this frame.
-            jboolean keepListening = env->CallStaticBooleanMethod(
-                    gPositionListener.clazz, gPositionListener.callPositionChanged, mListener,
-                    static_cast<jlong>(info.canvasContext.getFrameNumber()),
-                    static_cast<jint>(bounds.left), static_cast<jint>(bounds.top),
-                    static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom));
+            jboolean keepListening;
+            if (!enableClip) {
+                keepListening = env->CallStaticBooleanMethod(
+                        gPositionListener.clazz, gPositionListener.callPositionChanged, mListener,
+                        static_cast<jlong>(info.canvasContext.getFrameNumber()),
+                        static_cast<jint>(bounds.left), static_cast<jint>(bounds.top),
+                        static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom));
+            } else {
+                keepListening = env->CallStaticBooleanMethod(
+                        gPositionListener.clazz, gPositionListener.callPositionChanged2, mListener,
+                        static_cast<jlong>(info.canvasContext.getFrameNumber()),
+                        static_cast<jint>(bounds.left), static_cast<jint>(bounds.top),
+                        static_cast<jint>(bounds.right), static_cast<jint>(bounds.bottom),
+                        static_cast<jint>(clipBounds.fLeft), static_cast<jint>(clipBounds.fTop),
+                        static_cast<jint>(clipBounds.fRight),
+                        static_cast<jint>(clipBounds.fBottom));
+            }
             if (!keepListening) {
                 env->DeleteGlobalRef(mListener);
                 mListener = nullptr;
@@ -738,6 +763,7 @@
         JavaVM* mVm;
         jobject mListener;
         uirenderer::Rect mPreviousPosition;
+        uirenderer::Rect mPreviousClip;
     };
 
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
@@ -866,6 +892,8 @@
     gPositionListener.clazz = MakeGlobalRefOrDie(env, clazz);
     gPositionListener.callPositionChanged = GetStaticMethodIDOrDie(
             env, clazz, "callPositionChanged", "(Ljava/lang/ref/WeakReference;JIIII)Z");
+    gPositionListener.callPositionChanged2 = GetStaticMethodIDOrDie(
+            env, clazz, "callPositionChanged2", "(Ljava/lang/ref/WeakReference;JIIIIIIII)Z");
     gPositionListener.callApplyStretch = GetStaticMethodIDOrDie(
             env, clazz, "callApplyStretch", "(Ljava/lang/ref/WeakReference;JFFFFFFFFFF)Z");
     gPositionListener.callPositionLost = GetStaticMethodIDOrDie(
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index abd9284..576ebc1 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -24,6 +24,7 @@
 #include <SkColor.h>
 #include <android-base/stringprintf.h>
 #include <android-base/thread_annotations.h>
+#include <com_android_input_flags.h>
 #include <ftl/enum.h>
 
 #include <mutex>
@@ -34,6 +35,8 @@
 #define INDENT2 "    "
 #define INDENT3 "      "
 
+namespace input_flags = com::android::input::flags;
+
 namespace android {
 
 namespace {
@@ -63,10 +66,20 @@
 
 std::shared_ptr<PointerController> PointerController::create(
         const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
-        SpriteController& spriteController, bool enabled) {
+        SpriteController& spriteController, bool enabled, ControllerType type) {
     // using 'new' to access non-public constructor
-    std::shared_ptr<PointerController> controller = std::shared_ptr<PointerController>(
-            new PointerController(policy, looper, spriteController, enabled));
+    std::shared_ptr<PointerController> controller;
+    switch (type) {
+        case ControllerType::MOUSE:
+            controller = std::shared_ptr<PointerController>(
+                    new MousePointerController(policy, looper, spriteController, enabled));
+            break;
+        case ControllerType::LEGACY:
+        default:
+            controller = std::shared_ptr<PointerController>(
+                    new PointerController(policy, looper, spriteController, enabled));
+            break;
+    }
 
     /*
      * Now we need to hook up the constructed PointerController object to its callbacks.
@@ -375,4 +388,13 @@
     return dump;
 }
 
+// --- MousePointerController ---
+
+MousePointerController::MousePointerController(const sp<PointerControllerPolicyInterface>& policy,
+                                               const sp<Looper>& looper,
+                                               SpriteController& spriteController, bool enabled)
+      : PointerController(policy, looper, spriteController, enabled) {
+    PointerController::setPresentation(Presentation::POINTER);
+}
+
 } // namespace android
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index aa7ca3c..08e19a0 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -47,7 +47,8 @@
 public:
     static std::shared_ptr<PointerController> create(
             const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
-            SpriteController& spriteController, bool enabled);
+            SpriteController& spriteController, bool enabled,
+            ControllerType type = ControllerType::LEGACY);
 
     ~PointerController() override;
 
@@ -75,7 +76,7 @@
     void onDisplayInfosChangedLocked(const std::vector<gui::DisplayInfo>& displayInfos)
             REQUIRES(getLock());
 
-    std::string dump();
+    std::string dump() override;
 
 protected:
     using WindowListenerConsumer =
@@ -87,10 +88,10 @@
                       WindowListenerConsumer registerListener,
                       WindowListenerConsumer unregisterListener);
 
-private:
     PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
                       SpriteController& spriteController, bool enabled);
 
+private:
     friend PointerControllerContext::LooperCallback;
     friend PointerControllerContext::MessageHandler;
 
@@ -135,6 +136,24 @@
     void clearSpotsLocked() REQUIRES(getLock());
 };
 
+class MousePointerController : public PointerController {
+public:
+    /** A version of PointerController that controls one mouse pointer. */
+    MousePointerController(const sp<PointerControllerPolicyInterface>& policy,
+                           const sp<Looper>& looper, SpriteController& spriteController,
+                           bool enabled);
+
+    void setPresentation(Presentation) override {
+        LOG_ALWAYS_FATAL("Should not be called");
+    }
+    void setSpots(const PointerCoords*, const uint32_t*, BitSet32, int32_t) override {
+        LOG_ALWAYS_FATAL("Should not be called");
+    }
+    void clearSpots() override {
+        LOG_ALWAYS_FATAL("Should not be called");
+    }
+};
+
 } // namespace android
 
 #endif // _UI_POINTER_CONTROLLER_H
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index eea6357..5d211f4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -20,8 +20,8 @@
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
 import static android.content.Context.DEVICE_ID_DEFAULT;
 
-import static com.android.media.audio.flags.Flags.autoPublicVolumeApiHardening;
-import static com.android.media.audio.flags.Flags.FLAG_FOCUS_FREEZE_TEST_API;
+import static android.media.audio.Flags.autoPublicVolumeApiHardening;
+import static android.media.audio.Flags.FLAG_FOCUS_FREEZE_TEST_API;
 
 import android.Manifest;
 import android.annotation.CallbackExecutor;
@@ -686,6 +686,7 @@
             FLAG_ABSOLUTE_VOLUME,
     })
     @Retention(RetentionPolicy.SOURCE)
+    // TODO(308698465) remove due to potential conflict with the new flags class
     public @interface Flags {}
 
     /**
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 937151b..8ad3587 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -19,6 +19,7 @@
 import static android.media.MediaRouter2Utils.toUniqueId;
 
 import static com.android.media.flags.Flags.FLAG_ENABLE_AUDIO_POLICIES_DEVICE_AND_BLUETOOTH_CONTROLLER;
+import static com.android.media.flags.Flags.FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES;
 
 import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
@@ -306,6 +307,7 @@
      *
      * @see #getType
      */
+    @FlaggedApi(FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES)
     public static final int TYPE_REMOTE_TABLET = 1004;
 
     /**
@@ -316,6 +318,7 @@
      *
      * @see #getType
      */
+    @FlaggedApi(FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES)
     public static final int TYPE_REMOTE_TABLET_DOCKED = 1005;
 
     /**
@@ -326,6 +329,7 @@
      *
      * @see #getType
      */
+    @FlaggedApi(FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES)
     public static final int TYPE_REMOTE_COMPUTER = 1006;
 
     /**
@@ -336,6 +340,7 @@
      *
      * @see #getType
      */
+    @FlaggedApi(FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES)
     public static final int TYPE_REMOTE_GAME_CONSOLE = 1007;
 
     /**
@@ -346,6 +351,7 @@
      *
      * @see #getType
      */
+    @FlaggedApi(FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES)
     public static final int TYPE_REMOTE_CAR = 1008;
 
     /**
@@ -356,6 +362,7 @@
      *
      * @see #getType
      */
+    @FlaggedApi(FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES)
     public static final int TYPE_REMOTE_SMARTWATCH = 1009;
 
     /**
@@ -366,6 +373,7 @@
      *
      * @see #getType
      */
+    @FlaggedApi(FLAG_ENABLE_NEW_MEDIA_ROUTE_2_INFO_TYPES)
     public static final int TYPE_REMOTE_SMARTPHONE = 1010;
 
     /**
diff --git a/media/java/android/media/RingtoneSelection.java b/media/java/android/media/RingtoneSelection.java
index b74b6a3..b7c3721 100644
--- a/media/java/android/media/RingtoneSelection.java
+++ b/media/java/android/media/RingtoneSelection.java
@@ -642,6 +642,7 @@
      * allowing the user to configure their selection. Once a selection is stored as a Uri, then
      * the RingtoneSelection can be loaded directly using {@link RingtoneSelection#fromUri}.
      */
+    @FlaggedApi(Flags.FLAG_HAPTICS_CUSTOMIZATION_ENABLED)
     public static final class Builder {
         private Uri mSoundUri;
         private Uri mVibrationUri;
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 9ced2a4..e168498 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -49,7 +49,6 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.media.audio.flags.Flags;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/media/java/android/media/flags/media_better_together.aconfig b/media/java/android/media/flags/media_better_together.aconfig
index 386534b..dd1df47 100644
--- a/media/java/android/media/flags/media_better_together.aconfig
+++ b/media/java/android/media/flags/media_better_together.aconfig
@@ -15,29 +15,36 @@
 }
 
 flag {
-    namespace: "media_solutions"
     name: "enable_audio_policies_device_and_bluetooth_controller"
+    namespace: "media_solutions"
     description: "Use Audio Policies implementation for device and Bluetooth route controllers."
     bug: "280576228"
 }
 
 flag {
-    namespace: "media_solutions"
     name: "disable_screen_off_broadcast_receiver"
+    namespace: "media_solutions"
     description: "Disables the broadcast receiver that prevents scanning when the screen is off."
     bug: "304234628"
 }
 
 flag {
-    namespace: "media_solutions"
     name: "fallback_to_default_handling_when_media_session_has_fixed_volume_handling"
+    namespace: "media_solutions"
     description: "Fallbacks to the default handling for volume adjustment when media session has fixed volume handling and its app is in the foreground and setting a media controller."
     bug: "293743975"
 }
 
 flag {
-    namespace: "media_solutions"
     name: "enable_waiting_state_for_system_session_creation_request"
+    namespace: "media_solutions"
     description: "Introduces a waiting state for the session creation request and prevents it from early failing when the selectedRoute from the bluetooth stack doesn't match the pending request route id."
     bug: "307723189"
 }
+
+flag {
+    name: "enable_new_media_route_2_info_types"
+    namespace: "media_solutions"
+    description: "Enables the following type constants in MediaRoute2Info: CAR, COMPUTER, GAME_CONSOLE, SMARTPHONE, SMARTWATCH, TABLET, TABLET_DOCKED. Note that this doesn't gate any behavior. It only guards some API int symbols."
+    bug: "301713440"
+}
diff --git a/media/java/android/media/midi/MidiUmpDeviceService.java b/media/java/android/media/midi/MidiUmpDeviceService.java
index c54bfce..bbbef47 100644
--- a/media/java/android/media/midi/MidiUmpDeviceService.java
+++ b/media/java/android/media/midi/MidiUmpDeviceService.java
@@ -16,8 +16,6 @@
 
 package android.media.midi;
 
-import static com.android.media.midi.flags.Flags.FLAG_VIRTUAL_UMP;
-
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -57,11 +55,11 @@
  *             android:resource="@xml/device_info" />
  * &lt;/service></pre>
  */
-@FlaggedApi(FLAG_VIRTUAL_UMP)
+@FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
 public abstract class MidiUmpDeviceService extends Service {
     private static final String TAG = "MidiUmpDeviceService";
 
-    @FlaggedApi(FLAG_VIRTUAL_UMP)
+    @FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
     public static final String SERVICE_INTERFACE = "android.media.midi.MidiUmpDeviceService";
 
     private IMidiManager mMidiManager;
@@ -80,7 +78,7 @@
         }
     };
 
-    @FlaggedApi(FLAG_VIRTUAL_UMP)
+    @FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
     @Override
     public void onCreate() {
         mMidiManager = IMidiManager.Stub.asInterface(
@@ -118,7 +116,7 @@
      * The number of input and output ports must be equal and non-zero.
      * @return list of MidiReceivers
      */
-    @FlaggedApi(FLAG_VIRTUAL_UMP)
+    @FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
     public abstract @NonNull List<MidiReceiver> onGetInputPortReceivers();
 
     /**
@@ -127,7 +125,7 @@
      * The number of input and output ports must be equal and non-zero.
      * @return the list of MidiReceivers
      */
-    @FlaggedApi(FLAG_VIRTUAL_UMP)
+    @FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
     public final @NonNull List<MidiReceiver> getOutputPortReceivers() {
         if (mServer == null) {
             return new ArrayList<MidiReceiver>();
@@ -140,7 +138,7 @@
      * Returns the {@link MidiDeviceInfo} instance for this service
      * @return the MidiDeviceInfo of the virtual MIDI device if it was successfully created
      */
-    @FlaggedApi(FLAG_VIRTUAL_UMP)
+    @FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
     public final @Nullable MidiDeviceInfo getDeviceInfo() {
         return mDeviceInfo;
     }
@@ -149,7 +147,7 @@
      * Called to notify when the {@link MidiDeviceStatus} has changed
      * @param status the current status of the MIDI device
      */
-    @FlaggedApi(FLAG_VIRTUAL_UMP)
+    @FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
     public void onDeviceStatusChanged(@NonNull MidiDeviceStatus status) {
     }
 
@@ -157,11 +155,11 @@
      * Called to notify when the virtual MIDI device running in this service has been closed by
      * all its clients
      */
-    @FlaggedApi(FLAG_VIRTUAL_UMP)
+    @FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
     public void onClose() {
     }
 
-    @FlaggedApi(FLAG_VIRTUAL_UMP)
+    @FlaggedApi(Flags.FLAG_VIRTUAL_UMP)
     @Override
     public @Nullable IBinder onBind(@NonNull Intent intent) {
         if (SERVICE_INTERFACE.equals(intent.getAction()) && mServer != null) {
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index ed1072c..6031ef7 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -81,6 +81,7 @@
         "libhidlallocatorutils",
         "libhidlbase",
         "libsonivox",
+        "server_configurable_flags",
         "android.hardware.cas@1.0",
         "android.hardware.cas.native@1.0",
         "android.hardware.drm@1.3",
@@ -99,6 +100,7 @@
     static_libs: [
         "libgrallocusage",
         "libmedia_midiiowrapper",
+        "android.media.playback.flags-aconfig-cc",
     ],
 
     include_dirs: [
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 1458758..2a10fa7 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -35,7 +35,9 @@
 #include "android_media_MediaDataSource.h"
 #include "android_media_Streams.h"
 #include "android_util_Binder.h"
+#include <com_android_media_playback_flags.h>
 
+namespace playback_flags = com::android::media::playback::flags;
 using namespace android;
 
 struct fields_t {
@@ -374,9 +376,12 @@
         jniThrowException(env, "java/lang/IllegalStateException", "No retriever available");
         return NULL;
     }
-    // For getFrameAtTime family of calls, default to ANDROID_BITMAP_FORMAT_RGB_565
-    // to keep the behavior consistent with older releases
-    AndroidBitmapFormat colorFormat = getColorFormat(env, params, ANDROID_BITMAP_FORMAT_RGB_565);
+
+    AndroidBitmapFormat defaultColorFormat =
+            playback_flags::mediametadataretriever_default_rgba8888()
+            ? ANDROID_BITMAP_FORMAT_RGBA_8888
+            : ANDROID_BITMAP_FORMAT_RGB_565;
+    AndroidBitmapFormat colorFormat = getColorFormat(env, params, defaultColorFormat);
 
     // Call native method to retrieve a video frame
     VideoFrame *videoFrame = NULL;
diff --git a/media/jni/playback_flags.aconfig b/media/jni/playback_flags.aconfig
new file mode 100644
index 0000000..2bb0ec5
--- /dev/null
+++ b/media/jni/playback_flags.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.media.playback.flags"
+
+flag {
+  name: "mediametadataretriever_default_rgba8888"
+  namespace: "media_solutions"
+  description: "Change MediaMetadataRetriever to use RGBA8888 for bitmap handling by default."
+  bug: "298965955"
+}
diff --git a/media/tests/MediaFrameworkTest/Android.bp b/media/tests/MediaFrameworkTest/Android.bp
index bdd7afe..7a329bc 100644
--- a/media/tests/MediaFrameworkTest/Android.bp
+++ b/media/tests/MediaFrameworkTest/Android.bp
@@ -20,6 +20,8 @@
         "androidx.test.ext.junit",
         "androidx.test.rules",
         "android-ex-camera2",
+        "android.media.playback.flags-aconfig-java",
+        "flag-junit",
         "testables",
         "testng",
         "truth",
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
index f70d2d1..e3d3897 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaMetadataRetrieverTest.java
@@ -16,19 +16,27 @@
 
 package com.android.mediaframeworktest.unit;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.graphics.Bitmap;
 import android.media.MediaMetadataRetriever;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
 import android.util.Log;
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.media.playback.flags.Flags;
 import com.android.mediaframeworktest.MediaNames;
 import com.android.mediaframeworktest.MediaProfileReader;
 
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -40,6 +48,9 @@
 
     private static final String TAG = "MediaMetadataRetrieverTest";
 
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     // Test album art extraction.
     @MediumTest
     @Test
@@ -284,6 +295,34 @@
         assertTrue(!hasFailed);
     }
 
+    /** Test the thumbnail is generated when the default is set to RGBA8888 */
+    @MediumTest
+    // TODO(b/305160754) Remove the following annotation and use SetFlagsRule.enableFlags
+    @RequiresFlagsEnabled(Flags.FLAG_MEDIAMETADATARETRIEVER_DEFAULT_RGBA8888)
+    @Test
+    public void testGetFrameAtTimeWithRGBA8888Flag_Set() throws IOException {
+        try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
+            retriever.setDataSource(MediaNames.TEST_PATH_1);
+            Bitmap bitmap = retriever.getFrameAtTime(-1);
+            assertNotNull(bitmap);
+            assertEquals(Bitmap.Config.ARGB_8888, bitmap.getConfig());
+        }
+    }
+
+    /** Test the thumbnail is generated when the default is not set to RGBA8888 */
+    @MediumTest
+    // TODO(b/305160754) Remove the following annotation and use SetFlagsRule.disableFlags
+    @RequiresFlagsDisabled(Flags.FLAG_MEDIAMETADATARETRIEVER_DEFAULT_RGBA8888)
+    @Test
+    public void testGetFrameAtTimeWithRGBA8888Flag_Unset() throws IOException {
+        try (MediaMetadataRetriever retriever = new MediaMetadataRetriever()) {
+            retriever.setDataSource(MediaNames.TEST_PATH_1);
+            Bitmap bitmap = retriever.getFrameAtTime(-1);
+            assertNotNull(bitmap);
+            assertEquals(Bitmap.Config.RGB_565, bitmap.getConfig());
+        }
+    }
+
     // TODO:
     // Encode and test for the correct mix of metadata elements on a per-file basis?
     // We should be able to compare the actual returned metadata with the expected metadata
diff --git a/packages/SettingsLib/Spa/build.gradle.kts b/packages/SettingsLib/Spa/build.gradle.kts
index 1c8ddcb..80b944f 100644
--- a/packages/SettingsLib/Spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/build.gradle.kts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,11 +25,16 @@
     alias(libs.plugins.kotlin.android) apply false
 }
 
+val androidTop : String = File(rootDir, "../../../../..").canonicalPath
+
 allprojects {
+    extra["androidTop"] = androidTop
     extra["jetpackComposeVersion"] = "1.6.0-alpha08"
 }
 
 subprojects {
+    layout.buildDirectory.set(file("$androidTop/out/gradle-spa/$name"))
+
     plugins.withType<AndroidBasePlugin> {
         configure<BaseExtension> {
             compileSdkVersion(34)
@@ -38,10 +43,11 @@
                 minSdk = 21
                 targetSdk = 34
             }
+        }
 
-            compileOptions {
-                sourceCompatibility = JavaVersion.VERSION_17
-                targetCompatibility = JavaVersion.VERSION_17
+        configure<JavaPluginExtension> {
+            toolchain {
+                languageVersion.set(JavaLanguageVersion.of(libs.versions.jvm.get()))
             }
         }
     }
@@ -60,7 +66,7 @@
 
     tasks.withType<KotlinCompile> {
         kotlinOptions {
-            jvmTarget = "17"
+            jvmTarget = libs.versions.jvm.get()
             freeCompilerArgs = listOf("-Xjvm-default=all")
         }
     }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt
index 98b27b7..6caec07 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/itemList/ItemOperatePage.kt
@@ -17,9 +17,11 @@
 package com.android.settingslib.spa.gallery.itemList
 
 import android.os.Bundle
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.core.os.bundleOf
 import androidx.navigation.NavType
 import androidx.navigation.navArgument
@@ -79,13 +81,13 @@
         entryList.add(
             SettingsEntryBuilder.create("ItemOp", owner)
                 .setUiLayoutFn {
-                    val checked = rememberSaveable { mutableStateOf(false) }
+                    var checked by rememberSaveable { mutableStateOf(false) }
                     SwitchPreference(remember {
                         object : SwitchPreferenceModel {
                             override val title = "Item operation: $opName"
-                            override val checked = checked
+                            override val checked = { checked }
                             override val onCheckedChange =
-                                { newChecked: Boolean -> checked.value = newChecked }
+                                { newChecked: Boolean -> checked = newChecked }
                         }
                     })
                 }.build(),
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
index 5d6aa03..d763f77 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/ArgumentPageModel.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,7 +25,6 @@
 import com.android.settingslib.spa.framework.common.PageModel
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.util.getIntArg
 import com.android.settingslib.spa.framework.util.getStringArg
 import com.android.settingslib.spa.framework.util.navLink
@@ -110,7 +109,7 @@
     fun genStringParamPreferenceModel(): PreferenceModel {
         return object : PreferenceModel {
             override val title = STRING_PARAM_TITLE
-            override val summary = stateOf(stringParam!!)
+            override val summary = { stringParam!! }
         }
     }
 
@@ -118,7 +117,7 @@
     fun genIntParamPreferenceModel(): PreferenceModel {
         return object : PreferenceModel {
             override val title = INT_PARAM_TITLE
-            override val summary = stateOf(intParam!!.toString())
+            override val summary = { intParam!!.toString() }
         }
     }
 
@@ -130,7 +129,7 @@
         )
         return object : PreferenceModel {
             override val title = PAGE_TITLE
-            override val summary = stateOf(summaryArray.joinToString(", "))
+            override val summary = { summaryArray.joinToString(", ") }
             override val onClick = navigator(
                 SettingsPageProviderEnum.ARGUMENT.name + parameter.navLink(arguments)
             )
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPageProvider.kt
index 50c0eb7..345b47a 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/FooterPageProvider.kt
@@ -26,7 +26,6 @@
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.gallery.R
 import com.android.settingslib.spa.widget.preference.Preference
@@ -50,7 +49,7 @@
                     Preference(remember {
                         object : PreferenceModel {
                             override val title = "Some Preference"
-                            override val summary = stateOf("Some summary")
+                            override val summary = { "Some summary" }
                         }
                     })
                 }.build()
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/ListPreferencePageProvider.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/ListPreferencePageProvider.kt
index 43b6d0b..d7de9b4 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/ListPreferencePageProvider.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/ListPreferencePageProvider.kt
@@ -99,7 +99,7 @@
     ListPreference(remember {
         object : ListPreferenceModel {
             override val title = "Preferred network type"
-            override val enabled = enabled
+            override val enabled = { enabled.value }
             override val options = listOf(
                 ListPreferenceOption(id = 1, text = "5G (recommended)"),
                 ListPreferenceOption(id = 2, text = "LTE"),
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
index 442ace8..0d85c0e3 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/MainSwitchPreferencePage.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,16 +18,17 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.MainSwitchPreference
 import com.android.settingslib.spa.widget.preference.Preference
@@ -43,13 +44,13 @@
     override fun buildEntry(arguments: Bundle?): List<SettingsEntry> {
         val entryList = mutableListOf<SettingsEntry>()
         entryList.add(
-            SettingsEntryBuilder.create( "MainSwitchPreference", owner)
+            SettingsEntryBuilder.create("MainSwitchPreference", owner)
                 .setUiLayoutFn {
                     SampleMainSwitchPreference()
                 }.build()
         )
         entryList.add(
-            SettingsEntryBuilder.create( "MainSwitchPreference not changeable", owner)
+            SettingsEntryBuilder.create("MainSwitchPreference not changeable", owner)
                 .setUiLayoutFn {
                     SampleNotChangeableMainSwitchPreference()
                 }.build()
@@ -75,25 +76,25 @@
 
 @Composable
 private fun SampleMainSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     MainSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "MainSwitchPreference"
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleNotChangeableMainSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     MainSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "Not changeable"
-            override val changeable = stateOf(false)
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val changeable = { false }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePageProvider.kt
similarity index 94%
rename from packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
rename to packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePageProvider.kt
index 238204a..96de1a7 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePageProvider.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -34,7 +34,6 @@
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
 import com.android.settingslib.spa.framework.common.createSettingsPage
-import com.android.settingslib.spa.framework.compose.toState
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.framework.util.createIntent
 import com.android.settingslib.spa.gallery.R
@@ -136,8 +135,8 @@
                     Preference(
                         object : PreferenceModel {
                             override val title = ASYNC_PREFERENCE_TITLE
-                            override val summary = model.asyncSummary
-                            override val enabled = model.asyncEnable
+                            override val summary = { model.asyncSummary.value }
+                            override val enabled = { model.asyncEnable.value }
                         }
                     )
                 }
@@ -170,7 +169,7 @@
                     Preference(
                         object : PreferenceModel {
                             override val title = MANUAL_UPDATE_PREFERENCE_TITLE
-                            override val summary = manualUpdaterSummary
+                            override val summary = { manualUpdaterSummary.value }
                             override val onClick = { model.manualUpdaterOnClick() }
                             override val icon = @Composable {
                                 SettingsIcon(imageVector = Icons.Outlined.TouchApp)
@@ -205,11 +204,13 @@
             createEntry(EntryEnum.AUTO_UPDATE_PREFERENCE)
                 .setUiLayoutFn {
                     val model = PreferencePageModel.create()
-                    val autoUpdaterSummary = remember { model.getAutoUpdaterSummary() }
+                    val autoUpdaterSummary = remember {
+                        model.getAutoUpdaterSummary()
+                    }.observeAsState(" ")
                     Preference(
                         object : PreferenceModel {
                             override val title = AUTO_UPDATE_PREFERENCE_TITLE
-                            override val summary = autoUpdaterSummary.observeAsState(" ")
+                            override val summary = { autoUpdaterSummary.value }
                             override val icon = @Composable {
                                 SettingsIcon(imageVector = Icons.Outlined.Autorenew)
                             }
@@ -250,12 +251,12 @@
 
     private fun singleLineSummaryEntry() = createEntry(EntryEnum.SINGLE_LINE_SUMMARY_PREFERENCE)
         .setUiLayoutFn {
+            val summary = stringResource(R.string.single_line_summary_preference_summary)
             Preference(
                 model = object : PreferenceModel {
                     override val title: String =
                         stringResource(R.string.single_line_summary_preference_title)
-                    override val summary =
-                        stringResource(R.string.single_line_summary_preference_summary).toState()
+                    override val summary = { summary }
                 },
                 singleLineSummary = true,
             )
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePageProvider.kt
similarity index 84%
rename from packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
rename to packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePageProvider.kt
index b67e066..f2225fa 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePageProvider.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,17 +20,18 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.AirplanemodeActive
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.produceState
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -98,32 +99,32 @@
 
 @Composable
 private fun SampleSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleSwitchPreferenceWithSummary() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val summary = stateOf("With summary")
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val summary = { "With summary" }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleSwitchPreferenceWithAsyncSummary() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     val summary = produceState(initialValue = " ") {
         delay(1000L)
         value = "Async summary"
@@ -131,35 +132,35 @@
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val summary = summary
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val summary = { summary.value }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleNotChangeableSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val summary = stateOf("Not changeable")
-            override val changeable = stateOf(false)
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val summary = { "Not changeable" }
+            override val changeable = { false }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
 
 @Composable
 private fun SampleSwitchPreferenceWithIcon() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
             override val icon = @Composable {
                 SettingsIcon(imageVector = Icons.Outlined.AirplanemodeActive)
             }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePageProvider.kt
similarity index 84%
rename from packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
rename to packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePageProvider.kt
index a2cd283..19de31d 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/TwoTargetSwitchPreferencePageProvider.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,17 +18,18 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.produceState
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
 import com.android.settingslib.spa.framework.common.SettingsEntry
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.common.createSettingsPage
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
@@ -89,32 +90,32 @@
 
 @Composable
 private fun SampleTwoTargetSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     TwoTargetSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "TwoTargetSwitchPreference"
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     }) {}
 }
 
 @Composable
 private fun SampleTwoTargetSwitchPreferenceWithSummary() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     TwoTargetSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "TwoTargetSwitchPreference"
-            override val summary = stateOf("With summary")
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val summary = { "With summary" }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     }) {}
 }
 
 @Composable
 private fun SampleTwoTargetSwitchPreferenceWithAsyncSummary() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     val summary = produceState(initialValue = " ") {
         delay(1000L)
         value = "Async summary"
@@ -122,23 +123,23 @@
     TwoTargetSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "TwoTargetSwitchPreference"
-            override val summary = summary
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val summary = { summary.value }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     }) {}
 }
 
 @Composable
 private fun SampleNotChangeableTwoTargetSwitchPreference() {
-    val checked = rememberSaveable { mutableStateOf(true) }
+    var checked by rememberSaveable { mutableStateOf(true) }
     TwoTargetSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "TwoTargetSwitchPreference"
-            override val summary = stateOf("Not changeable")
-            override val changeable = stateOf(false)
-            override val checked = checked
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val summary = { "Not changeable" }
+            override val changeable = { false }
+            override val checked = { checked }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     }) {}
 }
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPageProvider.kt
similarity index 87%
rename from packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
rename to packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPageProvider.kt
index aeba6ea..5c5c504 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/ui/SpinnerPageProvider.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,10 +18,8 @@
 
 import android.os.Bundle
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
+import androidx.compose.runtime.mutableIntStateOf
 import androidx.compose.runtime.saveable.rememberSaveable
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.tooling.preview.Preview
@@ -58,7 +56,7 @@
     @Composable
     override fun Page(arguments: Bundle?) {
         RegularScaffold(title = getTitle(arguments)) {
-            var selectedId by rememberSaveable { mutableStateOf(1) }
+            var selectedId by rememberSaveable { mutableIntStateOf(1) }
             Spinner(
                 options = (1..3).map { SpinnerOption(id = it, text = "Option $it") },
                 selectedId = selectedId,
@@ -66,9 +64,7 @@
             )
             Preference(object : PreferenceModel {
                 override val title = "Selected id"
-                override val summary = remember {
-                    derivedStateOf { selectedId.toString() }
-                }
+                override val summary = { selectedId.toString() }
             })
         }
     }
diff --git a/packages/SettingsLib/Spa/gradle/libs.versions.toml b/packages/SettingsLib/Spa/gradle/libs.versions.toml
index aafae5f..fdb0471 100644
--- a/packages/SettingsLib/Spa/gradle/libs.versions.toml
+++ b/packages/SettingsLib/Spa/gradle/libs.versions.toml
@@ -18,6 +18,7 @@
 agp = "8.1.2"
 compose-compiler = "1.5.1"
 dexmaker-mockito = "2.28.3"
+jvm = "17"
 kotlin = "1.9.0"
 truth = "1.1.5"
 
diff --git a/packages/SettingsLib/Spa/screenshot/build.gradle.kts b/packages/SettingsLib/Spa/screenshot/build.gradle.kts
new file mode 100644
index 0000000..03e9d7d
--- /dev/null
+++ b/packages/SettingsLib/Spa/screenshot/build.gradle.kts
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+plugins {
+    alias(libs.plugins.android.library)
+    alias(libs.plugins.kotlin.android)
+}
+
+val androidTop: String by extra
+
+android {
+    namespace = "com.android.settingslib.spa.screenshot"
+
+    defaultConfig {
+        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    sourceSets {
+        sourceSets.getByName("main") {
+            java.setSrcDirs(
+                listOf("$androidTop/platform_testing/libraries/screenshot/src/main/java")
+            )
+        }
+        sourceSets.getByName("androidTest") {
+            kotlin.setSrcDirs(listOf("src"))
+            res.setSrcDirs(listOf("res"))
+            manifest.srcFile("AndroidManifest.xml")
+        }
+    }
+    buildFeatures {
+        compose = true
+    }
+}
+
+dependencies {
+    androidTestImplementation(project(":spa"))
+    androidTestImplementation(project(":testutils"))
+    androidTestImplementation(libs.dexmaker.mockito)
+}
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/Bitmap.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/Bitmap.kt
index 814d4a1..fb65d65 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/Bitmap.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/Bitmap.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.util
 
 import android.graphics.Bitmap
 import android.graphics.Canvas
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/DefaultDeviceEmulationSpec.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/DefaultDeviceEmulationSpec.kt
deleted file mode 100644
index d7f42b3..0000000
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/DefaultDeviceEmulationSpec.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.spa.screenshot
-
-import platform.test.screenshot.DeviceEmulationSpec
-import platform.test.screenshot.DisplaySpec
-
-/**
- * The emulations specs for all 8 permutations of:
- * - phone or tablet.
- * - dark of light mode.
- * - portrait or landscape.
- */
-val DeviceEmulationSpec.Companion.PhoneAndTabletFull
-    get() = PhoneAndTabletFullSpec
-
-private val PhoneAndTabletFullSpec =
-    DeviceEmulationSpec.forDisplays(Displays.Phone, Displays.Tablet)
-
-/**
- * The emulations specs of:
- * - phone + light mode + portrait.
- * - phone + light mode + landscape.
- * - tablet + dark mode + portrait.
- *
- * This allows to test the most important permutations of a screen/layout with only 3
- * configurations.
- */
-val DeviceEmulationSpec.Companion.PhoneAndTabletMinimal
-    get() = PhoneAndTabletMinimalSpec
-
-private val PhoneAndTabletMinimalSpec =
-    DeviceEmulationSpec.forDisplays(Displays.Phone, isDarkTheme = false) +
-        DeviceEmulationSpec.forDisplays(Displays.Tablet, isDarkTheme = true, isLandscape = false)
-
-object Displays {
-    val Phone =
-        DisplaySpec(
-            "phone",
-            width = 1440,
-            height = 3120,
-            densityDpi = 560,
-        )
-
-    val Tablet =
-        DisplaySpec(
-            "tablet",
-            width = 2560,
-            height = 1600,
-            densityDpi = 320,
-        )
-}
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/SettingsGoldenImagePathManager.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/SettingsGoldenImagePathManager.kt
index 25bc098..f5fba7f 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/SettingsGoldenImagePathManager.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/SettingsGoldenImagePathManager.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.util
 
 import androidx.test.platform.app.InstrumentationRegistry
 import platform.test.screenshot.GoldenImagePathManager
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/SettingsScreenshotTestRule.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/SettingsScreenshotTestRule.kt
index 7a7cf31..3dcefe9 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/SettingsScreenshotTestRule.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/util/SettingsScreenshotTestRule.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.util
 
 import androidx.activity.ComponentActivity
 import androidx.compose.material3.MaterialTheme
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/button/ActionButtonsScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/button/ActionButtonsScreenshotTest.kt
index b2e0b18..b74a243 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/button/ActionButtonsScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/button/ActionButtonsScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.button
 
 import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.automirrored.outlined.Launch
 import androidx.compose.material.icons.outlined.Delete
-import androidx.compose.material.icons.outlined.Launch
 import androidx.compose.material.icons.outlined.WarningAmber
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.button.ActionButton
 import com.android.settingslib.spa.widget.button.ActionButtons
 import org.junit.Rule
@@ -27,6 +28,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
@@ -48,7 +50,7 @@
     fun test() {
         screenshotRule.screenshotTest("actionButtons") {
             val actionButtons = listOf(
-                ActionButton(text = "Open", imageVector = Icons.Outlined.Launch) {},
+                ActionButton(text = "Open", imageVector = Icons.AutoMirrored.Outlined.Launch) {},
                 ActionButton(text = "Uninstall", imageVector = Icons.Outlined.Delete) {},
                 ActionButton(text = "Force stop", imageVector = Icons.Outlined.WarningAmber) {},
             )
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/BarChartScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/BarChartScreenshotTest.kt
index e6decb1..051ef77 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/BarChartScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/BarChartScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.chart
 
 import androidx.compose.material3.MaterialTheme
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.chart.BarChart
 import com.android.settingslib.spa.widget.chart.BarChartData
 import com.android.settingslib.spa.widget.chart.BarChartModel
@@ -26,6 +27,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
@@ -61,7 +63,7 @@
                     override val colors = listOf(color)
                     override val xValueFormatter =
                         IAxisValueFormatter { value, _ ->
-                            "${WeekDay.values()[value.toInt()]}"
+                            "${WeekDay.entries[value.toInt()]}"
                         }
                     override val yValueFormatter =
                         IAxisValueFormatter { value, _ ->
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/LineChartScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/LineChartScreenshotTest.kt
index f9d93f8..3822571 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/LineChartScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/LineChartScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.chart
 
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.chart.LineChart
 import com.android.settingslib.spa.widget.chart.LineChartData
 import com.android.settingslib.spa.widget.chart.LineChartModel
@@ -26,6 +27,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
@@ -59,7 +61,7 @@
                     )
                     override val xValueFormatter =
                         IAxisValueFormatter { value, _ ->
-                            "${WeekDay.values()[value.toInt()]}"
+                            "${WeekDay.entries[value.toInt()]}"
                         }
                     override val yValueFormatter =
                         IAxisValueFormatter { value, _ ->
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/PieChartScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/PieChartScreenshotTest.kt
index 34ded3c..6dd62ec 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/PieChartScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/chart/PieChartScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.chart
 
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.chart.PieChart
 import com.android.settingslib.spa.widget.chart.PieChartData
 import com.android.settingslib.spa.widget.chart.PieChartModel
@@ -24,6 +25,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
@@ -56,4 +58,4 @@
             )
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/illustration/ImageIllustrationScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/illustration/ImageIllustrationScreenshotTest.kt
index 91aca05..0ccfc0b 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/illustration/ImageIllustrationScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/illustration/ImageIllustrationScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.illustration
 
+import com.android.settingslib.spa.screenshot.R
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.illustration.Illustration
 import com.android.settingslib.spa.widget.illustration.IllustrationModel
 import com.android.settingslib.spa.widget.illustration.ResourceType
@@ -24,6 +26,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/MainSwitchPreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/MainSwitchPreferenceScreenshotTest.kt
index a366b9e..e547d26 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/MainSwitchPreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/MainSwitchPreferenceScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.preference
 
 import androidx.compose.foundation.layout.Column
-import com.android.settingslib.spa.framework.compose.stateOf
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.preference.MainSwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import org.junit.Rule
@@ -25,6 +25,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
@@ -49,14 +50,14 @@
                 MainSwitchPreference(
                     object : SwitchPreferenceModel {
                         override val title = "MainSwitchPreference"
-                        override val checked = stateOf(false)
+                        override val checked = { false }
                         override val onCheckedChange = null
                     })
 
                 MainSwitchPreference(object : SwitchPreferenceModel {
                     override val title = "Not changeable"
-                    override val changeable = stateOf(false)
-                    override val checked = stateOf(true)
+                    override val changeable = { false }
+                    override val checked = { true }
                     override val onCheckedChange = null
                 })
             }
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/PreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/PreferenceScreenshotTest.kt
index d72152c..dd6b553 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/PreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/PreferenceScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.preference
 
 import androidx.compose.foundation.layout.Column
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.Autorenew
 import androidx.compose.material.icons.outlined.DisabledByDefault
 import androidx.compose.runtime.Composable
-import com.android.settingslib.spa.framework.compose.toState
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spa.widget.ui.SettingsIcon
@@ -30,6 +30,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
@@ -61,18 +62,18 @@
 
                 Preference(object : PreferenceModel {
                     override val title = TITLE
-                    override val summary = SUMMARY.toState()
+                    override val summary = { SUMMARY }
                 })
 
                 Preference(object : PreferenceModel {
                     override val title = TITLE
-                    override val summary = LONG_SUMMARY.toState()
+                    override val summary = { LONG_SUMMARY }
                 })
 
                 Preference(object : PreferenceModel {
                     override val title = TITLE
-                    override val summary = SUMMARY.toState()
-                    override val enabled = false.toState()
+                    override val summary = { SUMMARY }
+                    override val enabled = { false }
                     override val icon = @Composable {
                         SettingsIcon(imageVector = Icons.Outlined.DisabledByDefault)
                     }
@@ -80,7 +81,7 @@
 
                 Preference(object : PreferenceModel {
                     override val title = TITLE
-                    override val summary = SUMMARY.toState()
+                    override val summary = { SUMMARY }
                     override val icon = @Composable {
                         SettingsIcon(imageVector = Icons.Outlined.Autorenew)
                     }
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/ProgressBarPreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/ProgressBarPreferenceScreenshotTest.kt
index 5fcaf85..357d815 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/ProgressBarPreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/ProgressBarPreferenceScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.preference
 
 import androidx.compose.foundation.layout.Column
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.Delete
 import androidx.compose.material.icons.outlined.SystemUpdate
 import androidx.compose.runtime.Composable
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.preference.ProgressBarPreference
 import com.android.settingslib.spa.widget.preference.ProgressBarPreferenceModel
 import com.android.settingslib.spa.widget.preference.ProgressBarWithDataPreference
@@ -30,6 +31,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SliderPreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SliderPreferenceScreenshotTest.kt
index 48c922d..fdee7ee 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SliderPreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SliderPreferenceScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.preference
 
 import androidx.compose.foundation.layout.Column
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.AccessAlarm
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.preference.SliderPreference
 import com.android.settingslib.spa.widget.preference.SliderPreferenceModel
 import org.junit.Rule
@@ -26,6 +27,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SwitchPreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SwitchPreferenceScreenshotTest.kt
index 2c84a8e..6966a74 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SwitchPreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/SwitchPreferenceScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.preference
 
 import androidx.compose.foundation.layout.Column
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.AirplanemodeActive
 import androidx.compose.runtime.Composable
-import com.android.settingslib.spa.framework.compose.stateOf
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spa.widget.ui.SettingsIcon
@@ -29,6 +29,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
@@ -63,7 +64,7 @@
 private fun SampleSwitchPreference() {
     SwitchPreference(object : SwitchPreferenceModel {
         override val title = "SwitchPreference"
-        override val checked = stateOf(false)
+        override val checked = { false }
         override val onCheckedChange = null
     })
 }
@@ -72,8 +73,8 @@
 private fun SampleSwitchPreferenceWithSummary() {
     SwitchPreference(object : SwitchPreferenceModel {
         override val title = "SwitchPreference"
-        override val summary = stateOf("With summary")
-        override val checked = stateOf(true)
+        override val summary = { "With summary" }
+        override val checked = { true }
         override val onCheckedChange = null
     })
 }
@@ -82,9 +83,9 @@
 private fun SampleNotChangeableSwitchPreference() {
     SwitchPreference(object : SwitchPreferenceModel {
         override val title = "SwitchPreference"
-        override val summary = stateOf("Not changeable")
-        override val changeable = stateOf(false)
-        override val checked = stateOf(true)
+        override val summary = { "Not changeable" }
+        override val changeable = { false }
+        override val checked = { true }
         override val onCheckedChange = null
     })
 }
@@ -93,7 +94,7 @@
 private fun SampleSwitchPreferenceWithIcon() {
     SwitchPreference(object : SwitchPreferenceModel {
         override val title = "SwitchPreference"
-        override val checked = stateOf(true)
+        override val checked = { true }
         override val onCheckedChange = null
         override val icon = @Composable {
             SettingsIcon(imageVector = Icons.Outlined.AirplanemodeActive)
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/TwoTargetSwitchPreferenceScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/TwoTargetSwitchPreferenceScreenshotTest.kt
index 2c37212..72c5cb8 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/TwoTargetSwitchPreferenceScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/preference/TwoTargetSwitchPreferenceScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,17 +14,19 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.preference
 
 import androidx.compose.foundation.layout.Column
 import com.android.settingslib.spa.framework.compose.stateOf
-import com.android.settingslib.spa.widget.preference.TwoTargetSwitchPreference
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
+import com.android.settingslib.spa.widget.preference.TwoTargetSwitchPreference
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
@@ -48,21 +50,21 @@
             Column {
                 TwoTargetSwitchPreference(object : SwitchPreferenceModel {
                     override val title = "TwoTargetSwitchPreference"
-                    override val checked = stateOf(false)
+                    override val checked = { false }
                     override val onCheckedChange = null
                 }) {}
 
                 TwoTargetSwitchPreference(object : SwitchPreferenceModel {
                     override val title = "TwoTargetSwitchPreference"
-                    override val summary = stateOf("With summary")
-                    override val checked = stateOf(true)
+                    override val summary = { "With summary" }
+                    override val checked = { true }
                     override val onCheckedChange = null
                 }) {}
 
                 TwoTargetSwitchPreference(object : SwitchPreferenceModel {
                     override val title = "Not changeable"
-                    override val changeable = stateOf(false)
-                    override val checked = stateOf(true)
+                    override val changeable = { false }
+                    override val checked = { true }
                     override val onCheckedChange = null
                 }) {}
             }
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/FooterScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/FooterScreenshotTest.kt
index 0a0faf6..fb01f77 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/FooterScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/FooterScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,14 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.ui
 
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.ui.Footer
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
diff --git a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/SpinnerScreenshotTest.kt b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/SpinnerScreenshotTest.kt
index 0b4d5e4..2867741 100644
--- a/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/SpinnerScreenshotTest.kt
+++ b/packages/SettingsLib/Spa/screenshot/src/com/android/settingslib/spa/screenshot/widget/ui/SpinnerScreenshotTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.settingslib.spa.screenshot
+package com.android.settingslib.spa.screenshot.widget.ui
 
+import com.android.settingslib.spa.screenshot.util.SettingsScreenshotTestRule
 import com.android.settingslib.spa.widget.ui.Spinner
 import com.android.settingslib.spa.widget.ui.SpinnerOption
 import org.junit.Rule
@@ -23,6 +24,7 @@
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.PhoneAndTabletMinimal
 
 /** A screenshot test for ExampleFeature. */
 @RunWith(Parameterized::class)
diff --git a/packages/SettingsLib/Spa/settings.gradle.kts b/packages/SettingsLib/Spa/settings.gradle.kts
index b8dfae3..e003c81 100644
--- a/packages/SettingsLib/Spa/settings.gradle.kts
+++ b/packages/SettingsLib/Spa/settings.gradle.kts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -49,3 +49,6 @@
 include(":testutils")
 include(":SettingsLibColor")
 project(":SettingsLibColor").projectDir = File(rootDir, "../Color")
+
+// Uncomment this for screenshot
+// include(":screenshot")
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/spa/build.gradle.kts b/packages/SettingsLib/Spa/spa/build.gradle.kts
index 189c2dd..4335173 100644
--- a/packages/SettingsLib/Spa/spa/build.gradle.kts
+++ b/packages/SettingsLib/Spa/spa/build.gradle.kts
@@ -1,5 +1,5 @@
 /*
- * Copyright 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -63,7 +63,7 @@
     api("androidx.compose.ui:ui-tooling-preview:$jetpackComposeVersion")
     api("androidx.lifecycle:lifecycle-livedata-ktx")
     api("androidx.lifecycle:lifecycle-runtime-compose")
-    api("androidx.navigation:navigation-compose:2.7.4")
+    api("androidx.navigation:navigation-compose:2.7.5")
     api("com.github.PhilJay:MPAndroidChart:v3.1.0-alpha")
     api("com.google.android.material:material:1.7.0-alpha03")
     debugApi("androidx.compose.ui:ui-tooling:$jetpackComposeVersion")
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugActivity.kt
index 078c925..14af508 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/debug/DebugActivity.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -37,7 +37,6 @@
 import com.android.settingslib.spa.framework.common.SpaEnvironmentFactory
 import com.android.settingslib.spa.framework.compose.localNavController
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.toState
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.framework.util.SESSION_BROWSE
 import com.android.settingslib.spa.framework.util.SESSION_SEARCH
@@ -137,7 +136,7 @@
                 val page = pageWithEntry.page
                 Preference(object : PreferenceModel {
                     override val title = "${page.debugBrief()} (${pageWithEntry.entries.size})"
-                    override val summary = page.debugArguments().toState()
+                    override val summary = { page.debugArguments() }
                     override val onClick = navigator(route = ROUTE_PAGE + "/${page.id}")
                 })
             }
@@ -179,8 +178,9 @@
             Text(text = "Entry size: ${pageWithEntry.entries.size}")
             Preference(model = object : PreferenceModel {
                 override val title = "open page"
-                override val enabled = (spaEnvironment.browseActivityClass != null &&
-                    page.isBrowsable()).toState()
+                override val enabled = {
+                    spaEnvironment.browseActivityClass != null && page.isBrowsable()
+                }
                 override val onClick = openPage(page)
             })
             EntryList(pageWithEntry.entries)
@@ -196,9 +196,10 @@
         RegularScaffold(title = "Entry - ${entry.debugBrief()}") {
             Preference(model = object : PreferenceModel {
                 override val title = "open entry"
-                override val enabled = (spaEnvironment.browseActivityClass != null &&
-                    entry.containerPage().isBrowsable())
-                    .toState()
+                override val enabled = {
+                    spaEnvironment.browseActivityClass != null &&
+                        entry.containerPage().isBrowsable()
+                }
                 override val onClick = openEntry(entry)
             })
             Text(text = entryContent)
@@ -210,8 +211,9 @@
         for (entry in entries) {
             Preference(object : PreferenceModel {
                 override val title = entry.debugBrief()
-                override val summary =
-                    "${entry.fromPage?.displayName} -> ${entry.toPage?.displayName}".toState()
+                override val summary = {
+                    "${entry.fromPage?.displayName} -> ${entry.toPage?.displayName}"
+                }
                 override val onClick = navigator(route = ROUTE_ENTRY + "/${entry.id}")
             })
         }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Flows.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Flows.kt
index 8bfcff8..83cb549 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Flows.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/util/Flows.kt
@@ -16,10 +16,16 @@
 
 package com.android.settingslib.spa.framework.util
 
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.take
+import kotlinx.coroutines.launch
 
 /**
  * Returns a [Flow] whose values are a list which containing the results of applying the given
@@ -46,3 +52,19 @@
  */
 fun <T1, T2> Flow<T1>.waitFirst(otherFlow: Flow<T2>): Flow<T1> =
     combine(otherFlow.take(1)) { value, _ -> value }
+
+
+/**
+ * Collects the latest value of given flow with a provided action with [LifecycleOwner].
+ */
+fun <T> Flow<T>.collectLatestWithLifecycle(
+    lifecycleOwner: LifecycleOwner,
+    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
+    action: suspend (value: T) -> Unit,
+) {
+    lifecycleOwner.lifecycleScope.launch {
+        lifecycleOwner.repeatOnLifecycle(minActiveState) {
+            collectLatest(action)
+        }
+    }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/livedata/LiveDataExt.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/livedata/LiveDataExt.kt
new file mode 100644
index 0000000..3d330fe
--- /dev/null
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/livedata/LiveDataExt.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.livedata
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.lifecycle.LiveData
+
+/**
+ * Starts observing this LiveData and represents its values via State and Callback.
+ *
+ * Every time there would be new value posted into the LiveData the returned State will be updated
+ * causing recomposition of every Callback usage.
+ */
+@Composable
+fun <T> LiveData<T>.observeAsCallback(): () -> T? {
+    val isAllowed by observeAsState()
+    return { isAllowed }
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ListPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ListPreference.kt
index 74f9c9d..a0149da 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ListPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/ListPreference.kt
@@ -27,8 +27,6 @@
 import androidx.compose.material3.RadioButton
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.IntState
-import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
@@ -37,7 +35,6 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.semantics.Role
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.dialog.SettingsDialog
 import com.android.settingslib.spa.widget.ui.SettingsDialogItem
@@ -69,8 +66,8 @@
      *
      * Disabled [ListPreference] will be displayed in disabled style.
      */
-    val enabled: State<Boolean>
-        get() = stateOf(true)
+    val enabled: () -> Boolean
+        get() = { true }
 
     val options: List<ListPreferenceOption>
 
@@ -89,7 +86,7 @@
         ) {
             Column(modifier = Modifier.selectableGroup()) {
                 for (option in model.options) {
-                    Radio(option, model.selectedId.intValue, model.enabled.value) {
+                    Radio(option, model.selectedId.intValue, model.enabled()) {
                         dialogOpened = false
                         model.onIdSelected(it)
                     }
@@ -100,7 +97,7 @@
     Preference(model = remember(model) {
         object : PreferenceModel {
             override val title = model.title
-            override val summary = derivedStateOf {
+            override val summary = {
                 model.options.find { it.id == model.selectedId.intValue }?.text ?: ""
             }
             override val icon = model.icon
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/MainSwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/MainSwitchPreference.kt
index 35c34d4..fc8de80 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/MainSwitchPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/MainSwitchPreference.kt
@@ -24,7 +24,6 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
-import com.android.settingslib.spa.framework.compose.toState
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsShape
 import com.android.settingslib.spa.framework.theme.SettingsTheme
@@ -35,7 +34,7 @@
     EntryHighlight {
         Surface(
             modifier = Modifier.padding(SettingsDimension.itemPaddingEnd),
-            color = when (model.checked.value) {
+            color = when (model.checked()) {
                 true -> MaterialTheme.colorScheme.primaryContainer
                 else -> MaterialTheme.colorScheme.secondaryContainer
             },
@@ -43,8 +42,8 @@
         ) {
             InternalSwitchPreference(
                 title = model.title,
-                checked = model.checked.value,
-                changeable = model.changeable.value,
+                checked = model.checked(),
+                changeable = model.changeable(),
                 onCheckedChange = model.onCheckedChange,
                 paddingStart = 20.dp,
                 paddingEnd = 20.dp,
@@ -61,12 +60,12 @@
         Column {
             MainSwitchPreference(object : SwitchPreferenceModel {
                 override val title = "Use Dark theme"
-                override val checked = true.toState()
+                override val checked = { true }
                 override val onCheckedChange: (Boolean) -> Unit = {}
             })
             MainSwitchPreference(object : SwitchPreferenceModel {
                 override val title = "Use Dark theme"
-                override val checked = false.toState()
+                override val checked = { false }
                 override val onCheckedChange: (Boolean) -> Unit = {}
             })
         }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
index 7ecbec7..bb7e857 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/Preference.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,14 +18,12 @@
 
 import androidx.compose.foundation.clickable
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import com.android.settingslib.spa.framework.common.EntryMacro
 import com.android.settingslib.spa.framework.common.EntrySearchData
 import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.util.EntryHighlight
 import com.android.settingslib.spa.framework.util.wrapOnClickWithLog
 import com.android.settingslib.spa.widget.ui.createSettingsIcon
@@ -42,9 +40,9 @@
     override fun UiLayout() {
         Preference(model = object : PreferenceModel {
             override val title: String = this@SimplePreferenceMacro.title
-            override val summary = stateOf(this@SimplePreferenceMacro.summary ?: "")
+            override val summary = { this@SimplePreferenceMacro.summary ?: "" }
             override val icon = createSettingsIcon(this@SimplePreferenceMacro.icon)
-            override val enabled = stateOf(!this@SimplePreferenceMacro.disabled)
+            override val enabled = { !disabled }
             override val onClick = navigator(clickRoute)
         })
     }
@@ -69,8 +67,8 @@
     /**
      * The summary of this [Preference].
      */
-    val summary: State<String>
-        get() = stateOf("")
+    val summary: () -> String
+        get() = { "" }
 
     /**
      * The icon of this [Preference].
@@ -85,8 +83,8 @@
      *
      * Disabled [Preference] will be displayed in disabled style.
      */
-    val enabled: State<Boolean>
-        get() = stateOf(true)
+    val enabled: () -> Boolean
+        get() = { true }
 
     /**
      * The on click handler of this [Preference].
@@ -108,10 +106,11 @@
     singleLineSummary: Boolean = false,
 ) {
     val onClickWithLog = wrapOnClickWithLog(model.onClick)
-    val modifier = remember(model.enabled.value) {
+    val enabled = model.enabled()
+    val modifier = remember(enabled) {
         if (onClickWithLog != null) {
             Modifier.clickable(
-                enabled = model.enabled.value,
+                enabled = enabled,
                 onClick = onClickWithLog
             )
         } else Modifier
@@ -119,11 +118,11 @@
     EntryHighlight {
         BasePreference(
             title = model.title,
-            summary = { model.summary.value },
+            summary = model.summary,
             singleLineSummary = singleLineSummary,
             modifier = modifier,
             icon = model.icon,
-            enabled = { model.enabled.value },
+            enabled = model.enabled,
         )
     }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/SwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/SwitchPreference.kt
index f14f68c..aceb545 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/SwitchPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/SwitchPreference.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,13 +25,11 @@
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.outlined.AirplanemodeActive
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.semantics.Role
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.Dp
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.framework.util.EntryHighlight
@@ -51,8 +49,8 @@
     /**
      * The summary of this [SwitchPreference].
      */
-    val summary: State<String>
-        get() = stateOf("")
+    val summary: () -> String
+        get() = { "" }
 
     /**
      * The icon of this [Preference].
@@ -67,15 +65,15 @@
      *
      * This can be `null` during the data loading before the data is available.
      */
-    val checked: State<Boolean?>
+    val checked: () -> Boolean?
 
     /**
      * Indicates whether this [SwitchPreference] is changeable.
      *
      * Not changeable [SwitchPreference] will be displayed in disabled style.
      */
-    val changeable: State<Boolean>
-        get() = stateOf(true)
+    val changeable: () -> Boolean
+        get() = { true }
 
     /**
      * The switch change handler of this [SwitchPreference].
@@ -95,10 +93,10 @@
     EntryHighlight {
         InternalSwitchPreference(
             title = model.title,
-            summary = { model.summary.value },
+            summary = model.summary,
             icon = model.icon,
-            checked = model.checked.value,
-            changeable = model.changeable.value,
+            checked = model.checked(),
+            changeable = model.changeable(),
             onCheckedChange = model.onCheckedChange,
         )
     }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetButtonPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetButtonPreference.kt
index b8db63c..9866023 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetButtonPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetButtonPreference.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,32 +16,32 @@
 
 package com.android.settingslib.spa.widget.preference
 
-import com.android.settingslib.spa.framework.util.EntryHighlight
+import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
-import androidx.compose.runtime.State
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.material3.Icon
+import com.android.settingslib.spa.framework.util.EntryHighlight
 
 @Composable
 fun TwoTargetButtonPreference(
-        title: String,
-        summary: State<String>,
-        icon: @Composable (() -> Unit)? = null,
-        onClick: () -> Unit,
-        buttonIcon: ImageVector,
-        buttonIconDescription: String,
-        onButtonClick: () -> Unit
+    title: String,
+    summary: () -> String,
+    icon: @Composable (() -> Unit)? = null,
+    onClick: () -> Unit,
+    buttonIcon: ImageVector,
+    buttonIconDescription: String,
+    onButtonClick: () -> Unit
 ) {
     EntryHighlight {
         TwoTargetPreference(
-                title = title,
-                summary = summary,
-                onClick = onClick,
-                icon = icon) {
+            title = title,
+            summary = summary,
+            onClick = onClick,
+            icon = icon,
+        ) {
             IconButton(onClick = onButtonClick) {
                 Icon(imageVector = buttonIcon, contentDescription = buttonIconDescription)
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetPreference.kt
index 5663610..e36572f 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetPreference.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,7 +24,6 @@
 import androidx.compose.foundation.layout.size
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
@@ -35,7 +34,7 @@
 @Composable
 internal fun TwoTargetPreference(
     title: String,
-    summary: State<String>,
+    summary: () -> String,
     onClick: () -> Unit,
     icon: @Composable (() -> Unit)? = null,
     widget: @Composable () -> Unit,
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
index 9a6580c..7eed745 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreference.kt
@@ -34,8 +34,8 @@
             icon = icon,
         ) {
             SettingsSwitch(
-                checked = model.checked.value,
-                changeable = { model.changeable.value },
+                checked = model.checked(),
+                changeable = model.changeable,
                 onCheckedChange = model.onCheckedChange,
             )
         }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsPager.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsPager.kt
index 9f7f040..aa148b0 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsPager.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SettingsPager.kt
@@ -21,7 +21,7 @@
 import androidx.compose.foundation.layout.padding
 import androidx.compose.foundation.pager.HorizontalPager
 import androidx.compose.foundation.pager.rememberPagerState
-import androidx.compose.material3.PrimaryTabRow
+import androidx.compose.material3.TabRow
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.Modifier
@@ -43,7 +43,7 @@
         val coroutineScope = rememberCoroutineScope()
         val pagerState = rememberPagerState { titles.size }
 
-        PrimaryTabRow(
+        TabRow(
             selectedTabIndex = pagerState.currentPage,
             modifier = Modifier.padding(horizontal = SettingsDimension.itemPaddingEnd),
             containerColor = Color.Transparent,
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/FlowsTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/FlowsTest.kt
index 71d69b2..a64b43b 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/FlowsTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/framework/util/FlowsTest.kt
@@ -16,7 +16,9 @@
 
 package com.android.settingslib.spa.framework.util
 
+import androidx.lifecycle.testing.TestLifecycleOwner
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.waitUntil
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.count
 import kotlinx.coroutines.flow.emptyFlow
@@ -85,4 +87,16 @@
 
         assertThat(outputFlow.toList()).containsExactly("A")
     }
+
+    @Test
+    fun collectLatestWithLifecycle() {
+        val mainFlow = flowOf("A")
+        var actual: String? = null
+
+        mainFlow.collectLatestWithLifecycle(TestLifecycleOwner()) {
+            actual = it
+        }
+
+        waitUntil { actual == "A" }
+    }
 }
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/ListPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/ListPreferenceTest.kt
index 997a023..796ac48 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/ListPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/ListPreferenceTest.kt
@@ -25,7 +25,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.testutils.onDialogText
 import org.junit.Rule
 import org.junit.Test
@@ -92,7 +91,7 @@
             ListPreference(remember {
                 object : ListPreferenceModel {
                     override val title = TITLE
-                    override val enabled = stateOf(false)
+                    override val enabled = { false }
                     override val options = listOf(ListPreferenceOption(id = 1, text = "A"))
                     override val selectedId = mutableIntStateOf(1)
                     override val onIdSelected: (Int) -> Unit = {}
@@ -154,7 +153,7 @@
             ListPreference(remember {
                 object : ListPreferenceModel {
                     override val title = TITLE
-                    override val enabled = enabledState
+                    override val enabled = { enabledState.value }
                     override val options = listOf(
                         ListPreferenceOption(id = 1, text = "A"),
                         ListPreferenceOption(id = 2, text = "B"),
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/MainSwitchPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/MainSwitchPreferenceTest.kt
index 6588cf5..8ce6979 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/MainSwitchPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/MainSwitchPreferenceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,9 +17,11 @@
 package com.android.settingslib.spa.widget.preference
 
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsOff
 import androidx.compose.ui.test.assertIsOn
@@ -28,7 +30,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -81,13 +82,13 @@
 
 @Composable
 private fun TestMainSwitchPreference(changeable: Boolean) {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     MainSwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = TITLE
-            override val checked = checked
-            override val changeable = stateOf(changeable)
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val changeable = { changeable }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
index 06936e1..8c363db 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/PreferenceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,7 +19,6 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.width
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
@@ -34,7 +33,6 @@
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.toState
 import com.google.common.truth.Truth.assertThat
 import org.junit.Assert.fail
 import org.junit.Rule
@@ -65,7 +63,7 @@
             Box(Modifier.width(BOX_WIDTH)) {
                 Preference(object : PreferenceModel {
                     override val title = TITLE
-                    override val summary = LONG_SUMMARY.toState()
+                    override val summary = { LONG_SUMMARY }
                 })
             }
             lineHeightDp = with(LocalDensity.current) {
@@ -85,7 +83,7 @@
                 Preference(
                     model = object : PreferenceModel {
                         override val title = TITLE
-                        override val summary = LONG_SUMMARY.toState()
+                        override val summary = { LONG_SUMMARY }
                     },
                     singleLineSummary = true,
                 )
@@ -113,7 +111,7 @@
             var count by remember { mutableStateOf(0) }
             Preference(object : PreferenceModel {
                 override val title = TITLE
-                override val summary = derivedStateOf { count.toString() }
+                override val summary = { count.toString() }
                 override val onClick: (() -> Unit) = { count++ }
             })
         }
@@ -128,8 +126,8 @@
             var count by remember { mutableStateOf(0) }
             Preference(object : PreferenceModel {
                 override val title = TITLE
-                override val summary = derivedStateOf { count.toString() }
-                override val enabled = false.toState()
+                override val summary = { count.toString() }
+                override val enabled = { false }
                 override val onClick: (() -> Unit) = { count++ }
             })
         }
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/ProgressBarPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/ProgressBarPreferenceTest.kt
index 2140c07..e6d2401 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/ProgressBarPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/ProgressBarPreferenceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,8 +17,7 @@
 package com.android.settingslib.spa.widget.preference
 
 import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.outlined.Launch
-import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.material.icons.automirrored.outlined.Launch
 import androidx.compose.ui.semantics.ProgressBarRangeInfo
 import androidx.compose.ui.semantics.SemanticsProperties.ProgressBarRangeInfo
 import androidx.compose.ui.test.SemanticsMatcher
@@ -49,11 +48,14 @@
     @Test
     fun data_displayed() {
         composeTestRule.setContent {
-            ProgressBarWithDataPreference(model = object : ProgressBarPreferenceModel {
-                override val title = "Title"
-                override val progress = 0.2f
-                override val icon: ImageVector = Icons.Outlined.Launch
-            }, data = "Data")
+            ProgressBarWithDataPreference(
+                model = object : ProgressBarPreferenceModel {
+                    override val title = "Title"
+                    override val progress = 0.2f
+                    override val icon = Icons.AutoMirrored.Outlined.Launch
+                },
+                data = "Data",
+            )
         }
         composeTestRule.onNodeWithText("Title").assertIsDisplayed()
         composeTestRule.onNodeWithText("Data").assertIsDisplayed()
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/SwitchPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/SwitchPreferenceTest.kt
index d6c8fbc..0b2127d 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/SwitchPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/SwitchPreferenceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,9 +17,11 @@
 package com.android.settingslib.spa.widget.preference
 
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsOff
 import androidx.compose.ui.test.assertIsOn
@@ -28,7 +30,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -79,13 +80,13 @@
 
 @Composable
 private fun TestSwitchPreference(changeable: Boolean) {
-    val checked = rememberSaveable { mutableStateOf(false) }
+    var checked by rememberSaveable { mutableStateOf(false) }
     SwitchPreference(remember {
         object : SwitchPreferenceModel {
             override val title = "SwitchPreference"
-            override val checked = checked
-            override val changeable = stateOf(changeable)
-            override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+            override val checked = { checked }
+            override val changeable = { changeable }
+            override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
         }
     })
 }
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetButtonPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetButtonPreferenceTest.kt
index 3a2b445..6de1933 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetButtonPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetButtonPreferenceTest.kt
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.android.settingslib.spa.widget.preference
 
 import androidx.compose.material.icons.Icons
@@ -9,7 +25,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.toState
 import com.google.common.truth.Truth
 import org.junit.Rule
 import org.junit.Test
@@ -64,10 +79,10 @@
 ) {
     TwoTargetButtonPreference(
         title = TEST_MODEL_TITLE,
-        summary = TEST_MODEL_SUMMARY.toState(),
+        summary = { TEST_MODEL_SUMMARY },
         onClick = onClick,
         buttonIcon = TEST_BUTTON_ICON,
         buttonIconDescription = TEST_BUTTON_ICON_DESCRIPTION,
         onButtonClick = onButtonClick
     )
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreferenceTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreferenceTest.kt
index c49e92d..3455851 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreferenceTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/preference/TwoTargetSwitchPreferenceTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,9 +17,11 @@
 package com.android.settingslib.spa.widget.preference
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.assertIsOff
 import androidx.compose.ui.test.assertIsOn
@@ -28,7 +30,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
 import org.junit.Test
@@ -41,9 +42,8 @@
 
     @Test
     fun title_displayed() {
-        val checked = mutableStateOf(false)
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = true)
+            TestTwoTargetSwitchPreference(changeable = true)
         }
 
         composeTestRule.onNodeWithText("TwoTargetSwitchPreference").assertIsDisplayed()
@@ -51,9 +51,8 @@
 
     @Test
     fun toggleable_initialStateIsCorrect() {
-        val checked = mutableStateOf(false)
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = true)
+            TestTwoTargetSwitchPreference(changeable = true)
         }
 
         composeTestRule.onNode(isToggleable()).assertIsOff()
@@ -61,9 +60,8 @@
 
     @Test
     fun toggleable_changeable_withEffect() {
-        val checked = mutableStateOf(false)
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = true)
+            TestTwoTargetSwitchPreference(changeable = true)
         }
 
         composeTestRule.onNode(isToggleable()).performClick()
@@ -72,9 +70,8 @@
 
     @Test
     fun toggleable_notChangeable_noEffect() {
-        val checked = mutableStateOf(false)
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = false)
+            TestTwoTargetSwitchPreference(changeable = false)
         }
 
         composeTestRule.onNode(isToggleable()).performClick()
@@ -83,10 +80,9 @@
 
     @Test
     fun clickable_canBeClick() {
-        val checked = mutableStateOf(false)
         var clicked = false
         composeTestRule.setContent {
-            TestTwoTargetSwitchPreference(checked = checked, changeable = false) {
+            TestTwoTargetSwitchPreference(changeable = false) {
                 clicked = true
             }
         }
@@ -98,17 +94,17 @@
 
 @Composable
 private fun TestTwoTargetSwitchPreference(
-    checked: MutableState<Boolean>,
     changeable: Boolean,
     onClick: () -> Unit = {},
 ) {
+    var checked by rememberSaveable { mutableStateOf(false) }
     TwoTargetSwitchPreference(
         model = remember {
             object : SwitchPreferenceModel {
                 override val title = "TwoTargetSwitchPreference"
-                override val checked = checked
-                override val changeable = stateOf(changeable)
-                override val onCheckedChange = { newChecked: Boolean -> checked.value = newChecked }
+                override val checked = { checked }
+                override val changeable = { changeable }
+                override val onCheckedChange = { newChecked: Boolean -> checked = newChecked }
             }
         },
         onClick = onClick,
diff --git a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/CategoryTest.kt b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/CategoryTest.kt
index 16e09ee..09a6e6d 100644
--- a/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/CategoryTest.kt
+++ b/packages/SettingsLib/Spa/tests/src/com/android/settingslib/spa/widget/ui/CategoryTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.compose.ui.test.onNodeWithText
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import org.junit.Rule
@@ -50,7 +49,7 @@
                 Preference(remember {
                     object : PreferenceModel {
                         override val title = "Some Preference"
-                        override val summary = stateOf("Some summary")
+                        override val summary = { "Some summary" }
                     }
                 })
             }
diff --git a/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/FlowTestUtil.kt b/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/FlowTestUtil.kt
index 7a11499..99c6a3f 100644
--- a/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/FlowTestUtil.kt
+++ b/packages/SettingsLib/Spa/testutils/src/com/android/settingslib/spa/testutils/FlowTestUtil.kt
@@ -18,9 +18,17 @@
 
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.toList
 import kotlinx.coroutines.withTimeoutOrNull
 
 suspend fun <T> Flow<T>.firstWithTimeoutOrNull(timeMillis: Long = 500): T? =
     withTimeoutOrNull(timeMillis) {
         first()
     }
+
+suspend fun <T> Flow<T>.toListWithTimeout(timeMillis: Long = 500): List<T> {
+    val list = mutableListOf<T>()
+    return withTimeoutOrNull(timeMillis) {
+        toList(list)
+    } ?: list
+}
diff --git a/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml b/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
index 17c139b..d992114 100644
--- a/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
+++ b/packages/SettingsLib/SpaPrivileged/AndroidManifest.xml
@@ -18,5 +18,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.settingslib.spaprivileged">
     <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
 </manifest>
-
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt
index f3ab80c7..9eee6ad 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt
@@ -19,7 +19,6 @@
 import android.content.pm.ApplicationInfo
 import android.icu.text.CollationKey
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import com.android.settingslib.spa.widget.ui.SpinnerOption
 import com.android.settingslib.spaprivileged.template.app.AppListItem
 import com.android.settingslib.spaprivileged.template.app.AppListItemModel
@@ -89,7 +88,7 @@
      * @return null if no summary should be displayed.
      */
     @Composable
-    fun getSummary(option: Int, record: T): State<String>? = null
+    fun getSummary(option: Int, record: T): (() -> String)? = null
 
     @Composable
     fun AppListItemModel<T>.AppItem() {
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt
new file mode 100644
index 0000000..8e702ea
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepository.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spaprivileged.settingsprovider
+
+import android.content.ContentResolver
+import android.content.Context
+import android.provider.Settings
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
+import kotlinx.coroutines.flow.Flow
+
+fun Context.settingsGlobalBoolean(name: String): ReadWriteProperty<Any?, Boolean> =
+    SettingsGlobalBooleanDelegate(this, name)
+
+fun Context.settingsGlobalBooleanFlow(name: String): Flow<Boolean> {
+    val value by settingsGlobalBoolean(name)
+    return settingsGlobalFlow(name) { value }
+}
+
+private class SettingsGlobalBooleanDelegate(context: Context, private val name: String) :
+    ReadWriteProperty<Any?, Boolean> {
+
+    private val contentResolver: ContentResolver = context.contentResolver
+
+    override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean =
+        Settings.Global.getInt(contentResolver, name, 0) != 0
+
+    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
+        Settings.Global.putInt(contentResolver, name, if (value) 1 else 0)
+    }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
new file mode 100644
index 0000000..4098987
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepository.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spaprivileged.settingsprovider
+
+import android.content.Context
+import kotlinx.coroutines.flow.Flow
+
+fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
+    settingsGlobalFlow(name, sendInitialValue) { }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalFlow.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalFlow.kt
new file mode 100644
index 0000000..de5c558
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalFlow.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spaprivileged.settingsprovider
+
+import android.content.Context
+import android.database.ContentObserver
+import android.os.Handler
+import android.provider.Settings
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.flowOn
+
+internal fun <T> Context.settingsGlobalFlow(
+    name: String,
+    sendInitialValue: Boolean = true,
+    value: () -> T,
+): Flow<T> = callbackFlow {
+    val contentObserver = object : ContentObserver(Handler.getMain()) {
+        override fun onChange(selfChange: Boolean) {
+            trySend(value())
+        }
+    }
+    val uri = Settings.Global.getUriFor(name)
+    contentResolver.registerContentObserver(uri, false, contentObserver)
+    if (sendInitialValue) {
+        trySend(value())
+    }
+
+    awaitClose { contentResolver.unregisterContentObserver(contentObserver) }
+}.conflate().flowOn(Dispatchers.Default)
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
index 066db34..7c45b64 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt
@@ -36,7 +36,6 @@
 import com.android.settingslib.spa.framework.compose.LogCompositions
 import com.android.settingslib.spa.framework.compose.TimeMeasurer.Companion.rememberTimeMeasurer
 import com.android.settingslib.spa.framework.compose.rememberLazyListStateAndHideKeyboardWhenStartScroll
-import com.android.settingslib.spa.framework.compose.toState
 import com.android.settingslib.spa.widget.ui.CategoryTitle
 import com.android.settingslib.spa.widget.ui.PlaceholderTitle
 import com.android.settingslib.spa.widget.ui.Spinner
@@ -150,7 +149,7 @@
                     ?.let { group -> CategoryTitle(title = group) }
 
                 val appEntry = list[it]
-                val summary = getSummary(option, appEntry.record) ?: "".toState()
+                val summary = getSummary(option, appEntry.record) ?: { "" }
                 remember(appEntry) {
                     AppListItemModel(appEntry.record, appEntry.label, summary)
                 }.AppItem()
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListItemModel.kt
similarity index 89%
rename from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListItem.kt
rename to packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListItemModel.kt
index 6d0d7d6..a7c5036 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListItem.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListItemModel.kt
@@ -17,11 +17,9 @@
 package com.android.settingslib.spaprivileged.template.app
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.tooling.preview.Preview
-import com.android.settingslib.spa.framework.compose.toState
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.framework.theme.SettingsTheme
 import com.android.settingslib.spa.widget.preference.Preference
@@ -31,7 +29,7 @@
 data class AppListItemModel<T : AppRecord>(
     val record: T,
     val label: String,
-    val summary: State<String>,
+    val summary: () -> String,
 )
 
 @Composable
@@ -55,6 +53,6 @@
         val record = object : AppRecord {
             override val app = LocalContext.current.applicationInfo
         }
-        AppListItemModel<AppRecord>(record, "Chrome", "Allowed".toState()).AppListItem {}
+        AppListItemModel<AppRecord>(record, "Chrome", { "Allowed" }).AppListItem {}
     }
 }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItem.kt
index 155905b..36877af 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItem.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItem.kt
@@ -17,7 +17,6 @@
 package com.android.settingslib.spaprivileged.template.app
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
@@ -25,8 +24,8 @@
 
 @Composable
 fun <T : AppRecord> AppListItemModel<T>.AppListSwitchItem(
-    checked: State<Boolean?>,
-    changeable: State<Boolean>,
+    checked: () -> Boolean?,
+    changeable: () -> Boolean,
     onCheckedChange: ((newChecked: Boolean) -> Unit)?,
 ) {
     SwitchPreference(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
index 99d3840..bea14c3 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItem.kt
@@ -17,7 +17,6 @@
 package com.android.settingslib.spaprivileged.template.app
 
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import com.android.settingslib.spa.framework.theme.SettingsDimension
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spa.widget.preference.TwoTargetSwitchPreference
@@ -26,8 +25,8 @@
 @Composable
 fun <T : AppRecord> AppListItemModel<T>.AppListTwoTargetSwitchItem(
     onClick: () -> Unit,
-    checked: State<Boolean?>,
-    changeable: State<Boolean>,
+    checked: () -> Boolean?,
+    changeable: () -> Boolean,
     onCheckedChange: ((newChecked: Boolean) -> Unit)?,
 ) {
     TwoTargetSwitchPreference(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
index e9da88e..7bd7fbe 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
@@ -22,11 +22,7 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.livedata.observeAsState
-import androidx.compose.runtime.remember
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.framework.util.asyncMapItem
 import com.android.settingslib.spa.framework.util.filterItem
 import com.android.settingslib.spaprivileged.model.app.AppOpsController
@@ -97,8 +93,9 @@
         with(packageManagers) {
             AppOpPermissionRecord(
                 app = app,
-                hasRequestBroaderPermission =
-                    broaderPermission?.let { app.hasRequestPermission(it) } ?: false,
+                hasRequestBroaderPermission = broaderPermission?.let {
+                    app.hasRequestPermission(it)
+                } ?: false,
                 hasRequestPermission = hasRequestPermission,
                 appOpsController = createAppOpsController(app),
             )
@@ -138,22 +135,19 @@
      * (This means pre-M gets approval during install time; M apps gets approval during runtime).
      */
     @Composable
-    override fun isAllowed(record: AppOpPermissionRecord): State<Boolean?> {
+    override fun isAllowed(record: AppOpPermissionRecord): () -> Boolean? {
         if (record.hasRequestBroaderPermission) {
             // Broader permission trumps the specific permission.
-            return stateOf(true)
+            return { true }
         }
 
         val mode = record.appOpsController.mode.observeAsState()
-        return remember {
-            derivedStateOf {
-                when (mode.value) {
-                    null -> null
-                    MODE_ALLOWED -> true
-                    MODE_DEFAULT ->
-                        with(packageManagers) { record.app.hasGrantPermission(permission) }
-                    else -> false
-                }
+        return {
+            when (mode.value) {
+                null -> null
+                MODE_ALLOWED -> true
+                MODE_DEFAULT -> with(packageManagers) { record.app.hasGrantPermission(permission) }
+                else -> false
             }
         }
     }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
index 62c5f70..3380b7d 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
@@ -22,9 +22,10 @@
 import androidx.annotation.VisibleForTesting
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.State
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
 import androidx.core.os.bundleOf
@@ -165,14 +166,16 @@
     context: Context,
     private val listModel: TogglePermissionAppListModel<T>,
     private val record: T,
-    isAllowed: State<Boolean?>,
+    isAllowed: () -> Boolean?,
 ) : SwitchPreferenceModel {
+    private var appChangeable by mutableStateOf(true)
+
     override val title: String = context.getString(listModel.switchTitleResId)
     override val checked = isAllowed
-    override val changeable = mutableStateOf(true)
+    override val changeable = { appChangeable }
 
     fun initState() {
-        changeable.value = listModel.isChangeable(record)
+        appChangeable = listModel.isChangeable(record)
     }
 
     override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
index 1ab6230..8704f20 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
@@ -19,7 +19,6 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
 import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
 import com.android.settingslib.spa.framework.common.SettingsPageProvider
 import com.android.settingslib.spa.framework.compose.rememberContext
@@ -64,7 +63,7 @@
      * Gets whether the permission is allowed for the given app.
      */
     @Composable
-    fun isAllowed(record: T): State<Boolean?>
+    fun isAllowed(record: T): () -> Boolean?
 
     /**
      * Gets whether the permission on / off is changeable for the given app.
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
index 17e9708..785f779 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
@@ -20,8 +20,7 @@
 import android.content.pm.ApplicationInfo
 import android.os.Bundle
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.remember
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringResource
@@ -149,33 +148,27 @@
     override fun getSummary(option: Int, record: T) = getSummary(record)
 
     @Composable
-    fun getSummary(record: T): State<String> {
+    fun getSummary(record: T): () -> String {
         val restrictions = remember(record.app.userId) {
             Restrictions(
                 userId = record.app.userId,
                 keys = listModel.switchRestrictionKeys,
             )
         }
-        val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions)
+        val restrictedMode by restrictionsProviderFactory.rememberRestrictedMode(restrictions)
         val allowed = listModel.isAllowed(record)
-        return remember {
-            derivedStateOf {
-                RestrictedSwitchPreference.getSummary(
-                    context = context,
-                    restrictedMode = restrictedMode.value,
-                    summaryIfNoRestricted = getSummaryIfNoRestricted(allowed),
-                    checked = allowed,
-                ).value
-            }
-        }
+        return RestrictedSwitchPreference.getSummary(
+            context = context,
+            restrictedModeSupplier = { restrictedMode },
+            summaryIfNoRestricted = { getSummaryIfNoRestricted(allowed()) },
+            checked = allowed,
+        )
     }
 
-    private fun getSummaryIfNoRestricted(allowed: State<Boolean?>) = derivedStateOf {
-        when (allowed.value) {
-            true -> context.getString(R.string.app_permission_summary_allowed)
-            false -> context.getString(R.string.app_permission_summary_not_allowed)
-            null -> context.getPlaceholder()
-        }
+    private fun getSummaryIfNoRestricted(allowed: Boolean?): String = when (allowed) {
+        true -> context.getString(R.string.app_permission_summary_allowed)
+        false -> context.getString(R.string.app_permission_summary_not_allowed)
+        null -> context.getPlaceholder()
     }
 
     @Composable
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedPreference.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedPreference.kt
index 50490c0..ac85dd4 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedPreference.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedPreference.kt
@@ -23,7 +23,6 @@
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.semantics.Role
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.widget.preference.Preference
 import com.android.settingslib.spa.widget.preference.PreferenceModel
 import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted
@@ -73,7 +72,7 @@
 
     override val enabled = when (restrictedMode) {
         NoRestricted -> model.enabled
-        else -> stateOf(false)
+        else -> ({ false })
     }
 
     override val onClick = when (restrictedMode) {
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
index 2129403..e41976f 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt
@@ -21,8 +21,6 @@
 import androidx.compose.foundation.clickable
 import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.State
-import androidx.compose.runtime.derivedStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
@@ -30,7 +28,6 @@
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.semantics.toggleableState
 import androidx.compose.ui.state.ToggleableState
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
@@ -75,17 +72,16 @@
 internal object RestrictedSwitchPreference {
     fun getSummary(
         context: Context,
-        restrictedMode: RestrictedMode?,
-        summaryIfNoRestricted: State<String>,
-        checked: State<Boolean?>,
-    ): State<String> = when (restrictedMode) {
-        is NoRestricted -> summaryIfNoRestricted
-        is BaseUserRestricted -> stateOf(
-            context.getString(com.android.settingslib.R.string.disabled)
-        )
-
-        is BlockedByAdmin -> derivedStateOf { restrictedMode.getSummary(checked.value) }
-        null -> stateOf(context.getPlaceholder())
+        restrictedModeSupplier: () -> RestrictedMode?,
+        summaryIfNoRestricted: () -> String,
+        checked: () -> Boolean?,
+    ): () -> String = {
+        when (val restrictedMode = restrictedModeSupplier()) {
+            is NoRestricted -> summaryIfNoRestricted()
+            is BaseUserRestricted -> context.getString(com.android.settingslib.R.string.disabled)
+            is BlockedByAdmin -> restrictedMode.getSummary(checked())
+            null -> context.getPlaceholder()
+        }
     }
 }
 
@@ -98,23 +94,23 @@
 
     override val summary = RestrictedSwitchPreference.getSummary(
         context = context,
-        restrictedMode = restrictedMode,
+        restrictedModeSupplier = { restrictedMode },
         summaryIfNoRestricted = model.summary,
         checked = model.checked,
     )
 
     override val checked = when (restrictedMode) {
-        null -> stateOf(null)
+        null -> ({ null })
         is NoRestricted -> model.checked
-        is BaseUserRestricted -> stateOf(false)
+        is BaseUserRestricted -> ({ false })
         is BlockedByAdmin -> model.checked
     }
 
     override val changeable = when (restrictedMode) {
-        null -> stateOf(false)
+        null -> ({ false })
         is NoRestricted -> model.changeable
-        is BaseUserRestricted -> stateOf(false)
-        is BlockedByAdmin -> stateOf(false)
+        is BaseUserRestricted -> ({ false })
+        is BlockedByAdmin -> ({ false })
     }
 
     override val onCheckedChange = when (restrictedMode) {
@@ -140,7 +136,7 @@
                     onClick = { restrictedMode.sendShowAdminSupportDetailsIntent() },
                 )
                 .semantics {
-                    this.toggleableState = ToggleableState(checked.value)
+                    this.toggleableState = ToggleableState(checked())
                 },
         ) { content() }
     }
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt
new file mode 100644
index 0000000..996c2d5
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBooleanRepositoryTest.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spaprivileged.settingsprovider
+
+import android.content.Context
+import android.provider.Settings
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
+import com.android.settingslib.spa.testutils.toListWithTimeout
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SettingsGlobalBooleanRepositoryTest {
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    @Test
+    fun getValue_setTrue_returnTrue() {
+        Settings.Global.putInt(context.contentResolver, TEST_NAME, 1)
+
+        val value by context.settingsGlobalBoolean(TEST_NAME)
+
+        assertThat(value).isTrue()
+    }
+
+    @Test
+    fun getValue_setFalse_returnFalse() {
+        Settings.Global.putInt(context.contentResolver, TEST_NAME, 0)
+
+        val value by context.settingsGlobalBoolean(TEST_NAME)
+
+        assertThat(value).isFalse()
+    }
+
+    @Test
+    fun setValue_setTrue_returnTrue() {
+        var value by context.settingsGlobalBoolean(TEST_NAME)
+
+        value = true
+
+        assertThat(Settings.Global.getInt(context.contentResolver, TEST_NAME, 0)).isEqualTo(1)
+    }
+
+    @Test
+    fun setValue_setFalse_returnFalse() {
+        var value by context.settingsGlobalBoolean(TEST_NAME)
+
+        value = false
+
+        assertThat(Settings.Global.getInt(context.contentResolver, TEST_NAME, 1)).isEqualTo(0)
+    }
+
+    @Test
+    fun settingsGlobalBooleanFlow_valueNotChanged() = runBlocking {
+        var value by context.settingsGlobalBoolean(TEST_NAME)
+        value = false
+
+        val flow = context.settingsGlobalBooleanFlow(TEST_NAME)
+
+        assertThat(flow.firstWithTimeoutOrNull()).isFalse()
+    }
+
+    @Test
+    fun settingsGlobalBooleanFlow_collectAfterValueChanged_onlyKeepLatest() = runBlocking {
+        var value by context.settingsGlobalBoolean(TEST_NAME)
+        value = false
+
+        val flow = context.settingsGlobalBooleanFlow(TEST_NAME)
+        value = true
+
+        assertThat(flow.firstWithTimeoutOrNull()).isTrue()
+    }
+
+    @Test
+    fun settingsGlobalBooleanFlow_collectBeforeValueChanged_getBoth() = runBlocking {
+        var value by context.settingsGlobalBoolean(TEST_NAME)
+        value = false
+
+        val listDeferred = async {
+            context.settingsGlobalBooleanFlow(TEST_NAME).toListWithTimeout()
+        }
+        delay(100)
+        value = true
+
+        assertThat(listDeferred.await()).containsExactly(false, true).inOrder()
+    }
+
+    private companion object {
+        const val TEST_NAME = "test_boolean_delegate"
+    }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepositoryTest.kt
new file mode 100644
index 0000000..37e00e6
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalChangeRepositoryTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spaprivileged.settingsprovider
+
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
+import com.android.settingslib.spa.testutils.toListWithTimeout
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SettingsGlobalChangeRepositoryTest {
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    @Test
+    fun settingsGlobalChangeFlow_sendInitialValueTrue() = runBlocking {
+        val flow = context.settingsGlobalChangeFlow(name = TEST_NAME, sendInitialValue = true)
+
+        assertThat(flow.firstWithTimeoutOrNull()).isNotNull()
+    }
+
+    @Test
+    fun settingsGlobalChangeFlow_sendInitialValueFalse() = runBlocking {
+        val flow = context.settingsGlobalChangeFlow(name = TEST_NAME, sendInitialValue = false)
+
+        assertThat(flow.firstWithTimeoutOrNull()).isNull()
+    }
+
+    @Test
+    fun settingsGlobalChangeFlow_collectAfterValueChanged_onlyKeepLatest() = runBlocking {
+        var value by context.settingsGlobalBoolean(TEST_NAME)
+        value = false
+
+        val flow = context.settingsGlobalBooleanFlow(TEST_NAME)
+        value = true
+
+        assertThat(flow.toListWithTimeout()).hasSize(1)
+    }
+
+    @Test
+    fun settingsGlobalChangeFlow_collectBeforeValueChanged_getBoth() = runBlocking {
+        var value by context.settingsGlobalBoolean(TEST_NAME)
+        value = false
+
+        val listDeferred = async {
+            context.settingsGlobalChangeFlow(TEST_NAME).toListWithTimeout()
+        }
+        delay(100)
+        value = true
+
+        assertThat(listDeferred.await()).hasSize(2)
+    }
+
+    private companion object {
+        const val TEST_NAME = "test_boolean_delegate"
+    }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItemTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItemTest.kt
index 2fd1b10..73dd295 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItemTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListSwitchItemTest.kt
@@ -27,7 +27,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spaprivileged.model.app.AppRecord
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -43,8 +42,8 @@
     fun appLabel_displayed() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -56,8 +55,8 @@
     fun summary_displayed() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -69,8 +68,8 @@
     fun switch_checkIsNull() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -82,8 +81,8 @@
     fun switch_checked() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(true),
-                changeable = stateOf(false),
+                checked = { true },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -95,8 +94,8 @@
     fun switch_notChecked() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -108,8 +107,8 @@
     fun switch_changeable() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(false),
-                changeable = stateOf(true),
+                checked = { false },
+                changeable = { true },
                 onCheckedChange = {},
             )
         }
@@ -121,8 +120,8 @@
     fun switch_notChangeable() {
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -135,8 +134,8 @@
         var switchClicked = false
         composeTestRule.setContent {
             ITEM_MODEL.AppListSwitchItem(
-                checked = stateOf(false),
-                changeable = stateOf(true),
+                checked = { false },
+                changeable = { true },
                 onCheckedChange = { switchClicked = true },
             )
         }
@@ -158,7 +157,7 @@
                 override val app = APP
             },
             label = LABEL,
-            summary = stateOf(SUMMARY),
+            summary = { SUMMARY },
         )
     }
 }
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItemTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItemTest.kt
index 6e7fc8e..d3cfb2d 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItemTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTwoTargetSwitchItemTest.kt
@@ -27,7 +27,6 @@
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spaprivileged.model.app.AppRecord
 import com.google.common.truth.Truth.assertThat
 import org.junit.Rule
@@ -44,8 +43,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -58,8 +57,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -73,8 +72,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = { titleClicked = true },
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -89,8 +88,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(null),
-                changeable = stateOf(false),
+                checked = { null },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -103,8 +102,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(true),
-                changeable = stateOf(false),
+                checked = { true },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -117,8 +116,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -131,8 +130,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(false),
-                changeable = stateOf(true),
+                checked = { false },
+                changeable = { true },
                 onCheckedChange = {},
             )
         }
@@ -145,8 +144,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(false),
-                changeable = stateOf(false),
+                checked = { false },
+                changeable = { false },
                 onCheckedChange = {},
             )
         }
@@ -160,8 +159,8 @@
         composeTestRule.setContent {
             ITEM_MODEL.AppListTwoTargetSwitchItem(
                 onClick = {},
-                checked = stateOf(false),
-                changeable = stateOf(true),
+                checked = { false },
+                changeable = { true },
                 onCheckedChange = { switchClicked = true },
             )
         }
@@ -183,7 +182,7 @@
                 override val app = APP
             },
             label = LABEL,
-            summary = stateOf(SUMMARY),
+            summary = { SUMMARY },
         )
     }
 }
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
index eb2055f..3b2fe0f 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
@@ -20,7 +20,6 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
-import androidx.compose.runtime.State
 import androidx.compose.ui.test.junit4.createComposeRule
 import androidx.lifecycle.MutableLiveData
 import androidx.test.core.app.ApplicationProvider
@@ -307,9 +306,9 @@
     }
 
     private fun getIsAllowed(record: AppOpPermissionRecord): Boolean? {
-        lateinit var isAllowedState: State<Boolean?>
+        lateinit var isAllowedState: () -> Boolean?
         composeTestRule.setContent { isAllowedState = listModel.isAllowed(record) }
-        return isAllowedState.value
+        return isAllowedState()
     }
 
     private inner class TestAppOpPermissionAppListModel :
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt
index 457b810..bf0ad0b 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPageTest.kt
@@ -19,7 +19,6 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.runtime.State
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.test.assertIsDisplayed
 import androidx.compose.ui.test.junit4.createComposeRule
@@ -27,7 +26,6 @@
 import androidx.compose.ui.test.performClick
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.settingslib.spa.framework.compose.stateOf
 import com.android.settingslib.spa.testutils.FakeNavControllerWrapper
 import com.android.settingslib.spaprivileged.R
 import com.android.settingslib.spaprivileged.framework.compose.getPlaceholder
@@ -72,10 +70,9 @@
         fakeRestrictionsProvider.restrictedMode = NoRestricted
         val listModel = TestTogglePermissionAppListModel(isAllowed = true)
 
-        val summaryState = getSummary(listModel)
+        val summary = getSummary(listModel)
 
-        assertThat(summaryState.value)
-            .isEqualTo(context.getString(R.string.app_permission_summary_allowed))
+        assertThat(summary).isEqualTo(context.getString(R.string.app_permission_summary_allowed))
     }
 
     @Test
@@ -83,9 +80,9 @@
         fakeRestrictionsProvider.restrictedMode = NoRestricted
         val listModel = TestTogglePermissionAppListModel(isAllowed = false)
 
-        val summaryState = getSummary(listModel)
+        val summary = getSummary(listModel)
 
-        assertThat(summaryState.value)
+        assertThat(summary)
             .isEqualTo(context.getString(R.string.app_permission_summary_not_allowed))
     }
 
@@ -94,9 +91,9 @@
         fakeRestrictionsProvider.restrictedMode = NoRestricted
         val listModel = TestTogglePermissionAppListModel(isAllowed = null)
 
-        val summaryState = getSummary(listModel)
+        val summary = getSummary(listModel)
 
-        assertThat(summaryState.value).isEqualTo(context.getPlaceholder())
+        assertThat(summary).isEqualTo(context.getPlaceholder())
     }
 
     @Test
@@ -108,7 +105,7 @@
                     AppListItemModel(
                         record = listModel.transformItem(APP),
                         label = LABEL,
-                        summary = stateOf(SUMMARY),
+                        summary = { SUMMARY },
                     ).AppItem()
                 }
             }
@@ -152,12 +149,12 @@
             restrictionsProviderFactory = { _, _ -> fakeRestrictionsProvider },
         )
 
-    private fun getSummary(listModel: TestTogglePermissionAppListModel): State<String> {
-        lateinit var summary: State<String>
+    private fun getSummary(listModel: TestTogglePermissionAppListModel): String {
+        lateinit var summary: () -> String
         composeTestRule.setContent {
             summary = createInternalAppListModel(listModel).getSummary(record = TestAppRecord(APP))
         }
-        return summary
+        return summary()
     }
 
     private companion object {
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt
index a13c483..00ba9b4 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreferenceTest.kt
@@ -49,8 +49,9 @@
 
     private val switchPreferenceModel = object : SwitchPreferenceModel {
         override val title = TITLE
-        override val checked = mutableStateOf(true)
-        override val onCheckedChange: (Boolean) -> Unit = { checked.value = it }
+        private val checkedState = mutableStateOf(true)
+        override val checked = { checkedState.value }
+        override val onCheckedChange: (Boolean) -> Unit = { checkedState.value = it }
     }
 
     @Test
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt
index 1bfc7ed..1790313 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/tests/testutils/TestTogglePermissionAppListModel.kt
@@ -18,7 +18,9 @@
 
 import android.content.pm.ApplicationInfo
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
 import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel
 import com.android.settingslib.spaprivileged.test.R
 import kotlinx.coroutines.flow.Flow
@@ -31,7 +33,7 @@
     override val switchTitleResId = R.string.test_permission_switch_title
     override val footerResId = R.string.test_permission_footer
 
-    private val isAllowedState = mutableStateOf(isAllowed)
+    private var isAllowed by mutableStateOf(isAllowed)
 
     override fun transformItem(app: ApplicationInfo) = TestAppRecord(app = app)
 
@@ -39,11 +41,11 @@
         recordListFlow
 
     @Composable
-    override fun isAllowed(record: TestAppRecord) = isAllowedState
+    override fun isAllowed(record: TestAppRecord) = { isAllowed }
 
     override fun isChangeable(record: TestAppRecord) = isChangeable
 
     override fun setAllowed(record: TestAppRecord, newAllowed: Boolean) {
-        isAllowedState.value = newAllowed
+        isAllowed = newAllowed
     }
 }
diff --git a/packages/SettingsLib/res/drawable/ic_hdmi.xml b/packages/SettingsLib/res/drawable/ic_hdmi.xml
new file mode 100644
index 0000000..c7a553b
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_hdmi.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="960"
+        android:viewportHeight="960"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M320,880L320,760L200,521L200,280L240,280L240,140Q240,117 258.5,98.5Q277,80 300,80L660,80Q683,80 701.5,98.5Q720,117 720,140L720,280L760,280L760,521L640,760L640,880L320,880ZM300,280L398,280L398,198L432,198L432,280L528,280L528,198L562,198L562,280L660,280L660,140Q660,140 660,140Q660,140 660,140L300,140Q300,140 300,140Q300,140 300,140L300,280ZM378,743L378,743L582,743L582,743L582,743L378,743L378,743ZM378,743L582,743L700,504L700,340L260,340L260,504L378,743Z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_tv.xml b/packages/SettingsLib/res/drawable/ic_tv.xml
new file mode 100644
index 0000000..87abaf4
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_tv.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="960"
+        android:viewportHeight="960"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M320,840L320,760L160,760Q127,760 103.5,736.5Q80,713 80,680L80,200Q80,167 103.5,143.5Q127,120 160,120L800,120Q833,120 856.5,143.5Q880,167 880,200L880,680Q880,713 856.5,736.5Q833,760 800,760L640,760L640,840L320,840ZM160,680L800,680Q800,680 800,680Q800,680 800,680L800,200Q800,200 800,200Q800,200 800,200L160,200Q160,200 160,200Q160,200 160,200L160,680Q160,680 160,680Q160,680 160,680ZM160,680Q160,680 160,680Q160,680 160,680L160,200Q160,200 160,200Q160,200 160,200L160,200Q160,200 160,200Q160,200 160,200L160,680Q160,680 160,680Q160,680 160,680L160,680Z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_usb.xml b/packages/SettingsLib/res/drawable/ic_usb.xml
new file mode 100644
index 0000000..b5f15ea
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_usb.xml
@@ -0,0 +1,26 @@
+<!--
+  ~ Copyright (C) 2023 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="960"
+        android:viewportHeight="960"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M480,880Q448,880 428,860Q408,840 408,808Q408,786 419,768Q430,750 450,739L450,628L302,628Q278,628 260,610Q242,592 242,568L242,459Q222,450 211,432.39Q200,414.78 200,392.28Q200,360 220,340Q240,320 272,320Q304,320 324,340Q344,360 344,392.41Q344,415 333,432.5Q322,450 302,459L302,568Q302,568 302,568Q302,568 302,568L450,568L450,228L370,228L480,79L590,228L510,228L510,568L658,568Q658,568 658,568Q658,568 658,568L658,464L616,464L616,320L760,320L760,464L718,464L718,568Q718,592 700,610Q682,628 658,628L510,628L510,739Q529.95,749.65 540.97,768.83Q552,788 552,808Q552,840 532,860Q512,880 480,880Z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_wired_device.xml b/packages/SettingsLib/res/drawable/ic_wired_device.xml
new file mode 100644
index 0000000..7964c9f
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_wired_device.xml
@@ -0,0 +1,25 @@
+<!--
+  Copyright (C) 2020 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="960"
+        android:viewportHeight="960"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M123,920L123,750Q89,737 64.5,707.5Q40,678 40,643L40,245L123,245L123,70Q123,56 131,48Q139,40 153,40Q167,40 175,48Q183,56 183,70L183,245L266,245L266,643Q266,678 242,707.5Q218,737 183,750L183,920L123,920ZM450,920L450,750Q416,737 391.5,707.5Q367,678 367,643L367,245L450,245L450,70Q450,56 458,48Q466,40 480,40Q494,40 502,48Q510,56 510,70L510,245L593,245L593,643Q593,678 569,707.5Q545,737 510,750L510,920L450,920ZM777,920L777,750Q743,737 718.5,707.5Q694,678 694,643L694,245L777,245L777,70Q777,56 785,48Q793,40 807,40Q821,40 829,48Q837,56 837,70L837,245L920,245L920,643Q920,678 895.5,707.5Q871,737 837,750L837,920L777,920ZM100,489L206,489L206,305L100,305L100,489ZM427,489L533,489L533,305L427,305L427,489ZM754,489L860,489L860,305L754,305L754,489ZM153,489L153,489L153,489L153,489L153,489ZM480,489L480,489L480,489L480,489L480,489ZM807,489L807,489L807,489L807,489L807,489ZM100,489L100,489L206,489L206,489L100,489ZM427,489L427,489L533,489L533,489L427,489ZM754,489L754,489L860,489L860,489L754,489Z"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 96029c8..1a5acf6 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1334,6 +1334,8 @@
     <string name="media_transfer_this_device_name" product="default">This phone</string>
     <!-- Name of the tablet device. [CHAR LIMIT=30] -->
     <string name="media_transfer_this_device_name" product="tablet">This tablet</string>
+    <!-- Name of the default media output of the TV. [CHAR LIMIT=30] -->
+    <string name="media_transfer_this_device_name" product="tv">@string/tv_media_transfer_default</string>
     <!-- Name of the dock device. [CHAR LIMIT=30] -->
     <string name="media_transfer_dock_speaker_device_name">Dock speaker</string>
     <!-- Default name of the external device. [CHAR LIMIT=30] -->
@@ -1357,6 +1359,26 @@
     <!-- Sub status indicates the device does not support the current media track. [CHAR LIMIT=NONE] -->
     <string name="media_output_status_track_unsupported">Can\’t play this media here</string>
 
+    <!-- Media output switcher. Default subtitle for any output option that is connected if no more information is known [CHAR LIMIT=NONE] -->
+    <string name="tv_media_transfer_connected">Connected</string>
+
+    <!-- TV media output switcher. Title for devices connected through HDMI ARC if no device name is available. [CHAR LIMIT=NONE] -->
+    <string name="tv_media_transfer_arc_fallback_title">HDMI ARC</string>
+    <!-- TV media output switcher. Title for devices connected through HDMI EARC if no device name is available. [CHAR LIMIT=NONE] -->
+    <string name="tv_media_transfer_earc_fallback_title">HDMI eARC</string>
+
+    <!-- TV media output switcher. Subtitle for devices connected through HDMI ARC if a device name is available. [CHAR LIMIT=NONE] -->
+    <string name="tv_media_transfer_arc_subtitle">Connected via ARC</string>
+    <!-- Media output switcher. Subtitle for devices connected through HDMI EARC if a device name is available. [CHAR LIMIT=NONE] -->
+    <string name="tv_media_transfer_earc_subtitle">Connected via eARC</string>
+
+    <!-- TV media output switcher. Title for the default audio output of the device [CHAR LIMIT=NONE] -->
+    <string name="tv_media_transfer_default">TV Default</string>
+    <!-- TV media output switcher. Subtitle for default audio output which is HDMI, e.g. TV dongle [CHAR LIMIT=NONE] -->
+    <string name="tv_media_transfer_hdmi">HDMI Output</string>
+    <!-- TV media output switcher. Subtitle for default audio output which is internal speaker, i.e. panel VTs [CHAR LIMIT=NONE] -->
+    <string name="tv_media_transfer_internal_speakers">Internal Speakers</string>
+
     <!-- Warning message to tell user is have problem during profile connect, it need to turn off device and back on. [CHAR_LIMIT=NONE] -->
     <string name="profile_connect_timeout_subtext">Problem connecting. Turn device off &amp; back on</string>
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 24083b6..e9f4b5c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1404,7 +1404,7 @@
                         lowBatteryColorRes);
             }
             if (rightBattery >= 0) {
-                if (!spannableBuilder.isEmpty()) {
+                if (spannableBuilder.length() > 0) {
                     spannableBuilder.append(" ");
                 }
                 String right = res.getString(
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/DeviceIconUtil.java b/packages/SettingsLib/src/com/android/settingslib/media/DeviceIconUtil.java
index 2a28417..cf224dc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/DeviceIconUtil.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/DeviceIconUtil.java
@@ -18,11 +18,13 @@
 
 import android.annotation.DrawableRes;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.media.AudioDeviceInfo;
 import android.media.MediaRoute2Info;
 
 import com.android.settingslib.R;
+import com.android.settingslib.media.flags.Flags;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -31,16 +33,25 @@
 
 /** A util class to get the appropriate icon for different device types. */
 public class DeviceIconUtil {
+
+    // A default icon to use if the type is not present in the map.
+    @DrawableRes private static final int DEFAULT_ICON = R.drawable.ic_smartphone;
+    @DrawableRes private static final int DEFAULT_ICON_TV = R.drawable.ic_media_speaker_device;
+
     // A map from a @AudioDeviceInfo.AudioDeviceType to full device information.
     private final Map<Integer, Device> mAudioDeviceTypeToIconMap = new HashMap<>();
     // A map from a @MediaRoute2Info.Type to full device information.
     private final Map<Integer, Device> mMediaRouteTypeToIconMap = new HashMap<>();
-    // A default icon to use if the type is not present in the map.
-    @DrawableRes private static final int DEFAULT_ICON = R.drawable.ic_smartphone;
 
-    public DeviceIconUtil() {
-        List<Device> deviceList =
-                Arrays.asList(
+    private final boolean mIsTv;
+
+    public DeviceIconUtil(Context context) {
+        this(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK));
+    }
+
+    public DeviceIconUtil(boolean isTv) {
+        mIsTv = isTv && Flags.enableTvMediaOutputDialog();
+        List<Device> deviceList = Arrays.asList(
                         new Device(
                                 AudioDeviceInfo.TYPE_USB_DEVICE,
                                 MediaRoute2Info.TYPE_USB_DEVICE,
@@ -52,7 +63,7 @@
                         new Device(
                                 AudioDeviceInfo.TYPE_USB_ACCESSORY,
                                 MediaRoute2Info.TYPE_USB_ACCESSORY,
-                                R.drawable.ic_headphone),
+                                mIsTv ? R.drawable.ic_usb : R.drawable.ic_headphone),
                         new Device(
                                 AudioDeviceInfo.TYPE_DOCK,
                                 MediaRoute2Info.TYPE_DOCK,
@@ -60,29 +71,27 @@
                         new Device(
                                 AudioDeviceInfo.TYPE_HDMI,
                                 MediaRoute2Info.TYPE_HDMI,
-                                R.drawable.ic_headphone),
-                        // TODO: b/306359110 - Put proper iconography for HDMI_ARC type.
+                                mIsTv ? R.drawable.ic_tv : R.drawable.ic_headphone),
                         new Device(
                                 AudioDeviceInfo.TYPE_HDMI_ARC,
                                 MediaRoute2Info.TYPE_HDMI_ARC,
-                                R.drawable.ic_headphone),
-                        // TODO: b/306359110 - Put proper iconography for HDMI_EARC type.
+                                mIsTv ? R.drawable.ic_hdmi : R.drawable.ic_headphone),
                         new Device(
                                 AudioDeviceInfo.TYPE_HDMI_EARC,
                                 MediaRoute2Info.TYPE_HDMI_EARC,
-                                R.drawable.ic_headphone),
+                                mIsTv ? R.drawable.ic_hdmi : R.drawable.ic_headphone),
                         new Device(
                                 AudioDeviceInfo.TYPE_WIRED_HEADSET,
                                 MediaRoute2Info.TYPE_WIRED_HEADSET,
-                                R.drawable.ic_headphone),
+                                mIsTv ? R.drawable.ic_wired_device : R.drawable.ic_headphone),
                         new Device(
                                 AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
                                 MediaRoute2Info.TYPE_WIRED_HEADPHONES,
-                                R.drawable.ic_headphone),
+                                mIsTv ? R.drawable.ic_wired_device : R.drawable.ic_headphone),
                         new Device(
                                 AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
                                 MediaRoute2Info.TYPE_BUILTIN_SPEAKER,
-                                R.drawable.ic_smartphone));
+                                mIsTv ? R.drawable.ic_tv : R.drawable.ic_smartphone));
         for (int i = 0; i < deviceList.size(); i++) {
             Device device = deviceList.get(i);
             mAudioDeviceTypeToIconMap.put(device.mAudioDeviceType, device);
@@ -90,6 +99,10 @@
         }
     }
 
+    private int getDefaultIcon() {
+        return mIsTv ? DEFAULT_ICON_TV : DEFAULT_ICON;
+    }
+
     /** Returns a drawable for an icon representing the given audioDeviceType. */
     public Drawable getIconFromAudioDeviceType(
             @AudioDeviceInfo.AudioDeviceType int audioDeviceType, Context context) {
@@ -103,7 +116,7 @@
         if (mAudioDeviceTypeToIconMap.containsKey(audioDeviceType)) {
             return mAudioDeviceTypeToIconMap.get(audioDeviceType).mIconDrawableRes;
         }
-        return DEFAULT_ICON;
+        return getDefaultIcon();
     }
 
     /** Returns a drawable res ID for an icon representing the given mediaRouteType. */
@@ -113,7 +126,7 @@
         if (mMediaRouteTypeToIconMap.containsKey(mediaRouteType)) {
             return mMediaRouteTypeToIconMap.get(mediaRouteType).mIconDrawableRes;
         }
-        return DEFAULT_ICON;
+        return getDefaultIcon();
     }
 
     private static class Device {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index c44f66e..80eeab5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -28,15 +28,24 @@
 
 import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_TRANSFER;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.HdmiDeviceInfo;
+import android.hardware.hdmi.HdmiPortInfo;
 import android.media.MediaRoute2Info;
 import android.media.RouteListingPreference;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
+import com.android.settingslib.media.flags.Flags;
+
+import java.util.List;
 
 /**
  * PhoneMediaDevice extends MediaDevice to represents Phone device.
@@ -58,6 +67,7 @@
     public static String getSystemRouteNameFromType(
             @NonNull Context context, @NonNull MediaRoute2Info routeInfo) {
         CharSequence name;
+        boolean isTv = isTv(context);
         switch (routeInfo.getType()) {
             case TYPE_WIRED_HEADSET:
             case TYPE_WIRED_HEADPHONES:
@@ -73,9 +83,32 @@
                 name = context.getString(R.string.media_transfer_this_device_name);
                 break;
             case TYPE_HDMI:
+                name = context.getString(isTv ? R.string.tv_media_transfer_default :
+                        R.string.media_transfer_external_device_name);
+                break;
             case TYPE_HDMI_ARC:
+                if (isTv) {
+                    String deviceName = getHdmiOutDeviceName(context);
+                    if (deviceName != null) {
+                        name = deviceName;
+                    } else {
+                        name = context.getString(R.string.tv_media_transfer_arc_fallback_title);
+                    }
+                } else {
+                    name = context.getString(R.string.media_transfer_external_device_name);
+                }
+                break;
             case TYPE_HDMI_EARC:
-                name = context.getString(R.string.media_transfer_external_device_name);
+                if (isTv) {
+                    String deviceName = getHdmiOutDeviceName(context);
+                    if (deviceName != null) {
+                        name = deviceName;
+                    } else {
+                        name = context.getString(R.string.tv_media_transfer_arc_fallback_title);
+                    }
+                } else {
+                    name = context.getString(R.string.media_transfer_external_device_name);
+                }
                 break;
             default:
                 name = context.getString(R.string.media_transfer_default_device_name);
@@ -94,10 +127,15 @@
             String packageName,
             RouteListingPreference.Item item) {
         super(context, info, packageName, item);
-        mDeviceIconUtil = new DeviceIconUtil();
+        mDeviceIconUtil = new DeviceIconUtil(mContext);
         initDeviceRecord();
     }
 
+    static boolean isTv(Context context) {
+        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+                && Flags.enableTvMediaOutputDialog();
+    }
+
     // MediaRoute2Info.getType was made public on API 34, but exists since API 30.
     @SuppressWarnings("NewApi")
     @Override
@@ -111,9 +149,64 @@
         return SELECTION_BEHAVIOR_TRANSFER;
     }
 
+    private static String getHdmiOutDeviceName(Context context) {
+        HdmiControlManager hdmiControlManager;
+        if (context.checkCallingOrSelfPermission(Manifest.permission.HDMI_CEC)
+                == PackageManager.PERMISSION_GRANTED) {
+            hdmiControlManager = context.getSystemService(HdmiControlManager.class);
+        } else {
+            Log.w(TAG, "Could not get HDMI device name, android.permission.HDMI_CEC denied");
+            return null;
+        }
+
+        HdmiPortInfo hdmiOutputPortInfo = null;
+        for (HdmiPortInfo hdmiPortInfo : hdmiControlManager.getPortInfo()) {
+            if (hdmiPortInfo.getType() == HdmiPortInfo.PORT_OUTPUT) {
+                hdmiOutputPortInfo = hdmiPortInfo;
+                break;
+            }
+        }
+        if (hdmiOutputPortInfo == null) {
+            return null;
+        }
+        List<HdmiDeviceInfo> connectedDevices = hdmiControlManager.getConnectedDevices();
+        for (HdmiDeviceInfo deviceInfo : connectedDevices) {
+            if (deviceInfo.getPortId() == hdmiOutputPortInfo.getId()) {
+                String deviceName = deviceInfo.getDisplayName();
+                if (deviceName != null && !deviceName.isEmpty()) {
+                    return deviceName;
+                }
+            }
+        }
+        return null;
+    }
+
     @Override
     public String getSummary() {
-        return mSummary;
+        if (!isTv(mContext)) {
+            return mSummary;
+        }
+        switch (mRouteInfo.getType()) {
+            case TYPE_BUILTIN_SPEAKER:
+                return mContext.getString(R.string.tv_media_transfer_internal_speakers);
+            case TYPE_HDMI:
+                return mContext.getString(R.string.tv_media_transfer_hdmi);
+            case TYPE_HDMI_ARC:
+                if (getHdmiOutDeviceName(mContext) == null) {
+                    // Connection type is already part of the title.
+                    return mContext.getString(R.string.tv_media_transfer_connected);
+                }
+                return mContext.getString(R.string.tv_media_transfer_arc_subtitle);
+            case TYPE_HDMI_EARC:
+                if (getHdmiOutDeviceName(mContext) == null) {
+                    // Connection type is already part of the title.
+                    return mContext.getString(R.string.tv_media_transfer_connected);
+                }
+                return mContext.getString(R.string.tv_media_transfer_earc_subtitle);
+            default:
+                return null;
+        }
+
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java
index 848b177..61c8ee7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java
@@ -25,6 +25,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -138,7 +139,8 @@
     private String getFileAuthority() {
         String authority = getIntent().getStringExtra(EXTRA_FILE_AUTHORITY);
         if (authority == null) {
-            throw new IllegalStateException("File authority must be provided");
+            Log.e(this.getClass().getName(), "File authority must be provided");
+            finish();
         }
         return authority;
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/DeviceIconUtilTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/DeviceIconUtilTest.java
index 72dfc17..5669276 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/DeviceIconUtilTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/DeviceIconUtilTest.java
@@ -20,131 +20,309 @@
 
 import android.media.AudioDeviceInfo;
 import android.media.MediaRoute2Info;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import com.android.settingslib.R;
+import com.android.settingslib.media.flags.Flags;
 
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 
 @RunWith(RobolectricTestRunner.class)
 public class DeviceIconUtilTest {
-    private final DeviceIconUtil mDeviceIconUtil = new DeviceIconUtil();
+
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+    @Before
+    public void setup() {
+        mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_TV_MEDIA_OUTPUT_DIALOG);
+    }
 
     @Test
     public void getIconResIdFromMediaRouteType_usbDevice_isHeadphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_DEVICE))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_DEVICE))
+                .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_DEVICE))
+                .isEqualTo(R.drawable.ic_headphone);
     }
 
     @Test
     public void getIconResIdFromMediaRouteType_usbHeadset_isHeadphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_HEADSET))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_HEADSET))
+                .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_HEADSET))
+                .isEqualTo(R.drawable.ic_headphone);
     }
 
     @Test
     public void getIconResIdFromMediaRouteType_usbAccessory_isHeadphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_ACCESSORY))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_ACCESSORY))
+                .isEqualTo(R.drawable.ic_headphone);
     }
 
     @Test
-    public void getIconResIdFromMediaRouteType_dock_isHeadphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_DOCK))
-            .isEqualTo(R.drawable.ic_headphone);
+    public void getIconResIdFromMediaRouteType_tv_usbAccessory_isUsb() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_USB_ACCESSORY))
+                .isEqualTo(R.drawable.ic_usb);
     }
 
     @Test
-    public void getIconResIdFromMediaRouteType_hdmi_isHeadphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_HDMI))
-            .isEqualTo(R.drawable.ic_headphone);
+    public void getIconResIdFromMediaRouteType_dock_isDock() {
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_DOCK))
+                .isEqualTo(R.drawable.ic_dock_device);
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_DOCK))
+                .isEqualTo(R.drawable.ic_dock_device);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_hdmi() {
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_HDMI))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_tv_hdmi_isTv() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_HDMI))
+                .isEqualTo(R.drawable.ic_tv);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_hdmiArc_isHeadphone() {
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_HDMI_ARC))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_tv_hdmiArc_isHdmi() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_HDMI_ARC))
+                .isEqualTo(R.drawable.ic_hdmi);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_hdmiEarc_isHeadphone() {
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_HDMI_EARC))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_tv_hdmiEarc_isHdmi() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_HDMI_EARC))
+                .isEqualTo(R.drawable.ic_hdmi);
     }
 
     @Test
     public void getIconResIdFromMediaRouteType_wiredHeadset_isHeadphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_WIRED_HEADSET))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_WIRED_HEADSET))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_tv_wiredHeadset_isWiredDevice() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_WIRED_HEADSET))
+                .isEqualTo(R.drawable.ic_wired_device);
     }
 
     @Test
     public void getIconResIdFromMediaRouteType_wiredHeadphones_isHeadphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_WIRED_HEADPHONES))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_WIRED_HEADPHONES))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_tv_wiredHeadphones_isWiredDevice() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_WIRED_HEADPHONES))
+                .isEqualTo(R.drawable.ic_wired_device);
     }
 
     @Test
     public void getIconResIdFromMediaRouteType_builtinSpeaker_isSmartphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_BUILTIN_SPEAKER))
-            .isEqualTo(R.drawable.ic_smartphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_BUILTIN_SPEAKER))
+                .isEqualTo(R.drawable.ic_smartphone);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_tv_builtinSpeaker_isTv() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_BUILTIN_SPEAKER))
+                .isEqualTo(R.drawable.ic_tv);
     }
 
     @Test
     public void getIconResIdFromMediaRouteType_unsupportedType_isSmartphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_UNKNOWN))
-            .isEqualTo(R.drawable.ic_smartphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_UNKNOWN))
+                .isEqualTo(R.drawable.ic_smartphone);
+    }
+
+    @Test
+    public void getIconResIdFromMediaRouteType_tv_unsupportedType_isSpeaker() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromMediaRouteType(MediaRoute2Info.TYPE_UNKNOWN))
+                .isEqualTo(R.drawable.ic_media_speaker_device);
     }
 
     @Test
     public void getIconResIdFromAudioDeviceType_usbDevice_isHeadphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_DEVICE))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_DEVICE))
+                .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_DEVICE))
+                .isEqualTo(R.drawable.ic_headphone);
     }
 
     @Test
     public void getIconResIdFromAudioDeviceType_usbHeadset_isHeadphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_HEADSET))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_HEADSET))
+                .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_HEADSET))
+                .isEqualTo(R.drawable.ic_headphone);
     }
 
     @Test
     public void getIconResIdFromAudioDeviceType_usbAccessory_isHeadphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_ACCESSORY))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_ACCESSORY))
+                .isEqualTo(R.drawable.ic_headphone);
     }
 
     @Test
-    public void getIconResIdFromAudioDeviceType_dock_isHeadphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_DOCK))
-            .isEqualTo(R.drawable.ic_headphone);
+    public void getIconResIdFromAudioDeviceType_tv_usbAccessory_isUsb() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_USB_ACCESSORY))
+                .isEqualTo(R.drawable.ic_usb);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_dock_isDock() {
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_DOCK))
+                .isEqualTo(R.drawable.ic_dock_device);
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_DOCK))
+                .isEqualTo(R.drawable.ic_dock_device);
     }
 
     @Test
     public void getIconResIdFromAudioDeviceType_hdmi_isHeadphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_HDMI))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_HDMI))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_tv_hdmi_isTv() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_HDMI))
+                .isEqualTo(R.drawable.ic_tv);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_hdmiArc_isHeadphone() {
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_HDMI_ARC))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_hdmiArc_isHdmi() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_HDMI_ARC))
+                .isEqualTo(R.drawable.ic_hdmi);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_hdmiEarc_isHeadphone() {
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_HDMI_EARC))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_tv_hdmiEarc() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_HDMI_EARC))
+                .isEqualTo(R.drawable.ic_hdmi);
     }
 
     @Test
     public void getIconResIdFromAudioDeviceType_wiredHeadset_isHeadphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_WIRED_HEADSET))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_WIRED_HEADSET))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_tv_wiredHeadset_isWiredDevice() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_WIRED_HEADSET))
+                .isEqualTo(R.drawable.ic_wired_device);
     }
 
     @Test
     public void getIconResIdFromAudioDeviceType_wiredHeadphones_isHeadphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_WIRED_HEADPHONES))
-            .isEqualTo(R.drawable.ic_headphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_WIRED_HEADPHONES))
+                .isEqualTo(R.drawable.ic_headphone);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_tv_wiredHeadphones_isWiredDevice() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_WIRED_HEADPHONES))
+                .isEqualTo(R.drawable.ic_wired_device);
     }
 
     @Test
     public void getIconResIdFromAudioDeviceType_builtinSpeaker_isSmartphone() {
-        assertThat(
-            mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER))
-            .isEqualTo(R.drawable.ic_smartphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER))
+                .isEqualTo(R.drawable.ic_smartphone);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_tv_builtinSpeaker_isTv() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER))
+                .isEqualTo(R.drawable.ic_tv);
     }
 
     @Test
     public void getIconResIdFromAudioDeviceType_unsupportedType_isSmartphone() {
-        assertThat(mDeviceIconUtil.getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_UNKNOWN))
-            .isEqualTo(R.drawable.ic_smartphone);
+        assertThat(new DeviceIconUtil(/* isTv */ false)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_UNKNOWN))
+                .isEqualTo(R.drawable.ic_smartphone);
+    }
+
+    @Test
+    public void getIconResIdFromAudioDeviceType_tv_unsupportedType_isSpeaker() {
+        assertThat(new DeviceIconUtil(/* isTv */ true)
+                .getIconResIdFromAudioDeviceType(AudioDeviceInfo.TYPE_UNKNOWN))
+                .isEqualTo(R.drawable.ic_media_speaker_device);
     }
 }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 4c9436b..89a8dd9 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -327,4 +327,12 @@
 
     <!-- Whether wifi is always requested by default. -->
     <bool name="def_enable_wifi_always_requested">false</bool>
+
+    <!-- Default for Settings.BATTERY_CHARGING_STATE_UPDATE_DELAY in millisecond.
+        -1 means system internal default value is used. -->
+    <integer name="def_battery_charging_state_update_delay_ms">-1</integer>
+
+    <!-- Default for Settings.BATTERY_CHARGING_STATE_ENFORCE_LEVEL.
+        -1 means system internal default value is used. -->
+    <integer name="def_battery_charging_state_enforce_level">-1</integer>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index 976ba21..6bc2716 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -68,7 +68,7 @@
     private static final List<String> sAconfigTextProtoFilesOnDevice = List.of(
             "/system/etc/aconfig_flags.pb",
             "/system_ext/etc/aconfig_flags.pb",
-            "/system_ext/etc/aconfig_flags.pb",
+            "/product/etc/aconfig_flags.pb",
             "/vendor/etc/aconfig_flags.pb");
 
     private static final List<String> PRIVATE_NAMESPACES = List.of(
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 8c8a71c..b0abf92 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3030,11 +3030,25 @@
         }
 
         @GuardedBy("mLock")
-        public void ensureSettingsForUserLocked(int userId) {
+        @Nullable
+        private SettingsState getOrCreateSettingsStateLocked(int key) {
+            SettingsState settingsState = mSettingsStates.get(key);
+            if (settingsState != null) {
+                return settingsState;
+            }
+
+            if (!ensureSettingsForUserLocked(getUserIdFromKey(key))) {
+                return null;
+            }
+            return mSettingsStates.get(key);
+        }
+
+        @GuardedBy("mLock")
+        public boolean ensureSettingsForUserLocked(int userId) {
             // First make sure this user actually exists.
             if (mUserManager.getUserInfo(userId) == null) {
                 Slog.wtf(LOG_TAG, "Requested user " + userId + " does not exist");
-                return;
+                return false;
             }
 
             // Migrate the setting for this user if needed.
@@ -3072,6 +3086,7 @@
             // Upgrade the settings to the latest version.
             UpgradeController upgrader = new UpgradeController(userId);
             upgrader.upgradeIfNeededLocked();
+            return true;
         }
 
         @GuardedBy("mLock")
@@ -3149,7 +3164,7 @@
 
             boolean success = false;
             boolean wasUnsetNonPredefinedSetting = false;
-            SettingsState settingsState = mSettingsStates.get(key);
+            SettingsState settingsState = getOrCreateSettingsStateLocked(key);
             if (settingsState != null) {
                 if (!isSettingPreDefined(name, type) && !settingsState.hasSetting(name)) {
                     wasUnsetNonPredefinedSetting = true;
@@ -3184,7 +3199,7 @@
         @GuardedBy("mLock")
         public boolean setConfigSettingsLocked(int key, String prefix,
                 Map<String, String> keyValues, String packageName) {
-            SettingsState settingsState = mSettingsStates.get(key);
+            SettingsState settingsState = getOrCreateSettingsStateLocked(key);
             if (settingsState != null) {
                 if (settingsState.isNewConfigBannedLocked(prefix, keyValues)) {
                     return false;
@@ -3207,7 +3222,7 @@
             final int key = makeKey(type, userId);
 
             boolean success = false;
-            SettingsState settingsState = mSettingsStates.get(key);
+            SettingsState settingsState = getOrCreateSettingsStateLocked(key);
             if (settingsState != null) {
                 success = settingsState.deleteSettingLocked(name);
             }
@@ -3232,7 +3247,7 @@
             final int key = makeKey(type, userId);
 
             boolean success = false;
-            SettingsState settingsState = mSettingsStates.get(key);
+            SettingsState settingsState = getOrCreateSettingsStateLocked(key);
             if (settingsState != null) {
                 success = settingsState.updateSettingLocked(name, value, tag,
                         makeDefault, packageName);
@@ -3284,7 +3299,7 @@
         public boolean resetSettingsLocked(int type, int userId, String packageName, int mode,
                 String tag, @Nullable String prefix) {
             final int key = makeKey(type, userId);
-            SettingsState settingsState = mSettingsStates.get(key);
+            SettingsState settingsState = getOrCreateSettingsStateLocked(key);
             if (settingsState == null) {
                 return false;
             }
@@ -3777,7 +3792,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 223;
+            private static final int SETTINGS_VERSION = 224;
 
             private final int mUserId;
 
@@ -5950,8 +5965,23 @@
                             // Do nothing. Leave the value as is.
                         }
                     }
+                }
 
-                    currentVersion = 223;
+                currentVersion = 223;
+
+                // Version 223: make charging constraint update criteria customizable.
+                if (currentVersion == 223) {
+                    initGlobalSettingsDefaultValLocked(
+                            Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
+                            getContext().getResources().getInteger(
+                                    R.integer.def_battery_charging_state_update_delay_ms));
+
+                    initGlobalSettingsDefaultValLocked(
+                            Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
+                            getContext().getResources().getInteger(
+                                    R.integer.def_battery_charging_state_enforce_level)
+                    );
+                    currentVersion = 224;
                 }
 
                 // vXXX: Add new settings above this point.
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 9dacade..2e174e2 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -145,6 +145,7 @@
                     Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS,
                     Settings.Global.AUTO_TIME_ZONE_EXPLICIT,
                     Settings.Global.AVERAGE_TIME_TO_DISCHARGE,
+                    Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
                     Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY,
                     Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME,
                     Settings.Global.BROADCAST_BG_CONSTANTS,
@@ -691,6 +692,7 @@
              newHashSet(
                  Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
                  Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, // Deprecated since O.
+                 Settings.Secure.ALLOW_PRIMARY_GAIA_ACCOUNT_REMOVAL_FOR_TESTS,
                  Settings.Secure.ALLOWED_GEOLOCATION_ORIGINS,
                  Settings.Secure.ALWAYS_ON_VPN_APP,
                  Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN,
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index f78811f..88abf69 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -165,6 +165,7 @@
         "SystemUI-statsd",
         "SettingsLib",
         "com_android_systemui_flags_lib",
+        "com_android_systemui_shared_flags_lib",
         "androidx.core_core-ktx",
         "androidx.viewpager2_viewpager2",
         "androidx.legacy_legacy-support-v4",
@@ -365,6 +366,7 @@
         "tests/src/com/android/systemui/qs/pipeline/shared/TileSpecTest.kt",
         "tests/src/com/android/systemui/qs/tiles/base/**/*.kt",
         "tests/src/com/android/systemui/qs/tiles/viewmodel/**/*.kt",
+        "tests/src/com/android/systemui/qs/tiles/impl/**/*.kt",
 
         /* Authentication */
         "tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt",
@@ -442,6 +444,7 @@
         "SystemUI-statsd",
         "SettingsLib",
         "com_android_systemui_flags_lib",
+        "com_android_systemui_shared_flags_lib",
         "flag-junit-base",
         "androidx.viewpager2_viewpager2",
         "androidx.legacy_legacy-support-v4",
diff --git a/packages/SystemUI/aconfig/Android.bp b/packages/SystemUI/aconfig/Android.bp
index dc4208e..e842967 100644
--- a/packages/SystemUI/aconfig/Android.bp
+++ b/packages/SystemUI/aconfig/Android.bp
@@ -1,3 +1,31 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * These flags are meant only for internal use in SystemUI and its variants.
+ * For shared, cross-process flags, see //frameworks/libs/systemui/aconfig
+ */
+
+package {
+    default_visibility: [
+        "//visibility:override",
+        "//frameworks/base/packages/SystemUI:__subpackages__",
+    ],
+}
+
 aconfig_declarations {
     name: "com_android_systemui_flags",
     package: "com.android.systemui",
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 8eff9bf..069ba6c 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -53,9 +53,32 @@
 }
 
 flag {
+    name: "keyguard_bottom_area_refactor"
+    namespace: "systemui"
+    description: "Bottom area of keyguard refactor move into KeyguardRootView. Includes "
+        "lock icon and others."
+    bug: "290652751"
+}
+
+flag {
     name: "visual_interruptions_refactor"
     namespace: "systemui"
     description: "Enables the refactored version of the code to decide when notifications "
         "HUN, bubble, pulse, or FSI."
     bug: "261728888"
 }
+
+flag {
+    name: "haptic_brightness_slider"
+    namespace: "systemui"
+    description: "Adds haptic feedback to the brightness slider."
+    bug: "296467915"
+}
+
+flag {
+    name: "keyguard_shade_migration_nssl"
+    namespace: "systemui"
+    description: "Moves NSSL into a shared element between the notification_panel and "
+        "keyguard_root_view."
+    bug: "278054201"
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index f2b7b32..56970d7 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -19,6 +19,7 @@
 import android.app.AlertDialog
 import android.app.Dialog
 import android.content.DialogInterface
+import android.content.res.Configuration
 import androidx.compose.animation.Crossfade
 import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.animation.core.snap
@@ -50,6 +51,7 @@
 import androidx.compose.material3.Icon
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
+import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
 import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
@@ -63,6 +65,7 @@
 import androidx.compose.ui.graphics.asImageBitmap
 import androidx.compose.ui.graphics.graphicsLayer
 import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.platform.LocalConfiguration
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.platform.LocalLayoutDirection
 import androidx.compose.ui.res.stringResource
@@ -136,7 +139,7 @@
     modifier: Modifier = Modifier,
 ) {
     val backgroundColor = MaterialTheme.colorScheme.surface
-    val windowSizeClass = LocalWindowSizeClass.current
+    val layout = calculateLayout()
 
     Box(modifier) {
         Canvas(Modifier.element(Bouncer.Elements.Background).fillMaxSize()) {
@@ -146,22 +149,30 @@
         val childModifier = Modifier.element(Bouncer.Elements.Content).fillMaxSize()
         val isFullScreenUserSwitcherEnabled = viewModel.isUserSwitcherVisible
 
-        when {
-            windowSizeClass.widthSizeClass == WindowWidthSizeClass.Expanded ->
+        when (layout) {
+            Layout.STANDARD ->
+                Bouncer(
+                    viewModel = viewModel,
+                    dialogFactory = dialogFactory,
+                    isUserInputAreaVisible = true,
+                    modifier = childModifier,
+                )
+            Layout.SIDE_BY_SIDE ->
                 SideBySide(
                     viewModel = viewModel,
                     dialogFactory = dialogFactory,
+                    isUserSwitcherVisible = isFullScreenUserSwitcherEnabled,
                     modifier = childModifier,
                 )
-            isFullScreenUserSwitcherEnabled &&
-                windowSizeClass.widthSizeClass == WindowWidthSizeClass.Medium ->
+            Layout.STACKED ->
                 Stacked(
                     viewModel = viewModel,
                     dialogFactory = dialogFactory,
+                    isUserSwitcherVisible = isFullScreenUserSwitcherEnabled,
                     modifier = childModifier,
                 )
-            else ->
-                Bouncer(
+            Layout.SPLIT ->
+                Split(
                     viewModel = viewModel,
                     dialogFactory = dialogFactory,
                     modifier = childModifier,
@@ -178,11 +189,10 @@
 private fun Bouncer(
     viewModel: BouncerViewModel,
     dialogFactory: BouncerSceneDialogFactory,
+    isUserInputAreaVisible: Boolean,
     modifier: Modifier = Modifier,
 ) {
     val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState()
-    val authMethodViewModel: AuthMethodBouncerViewModel? by
-        viewModel.authMethodViewModel.collectAsState()
     val dialogMessage: String? by viewModel.throttlingDialogMessage.collectAsState()
     var dialog: Dialog? by remember { mutableStateOf(null) }
 
@@ -204,25 +214,11 @@
         }
 
         Box(Modifier.weight(1f)) {
-            when (val nonNullViewModel = authMethodViewModel) {
-                is PinBouncerViewModel ->
-                    PinBouncer(
-                        viewModel = nonNullViewModel,
-                        modifier = Modifier.align(Alignment.Center),
-                    )
-                is PasswordBouncerViewModel ->
-                    PasswordBouncer(
-                        viewModel = nonNullViewModel,
-                        modifier = Modifier.align(Alignment.Center),
-                    )
-                is PatternBouncerViewModel ->
-                    PatternBouncer(
-                        viewModel = nonNullViewModel,
-                        modifier =
-                            Modifier.aspectRatio(1f, matchHeightConstraintsFirst = false)
-                                .align(Alignment.BottomCenter),
-                    )
-                else -> Unit
+            if (isUserInputAreaVisible) {
+                UserInputArea(
+                    viewModel = viewModel,
+                    modifier = Modifier.align(Alignment.Center),
+                )
             }
         }
 
@@ -265,6 +261,40 @@
     }
 }
 
+/**
+ * Renders the user input area, where the user interacts with the UI to enter their credentials.
+ *
+ * For example, this can be the pattern input area, the password text box, or pin pad.
+ */
+@Composable
+private fun UserInputArea(
+    viewModel: BouncerViewModel,
+    modifier: Modifier = Modifier,
+) {
+    val authMethodViewModel: AuthMethodBouncerViewModel? by
+        viewModel.authMethodViewModel.collectAsState()
+
+    when (val nonNullViewModel = authMethodViewModel) {
+        is PinBouncerViewModel ->
+            PinBouncer(
+                viewModel = nonNullViewModel,
+                modifier = modifier,
+            )
+        is PasswordBouncerViewModel ->
+            PasswordBouncer(
+                viewModel = nonNullViewModel,
+                modifier = modifier,
+            )
+        is PatternBouncerViewModel ->
+            PatternBouncer(
+                viewModel = nonNullViewModel,
+                modifier =
+                    Modifier.aspectRatio(1f, matchHeightConstraintsFirst = false).then(modifier)
+            )
+        else -> Unit
+    }
+}
+
 /** Renders the UI of the user switcher that's displayed on large screens next to the bouncer UI. */
 @Composable
 private fun UserSwitcher(
@@ -287,62 +317,57 @@
             )
         }
 
-        UserSwitcherDropdown(
-            items = dropdownItems,
-        )
-    }
-}
+        val (isDropdownExpanded, setDropdownExpanded) = remember { mutableStateOf(false) }
 
-@Composable
-private fun UserSwitcherDropdown(
-    items: List<BouncerViewModel.UserSwitcherDropdownItemViewModel>,
-) {
-    val (isDropdownExpanded, setDropdownExpanded) = remember { mutableStateOf(false) }
+        dropdownItems.firstOrNull()?.let { firstDropdownItem ->
+            Spacer(modifier = Modifier.height(40.dp))
 
-    items.firstOrNull()?.let { firstDropdownItem ->
-        Spacer(modifier = Modifier.height(40.dp))
+            Box {
+                PlatformButton(
+                    modifier =
+                        Modifier
+                            // Remove the built-in padding applied inside PlatformButton:
+                            .padding(vertical = 0.dp)
+                            .width(UserSwitcherDropdownWidth)
+                            .height(UserSwitcherDropdownHeight),
+                    colors =
+                        ButtonDefaults.buttonColors(
+                            containerColor = MaterialTheme.colorScheme.surfaceContainerHighest,
+                            contentColor = MaterialTheme.colorScheme.onSurface,
+                        ),
+                    onClick = { setDropdownExpanded(!isDropdownExpanded) },
+                ) {
+                    val context = LocalContext.current
+                    Text(
+                        text = checkNotNull(firstDropdownItem.text.loadText(context)),
+                        style = MaterialTheme.typography.headlineSmall,
+                        maxLines = 1,
+                        overflow = TextOverflow.Ellipsis,
+                    )
 
-        Box {
-            PlatformButton(
-                modifier =
-                    Modifier
-                        // Remove the built-in padding applied inside PlatformButton:
-                        .padding(vertical = 0.dp)
-                        .width(UserSwitcherDropdownWidth)
-                        .height(UserSwitcherDropdownHeight),
-                colors =
-                    ButtonDefaults.buttonColors(
-                        containerColor = MaterialTheme.colorScheme.surfaceContainerHighest,
-                        contentColor = MaterialTheme.colorScheme.onSurface,
-                    ),
-                onClick = { setDropdownExpanded(!isDropdownExpanded) },
-            ) {
-                val context = LocalContext.current
-                Text(
-                    text = checkNotNull(firstDropdownItem.text.loadText(context)),
-                    style = MaterialTheme.typography.headlineSmall,
-                    maxLines = 1,
-                    overflow = TextOverflow.Ellipsis,
-                )
+                    Spacer(modifier = Modifier.weight(1f))
 
-                Spacer(modifier = Modifier.weight(1f))
+                    Icon(
+                        imageVector = Icons.Default.KeyboardArrowDown,
+                        contentDescription = null,
+                        modifier = Modifier.size(32.dp),
+                    )
+                }
 
-                Icon(
-                    imageVector = Icons.Default.KeyboardArrowDown,
-                    contentDescription = null,
-                    modifier = Modifier.size(32.dp),
+                UserSwitcherDropdownMenu(
+                    isExpanded = isDropdownExpanded,
+                    items = dropdownItems,
+                    onDismissed = { setDropdownExpanded(false) },
                 )
             }
-
-            UserSwitcherDropdownMenu(
-                isExpanded = isDropdownExpanded,
-                items = items,
-                onDismissed = { setDropdownExpanded(false) },
-            )
         }
     }
 }
 
+/**
+ * Renders the dropdowm menu that displays the actual users and/or user actions that can be
+ * selected.
+ */
 @Composable
 private fun UserSwitcherDropdownMenu(
     isExpanded: Boolean,
@@ -396,19 +421,47 @@
 }
 
 /**
- * Arranges the bouncer contents and user switcher contents side-by-side, supporting a double tap
- * anywhere on the background to flip their positions.
+ * Renders the bouncer UI in split mode, with half on one side and half on the other side, swappable
+ * by double-tapping on the side.
  */
 @Composable
-private fun SideBySide(
+private fun Split(
     viewModel: BouncerViewModel,
     dialogFactory: BouncerSceneDialogFactory,
     modifier: Modifier = Modifier,
 ) {
+    SwappableLayout(
+        startContent = { startContentModifier ->
+            Bouncer(
+                viewModel = viewModel,
+                dialogFactory = dialogFactory,
+                isUserInputAreaVisible = false,
+                modifier = startContentModifier,
+            )
+        },
+        endContent = { endContentModifier ->
+            UserInputArea(
+                viewModel = viewModel,
+                modifier = endContentModifier,
+            )
+        },
+        modifier = modifier
+    )
+}
+
+/**
+ * Arranges the given two contents side-by-side, supporting a double tap anywhere on the background
+ * to flip their positions.
+ */
+@Composable
+private fun SwappableLayout(
+    startContent: @Composable (Modifier) -> Unit,
+    endContent: @Composable (Modifier) -> Unit,
+    modifier: Modifier = Modifier,
+) {
     val layoutDirection = LocalLayoutDirection.current
     val isLeftToRight = layoutDirection == LayoutDirection.Ltr
-    val (isUserSwitcherFirst, setUserSwitcherFirst) =
-        rememberSaveable(isLeftToRight) { mutableStateOf(isLeftToRight) }
+    val (isSwapped, setSwapped) = rememberSaveable(isLeftToRight) { mutableStateOf(!isLeftToRight) }
 
     Row(
         modifier =
@@ -416,9 +469,8 @@
                 detectTapGestures(
                     onDoubleTap = { offset ->
                         // Depending on where the user double tapped, switch the elements such that
-                        // the bouncer contents element is closer to the side that was double
-                        // tapped.
-                        setUserSwitcherFirst(offset.x > size.width / 2)
+                        // the endContent is closer to the side that was double tapped.
+                        setSwapped(offset.x < size.width / 2)
                     }
                 )
             },
@@ -426,39 +478,30 @@
         val animatedOffset by
             animateFloatAsState(
                 targetValue =
-                    if (isUserSwitcherFirst) {
-                        // When the user switcher is first, both elements have their natural
-                        // placement so they are not offset in any way.
+                    if (!isSwapped) {
+                        // When startContent is first, both elements have their natural placement so
+                        // they are not offset in any way.
                         0f
                     } else if (isLeftToRight) {
-                        // Since the user switcher is not first, the elements have to be swapped
-                        // horizontally. In the case of LTR locales, this means pushing the user
-                        // switcher to the right, hence the positive number.
+                        // Since startContent is not first, the elements have to be swapped
+                        // horizontally. In the case of LTR locales, this means pushing startContent
+                        // to the right, hence the positive number.
                         1f
                     } else {
-                        // Since the user switcher is not first, the elements have to be swapped
-                        // horizontally. In the case of RTL locale, this means pushing the user
-                        // switcher to the left, hence the negative number.
+                        // Since startContent is not first, the elements have to be swapped
+                        // horizontally. In the case of RTL locales, this means pushing startContent
+                        // to the left, hence the negative number.
                         -1f
                     },
                 label = "offset",
             )
 
-        val userSwitcherModifier =
+        startContent(
             Modifier.fillMaxHeight().weight(1f).graphicsLayer {
                 translationX = size.width * animatedOffset
                 alpha = animatedAlpha(animatedOffset)
             }
-        if (viewModel.isUserSwitcherVisible) {
-            UserSwitcher(
-                viewModel = viewModel,
-                modifier = userSwitcherModifier,
-            )
-        } else {
-            Box(
-                modifier = userSwitcherModifier,
-            )
-        }
+        )
 
         Box(
             modifier =
@@ -469,41 +512,124 @@
                     alpha = animatedAlpha(animatedOffset)
                 }
         ) {
-            Bouncer(
-                viewModel = viewModel,
-                dialogFactory = dialogFactory,
-                modifier = Modifier.widthIn(max = 400.dp).align(Alignment.BottomCenter),
-            )
+            endContent(Modifier.widthIn(max = 400.dp).align(Alignment.BottomCenter))
         }
     }
 }
 
-/** Arranges the bouncer contents and user switcher contents one on top of the other. */
+/**
+ * Arranges the bouncer contents and user switcher contents side-by-side, supporting a double tap
+ * anywhere on the background to flip their positions.
+ */
+@Composable
+private fun SideBySide(
+    viewModel: BouncerViewModel,
+    dialogFactory: BouncerSceneDialogFactory,
+    isUserSwitcherVisible: Boolean,
+    modifier: Modifier = Modifier,
+) {
+    SwappableLayout(
+        startContent = { startContentModifier ->
+            if (isUserSwitcherVisible) {
+                UserSwitcher(
+                    viewModel = viewModel,
+                    modifier = startContentModifier,
+                )
+            } else {
+                Box(
+                    modifier = startContentModifier,
+                )
+            }
+        },
+        endContent = { endContentModifier ->
+            Bouncer(
+                viewModel = viewModel,
+                dialogFactory = dialogFactory,
+                isUserInputAreaVisible = true,
+                modifier = endContentModifier,
+            )
+        },
+        modifier = modifier,
+    )
+}
+
+/** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */
 @Composable
 private fun Stacked(
     viewModel: BouncerViewModel,
     dialogFactory: BouncerSceneDialogFactory,
+    isUserSwitcherVisible: Boolean,
     modifier: Modifier = Modifier,
 ) {
     Column(
         modifier = modifier,
     ) {
-        UserSwitcher(
-            viewModel = viewModel,
-            modifier = Modifier.fillMaxWidth().weight(1f),
-        )
+        if (isUserSwitcherVisible) {
+            UserSwitcher(
+                viewModel = viewModel,
+                modifier = Modifier.fillMaxWidth().weight(1f),
+            )
+        }
+
         Bouncer(
             viewModel = viewModel,
             dialogFactory = dialogFactory,
+            isUserInputAreaVisible = true,
             modifier = Modifier.fillMaxWidth().weight(1f),
         )
     }
 }
 
+@Composable
+private fun calculateLayout(): Layout {
+    val windowSizeClass = LocalWindowSizeClass.current
+    val width = windowSizeClass.widthSizeClass
+    val height = windowSizeClass.heightSizeClass
+    val isLarge = width > WindowWidthSizeClass.Compact && height > WindowHeightSizeClass.Compact
+    val isTall =
+        when (height) {
+            WindowHeightSizeClass.Expanded -> width < WindowWidthSizeClass.Expanded
+            WindowHeightSizeClass.Medium -> width < WindowWidthSizeClass.Medium
+            else -> false
+        }
+    val isSquare =
+        when (width) {
+            WindowWidthSizeClass.Compact -> height == WindowHeightSizeClass.Compact
+            WindowWidthSizeClass.Medium -> height == WindowHeightSizeClass.Medium
+            WindowWidthSizeClass.Expanded -> height == WindowHeightSizeClass.Expanded
+            else -> false
+        }
+    val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE
+
+    return when {
+        // Small and tall devices (i.e. phone/folded in portrait) or square device not in landscape
+        // mode (unfolded with hinge along horizontal plane).
+        (!isLarge && isTall) || (isSquare && !isLandscape) -> Layout.STANDARD
+        // Small and wide devices (i.e. phone/folded in landscape).
+        !isLarge -> Layout.SPLIT
+        // Large and tall devices (i.e. tablet in portrait).
+        isTall -> Layout.STACKED
+        // Large and wide/square devices (i.e. tablet in landscape, unfolded).
+        else -> Layout.SIDE_BY_SIDE
+    }
+}
+
 interface BouncerSceneDialogFactory {
     operator fun invoke(): AlertDialog
 }
 
+/** Enumerates all known adaptive layout configurations. */
+private enum class Layout {
+    /** The default UI with the bouncer laid out normally. */
+    STANDARD,
+    /** The bouncer is displayed vertically stacked with the user switcher. */
+    STACKED,
+    /** The bouncer is displayed side-by-side with the user switcher or an empty space. */
+    SIDE_BY_SIDE,
+    /** The bouncer is split in two with both sides shown side-by-side. */
+    SPLIT,
+}
+
 /**
  * Calculates an alpha for the user switcher and bouncer such that it's at `1` when the offset of
  * the two reaches a stopping point but `0` in the middle of the transition.
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index 46d418a..3780468 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -14,6 +14,7 @@
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
@@ -29,12 +30,9 @@
 import com.android.compose.animation.scene.SceneTransitionLayout
 import com.android.compose.animation.scene.Swipe
 import com.android.compose.animation.scene.transitions
+import com.android.systemui.communal.shared.model.CommunalSceneKey
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
-
-object Scenes {
-    val Blank = SceneKey(name = "blank")
-    val Communal = SceneKey(name = "communal")
-}
+import kotlinx.coroutines.flow.transform
 
 object Communal {
     object Elements {
@@ -43,7 +41,7 @@
 }
 
 val sceneTransitions = transitions {
-    from(Scenes.Blank, to = Scenes.Communal) {
+    from(TransitionSceneKey.Blank, to = TransitionSceneKey.Communal) {
         spec = tween(durationMillis = 500)
 
         translate(Communal.Elements.Content, Edge.Right)
@@ -58,8 +56,14 @@
  * handling and transitions before the full Flexiglass layout is ready.
  */
 @Composable
-fun CommunalContainer(modifier: Modifier = Modifier, viewModel: CommunalViewModel) {
-    val (currentScene, setCurrentScene) = remember { mutableStateOf(Scenes.Blank) }
+fun CommunalContainer(
+    modifier: Modifier = Modifier,
+    viewModel: CommunalViewModel,
+) {
+    val currentScene: SceneKey by
+        viewModel.currentScene
+            .transform<CommunalSceneKey, SceneKey> { value -> value.toTransitionSceneKey() }
+            .collectAsState(TransitionSceneKey.Blank)
 
     // Failsafe to hide the whole SceneTransitionLayout in case of bugginess.
     var showSceneTransitionLayout by remember { mutableStateOf(true) }
@@ -70,16 +74,19 @@
     SceneTransitionLayout(
         modifier = modifier.fillMaxSize(),
         currentScene = currentScene,
-        onChangeScene = setCurrentScene,
+        onChangeScene = { sceneKey -> viewModel.onSceneChanged(sceneKey.toCommunalSceneKey()) },
         transitions = sceneTransitions,
     ) {
-        scene(Scenes.Blank, userActions = mapOf(Swipe.Left to Scenes.Communal)) {
+        scene(
+            TransitionSceneKey.Blank,
+            userActions = mapOf(Swipe.Left to TransitionSceneKey.Communal)
+        ) {
             BlankScene { showSceneTransitionLayout = false }
         }
 
         scene(
-            Scenes.Communal,
-            userActions = mapOf(Swipe.Right to Scenes.Blank),
+            TransitionSceneKey.Communal,
+            userActions = mapOf(Swipe.Right to TransitionSceneKey.Blank),
         ) {
             CommunalScene(viewModel, modifier = modifier)
         }
@@ -121,3 +128,17 @@
 ) {
     Box(modifier.element(Communal.Elements.Content)) { CommunalHub(viewModel = viewModel) }
 }
+
+// TODO(b/293899074): Remove these conversions once Compose can be used throughout SysUI.
+object TransitionSceneKey {
+    val Blank = CommunalSceneKey.Blank.toTransitionSceneKey()
+    val Communal = CommunalSceneKey.Communal.toTransitionSceneKey()
+}
+
+fun CommunalSceneKey.toTransitionSceneKey(): SceneKey {
+    return SceneKey(name = toString(), identity = this)
+}
+
+fun SceneKey.toCommunalSceneKey(): CommunalSceneKey {
+    return this.identity as CommunalSceneKey
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 2e93a09..0da562b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -161,7 +161,8 @@
                 fromScene = fromScene.toModel().key,
                 toScene = toScene.toModel().key,
                 progress = progress,
-                isUserInputDriven = isUserInputDriven,
+                isInitiatedByUserInput = isInitiatedByUserInput,
+                isUserInputOngoing = isUserInputOngoing,
             )
     }
 }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
index 88944f10..199832b 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateToScene.kt
@@ -108,7 +108,7 @@
 ) {
     val fromScene = layoutImpl.state.transitionState.currentScene
     val isUserInput =
-        (layoutImpl.state.transitionState as? TransitionState.Transition)?.isUserInputDriven
+        (layoutImpl.state.transitionState as? TransitionState.Transition)?.isInitiatedByUserInput
             ?: false
 
     val animationSpec = layoutImpl.transitions.transitionSpec(fromScene, target).spec
@@ -119,9 +119,23 @@
     val targetProgress = if (reversed) 0f else 1f
     val transition =
         if (reversed) {
-            OneOffTransition(target, fromScene, currentScene = target, isUserInput, animatable)
+            OneOffTransition(
+                fromScene = target,
+                toScene = fromScene,
+                currentScene = target,
+                isInitiatedByUserInput = isUserInput,
+                isUserInputOngoing = false,
+                animatable = animatable,
+            )
         } else {
-            OneOffTransition(fromScene, target, currentScene = target, isUserInput, animatable)
+            OneOffTransition(
+                fromScene = fromScene,
+                toScene = target,
+                currentScene = target,
+                isInitiatedByUserInput = isUserInput,
+                isUserInputOngoing = false,
+                animatable = animatable,
+            )
         }
 
     // Change the current layout state to use this new transition.
@@ -142,7 +156,8 @@
     override val fromScene: SceneKey,
     override val toScene: SceneKey,
     override val currentScene: SceneKey,
-    override val isUserInputDriven: Boolean,
+    override val isInitiatedByUserInput: Boolean,
+    override val isUserInputOngoing: Boolean,
     private val animatable: Animatable<Float, AnimationVector1D>,
 ) : TransitionState.Transition {
     override val progress: Float
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt
new file mode 100644
index 0000000..82d4239
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/EdgeDetector.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.dp
+
+interface EdgeDetector {
+    /**
+     * Return the [Edge] associated to [position] inside a layout of size [layoutSize], given
+     * [density] and [orientation].
+     */
+    fun edge(
+        layoutSize: IntSize,
+        position: IntOffset,
+        density: Density,
+        orientation: Orientation,
+    ): Edge?
+}
+
+val DefaultEdgeDetector = FixedSizeEdgeDetector(40.dp)
+
+/** An [EdgeDetector] that detects edges assuming a fixed edge size of [size]. */
+class FixedSizeEdgeDetector(val size: Dp) : EdgeDetector {
+    override fun edge(
+        layoutSize: IntSize,
+        position: IntOffset,
+        density: Density,
+        orientation: Orientation,
+    ): Edge? {
+        val axisSize: Int
+        val axisPosition: Int
+        val topOrLeft: Edge
+        val bottomOrRight: Edge
+        when (orientation) {
+            Orientation.Horizontal -> {
+                axisSize = layoutSize.width
+                axisPosition = position.x
+                topOrLeft = Edge.Left
+                bottomOrRight = Edge.Right
+            }
+            Orientation.Vertical -> {
+                axisSize = layoutSize.height
+                axisPosition = position.y
+                topOrLeft = Edge.Top
+                bottomOrRight = Edge.Bottom
+            }
+        }
+
+        val sizePx = with(density) { size.toPx() }
+        return when {
+            axisPosition <= sizePx -> topOrLeft
+            axisPosition >= axisSize - sizePx -> bottomOrRight
+            else -> null
+        }
+    }
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt
index d005413..ae7d8f5 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/GestureHandler.kt
@@ -2,7 +2,6 @@
 
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
-import kotlinx.coroutines.CoroutineScope
 
 interface GestureHandler {
     val draggable: DraggableHandler
@@ -10,9 +9,9 @@
 }
 
 interface DraggableHandler {
-    suspend fun onDragStarted(coroutineScope: CoroutineScope, startedPosition: Offset)
+    fun onDragStarted(startedPosition: Offset, pointersDown: Int = 1)
     fun onDelta(pixels: Float)
-    suspend fun onDragStopped(coroutineScope: CoroutineScope, velocity: Float)
+    fun onDragStopped(velocity: Float)
 }
 
 interface NestedScrollHandler {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
new file mode 100644
index 0000000..97d3fff
--- /dev/null
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MultiPointerDraggable.kt
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.gestures.awaitEachGesture
+import androidx.compose.foundation.gestures.awaitFirstDown
+import androidx.compose.foundation.gestures.awaitHorizontalTouchSlopOrCancellation
+import androidx.compose.foundation.gestures.awaitVerticalTouchSlopOrCancellation
+import androidx.compose.foundation.gestures.horizontalDrag
+import androidx.compose.foundation.gestures.verticalDrag
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberUpdatedState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.geometry.Offset
+import androidx.compose.ui.input.pointer.PointerEventPass
+import androidx.compose.ui.input.pointer.PointerId
+import androidx.compose.ui.input.pointer.PointerInputChange
+import androidx.compose.ui.input.pointer.PointerInputScope
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.input.pointer.positionChange
+import androidx.compose.ui.input.pointer.util.VelocityTracker
+import androidx.compose.ui.input.pointer.util.addPointerInputChange
+import androidx.compose.ui.platform.LocalViewConfiguration
+import androidx.compose.ui.unit.Velocity
+import androidx.compose.ui.util.fastForEach
+
+/**
+ * Make an element draggable in the given [orientation].
+ *
+ * The main difference with [multiPointerDraggable] and
+ * [androidx.compose.foundation.gestures.draggable] is that [onDragStarted] also receives the number
+ * of pointers that are down when the drag is started. If you don't need this information, you
+ * should use `draggable` instead.
+ *
+ * Note that the current implementation is trivial: we wait for the touch slope on the *first* down
+ * pointer, then we count the number of distinct pointers that are down right before calling
+ * [onDragStarted]. This means that the drag won't start when a first pointer is down (but not
+ * dragged) and a second pointer is down and dragged. This is an implementation detail that might
+ * change in the future.
+ */
+// TODO(b/291055080): Migrate to the Modifier.Node API.
+@Composable
+internal fun Modifier.multiPointerDraggable(
+    orientation: Orientation,
+    enabled: Boolean,
+    startDragImmediately: Boolean,
+    onDragStarted: (startedPosition: Offset, pointersDown: Int) -> Unit,
+    onDragDelta: (Float) -> Unit,
+    onDragStopped: (velocity: Float) -> Unit,
+): Modifier {
+    val onDragStarted by rememberUpdatedState(onDragStarted)
+    val onDragStopped by rememberUpdatedState(onDragStopped)
+    val onDragDelta by rememberUpdatedState(onDragDelta)
+    val startDragImmediately by rememberUpdatedState(startDragImmediately)
+
+    val velocityTracker = remember { VelocityTracker() }
+    val maxFlingVelocity =
+        LocalViewConfiguration.current.maximumFlingVelocity.let { max ->
+            val maxF = max.toFloat()
+            Velocity(maxF, maxF)
+        }
+
+    return this.pointerInput(enabled, orientation, maxFlingVelocity) {
+        if (!enabled) {
+            return@pointerInput
+        }
+
+        val onDragStart: (Offset, Int) -> Unit = { startedPosition, pointersDown ->
+            velocityTracker.resetTracking()
+            onDragStarted(startedPosition, pointersDown)
+        }
+
+        val onDragCancel: () -> Unit = { onDragStopped(/* velocity= */ 0f) }
+
+        val onDragEnd: () -> Unit = {
+            val velocity = velocityTracker.calculateVelocity(maxFlingVelocity)
+            onDragStopped(
+                when (orientation) {
+                    Orientation.Horizontal -> velocity.x
+                    Orientation.Vertical -> velocity.y
+                }
+            )
+        }
+
+        val onDrag: (change: PointerInputChange, dragAmount: Float) -> Unit = { change, amount ->
+            velocityTracker.addPointerInputChange(change)
+            onDragDelta(amount)
+        }
+
+        detectDragGestures(
+            orientation = orientation,
+            startDragImmediately = { startDragImmediately },
+            onDragStart = onDragStart,
+            onDragEnd = onDragEnd,
+            onDragCancel = onDragCancel,
+            onDrag = onDrag,
+        )
+    }
+}
+
+/**
+ * Detect drag gestures in the given [orientation].
+ *
+ * This function is a mix of [androidx.compose.foundation.gestures.awaitDownAndSlop] and
+ * [androidx.compose.foundation.gestures.detectVerticalDragGestures] to add support for:
+ * 1) starting the gesture immediately without requiring a drag >= touch slope;
+ * 2) passing the number of pointers down to [onDragStart].
+ */
+private suspend fun PointerInputScope.detectDragGestures(
+    orientation: Orientation,
+    startDragImmediately: () -> Boolean,
+    onDragStart: (startedPosition: Offset, pointersDown: Int) -> Unit,
+    onDragEnd: () -> Unit,
+    onDragCancel: () -> Unit,
+    onDrag: (change: PointerInputChange, dragAmount: Float) -> Unit,
+) {
+    awaitEachGesture {
+        val initialDown = awaitFirstDown(requireUnconsumed = false, pass = PointerEventPass.Initial)
+        var overSlop = 0f
+        val drag =
+            if (startDragImmediately()) {
+                initialDown.consume()
+                initialDown
+            } else {
+                val down = awaitFirstDown(requireUnconsumed = false)
+                val onSlopReached = { change: PointerInputChange, over: Float ->
+                    change.consume()
+                    overSlop = over
+                }
+
+                // TODO(b/291055080): Replace by await[Orientation]PointerSlopOrCancellation once
+                // it is public.
+                when (orientation) {
+                    Orientation.Horizontal ->
+                        awaitHorizontalTouchSlopOrCancellation(down.id, onSlopReached)
+                    Orientation.Vertical ->
+                        awaitVerticalTouchSlopOrCancellation(down.id, onSlopReached)
+                }
+            }
+
+        if (drag != null) {
+            // Count the number of pressed pointers.
+            val pressed = mutableSetOf<PointerId>()
+            currentEvent.changes.fastForEach { change ->
+                if (change.pressed) {
+                    pressed.add(change.id)
+                }
+            }
+
+            onDragStart(drag.position, pressed.size)
+            onDrag(drag, overSlop)
+
+            val successful =
+                when (orientation) {
+                    Orientation.Horizontal ->
+                        horizontalDrag(drag.id) {
+                            onDrag(it, it.positionChange().x)
+                            it.consume()
+                        }
+                    Orientation.Vertical ->
+                        verticalDrag(drag.id) {
+                            onDrag(it, it.positionChange().y)
+                            it.consume()
+                        }
+                }
+
+            if (successful) {
+                onDragEnd()
+            } else {
+                onDragCancel()
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
index ccdec6e..1b79dbd 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/ObservableTransitionState.kt
@@ -52,7 +52,14 @@
          * scene, this value will remain true after the pointer is no longer touching the screen and
          * will be true in any transition created to animate back to the original position.
          */
-        val isUserInputDriven: Boolean,
+        val isInitiatedByUserInput: Boolean,
+
+        /**
+         * Whether user input is currently driving the transition. For example, if a user is
+         * dragging a pointer, this emits true. Once they lift their finger, this emits false while
+         * the transition completes/settles.
+         */
+        val isUserInputOngoing: Flow<Boolean>,
     ) : ObservableTransitionState()
 }
 
@@ -73,7 +80,8 @@
                             fromScene = state.fromScene,
                             toScene = state.toScene,
                             progress = snapshotFlow { state.progress },
-                            isUserInputDriven = state.isUserInputDriven,
+                            isInitiatedByUserInput = state.isInitiatedByUserInput,
+                            isUserInputOngoing = snapshotFlow { state.isUserInputOngoing },
                         )
                     }
                 }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
index 9c799b28..3fd6828 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Scene.kt
@@ -16,7 +16,6 @@
 
 package com.android.compose.animation.scene
 
-import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
@@ -101,19 +100,3 @@
         MovableElement(layoutImpl, scene, key, modifier, content)
     }
 }
-
-/** The destination scene when swiping up or left from [upOrLeft]. */
-internal fun Scene.upOrLeft(orientation: Orientation): SceneKey? {
-    return when (orientation) {
-        Orientation.Vertical -> userActions[Swipe.Up]
-        Orientation.Horizontal -> userActions[Swipe.Left]
-    }
-}
-
-/** The destination scene when swiping down or right from [downOrRight]. */
-internal fun Scene.downOrRight(orientation: Orientation): SceneKey? {
-    return when (orientation) {
-        Orientation.Vertical -> userActions[Swipe.Down]
-        Orientation.Horizontal -> userActions[Swipe.Right]
-    }
-}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index 74e66d2..1f38e70 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -16,6 +16,7 @@
 
 package com.android.compose.animation.scene
 
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.remember
@@ -37,6 +38,7 @@
  *   instance by triggering back navigation or by swiping to a new scene.
  * @param transitions the definition of the transitions used to animate a change of scene.
  * @param state the observable state of this layout.
+ * @param edgeDetector the edge detector used to detect which edge a swipe is started from, if any.
  * @param scenes the configuration of the different scenes of this layout.
  */
 @Composable
@@ -46,6 +48,7 @@
     transitions: SceneTransitions,
     modifier: Modifier = Modifier,
     state: SceneTransitionLayoutState = remember { SceneTransitionLayoutState(currentScene) },
+    edgeDetector: EdgeDetector = DefaultEdgeDetector,
     scenes: SceneTransitionLayoutScope.() -> Unit,
 ) {
     val density = LocalDensity.current
@@ -56,15 +59,17 @@
             transitions,
             state,
             density,
+            edgeDetector,
         )
     }
 
     layoutImpl.onChangeScene = onChangeScene
     layoutImpl.transitions = transitions
     layoutImpl.density = density
+    layoutImpl.edgeDetector = edgeDetector
+
     layoutImpl.setScenes(scenes)
     layoutImpl.setCurrentScene(currentScene)
-
     layoutImpl.Content(modifier)
 }
 
@@ -191,9 +196,9 @@
     }
 }
 
-enum class SwipeDirection {
-    Up,
-    Down,
-    Left,
-    Right,
+enum class SwipeDirection(val orientation: Orientation) {
+    Up(Orientation.Vertical),
+    Down(Orientation.Vertical),
+    Left(Orientation.Horizontal),
+    Right(Orientation.Horizontal),
 }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
index a40b299..fd62659 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutImpl.kt
@@ -37,7 +37,7 @@
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.unit.Density
 import androidx.compose.ui.unit.IntSize
-import com.android.compose.ui.util.fastForEach
+import androidx.compose.ui.util.fastForEach
 import kotlinx.coroutines.channels.Channel
 
 @VisibleForTesting
@@ -47,6 +47,7 @@
     transitions: SceneTransitions,
     internal val state: SceneTransitionLayoutState,
     density: Density,
+    edgeDetector: EdgeDetector,
 ) {
     internal val scenes = SnapshotStateMap<SceneKey, Scene>()
     internal val elements = SnapshotStateMap<ElementKey, Element>()
@@ -57,6 +58,7 @@
     internal var onChangeScene by mutableStateOf(onChangeScene)
     internal var transitions by mutableStateOf(transitions)
     internal var density: Density by mutableStateOf(density)
+    internal var edgeDetector by mutableStateOf(edgeDetector)
 
     /**
      * The size of this layout. Note that this could be [IntSize.Zero] if this layour does not have
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
index 7a21211..b9f83c5 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayoutState.kt
@@ -70,6 +70,9 @@
         val progress: Float
 
         /** Whether the transition was triggered by user input rather than being programmatic. */
-        val isUserInputDriven: Boolean
+        val isInitiatedByUserInput: Boolean
+
+        /** Whether user input is currently driving the transition. */
+        val isUserInputOngoing: Boolean
     }
 }
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
index 75dcb2e..b163a2a 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitions.kt
@@ -21,6 +21,8 @@
 import androidx.compose.animation.core.snap
 import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.util.fastForEach
+import androidx.compose.ui.util.fastMap
 import com.android.compose.animation.scene.transformation.AnchoredSize
 import com.android.compose.animation.scene.transformation.AnchoredTranslate
 import com.android.compose.animation.scene.transformation.EdgeTranslate
@@ -32,8 +34,6 @@
 import com.android.compose.animation.scene.transformation.SharedElementTransformation
 import com.android.compose.animation.scene.transformation.Transformation
 import com.android.compose.animation.scene.transformation.Translate
-import com.android.compose.ui.util.fastForEach
-import com.android.compose.ui.util.fastMap
 
 /** The transitions configuration of a [SceneTransitionLayout]. */
 class SceneTransitions(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
index 2dc53ab..877ac09 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SwipeToScene.kt
@@ -22,8 +22,6 @@
 import androidx.compose.animation.core.Spring
 import androidx.compose.animation.core.spring
 import androidx.compose.foundation.gestures.Orientation
-import androidx.compose.foundation.gestures.draggable
-import androidx.compose.foundation.gestures.rememberDraggableState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.getValue
@@ -37,6 +35,7 @@
 import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.unit.Velocity
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.round
 import com.android.compose.nestedscroll.PriorityNestedScrollConnection
 import kotlin.math.absoluteValue
 import kotlinx.coroutines.CoroutineScope
@@ -55,7 +54,7 @@
 
     /** Whether swipe should be enabled in the given [orientation]. */
     fun Scene.shouldEnableSwipes(orientation: Orientation): Boolean =
-        upOrLeft(orientation) != null || downOrRight(orientation) != null
+        userActions.keys.any { it is Swipe && it.direction.orientation == orientation }
 
     val currentScene = gestureHandler.currentScene
     val canSwipe = currentScene.shouldEnableSwipes(orientation)
@@ -68,8 +67,7 @@
         )
 
     return nestedScroll(connection = gestureHandler.nestedScroll.connection)
-        .draggable(
-            state = rememberDraggableState(onDelta = gestureHandler.draggable::onDelta),
+        .multiPointerDraggable(
             orientation = orientation,
             enabled = gestureHandler.isDrivingTransition || canSwipe,
             // Immediately start the drag if this our [transition] is currently animating to a scene
@@ -80,6 +78,7 @@
                     gestureHandler.isAnimatingOffset &&
                     !canOppositeSwipe,
             onDragStarted = gestureHandler.draggable::onDragStarted,
+            onDragDelta = gestureHandler.draggable::onDelta,
             onDragStopped = gestureHandler.draggable::onDragStopped,
         )
 }
@@ -159,7 +158,7 @@
 
     internal var gestureWithPriority: Any? = null
 
-    internal fun onDragStarted() {
+    internal fun onDragStarted(pointersDown: Int, startedPosition: Offset?) {
         if (isDrivingTransition) {
             // This [transition] was already driving the animation: simply take over it.
             // Stop animating and start from where the current offset.
@@ -199,6 +198,48 @@
                 Orientation.Vertical -> layoutImpl.size.height
             }.toFloat()
 
+        val fromEdge =
+            startedPosition?.let { position ->
+                layoutImpl.edgeDetector.edge(
+                    layoutImpl.size,
+                    position.round(),
+                    layoutImpl.density,
+                    orientation,
+                )
+            }
+
+        swipeTransition.actionUpOrLeft =
+            Swipe(
+                direction =
+                    when (orientation) {
+                        Orientation.Horizontal -> SwipeDirection.Left
+                        Orientation.Vertical -> SwipeDirection.Up
+                    },
+                pointerCount = pointersDown,
+                fromEdge = fromEdge,
+            )
+
+        swipeTransition.actionDownOrRight =
+            Swipe(
+                direction =
+                    when (orientation) {
+                        Orientation.Horizontal -> SwipeDirection.Right
+                        Orientation.Vertical -> SwipeDirection.Down
+                    },
+                pointerCount = pointersDown,
+                fromEdge = fromEdge,
+            )
+
+        if (fromEdge == null) {
+            swipeTransition.actionUpOrLeftNoEdge = null
+            swipeTransition.actionDownOrRightNoEdge = null
+        } else {
+            swipeTransition.actionUpOrLeftNoEdge =
+                (swipeTransition.actionUpOrLeft as Swipe).copy(fromEdge = null)
+            swipeTransition.actionDownOrRightNoEdge =
+                (swipeTransition.actionDownOrRight as Swipe).copy(fromEdge = null)
+        }
+
         if (swipeTransition.absoluteDistance > 0f) {
             transitionState = swipeTransition
         }
@@ -246,11 +287,11 @@
         // to the next screen or go back to the previous one.
         val offset = swipeTransition.dragOffset
         val absoluteDistance = swipeTransition.absoluteDistance
-        if (offset <= -absoluteDistance && fromScene.upOrLeft(orientation) == toScene.key) {
+        if (offset <= -absoluteDistance && swipeTransition.upOrLeft(fromScene) == toScene.key) {
             swipeTransition.dragOffset += absoluteDistance
             swipeTransition._fromScene = toScene
         } else if (
-            offset >= absoluteDistance && fromScene.downOrRight(orientation) == toScene.key
+            offset >= absoluteDistance && swipeTransition.downOrRight(fromScene) == toScene.key
         ) {
             swipeTransition.dragOffset -= absoluteDistance
             swipeTransition._fromScene = toScene
@@ -266,27 +307,21 @@
     )
 
     private fun Scene.findTargetSceneAndDistance(directionOffset: Float): TargetScene {
-        val maxDistance =
-            when (orientation) {
-                Orientation.Horizontal -> layoutImpl.size.width
-                Orientation.Vertical -> layoutImpl.size.height
-            }.toFloat()
-
-        val upOrLeft = upOrLeft(orientation)
-        val downOrRight = downOrRight(orientation)
+        val upOrLeft = swipeTransition.upOrLeft(this)
+        val downOrRight = swipeTransition.downOrRight(this)
 
         // Compute the target scene depending on the current offset.
         return when {
             directionOffset < 0f && upOrLeft != null -> {
                 TargetScene(
                     sceneKey = upOrLeft,
-                    distance = -maxDistance,
+                    distance = -swipeTransition.absoluteDistance,
                 )
             }
             directionOffset > 0f && downOrRight != null -> {
                 TargetScene(
                     sceneKey = downOrRight,
-                    distance = maxDistance,
+                    distance = swipeTransition.absoluteDistance,
                 )
             }
             else -> {
@@ -473,7 +508,7 @@
                 return offset / distance
             }
 
-        override val isUserInputDriven = true
+        override val isInitiatedByUserInput = true
 
         /** The current offset caused by the drag gesture. */
         var dragOffset by mutableFloatStateOf(0f)
@@ -484,6 +519,10 @@
          */
         var isAnimatingOffset by mutableStateOf(false)
 
+        // If we are not animating offset, it means the offset is being driven by the user's finger.
+        override val isUserInputOngoing: Boolean
+            get() = !isAnimatingOffset
+
         /** The animatable used to animate the offset once the user lifted its finger. */
         val offsetAnimatable = Animatable(0f, OffsetVisibilityThreshold)
 
@@ -516,6 +555,22 @@
         var _distance by mutableFloatStateOf(0f)
         val distance: Float
             get() = _distance
+
+        /** The [UserAction]s associated to this swipe. */
+        var actionUpOrLeft: UserAction = Back
+        var actionDownOrRight: UserAction = Back
+        var actionUpOrLeftNoEdge: UserAction? = null
+        var actionDownOrRightNoEdge: UserAction? = null
+
+        fun upOrLeft(scene: Scene): SceneKey? {
+            return scene.userActions[actionUpOrLeft]
+                ?: actionUpOrLeftNoEdge?.let { scene.userActions[it] }
+        }
+
+        fun downOrRight(scene: Scene): SceneKey? {
+            return scene.userActions[actionDownOrRight]
+                ?: actionDownOrRightNoEdge?.let { scene.userActions[it] }
+        }
     }
 
     companion object {
@@ -526,9 +581,9 @@
 private class SceneDraggableHandler(
     private val gestureHandler: SceneGestureHandler,
 ) : DraggableHandler {
-    override suspend fun onDragStarted(coroutineScope: CoroutineScope, startedPosition: Offset) {
+    override fun onDragStarted(startedPosition: Offset, pointersDown: Int) {
         gestureHandler.gestureWithPriority = this
-        gestureHandler.onDragStarted()
+        gestureHandler.onDragStarted(pointersDown, startedPosition)
     }
 
     override fun onDelta(pixels: Float) {
@@ -537,7 +592,7 @@
         }
     }
 
-    override suspend fun onDragStopped(coroutineScope: CoroutineScope, velocity: Float) {
+    override fun onDragStopped(velocity: Float) {
         if (gestureHandler.gestureWithPriority == this) {
             gestureHandler.gestureWithPriority = null
             gestureHandler.onDragStopped(velocity = velocity, canChangeScene = true)
@@ -580,11 +635,31 @@
         // moving on to the next scene.
         var gestureStartedOnNestedChild = false
 
+        val actionUpOrLeft =
+            Swipe(
+                direction =
+                    when (gestureHandler.orientation) {
+                        Orientation.Horizontal -> SwipeDirection.Left
+                        Orientation.Vertical -> SwipeDirection.Up
+                    },
+                pointerCount = 1,
+            )
+
+        val actionDownOrRight =
+            Swipe(
+                direction =
+                    when (gestureHandler.orientation) {
+                        Orientation.Horizontal -> SwipeDirection.Right
+                        Orientation.Vertical -> SwipeDirection.Down
+                    },
+                pointerCount = 1,
+            )
+
         fun findNextScene(amount: Float): SceneKey? {
             val fromScene = gestureHandler.currentScene
             return when {
-                amount < 0f -> fromScene.upOrLeft(gestureHandler.orientation)
-                amount > 0f -> fromScene.downOrRight(gestureHandler.orientation)
+                amount < 0f -> fromScene.userActions[actionUpOrLeft]
+                amount > 0f -> fromScene.userActions[actionDownOrRight]
                 else -> null
             }
         }
@@ -625,7 +700,7 @@
             onStart = {
                 gestureHandler.gestureWithPriority = this
                 priorityScene = nextScene
-                gestureHandler.onDragStarted()
+                gestureHandler.onDragStarted(pointersDown = 1, startedPosition = null)
             },
             onScroll = { offsetAvailable ->
                 if (gestureHandler.gestureWithPriority != this) {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/ui/util/ListUtils.kt b/packages/SystemUI/compose/scene/src/com/android/compose/ui/util/ListUtils.kt
deleted file mode 100644
index 741f00d..0000000
--- a/packages/SystemUI/compose/scene/src/com/android/compose/ui/util/ListUtils.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.compose.ui.util
-
-import kotlin.contracts.ExperimentalContracts
-import kotlin.contracts.contract
-
-/**
- * Iterates through a [List] using the index and calls [action] for each item. This does not
- * allocate an iterator like [Iterable.forEach].
- *
- * **Do not use for collections that come from public APIs**, since they may not support random
- * access in an efficient way, and this method may actually be a lot slower. Only use for
- * collections that are created by code we control and are known to support random access.
- */
-@Suppress("BanInlineOptIn")
-@OptIn(ExperimentalContracts::class)
-internal inline fun <T> List<T>.fastForEach(action: (T) -> Unit) {
-    contract { callsInPlace(action) }
-    for (index in indices) {
-        val item = get(index)
-        action(item)
-    }
-}
-
-/**
- * Returns a list containing the results of applying the given [transform] function to each element
- * in the original collection.
- *
- * **Do not use for collections that come from public APIs**, since they may not support random
- * access in an efficient way, and this method may actually be a lot slower. Only use for
- * collections that are created by code we control and are known to support random access.
- */
-@Suppress("BanInlineOptIn")
-@OptIn(ExperimentalContracts::class)
-internal inline fun <T, R> List<T>.fastMap(transform: (T) -> R): List<R> {
-    contract { callsInPlace(transform) }
-    val target = ArrayList<R>(size)
-    fastForEach { target += transform(it) }
-    return target
-}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt
new file mode 100644
index 0000000..a68282a
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/FixedSizeEdgeDetectorTest.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.animation.scene
+
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.Density
+import androidx.compose.ui.unit.IntOffset
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.dp
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class FixedSizeEdgeDetectorTest {
+    private val detector = FixedSizeEdgeDetector(30.dp)
+    private val layoutSize = IntSize(100, 100)
+    private val density = Density(1f)
+
+    @Test
+    fun horizontalEdges() {
+        fun horizontalEdge(position: Int): Edge? =
+            detector.edge(
+                layoutSize,
+                position = IntOffset(position, 0),
+                density,
+                Orientation.Horizontal,
+            )
+
+        assertThat(horizontalEdge(0)).isEqualTo(Edge.Left)
+        assertThat(horizontalEdge(30)).isEqualTo(Edge.Left)
+        assertThat(horizontalEdge(31)).isEqualTo(null)
+        assertThat(horizontalEdge(69)).isEqualTo(null)
+        assertThat(horizontalEdge(70)).isEqualTo(Edge.Right)
+        assertThat(horizontalEdge(100)).isEqualTo(Edge.Right)
+    }
+
+    @Test
+    fun verticalEdges() {
+        fun verticalEdge(position: Int): Edge? =
+            detector.edge(
+                layoutSize,
+                position = IntOffset(0, position),
+                density,
+                Orientation.Vertical,
+            )
+
+        assertThat(verticalEdge(0)).isEqualTo(Edge.Top)
+        assertThat(verticalEdge(30)).isEqualTo(Edge.Top)
+        assertThat(verticalEdge(31)).isEqualTo(null)
+        assertThat(verticalEdge(69)).isEqualTo(null)
+        assertThat(verticalEdge(70)).isEqualTo(Edge.Bottom)
+        assertThat(verticalEdge(100)).isEqualTo(Edge.Bottom)
+    }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt
index 6791a85..1eb3392 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneGestureHandlerTest.kt
@@ -55,7 +55,8 @@
                             builder = scenesBuilder,
                             transitions = EmptyTestTransitions,
                             state = layoutState,
-                            density = Density(1f)
+                            density = Density(1f),
+                            edgeDetector = DefaultEdgeDetector,
                         )
                         .also { it.size = IntSize(SCREEN_SIZE.toInt(), SCREEN_SIZE.toInt()) },
                 orientation = Orientation.Vertical,
@@ -104,13 +105,13 @@
 
     @Test
     fun onDragStarted_shouldStartATransition() = runGestureTest {
-        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        draggable.onDragStarted(startedPosition = Offset.Zero)
         assertScene(currentScene = SceneA, isIdle = false)
     }
 
     @Test
     fun afterSceneTransitionIsStarted_interceptDragEvents() = runGestureTest {
-        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        draggable.onDragStarted(startedPosition = Offset.Zero)
         assertScene(currentScene = SceneA, isIdle = false)
         val transition = transitionState as Transition
 
@@ -123,14 +124,13 @@
 
     @Test
     fun onDragStoppedAfterDrag_velocityLowerThanThreshold_remainSameScene() = runGestureTest {
-        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        draggable.onDragStarted(startedPosition = Offset.Zero)
         assertScene(currentScene = SceneA, isIdle = false)
 
         draggable.onDelta(pixels = deltaInPixels10)
         assertScene(currentScene = SceneA, isIdle = false)
 
         draggable.onDragStopped(
-            coroutineScope = coroutineScope,
             velocity = velocityThreshold - 0.01f,
         )
         assertScene(currentScene = SceneA, isIdle = false)
@@ -142,14 +142,13 @@
 
     @Test
     fun onDragStoppedAfterDrag_velocityAtLeastThreshold_goToNextScene() = runGestureTest {
-        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        draggable.onDragStarted(startedPosition = Offset.Zero)
         assertScene(currentScene = SceneA, isIdle = false)
 
         draggable.onDelta(pixels = deltaInPixels10)
         assertScene(currentScene = SceneA, isIdle = false)
 
         draggable.onDragStopped(
-            coroutineScope = coroutineScope,
             velocity = velocityThreshold,
         )
         assertScene(currentScene = SceneC, isIdle = false)
@@ -161,23 +160,22 @@
 
     @Test
     fun onDragStoppedAfterStarted_returnImmediatelyToIdle() = runGestureTest {
-        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        draggable.onDragStarted(startedPosition = Offset.Zero)
         assertScene(currentScene = SceneA, isIdle = false)
 
-        draggable.onDragStopped(coroutineScope = coroutineScope, velocity = 0f)
+        draggable.onDragStopped(velocity = 0f)
         assertScene(currentScene = SceneA, isIdle = true)
     }
 
     @Test
     fun startGestureDuringAnimatingOffset_shouldImmediatelyStopTheAnimation() = runGestureTest {
-        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        draggable.onDragStarted(startedPosition = Offset.Zero)
         assertScene(currentScene = SceneA, isIdle = false)
 
         draggable.onDelta(pixels = deltaInPixels10)
         assertScene(currentScene = SceneA, isIdle = false)
 
         draggable.onDragStopped(
-            coroutineScope = coroutineScope,
             velocity = velocityThreshold,
         )
 
@@ -191,7 +189,7 @@
         assertScene(currentScene = SceneC, isIdle = false)
 
         // Start a new gesture while the offset is animating
-        draggable.onDragStarted(coroutineScope = coroutineScope, startedPosition = Offset.Zero)
+        draggable.onDragStarted(startedPosition = Offset.Zero)
         assertThat(sceneGestureHandler.isAnimatingOffset).isFalse()
     }
 
@@ -320,7 +318,7 @@
     }
     @Test
     fun beforeDraggableStart_stop_shouldBeIgnored() = runGestureTest {
-        draggable.onDragStopped(coroutineScope, velocityThreshold)
+        draggable.onDragStopped(velocityThreshold)
         assertScene(currentScene = SceneA, isIdle = true)
     }
 
@@ -332,7 +330,7 @@
 
     @Test
     fun startNestedScrollWhileDragging() = runGestureTest {
-        draggable.onDragStarted(coroutineScope, Offset.Zero)
+        draggable.onDragStarted(Offset.Zero)
         assertScene(currentScene = SceneA, isIdle = false)
         val transition = transitionState as Transition
 
@@ -344,7 +342,7 @@
         assertThat(transition.progress).isEqualTo(0.2f)
 
         // this should be ignored, we are scrolling now!
-        draggable.onDragStopped(coroutineScope, velocityThreshold)
+        draggable.onDragStopped(velocityThreshold)
         assertScene(currentScene = SceneA, isIdle = false)
 
         nestedScrollEvents(available = offsetY10)
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index df3b72a..58d853e 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -48,6 +48,14 @@
         /** The middle of the layout, in pixels. */
         private val Density.middle: Offset
             get() = Offset((LayoutWidth / 2).toPx(), (LayoutHeight / 2).toPx())
+
+        /** The middle-top of the layout, in pixels. */
+        private val Density.middleTop: Offset
+            get() = Offset((LayoutWidth / 2).toPx(), 0f)
+
+        /** The middle-left of the layout, in pixels. */
+        private val Density.middleLeft: Offset
+            get() = Offset(0f, (LayoutHeight / 2).toPx())
     }
 
     private var currentScene by mutableStateOf(TestScenes.SceneA)
@@ -83,7 +91,13 @@
             }
             scene(
                 TestScenes.SceneC,
-                userActions = mapOf(Swipe.Down to TestScenes.SceneA),
+                userActions =
+                    mapOf(
+                        Swipe.Down to TestScenes.SceneA,
+                        Swipe(SwipeDirection.Down, pointerCount = 2) to TestScenes.SceneB,
+                        Swipe(SwipeDirection.Right, fromEdge = Edge.Left) to TestScenes.SceneB,
+                        Swipe(SwipeDirection.Down, fromEdge = Edge.Top) to TestScenes.SceneB,
+                    ),
             ) {
                 Box(Modifier.fillMaxSize())
             }
@@ -122,7 +136,7 @@
         assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
         assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
         assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
-        assertThat(transition.isUserInputDriven).isTrue()
+        assertThat(transition.isInitiatedByUserInput).isTrue()
 
         // Release the finger. We should now be animating back to A (currentScene = SceneA) given
         // that 55dp < positional threshold.
@@ -134,7 +148,7 @@
         assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
         assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
         assertThat(transition.progress).isEqualTo(55.dp / LayoutWidth)
-        assertThat(transition.isUserInputDriven).isTrue()
+        assertThat(transition.isInitiatedByUserInput).isTrue()
 
         // Wait for the animation to finish. We should now be in scene A.
         rule.waitForIdle()
@@ -156,7 +170,7 @@
         assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
         assertThat(transition.currentScene).isEqualTo(TestScenes.SceneA)
         assertThat(transition.progress).isEqualTo(56.dp / LayoutHeight)
-        assertThat(transition.isUserInputDriven).isTrue()
+        assertThat(transition.isInitiatedByUserInput).isTrue()
 
         // Release the finger. We should now be animating to C (currentScene = SceneC) given
         // that 56dp >= positional threshold.
@@ -168,7 +182,7 @@
         assertThat(transition.toScene).isEqualTo(TestScenes.SceneC)
         assertThat(transition.currentScene).isEqualTo(TestScenes.SceneC)
         assertThat(transition.progress).isEqualTo(56.dp / LayoutHeight)
-        assertThat(transition.isUserInputDriven).isTrue()
+        assertThat(transition.isInitiatedByUserInput).isTrue()
 
         // Wait for the animation to finish. We should now be in scene C.
         rule.waitForIdle()
@@ -242,4 +256,100 @@
         assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
         assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
     }
+
+    @Test
+    fun multiPointerSwipe() {
+        // Start at scene C.
+        currentScene = TestScenes.SceneC
+
+        // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
+        // detected as a drag event.
+        var touchSlop = 0f
+        rule.setContent {
+            touchSlop = LocalViewConfiguration.current.touchSlop
+            TestContent()
+        }
+
+        assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+
+        // Swipe down with two fingers.
+        rule.onRoot().performTouchInput {
+            repeat(2) { i -> down(pointerId = i, middle) }
+            repeat(2) { i ->
+                moveBy(pointerId = i, Offset(0f, touchSlop + 10.dp.toPx()), delayMillis = 1_000)
+            }
+        }
+
+        // We are transitioning to B because we used 2 fingers.
+        val transition = layoutState.transitionState
+        assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
+        assertThat((transition as TransitionState.Transition).fromScene)
+            .isEqualTo(TestScenes.SceneC)
+        assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
+
+        // Release the fingers and wait for the animation to end. We are back to C because we only
+        // swiped 10dp.
+        rule.onRoot().performTouchInput { repeat(2) { i -> up(pointerId = i) } }
+        rule.waitForIdle()
+        assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+    }
+
+    @Test
+    fun defaultEdgeSwipe() {
+        // Start at scene C.
+        currentScene = TestScenes.SceneC
+
+        // The draggable touch slop, i.e. the min px distance a touch pointer must move before it is
+        // detected as a drag event.
+        var touchSlop = 0f
+        rule.setContent {
+            touchSlop = LocalViewConfiguration.current.touchSlop
+            TestContent()
+        }
+
+        assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+
+        // Swipe down from the top edge.
+        rule.onRoot().performTouchInput {
+            down(middleTop)
+            moveBy(Offset(0f, touchSlop + 10.dp.toPx()), delayMillis = 1_000)
+        }
+
+        // We are transitioning to B (and not A) because we started from the top edge.
+        var transition = layoutState.transitionState
+        assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
+        assertThat((transition as TransitionState.Transition).fromScene)
+            .isEqualTo(TestScenes.SceneC)
+        assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
+
+        // Release the fingers and wait for the animation to end. We are back to C because we only
+        // swiped 10dp.
+        rule.onRoot().performTouchInput { up() }
+        rule.waitForIdle()
+        assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+
+        // Swipe right from the left edge.
+        rule.onRoot().performTouchInput {
+            down(middleLeft)
+            moveBy(Offset(touchSlop + 10.dp.toPx(), 0f), delayMillis = 1_000)
+        }
+
+        // We are transitioning to B (and not A) because we started from the left edge.
+        transition = layoutState.transitionState
+        assertThat(transition).isInstanceOf(TransitionState.Transition::class.java)
+        assertThat((transition as TransitionState.Transition).fromScene)
+            .isEqualTo(TestScenes.SceneC)
+        assertThat(transition.toScene).isEqualTo(TestScenes.SceneB)
+
+        // Release the fingers and wait for the animation to end. We are back to C because we only
+        // swiped 10dp.
+        rule.onRoot().performTouchInput { up() }
+        rule.waitForIdle()
+        assertThat(layoutState.transitionState).isInstanceOf(TransitionState.Idle::class.java)
+        assertThat(layoutState.transitionState.currentScene).isEqualTo(TestScenes.SceneC)
+    }
 }
diff --git a/packages/SystemUI/res-keyguard/layout/sidefps_progress_bar.xml b/packages/SystemUI/res-keyguard/layout/sidefps_progress_bar.xml
index 183f0e5..9d74677 100644
--- a/packages/SystemUI/res-keyguard/layout/sidefps_progress_bar.xml
+++ b/packages/SystemUI/res-keyguard/layout/sidefps_progress_bar.xml
@@ -15,18 +15,18 @@
   ~
   -->
 
-<LinearLayout android:layout_height="match_parent"
+<RelativeLayout
     android:layout_width="match_parent"
-    android:orientation="vertical"
-    android:layoutDirection="ltr"
-    android:gravity="center"
+    android:layout_height="match_parent"
+    android:gravity="left|top"
+    android:background="@android:color/transparent"
     xmlns:android="http://schemas.android.com/apk/res/android">
     <ProgressBar
         android:id="@+id/side_fps_progress_bar"
-        android:layout_width="55dp"
-        android:layout_height="10dp"
+        android:layout_width="0dp"
+        android:layout_height="@dimen/sfps_progress_bar_thickness"
         android:indeterminateOnly="false"
         android:min="0"
         android:max="100"
         android:progressDrawable="@drawable/progress_bar" />
-</LinearLayout>
+</RelativeLayout>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index d1067a9..0628c3e 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -157,4 +157,11 @@
     <dimen name="weather_clock_smartspace_translateX">0dp</dimen>
     <dimen name="weather_clock_smartspace_translateY">0dp</dimen>
 
+    <!-- Additional length to add to the SFPS sensor length we get from framework so that the length
+     of the progress bar matches the length of the power button  -->
+    <dimen name="sfps_progress_bar_length_extra_padding">12dp</dimen>
+    <!-- Thickness of the progress bar we show for the SFPS based authentication. -->
+    <dimen name="sfps_progress_bar_thickness">6dp</dimen>
+    <!-- Padding from the edge of the screen for the progress bar -->
+    <dimen name="sfps_progress_bar_padding_from_edge">7dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 10fd8b5..30392d2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -34,6 +34,9 @@
     <dimen name="navigation_handle_bottom">10dp</dimen>
     <dimen name="navigation_handle_sample_horizontal_margin">10dp</dimen>
     <dimen name="navigation_home_handle_width">108dp</dimen>
+    <!-- Used while animating the navbar during a long press. -->
+    <dimen name="navigation_home_handle_additional_width_for_animation">20dp</dimen>
+    <dimen name="navigation_home_handle_additional_height_for_animation">4dp</dimen>
 
     <!-- Size of the nav bar edge panels, should be greater to the
          edge sensitivity + the drag threshold -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4c520444..12bff4a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1045,8 +1045,8 @@
     <!-- Indication on the keyguard that is shown when the device is dock charging. [CHAR LIMIT=80]-->
     <string name="keyguard_indication_charging_time_dock"><xliff:g id="percentage" example="20%">%2$s</xliff:g> • Charging • Full in <xliff:g id="charging_time_left" example="4 hr, 2 min">%1$s</xliff:g></string>
 
-    <!-- Indicator shown to start the communal tutorial. [CHAR LIMIT=100] -->
-    <string name="communal_tutorial_indicator_text">Click on the arrow button to start the communal tutorial</string>
+    <!-- Indicator on keyguard to start the communal tutorial. [CHAR LIMIT=100] -->
+    <string name="communal_tutorial_indicator_text">Swipe left to start the communal tutorial</string>
 
     <!-- Related to user switcher --><skip/>
 
diff --git a/packages/SystemUI/shared/Android.bp b/packages/SystemUI/shared/Android.bp
index 9c368eb..5b59e7d 100644
--- a/packages/SystemUI/shared/Android.bp
+++ b/packages/SystemUI/shared/Android.bp
@@ -53,6 +53,7 @@
         "SystemUIPluginLib",
         "SystemUIUnfoldLib",
         "SystemUISharedLib-Keyguard",
+        "tracinglib",
         "androidx.dynamicanimation_dynamicanimation",
         "androidx.concurrent_concurrent-futures",
         "androidx.lifecycle_lifecycle-runtime-ktx",
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListener.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListener.kt
index 7719246..637ce5f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListener.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/DisableSubpixelTextTransitionListener.kt
@@ -19,7 +19,7 @@
 import android.view.ViewGroup
 import android.widget.TextView
 import androidx.core.view.forEach
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
 import java.lang.ref.WeakReference
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index dc34ef7..26e785d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -144,5 +144,15 @@
      */
     oneway void onStatusBarTrackpadEvent(in MotionEvent event) = 52;
 
-    // Next id = 54
+    /**
+     * Animate the nav bar being long-pressed.
+     *
+     * @param isTouchDown {@code true} if the button is starting to be pressed ({@code false} if
+     *                                released or canceled)
+     * @param durationMs how long the animation should take (for the {@code isTouchDown} case, this
+     *                   should be the same as the amount of time to trigger a long-press)
+     */
+    oneway void animateNavBarLongPress(boolean isTouchDown, long durationMs) = 54;
+
+    // Next id = 55
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index 3605ac2..f06e333 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -216,7 +216,6 @@
     @Nullable public Drawable icon;
     @Nullable public ThumbnailData thumbnail;
     @ViewDebug.ExportedProperty(category="recents")
-    @Deprecated
     public String title;
     @ViewDebug.ExportedProperty(category="recents")
     public String titleDescription;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 631423e..10393cf 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -137,14 +137,12 @@
     }
 
     /**
-     * @return a {@link ThumbnailData} with {@link TaskSnapshot} for the given {@param taskId}.
-     *         The snapshot will be triggered if no cached {@link TaskSnapshot} exists.
+     * @return the task snapshot for the given {@param taskId}.
      */
     public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
         TaskSnapshot snapshot = null;
         try {
-            snapshot = getService().getTaskSnapshot(taskId, isLowResolution,
-                    true /* takeSnapshotIfNeeded */);
+            snapshot = getService().getTaskSnapshot(taskId, isLowResolution);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to retrieve task snapshot", e);
         }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java
deleted file mode 100644
index aeb0415..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.shared.system;
-
-import android.graphics.Region;
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.ISystemGestureExclusionListener;
-import android.view.WindowManagerGlobal;
-
-/**
- * Utility class to listen for exclusion rect changes.
- */
-public abstract class SystemGestureExclusionListenerCompat {
-
-    private static final String TAG = "SGEListenerCompat";
-
-    private final int mDisplayId;
-
-    private ISystemGestureExclusionListener mGestureExclusionListener =
-            new ISystemGestureExclusionListener.Stub() {
-                @Override
-                public void onSystemGestureExclusionChanged(int displayId,
-                        Region systemGestureExclusion, Region unrestrictedOrNull) {
-                    if (displayId == mDisplayId) {
-                        Region unrestricted = (unrestrictedOrNull == null)
-                                ? systemGestureExclusion : unrestrictedOrNull;
-                        onExclusionChanged(systemGestureExclusion, unrestricted);
-                    }
-                }
-            };
-    private boolean mRegistered;
-
-    public SystemGestureExclusionListenerCompat(int displayId) {
-        mDisplayId = displayId;
-    }
-
-    /**
-     * Called when the exclusion region has changed.
-     *
-     * TODO: remove, once all subclasses have migrated to
-     *       {@link #onExclusionChanged(Region, Region)}.
-     */
-    public abstract void onExclusionChanged(Region systemGestureExclusion);
-
-    /**
-     * Called when the exclusion region has changed.
-     *
-     * @param systemGestureExclusion the system gesture exclusion to be applied
-     * @param systemGestureExclusionUnrestricted what would be the system gesture exclusion, if
-     *           there were no restrictions being applied. For logging purposes only.
-     *
-     */
-    public void onExclusionChanged(Region systemGestureExclusion,
-            Region systemGestureExclusionUnrestricted) {
-        // TODO: make abstract, once all subclasses have migrated away from
-        //       onExclusionChanged(Region)
-        onExclusionChanged(systemGestureExclusion);
-    }
-
-    /**
-     * Registers the listener for getting exclusion rect changes.
-     */
-    public void register() {
-        if (!mRegistered) {
-            try {
-                WindowManagerGlobal.getWindowManagerService()
-                        .registerSystemGestureExclusionListener(
-                                mGestureExclusionListener, mDisplayId);
-                mRegistered = true;
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to register window manager callbacks", e);
-            }
-        }
-    }
-
-    /**
-     * Unregisters the receiver if previously registered
-     */
-    public void unregister() {
-        if (mRegistered) {
-            try {
-                WindowManagerGlobal.getWindowManagerService()
-                        .unregisterSystemGestureExclusionListener(
-                                mGestureExclusionListener, mDisplayId);
-                mRegistered = false;
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to unregister window manager callbacks", e);
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceContextElement.kt b/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceContextElement.kt
deleted file mode 100644
index 7d1b65a..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceContextElement.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.tracing
-
-import com.android.systemui.tracing.TraceUtils.Companion.instant
-import com.android.systemui.tracing.TraceUtils.Companion.traceCoroutine
-import kotlin.coroutines.CoroutineContext
-import kotlinx.coroutines.CopyableThreadContextElement
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-
-/**
- * Used for safely persisting [TraceData] state when coroutines are suspended and resumed.
- *
- * This is internal machinery for [traceCoroutine]. It cannot be made `internal` or `private`
- * because [traceCoroutine] is a Public-API inline function.
- *
- * @see traceCoroutine
- */
-@OptIn(DelicateCoroutinesApi::class)
-@ExperimentalCoroutinesApi
-class TraceContextElement(private val traceData: TraceData = TraceData()) :
-    CopyableThreadContextElement<TraceData?> {
-
-    companion object Key : CoroutineContext.Key<TraceContextElement>
-
-    override val key: CoroutineContext.Key<TraceContextElement> = Key
-
-    @OptIn(ExperimentalStdlibApi::class)
-    override fun updateThreadContext(context: CoroutineContext): TraceData? {
-        val oldState = threadLocalTrace.get()
-        oldState?.endAllOnThread()
-        threadLocalTrace.set(traceData)
-        instant("resuming ${context[CoroutineDispatcher]}")
-        traceData.beginAllOnThread()
-        return oldState
-    }
-
-    @OptIn(ExperimentalStdlibApi::class)
-    override fun restoreThreadContext(context: CoroutineContext, oldState: TraceData?) {
-        instant("suspending ${context[CoroutineDispatcher]}")
-        traceData.endAllOnThread()
-        threadLocalTrace.set(oldState)
-        oldState?.beginAllOnThread()
-    }
-
-    override fun copyForChild(): CopyableThreadContextElement<TraceData?> {
-        return TraceContextElement(traceData.copy())
-    }
-
-    override fun mergeForChild(overwritingElement: CoroutineContext.Element): CoroutineContext {
-        return TraceContextElement(traceData.copy())
-    }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceData.kt b/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceData.kt
deleted file mode 100644
index b68d38c..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceData.kt
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.tracing
-
-import android.os.Build
-import android.util.Log
-import com.android.systemui.tracing.TraceUtils.Companion.beginSlice
-import com.android.systemui.tracing.TraceUtils.Companion.endSlice
-import com.android.systemui.tracing.TraceUtils.Companion.traceCoroutine
-import kotlin.random.Random
-
-/**
- * Used for giving each thread a unique [TraceData] for thread-local storage. `null` by default.
- * [threadLocalTrace] can only be used when it is paired with a [TraceContextElement].
- *
- * This ThreadLocal will be `null` if either 1) we aren't in a coroutine, or 2) the coroutine we are
- * in does not have a [TraceContextElement].
- *
- * This is internal machinery for [traceCoroutine]. It cannot be made `internal` or `private`
- * because [traceCoroutine] is a Public-API inline function.
- *
- * @see traceCoroutine
- */
-val threadLocalTrace = ThreadLocal<TraceData?>()
-
-/**
- * Used for storing trace sections so that they can be added and removed from the currently running
- * thread when the coroutine is suspended and resumed.
- *
- * This is internal machinery for [traceCoroutine]. It cannot be made `internal` or `private`
- * because [traceCoroutine] is a Public-API inline function.
- *
- * @see traceCoroutine
- */
-class TraceData {
-    private var slices = mutableListOf<TraceSection>()
-
-    /** Adds current trace slices back to the current thread. Called when coroutine is resumed. */
-    fun beginAllOnThread() {
-        slices.forEach { beginSlice(it.name) }
-    }
-
-    /**
-     * Removes all current trace slices from the current thread. Called when coroutine is suspended.
-     */
-    fun endAllOnThread() {
-        for (i in 0..slices.size) {
-            endSlice()
-        }
-    }
-
-    /**
-     * Creates a new trace section with a unique ID and adds it to the current trace data. The slice
-     * will also be added to the current thread immediately. This slice will not propagate to parent
-     * coroutines, or to child coroutines that have already started. The unique ID is used to verify
-     * that the [endSpan] is corresponds to a [beginSpan].
-     */
-    fun beginSpan(name: String): Int {
-        val newSlice = TraceSection(name, Random.nextInt(FIRST_VALID_SPAN, Int.MAX_VALUE))
-        slices.add(newSlice)
-        beginSlice(name)
-        return newSlice.id
-    }
-
-    /**
-     * Used by [TraceContextElement] when launching a child coroutine so that the child coroutine's
-     * state is isolated from the parent.
-     */
-    fun copy(): TraceData {
-        return TraceData().also { it.slices.addAll(slices) }
-    }
-
-    /**
-     * Ends the trace section and validates it corresponds with an earlier call to [beginSpan]. The
-     * trace slice will immediately be removed from the current thread. This information will not
-     * propagate to parent coroutines, or to child coroutines that have already started.
-     */
-    fun endSpan(id: Int) {
-        val v = slices.removeLast()
-        if (v.id != id) {
-            if (STRICT_MODE) {
-                throw IllegalArgumentException(errorMsg)
-            } else if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, errorMsg)
-            }
-        }
-        endSlice()
-    }
-
-    companion object {
-        private const val TAG = "TraceData"
-        const val INVALID_SPAN = -1
-        const val FIRST_VALID_SPAN = 1
-
-        /**
-         * If true, throw an exception instead of printing a warning when trace sections beginnings
-         * and ends are mismatched.
-         */
-        private val STRICT_MODE = Build.IS_ENG
-
-        private const val errorMsg =
-            "Mismatched trace section. This likely means you are accessing the trace local " +
-                "storage (threadLocalTrace) without a corresponding CopyableThreadContextElement." +
-                " This could happen if you are using a global dispatcher like Dispatchers.IO." +
-                " To fix this, use one of the coroutine contexts provided by the dagger scope " +
-                "(e.g. \"@Main CoroutineContext\")."
-    }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceSection.kt b/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceSection.kt
deleted file mode 100644
index 469d9a2..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceSection.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.tracing
-
-import com.android.systemui.tracing.TraceUtils.Companion.traceCoroutine
-
-/**
- * Represents a section of code executing in a coroutine. This can be split up into multiple slices
- * on different threads as the coroutine is suspended and resumed.
- *
- * This is internal machinery for [traceCoroutine]. It cannot be made `internal` or `private`
- * because [traceCoroutine] is a Public-API inline function.
- *
- * @param name the name of the slice to appear on the current thread's track.
- * @param id used for matching the beginning and end of trace sections and validating correctness
- * @see traceCoroutine
- */
-data class TraceSection(
-    val name: String,
-    val id: Int,
-)
diff --git a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceStateLogger.kt b/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceStateLogger.kt
deleted file mode 100644
index 3e235f5..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceStateLogger.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.tracing
-
-import android.os.Trace
-
-/**
- * Utility class used to log state changes easily in a track with a custom name.
- *
- * Example of usage:
- * ```kotlin
- * class MyClass {
- *    val screenStateLogger = TraceStateLogger("Screen state")
- *
- *    fun onTurnedOn() { screenStateLogger.log("on") }
- *    fun onTurnedOff() { screenStateLogger.log("off") }
- * }
- * ```
- *
- * This creates a new slice in a perfetto trace only if the state is different than the previous
- * one.
- */
-class TraceStateLogger(
-    private val trackName: String,
-    private val logOnlyIfDifferent: Boolean = true,
-    private val instantEvent: Boolean = true
-) {
-
-    private var previousValue: String? = null
-
-    /** If needed, logs the value to a track with name [trackName]. */
-    fun log(newValue: String) {
-        if (instantEvent) {
-            Trace.instantForTrack(Trace.TRACE_TAG_APP, trackName, newValue)
-        }
-        if (logOnlyIfDifferent && previousValue == newValue) return
-        Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, trackName, 0)
-        Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, trackName, newValue, 0)
-        previousValue = newValue
-    }
-}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceUtils.kt b/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceUtils.kt
deleted file mode 100644
index 12a20ae..0000000
--- a/packages/SystemUI/shared/src/com/android/systemui/tracing/TraceUtils.kt
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.tracing
-
-import android.os.Trace
-import android.os.TraceNameSupplier
-import android.util.Log
-import com.android.systemui.tracing.TraceData.Companion.FIRST_VALID_SPAN
-import com.android.systemui.tracing.TraceData.Companion.INVALID_SPAN
-import java.util.concurrent.atomic.AtomicInteger
-import kotlin.coroutines.CoroutineContext
-import kotlin.coroutines.EmptyCoroutineContext
-import kotlin.coroutines.coroutineContext
-import kotlin.random.Random
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.async
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.withContext
-
-/**
- * Run a block within a [Trace] section. Calls [Trace.beginSection] before and [Trace.endSection]
- * after the passed block.
- */
-inline fun <T> traceSection(tag: String, block: () -> T): T =
-    if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) {
-        Trace.traceBegin(Trace.TRACE_TAG_APP, tag)
-        try {
-            block()
-        } finally {
-            Trace.traceEnd(Trace.TRACE_TAG_APP)
-        }
-    } else {
-        block()
-    }
-
-class TraceUtils {
-    companion object {
-        const val TAG = "TraceUtils"
-        private const val DEBUG_COROUTINE_TRACING = false
-        const val DEFAULT_TRACK_NAME = "AsyncTraces"
-
-        inline fun traceRunnable(tag: String, crossinline block: () -> Unit): Runnable {
-            return Runnable { traceSection(tag) { block() } }
-        }
-
-        /**
-         * Helper function for creating a Runnable object that implements TraceNameSupplier.
-         *
-         * This is useful for posting Runnables to Handlers with meaningful names.
-         */
-        inline fun namedRunnable(tag: String, crossinline block: () -> Unit): Runnable {
-            return object : Runnable, TraceNameSupplier {
-                override fun getTraceName(): String = tag
-                override fun run() = block()
-            }
-        }
-
-        /**
-         * Cookie used for async traces. Shouldn't be public, but to use it inside inline methods
-         * there is no other way around.
-         */
-        val lastCookie = AtomicInteger(0)
-
-        /**
-         * Creates an async slice in a track called "AsyncTraces".
-         *
-         * This can be used to trace coroutine code. Note that all usages of this method will appear
-         * under a single track.
-         */
-        inline fun <T> traceAsync(method: String, block: () -> T): T =
-            traceAsync(DEFAULT_TRACK_NAME, method, block)
-
-        /**
-         * Creates an async slice in a track with [trackName] while [block] runs.
-         *
-         * This can be used to trace coroutine code. [method] will be the name of the slice,
-         * [trackName] of the track. The track is one of the rows visible in a perfetto trace inside
-         * SystemUI process.
-         */
-        inline fun <T> traceAsync(trackName: String, method: String, block: () -> T): T {
-            val cookie = lastCookie.incrementAndGet()
-            Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, trackName, method, cookie)
-            try {
-                return block()
-            } finally {
-                Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, trackName, cookie)
-            }
-        }
-
-        /**
-         * Convenience function for calling [CoroutineScope.launch] with [traceCoroutine] enable
-         * tracing.
-         *
-         * @see traceCoroutine
-         */
-        inline fun CoroutineScope.launch(
-            crossinline spanName: () -> String,
-            context: CoroutineContext = EmptyCoroutineContext,
-            // TODO(b/306457056): DO NOT pass CoroutineStart; doing so will regress .odex size
-            crossinline block: suspend CoroutineScope.() -> Unit
-        ): Job = launch(context) { traceCoroutine(spanName) { block() } }
-
-        /**
-         * Convenience function for calling [CoroutineScope.launch] with [traceCoroutine] enable
-         * tracing.
-         *
-         * @see traceCoroutine
-         */
-        inline fun CoroutineScope.launch(
-            spanName: String,
-            context: CoroutineContext = EmptyCoroutineContext,
-            // TODO(b/306457056): DO NOT pass CoroutineStart; doing so will regress .odex size
-            crossinline block: suspend CoroutineScope.() -> Unit
-        ): Job = launch(context) { traceCoroutine(spanName) { block() } }
-
-        /**
-         * Convenience function for calling [CoroutineScope.async] with [traceCoroutine] enable
-         * tracing
-         *
-         * @see traceCoroutine
-         */
-        inline fun <T> CoroutineScope.async(
-            crossinline spanName: () -> String,
-            context: CoroutineContext = EmptyCoroutineContext,
-            // TODO(b/306457056): DO NOT pass CoroutineStart; doing so will regress .odex size
-            crossinline block: suspend CoroutineScope.() -> T
-        ): Deferred<T> = async(context) { traceCoroutine(spanName) { block() } }
-
-        /**
-         * Convenience function for calling [CoroutineScope.async] with [traceCoroutine] enable
-         * tracing.
-         *
-         * @see traceCoroutine
-         */
-        inline fun <T> CoroutineScope.async(
-            spanName: String,
-            context: CoroutineContext = EmptyCoroutineContext,
-            // TODO(b/306457056): DO NOT pass CoroutineStart; doing so will regress .odex size
-            crossinline block: suspend CoroutineScope.() -> T
-        ): Deferred<T> = async(context) { traceCoroutine(spanName) { block() } }
-
-        /**
-         * Convenience function for calling [runBlocking] with [traceCoroutine] to enable tracing.
-         *
-         * @see traceCoroutine
-         */
-        inline fun <T> runBlocking(
-            crossinline spanName: () -> String,
-            context: CoroutineContext,
-            crossinline block: suspend () -> T
-        ): T = runBlocking(context) { traceCoroutine(spanName) { block() } }
-
-        /**
-         * Convenience function for calling [runBlocking] with [traceCoroutine] to enable tracing.
-         *
-         * @see traceCoroutine
-         */
-        inline fun <T> runBlocking(
-            spanName: String,
-            context: CoroutineContext,
-            crossinline block: suspend CoroutineScope.() -> T
-        ): T = runBlocking(context) { traceCoroutine(spanName) { block() } }
-
-        /**
-         * Convenience function for calling [withContext] with [traceCoroutine] to enable tracing.
-         *
-         * @see traceCoroutine
-         */
-        suspend inline fun <T> withContext(
-            spanName: String,
-            context: CoroutineContext,
-            crossinline block: suspend CoroutineScope.() -> T
-        ): T = withContext(context) { traceCoroutine(spanName) { block() } }
-
-        /**
-         * Convenience function for calling [withContext] with [traceCoroutine] to enable tracing.
-         *
-         * @see traceCoroutine
-         */
-        suspend inline fun <T> withContext(
-            crossinline spanName: () -> String,
-            context: CoroutineContext,
-            crossinline block: suspend CoroutineScope.() -> T
-        ): T = withContext(context) { traceCoroutine(spanName) { block() } }
-
-        /**
-         * A hacky way to propagate the value of the COROUTINE_TRACING flag for static usage in this
-         * file. It should only every be set to true during startup. Once true, it cannot be set to
-         * false again.
-         */
-        var coroutineTracingIsEnabled = false
-            set(v) {
-                if (v) field = true
-            }
-
-        /**
-         * Traces a section of work of a `suspend` [block]. The trace sections will appear on the
-         * thread that is currently executing the [block] of work. If the [block] is suspended, all
-         * trace sections added using this API will end until the [block] is resumed, which could
-         * happen either on this thread or on another thread. If a child coroutine is started, it
-         * will inherit the trace sections of its parent. The child will continue to print these
-         * trace sections whether or not the parent coroutine is still running them.
-         *
-         * The current [CoroutineContext] must have a [TraceContextElement] for this API to work.
-         * Otherwise, the trace sections will be dropped.
-         *
-         * For example, in the following trace, Thread #1 ran some work, suspended, then continued
-         * working on Thread #2. Meanwhile, Thread #2 created a new child coroutine which inherited
-         * its trace sections. Then, the original coroutine resumed on Thread #1 before ending.
-         * Meanwhile Thread #3 is still printing trace sections from its parent because they were
-         * copied when it was created. There is no way for the parent to communicate to the child
-         * that it marked these slices as completed. While this might seem counterintuitive, it
-         * allows us to pinpoint the origin of the child coroutine's work.
-         *
-         * ```
-         * Thread #1 | [==== Slice A ====]                        [==== Slice A ====]
-         *           |       [==== B ====]                        [=== B ===]
-         * --------------------------------------------------------------------------------------
-         * Thread #2 |                    [====== Slice A ======]
-         *           |                    [========= B =========]
-         *           |                        [===== C ======]
-         * --------------------------------------------------------------------------------------
-         * Thread #3 |                            [== Slice A ==]                [== Slice A ==]
-         *           |                            [===== B =====]                [===== B =====]
-         *           |                            [===== C =====]                [===== C =====]
-         *           |                                                               [=== D ===]
-         * ```
-         *
-         * @param name The name of the code section to appear in the trace
-         * @see endSlice
-         * @see traceCoroutine
-         */
-        @OptIn(ExperimentalCoroutinesApi::class)
-        suspend inline fun <T> traceCoroutine(
-            spanName: Lazy<String>,
-            crossinline block: suspend () -> T
-        ): T {
-            // For coroutine tracing to work, trace spans must be added and removed even when
-            // tracing is not active (i.e. when TRACE_TAG_APP is disabled). Otherwise, when the
-            // coroutine resumes when tracing is active, we won't know its name.
-            val tracer = getTraceData(spanName)
-            val coroutineSpanCookie = tracer?.beginSpan(spanName.value) ?: INVALID_SPAN
-
-            // For now, also trace to "AsyncTraces". This will allow us to verify the correctness
-            // of the COROUTINE_TRACING feature flag.
-            val asyncTraceCookie =
-                if (Trace.isTagEnabled(Trace.TRACE_TAG_APP))
-                    Random.nextInt(FIRST_VALID_SPAN, Int.MAX_VALUE)
-                else INVALID_SPAN
-            if (asyncTraceCookie != INVALID_SPAN) {
-                Trace.asyncTraceForTrackBegin(
-                    Trace.TRACE_TAG_APP,
-                    DEFAULT_TRACK_NAME,
-                    spanName.value,
-                    asyncTraceCookie
-                )
-            }
-            try {
-                return block()
-            } finally {
-                if (asyncTraceCookie != INVALID_SPAN) {
-                    Trace.asyncTraceForTrackEnd(
-                        Trace.TRACE_TAG_APP,
-                        DEFAULT_TRACK_NAME,
-                        asyncTraceCookie
-                    )
-                }
-                tracer?.endSpan(coroutineSpanCookie)
-            }
-        }
-
-        @OptIn(ExperimentalCoroutinesApi::class)
-        suspend fun getTraceData(spanName: Lazy<String>): TraceData? {
-            if (!coroutineTracingIsEnabled) {
-                logVerbose("Experimental flag COROUTINE_TRACING is off", spanName)
-            } else if (coroutineContext[TraceContextElement] == null) {
-                logVerbose("Current CoroutineContext is missing TraceContextElement", spanName)
-            } else {
-                return threadLocalTrace.get().also {
-                    if (it == null) logVerbose("ThreadLocal TraceData is null", spanName)
-                }
-            }
-            return null
-        }
-
-        private fun logVerbose(logMessage: String, spanName: Lazy<String>) {
-            if (DEBUG_COROUTINE_TRACING && Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.v(TAG, "$logMessage. Dropping trace section: \"${spanName.value}\"")
-            }
-        }
-
-        /** @see traceCoroutine */
-        suspend inline fun <T> traceCoroutine(
-            spanName: String,
-            crossinline block: suspend () -> T
-        ): T = traceCoroutine(lazyOf(spanName)) { block() }
-
-        /** @see traceCoroutine */
-        suspend inline fun <T> traceCoroutine(
-            crossinline spanName: () -> String,
-            crossinline block: suspend () -> T
-        ): T = traceCoroutine(lazy(LazyThreadSafetyMode.PUBLICATION) { spanName() }) { block() }
-
-        /**
-         * Writes a trace message to indicate that a given section of code has begun running __on
-         * the current thread__. This must be followed by a corresponding call to [endSlice] in a
-         * reasonably short amount of time __on the same thread__ (i.e. _before_ the thread becomes
-         * idle again and starts running other, unrelated work).
-         *
-         * Calls to [beginSlice] and [endSlice] may be nested, and they will render in Perfetto as
-         * follows:
-         * ```
-         * Thread #1 | [==========================]
-         *           |       [==============]
-         *           |           [====]
-         * ```
-         *
-         * This function is provided for convenience to wrap a call to [Trace.traceBegin], which is
-         * more verbose to call than [Trace.beginSection], but has the added benefit of not throwing
-         * an [IllegalArgumentException] if the provided string is longer than 127 characters. We
-         * use the term "slice" instead of "section" to be consistent with Perfetto.
-         *
-         * # Avoiding malformed traces
-         *
-         * Improper usage of this API will lead to malformed traces with long slices that sometimes
-         * never end. This will look like the following:
-         * ```
-         * Thread #1 | [===================================================================== ...
-         *           |       [==============]         [====================================== ...
-         *           |           [=======]              [======]       [===================== ...
-         *           |                                                       [=======]
-         * ```
-         *
-         * To avoid this, [beginSlice] and [endSlice] should never be called from `suspend` blocks
-         * (instead, use [traceCoroutine] for tracing suspending functions). While it would be
-         * technically okay to call from a suspending function if that function were to only wrap
-         * non-suspending blocks with [beginSlice] and [endSlice], doing so is risky because suspend
-         * calls could be mistakenly added to that block as the code is refactored.
-         *
-         * Additionally, it is _not_ okay to call [beginSlice] when registering a callback and match
-         * it with a call to [endSlice] inside that callback, even if the callback runs on the same
-         * thread. Doing so would cause malformed traces because the [beginSlice] wasn't closed
-         * before the thread became idle and started running unrelated work.
-         *
-         * @param sliceName The name of the code section to appear in the trace
-         * @see endSlice
-         * @see traceCoroutine
-         */
-        fun beginSlice(sliceName: String) {
-            Trace.traceBegin(Trace.TRACE_TAG_APP, sliceName)
-        }
-
-        /**
-         * Writes a trace message to indicate that a given section of code has ended. This call must
-         * be preceded by a corresponding call to [beginSlice]. See [beginSlice] for important
-         * information regarding usage.
-         *
-         * @see beginSlice
-         * @see traceCoroutine
-         */
-        fun endSlice() {
-            Trace.traceEnd(Trace.TRACE_TAG_APP)
-        }
-
-        /**
-         * Writes a trace message indicating that an instant event occurred on the current thread.
-         * Unlike slices, instant events have no duration and do not need to be matched with another
-         * call. Perfetto will display instant events using an arrow pointing to the timestamp they
-         * occurred:
-         * ```
-         * Thread #1 | [==============]               [======]
-         *           |     [====]                        ^
-         *           |        ^
-         * ```
-         *
-         * @param eventName The name of the event to appear in the trace.
-         */
-        fun instant(eventName: String) {
-            Trace.instant(Trace.TRACE_TAG_APP, eventName)
-        }
-
-        /**
-         * Writes a trace message indicating that an instant event occurred on the given track.
-         * Unlike slices, instant events have no duration and do not need to be matched with another
-         * call. Perfetto will display instant events using an arrow pointing to the timestamp they
-         * occurred:
-         * ```
-         * Async  | [==============]               [======]
-         *  Track |     [====]                        ^
-         *   Name |        ^
-         * ```
-         *
-         * @param trackName The track where the event should appear in the trace.
-         * @param eventName The name of the event to appear in the trace.
-         */
-        fun instantForTrack(trackName: String, eventName: String) {
-            Trace.instantForTrack(Trace.TRACE_TAG_APP, trackName, eventName)
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 7bf3e8f..54f1457 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -45,6 +45,8 @@
 import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.ui.binder.KeyguardRootViewBinder;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel;
 import com.android.systemui.log.LogBuffer;
 import com.android.systemui.log.core.LogLevel;
 import com.android.systemui.log.dagger.KeyguardClockLog;
@@ -95,6 +97,7 @@
     private final ClockEventController mClockEventController;
     private final LogBuffer mLogBuffer;
     private final NotificationIconContainerAlwaysOnDisplayViewModel mAodIconsViewModel;
+    private final KeyguardRootViewModel mKeyguardRootViewModel;
     private final ConfigurationState mConfigurationState;
     private final ConfigurationController mConfigurationController;
     private final DozeParameters mDozeParameters;
@@ -127,7 +130,7 @@
     private KeyguardInteractor mKeyguardInteractor;
     private final DelayableExecutor mUiExecutor;
     private boolean mCanShowDoubleLineClock = true;
-    private DisposableHandle mAodIconsBindJob;
+    private DisposableHandle mAodIconsBindHandle;
     @Nullable private NotificationIconContainer mAodIconContainer;
 
     @VisibleForTesting
@@ -179,6 +182,7 @@
             ClockEventController clockEventController,
             @KeyguardClockLog LogBuffer logBuffer,
             NotificationIconContainerAlwaysOnDisplayViewModel aodIconsViewModel,
+            KeyguardRootViewModel keyguardRootViewModel,
             ConfigurationState configurationState,
             DozeParameters dozeParameters,
             AlwaysOnDisplayNotificationIconViewStore aodIconViewStore,
@@ -199,6 +203,7 @@
         mClockEventController = clockEventController;
         mLogBuffer = logBuffer;
         mAodIconsViewModel = aodIconsViewModel;
+        mKeyguardRootViewModel = keyguardRootViewModel;
         mConfigurationState = configurationState;
         mDozeParameters = dozeParameters;
         mAodIconViewStore = aodIconViewStore;
@@ -567,21 +572,32 @@
                     mView.findViewById(
                             com.android.systemui.res.R.id.left_aligned_notification_icon_container);
             if (NotificationIconContainerRefactor.isEnabled()) {
-                if (mAodIconsBindJob != null) {
-                    mAodIconsBindJob.dispose();
+                if (mAodIconsBindHandle != null) {
+                    mAodIconsBindHandle.dispose();
                 }
                 if (nic != null) {
                     nic.setOnLockScreen(true);
-                    mAodIconsBindJob = NotificationIconContainerViewBinder.bind(
-                        nic,
-                        mAodIconsViewModel,
-                        mConfigurationState,
-                        mConfigurationController,
-                        mDozeParameters,
-                        mFeatureFlags,
-                        mScreenOffAnimationController,
-                        mAodIconViewStore
-                    );
+                    final DisposableHandle viewHandle = NotificationIconContainerViewBinder.bind(
+                            nic,
+                            mAodIconsViewModel,
+                            mConfigurationState,
+                            mConfigurationController,
+                            mDozeParameters,
+                            mAodIconViewStore);
+                    final DisposableHandle visHandle = KeyguardRootViewBinder.bindAodIconVisibility(
+                            nic,
+                            mKeyguardRootViewModel.isNotifIconContainerVisible(),
+                            mConfigurationState,
+                            mFeatureFlags,
+                            mScreenOffAnimationController);
+                    if (visHandle == null) {
+                        mAodIconsBindHandle = viewHandle;
+                    } else {
+                        mAodIconsBindHandle = () -> {
+                            viewHandle.dispose();
+                            visHandle.dispose();
+                        };
+                    }
                     mAodIconContainer = nic;
                 }
             } else {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
index 4160ae1..953cf88 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardFingerprintListenModel.kt
@@ -30,6 +30,7 @@
     var allowOnCurrentOccludingActivity: Boolean = false,
     var alternateBouncerShowing: Boolean = false,
     var biometricEnabledForUser: Boolean = false,
+    var biometricPromptShowing: Boolean = false,
     var bouncerIsOrWillShow: Boolean = false,
     var canSkipBouncer: Boolean = false,
     var credentialAttempted: Boolean = false,
@@ -61,6 +62,7 @@
             allowOnCurrentOccludingActivity.toString(),
             alternateBouncerShowing.toString(),
             biometricEnabledForUser.toString(),
+            biometricPromptShowing.toString(),
             bouncerIsOrWillShow.toString(),
             canSkipBouncer.toString(),
             credentialAttempted.toString(),
@@ -101,6 +103,7 @@
                 allowOnCurrentOccludingActivity = model.allowOnCurrentOccludingActivity
                 alternateBouncerShowing = model.alternateBouncerShowing
                 biometricEnabledForUser = model.biometricEnabledForUser
+                biometricPromptShowing = model.biometricPromptShowing
                 bouncerIsOrWillShow = model.bouncerIsOrWillShow
                 canSkipBouncer = model.canSkipBouncer
                 credentialAttempted = model.credentialAttempted
@@ -147,6 +150,7 @@
                 "allowOnCurrentOccludingActivity",
                 "alternateBouncerShowing",
                 "biometricAllowedForUser",
+                "biometricPromptShowing",
                 "bouncerIsOrWillShow",
                 "canSkipBouncer",
                 "credentialAttempted",
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f19a9ed..baab637 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -380,6 +380,7 @@
     private boolean mOccludingAppRequestingFace;
     private boolean mSecureCameraLaunched;
     private boolean mAllowedDisplayStateWhileAwakeForFaceAuth = true;
+    private boolean mBiometricPromptShowing;
     @VisibleForTesting
     protected boolean mTelephonyCapable;
     private boolean mAllowFingerprintOnCurrentOccludingActivity;
@@ -2010,9 +2011,17 @@
             };
 
     private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback =
-            (sensorId, userId, isStrongBiometric) -> {
-                // Trigger the fingerprint detected path so the bouncer can be shown
-                handleBiometricDetected(userId, FINGERPRINT, isStrongBiometric);
+            new FingerprintManager.FingerprintDetectionCallback() {
+                @Override
+                public void onDetectionError(int errorMsgId) {
+                    handleFingerprintError(errorMsgId, "");
+                }
+
+                @Override
+                public void onFingerprintDetected(int sensorId, int userId,
+                        boolean isStrongBiometric) {
+                    handleBiometricDetected(userId, FINGERPRINT, isStrongBiometric);
+                }
             };
 
     private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
@@ -2641,6 +2650,19 @@
                 mainExecutor.execute(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE,
                         FACE_AUTH_TRIGGERED_ENROLLMENTS_CHANGED));
             }
+
+            @Override
+            public void onBiometricPromptShown() {
+                // SysUI should give priority to the biometric prompt requesting FP instead of
+                // taking over the fingerprint listening state.
+                mBiometricPromptShowing = true;
+            }
+
+            @Override
+            public void onBiometricPromptDismissed() {
+                mBiometricPromptShowing = false;
+                updateFingerprintListeningState(BIOMETRIC_ACTION_START);
+            }
         });
         if (mConfigFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) {
             mPostureController.addCallback(mPostureCallback);
@@ -3139,7 +3161,7 @@
 
 
         boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
-                && shouldListenBouncerState && shouldListenUdfpsState;
+                && shouldListenBouncerState && shouldListenUdfpsState && !mBiometricPromptShowing;
         logListenerModelData(
                 new KeyguardFingerprintListenModel(
                     System.currentTimeMillis(),
@@ -3148,6 +3170,7 @@
                     mAllowFingerprintOnCurrentOccludingActivity,
                     mAlternateBouncerShowing,
                     biometricEnabledForUser,
+                    mBiometricPromptShowing,
                     mPrimaryBouncerIsOrWillBeShowing,
                     userCanSkipBouncer,
                     mCredentialAttempted,
diff --git a/packages/SystemUI/src/com/android/systemui/aconfig/AConfigModule.kt b/packages/SystemUI/src/com/android/systemui/aconfig/AConfigModule.kt
deleted file mode 100644
index fa61bba..0000000
--- a/packages/SystemUI/src/com/android/systemui/aconfig/AConfigModule.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.aconfig
-
-import com.android.systemui.FeatureFlags
-import com.android.systemui.FeatureFlagsImpl
-import com.android.systemui.dagger.SysUISingleton
-import dagger.Module
-import dagger.Provides
-
-@Module
-abstract class AConfigModule {
-    @Module
-    companion object {
-        @Provides
-        @SysUISingleton
-        fun providesImpl(): FeatureFlags {
-            return FeatureFlagsImpl()
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index 52923a7..345f15c 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -16,6 +16,8 @@
 
 package com.android.systemui.authentication.domain.interactor
 
+import com.android.app.tracing.TraceUtils.Companion.async
+import com.android.app.tracing.TraceUtils.Companion.withContext
 import com.android.internal.widget.LockPatternView
 import com.android.internal.widget.LockscreenCredential
 import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
@@ -27,8 +29,6 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
-import com.android.systemui.tracing.TraceUtils.Companion.async
-import com.android.systemui.tracing.TraceUtils.Companion.withContext
 import com.android.systemui.user.data.repository.UserRepository
 import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index e69eced..1ac4163 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -489,6 +489,10 @@
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
 
+        if (mContainerState == STATE_ANIMATING_OUT) {
+            return;
+        }
+
         mWakefulnessLifecycle.addObserver(this);
         mPanelInteractionDetector.enable(
                 () -> animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED));
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index 949c117..10e7227 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -53,6 +53,7 @@
 import com.airbnb.lottie.LottieProperty
 import com.airbnb.lottie.model.KeyPath
 import com.android.app.animation.Interpolators
+import com.android.app.tracing.traceSection
 import com.android.internal.annotations.VisibleForTesting
 import com.android.keyguard.KeyguardPINView
 import com.android.systemui.Dumpable
@@ -63,7 +64,6 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.res.R
-import com.android.systemui.tracing.traceSection
 import com.android.systemui.util.boundsOnScreen
 import com.android.systemui.util.concurrency.DelayableExecutor
 import java.io.PrintWriter
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
index f85203e..f513799 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractor.kt
@@ -19,25 +19,25 @@
 import android.content.Context
 import android.hardware.biometrics.SensorLocationInternal
 import android.view.WindowManager
+import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
 import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
 import com.android.systemui.biometrics.domain.model.SideFpsSensorLocation
 import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.android.systemui.biometrics.shared.model.isDefaultOrientation
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
+import com.android.systemui.log.SideFpsLogger
 import com.android.systemui.res.R
+import java.util.Optional
 import javax.inject.Inject
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
 
-@OptIn(ExperimentalCoroutinesApi::class)
 @SysUISingleton
 class SideFpsSensorInteractor
 @Inject
@@ -46,10 +46,11 @@
     fingerprintPropertyRepository: FingerprintPropertyRepository,
     windowManager: WindowManager,
     displayStateInteractor: DisplayStateInteractor,
-    featureFlags: FeatureFlagsClassic,
+    fingerprintInteractiveToAuthProvider: Optional<FingerprintInteractiveToAuthProvider>,
+    private val logger: SideFpsLogger,
 ) {
 
-    private val sensorForCurrentDisplay =
+    private val sensorLocationForCurrentDisplay =
         combine(
                 displayStateInteractor.displayChanges,
                 fingerprintPropertyRepository.sensorLocations,
@@ -61,76 +62,100 @@
     val isAvailable: Flow<Boolean> =
         fingerprintPropertyRepository.sensorType.map { it == FingerprintSensorType.POWER_BUTTON }
 
-    val authenticationDuration: Flow<Long> =
-        flowOf(context.resources?.getInteger(R.integer.config_restToUnlockDuration)?.toLong() ?: 0L)
+    val authenticationDuration: Long =
+        context.resources?.getInteger(R.integer.config_restToUnlockDuration)?.toLong() ?: 0L
 
     val isProlongedTouchRequiredForAuthentication: Flow<Boolean> =
-        isAvailable.flatMapLatest { sfpsAvailable ->
-            if (sfpsAvailable) {
-                // todo (b/305236201) also add the settings check here.
-                flowOf(featureFlags.isEnabled(Flags.REST_TO_UNLOCK))
-            } else {
-                flowOf(false)
+        if (fingerprintInteractiveToAuthProvider.isEmpty) {
+            flowOf(false)
+        } else {
+            combine(
+                isAvailable,
+                fingerprintInteractiveToAuthProvider.get().enabledForCurrentUser
+            ) { sfpsAvailable, isSettingEnabled ->
+                sfpsAvailable && isSettingEnabled
             }
         }
 
     val sensorLocation: Flow<SideFpsSensorLocation> =
-        combine(displayStateInteractor.currentRotation, sensorForCurrentDisplay, ::Pair).map {
-            (rotation, sensorLocation: SensorLocationInternal) ->
-            val isSensorVerticalInDefaultOrientation = sensorLocation.sensorLocationY != 0
-            // device dimensions in the current rotation
-            val size = windowManager.maximumWindowMetrics.bounds
-            val isDefaultOrientation = rotation.isDefaultOrientation()
-            // Width and height are flipped is device is not in rotation_0 or rotation_180
-            // Flipping it to the width and height of the device in default orientation.
-            val displayWidth = if (isDefaultOrientation) size.width() else size.height()
-            val displayHeight = if (isDefaultOrientation) size.height() else size.width()
-            val sensorWidth = context.resources?.getInteger(R.integer.config_sfpsSensorWidth) ?: 0
+        combine(displayStateInteractor.currentRotation, sensorLocationForCurrentDisplay, ::Pair)
+            .map { (rotation, sensorLocation: SensorLocationInternal) ->
+                val isSensorVerticalInDefaultOrientation = sensorLocation.sensorLocationY != 0
+                // device dimensions in the current rotation
+                val windowMetrics = windowManager.maximumWindowMetrics
+                val size = windowMetrics.bounds
+                val isDefaultOrientation = rotation.isDefaultOrientation()
+                // Width and height are flipped is device is not in rotation_0 or rotation_180
+                // Flipping it to the width and height of the device in default orientation.
+                val displayWidth = if (isDefaultOrientation) size.width() else size.height()
+                val displayHeight = if (isDefaultOrientation) size.height() else size.width()
+                val sensorLengthInPx = sensorLocation.sensorRadius * 2
 
-            val (sensorLeft, sensorTop) =
-                if (isSensorVerticalInDefaultOrientation) {
-                    when (rotation) {
-                        DisplayRotation.ROTATION_0 -> {
-                            Pair(displayWidth, sensorLocation.sensorLocationY)
+                val (sensorLeft, sensorTop) =
+                    if (isSensorVerticalInDefaultOrientation) {
+                        when (rotation) {
+                            DisplayRotation.ROTATION_0 -> {
+                                Pair(displayWidth, sensorLocation.sensorLocationY)
+                            }
+                            DisplayRotation.ROTATION_90 -> {
+                                Pair(sensorLocation.sensorLocationY, 0)
+                            }
+                            DisplayRotation.ROTATION_180 -> {
+                                Pair(
+                                    0,
+                                    displayHeight -
+                                        sensorLocation.sensorLocationY -
+                                        sensorLengthInPx
+                                )
+                            }
+                            DisplayRotation.ROTATION_270 -> {
+                                Pair(
+                                    displayHeight -
+                                        sensorLocation.sensorLocationY -
+                                        sensorLengthInPx,
+                                    displayWidth
+                                )
+                            }
                         }
-                        DisplayRotation.ROTATION_90 -> {
-                            Pair(sensorLocation.sensorLocationY, 0)
-                        }
-                        DisplayRotation.ROTATION_180 -> {
-                            Pair(0, displayHeight - sensorLocation.sensorLocationY - sensorWidth)
-                        }
-                        DisplayRotation.ROTATION_270 -> {
-                            Pair(
-                                displayHeight - sensorLocation.sensorLocationY - sensorWidth,
-                                displayWidth
-                            )
+                    } else {
+                        when (rotation) {
+                            DisplayRotation.ROTATION_0 -> {
+                                Pair(sensorLocation.sensorLocationX, 0)
+                            }
+                            DisplayRotation.ROTATION_90 -> {
+                                Pair(
+                                    0,
+                                    displayWidth - sensorLocation.sensorLocationX - sensorLengthInPx
+                                )
+                            }
+                            DisplayRotation.ROTATION_180 -> {
+                                Pair(
+                                    displayWidth -
+                                        sensorLocation.sensorLocationX -
+                                        sensorLengthInPx,
+                                    displayHeight
+                                )
+                            }
+                            DisplayRotation.ROTATION_270 -> {
+                                Pair(displayHeight, sensorLocation.sensorLocationX)
+                            }
                         }
                     }
-                } else {
-                    when (rotation) {
-                        DisplayRotation.ROTATION_0 -> {
-                            Pair(sensorLocation.sensorLocationX, 0)
-                        }
-                        DisplayRotation.ROTATION_90 -> {
-                            Pair(0, displayWidth - sensorLocation.sensorLocationX - sensorWidth)
-                        }
-                        DisplayRotation.ROTATION_180 -> {
-                            Pair(
-                                displayWidth - sensorLocation.sensorLocationX - sensorWidth,
-                                displayHeight
-                            )
-                        }
-                        DisplayRotation.ROTATION_270 -> {
-                            Pair(displayHeight, sensorLocation.sensorLocationX)
-                        }
-                    }
-                }
 
-            SideFpsSensorLocation(
-                left = sensorLeft,
-                top = sensorTop,
-                width = sensorWidth,
-                isSensorVerticalInDefaultOrientation = isSensorVerticalInDefaultOrientation
-            )
-        }
+                SideFpsSensorLocation(
+                    left = sensorLeft,
+                    top = sensorTop,
+                    length = sensorLengthInPx,
+                    isSensorVerticalInDefaultOrientation = isSensorVerticalInDefaultOrientation
+                )
+            }
+            .distinctUntilChanged()
+            .onEach {
+                logger.sensorLocationStateChanged(
+                    it.left,
+                    it.top,
+                    it.length,
+                    it.isSensorVerticalInDefaultOrientation
+                )
+            }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/SideFpsSensorLocation.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/SideFpsSensorLocation.kt
index 35f8e3b..12f374f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/SideFpsSensorLocation.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/SideFpsSensorLocation.kt
@@ -21,8 +21,8 @@
     val left: Int,
     /** Pixel offset from the top of the screen */
     val top: Int,
-    /** Width in pixels of the SFPS sensor */
-    val width: Int,
+    /** Length of the SFPS sensor in pixels in current display density */
+    val length: Int,
     /**
      * Whether the sensor is vertical when the device is in its default orientation (Rotation_0 or
      * Rotation_180)
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
index 485e512..5c4ee35 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalRepository.kt
@@ -1,26 +1,44 @@
 package com.android.systemui.communal.data.repository
 
-import com.android.systemui.FeatureFlags
+import com.android.systemui.Flags.communalHub
+import com.android.systemui.communal.shared.model.CommunalSceneKey
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 
 /** Encapsulates the state of communal mode. */
 interface CommunalRepository {
     /** Whether communal features are enabled. */
     val isCommunalEnabled: Boolean
+
+    /**
+     * Target scene as requested by the underlying [SceneTransitionLayout] or through
+     * [setDesiredScene].
+     */
+    val desiredScene: StateFlow<CommunalSceneKey>
+
+    /** Updates the requested scene. */
+    fun setDesiredScene(desiredScene: CommunalSceneKey)
 }
 
 @SysUISingleton
 class CommunalRepositoryImpl
 @Inject
 constructor(
-    private val featureFlags: FeatureFlags,
     private val featureFlagsClassic: FeatureFlagsClassic,
 ) : CommunalRepository {
     override val isCommunalEnabled: Boolean
-        get() =
-            featureFlagsClassic.isEnabled(Flags.COMMUNAL_SERVICE_ENABLED) &&
-                featureFlags.communalHub()
+        get() = featureFlagsClassic.isEnabled(Flags.COMMUNAL_SERVICE_ENABLED) && communalHub()
+
+    private val _desiredScene: MutableStateFlow<CommunalSceneKey> =
+        MutableStateFlow(CommunalSceneKey.Blank)
+    override val desiredScene: StateFlow<CommunalSceneKey> = _desiredScene.asStateFlow()
+
+    override fun setDesiredScene(desiredScene: CommunalSceneKey) {
+        _desiredScene.value = desiredScene
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index 6238707..ccccbb6 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -19,10 +19,13 @@
 import com.android.systemui.communal.data.repository.CommunalRepository
 import com.android.systemui.communal.data.repository.CommunalWidgetRepository
 import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo
+import com.android.systemui.communal.shared.model.CommunalSceneKey
 import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
 import com.android.systemui.dagger.SysUISingleton
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.map
 
 /** Encapsulates business-logic related to communal mode. */
 @SysUISingleton
@@ -47,4 +50,22 @@
      * (have an allocated id).
      */
     val widgetContent: Flow<List<CommunalWidgetContentModel>> = widgetRepository.communalWidgets
+
+    /**
+     * Target scene as requested by the underlying [SceneTransitionLayout] or through
+     * [onSceneChanged].
+     */
+    val desiredScene: StateFlow<CommunalSceneKey> = communalRepository.desiredScene
+
+    /**
+     * Flow that emits a boolean if the communal UI is showing, ie. the [desiredScene] is the
+     * [CommunalSceneKey.Communal].
+     */
+    val isCommunalShowing: Flow<Boolean> =
+        communalRepository.desiredScene.map { it == CommunalSceneKey.Communal }
+
+    /** Callback received whenever the [SceneTransitionLayout] finishes a scene transition. */
+    fun onSceneChanged(newScene: CommunalSceneKey) {
+        communalRepository.setDesiredScene(newScene)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt
index 276df4e..7f43eb5 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractor.kt
@@ -19,12 +19,23 @@
 import android.provider.Settings
 import com.android.systemui.communal.data.repository.CommunalTutorialRepository
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
+import com.android.systemui.scene.shared.model.SceneKey
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
 
 /** Encapsulates business-logic related to communal tutorial state. */
 @OptIn(ExperimentalCoroutinesApi::class)
@@ -32,8 +43,12 @@
 class CommunalTutorialInteractor
 @Inject
 constructor(
-    communalTutorialRepository: CommunalTutorialRepository,
+    @Application private val scope: CoroutineScope,
+    private val communalTutorialRepository: CommunalTutorialRepository,
     keyguardInteractor: KeyguardInteractor,
+    private val communalInteractor: CommunalInteractor,
+    private val sceneContainerFlags: SceneContainerFlags,
+    private val sceneInteractor: SceneInteractor,
 ) {
     /** An observable for whether the tutorial is available. */
     val isTutorialAvailable: Flow<Boolean> =
@@ -45,4 +60,63 @@
                     tutorialSettingState != Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED
             }
             .distinctUntilChanged()
+
+    /**
+     * A flow of the new tutorial state after transitioning. The new state will be calculated based
+     * on the current tutorial state and transition state as following:
+     * HUB_MODE_TUTORIAL_NOT_STARTED + communal scene -> HUB_MODE_TUTORIAL_STARTED
+     * HUB_MODE_TUTORIAL_STARTED + non-communal scene -> HUB_MODE_TUTORIAL_COMPLETED
+     * HUB_MODE_TUTORIAL_COMPLETED + any scene -> won't emit
+     */
+    private val tutorialStateToUpdate: Flow<Int> =
+        communalTutorialRepository.tutorialSettingState
+            .flatMapLatest { tutorialSettingState ->
+                if (tutorialSettingState == Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED) {
+                    return@flatMapLatest flowOf(null)
+                }
+                if (sceneContainerFlags.isEnabled()) {
+                    sceneInteractor.desiredScene.map { sceneModel ->
+                        nextStateAfterTransition(
+                            tutorialSettingState,
+                            sceneModel.key == SceneKey.Communal
+                        )
+                    }
+                } else {
+                    communalInteractor.isCommunalShowing.map {
+                        nextStateAfterTransition(tutorialSettingState, it)
+                    }
+                }
+            }
+            .filterNotNull()
+            .distinctUntilChanged()
+
+    private fun nextStateAfterTransition(tutorialState: Int, isCommunalShowing: Boolean): Int? {
+        if (tutorialState == Settings.Secure.HUB_MODE_TUTORIAL_NOT_STARTED && isCommunalShowing) {
+            return Settings.Secure.HUB_MODE_TUTORIAL_STARTED
+        }
+        if (tutorialState == Settings.Secure.HUB_MODE_TUTORIAL_STARTED && !isCommunalShowing) {
+            return Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED
+        }
+        return null
+    }
+
+    private var job: Job? = null
+    private fun listenForTransitionToUpdateTutorialState() {
+        if (!communalInteractor.isCommunalEnabled) {
+            return
+        }
+        job =
+            scope.launch {
+                tutorialStateToUpdate.collect {
+                    communalTutorialRepository.setTutorialState(it)
+                    if (it == Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED) {
+                        job?.cancel()
+                    }
+                }
+            }
+    }
+
+    init {
+        listenForTransitionToUpdateTutorialState()
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalSceneKey.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalSceneKey.kt
new file mode 100644
index 0000000..2be909c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/model/CommunalSceneKey.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.shared.model
+
+/** Definition of the possible scenes for the communal UI. */
+sealed class CommunalSceneKey(
+    private val loggingName: String,
+) {
+    /** The communal scene containing the hub UI. */
+    object Communal : CommunalSceneKey("communal")
+
+    /** The default scene, shows nothing and is only there to allow swiping to communal. */
+    object Blank : CommunalSceneKey("blank")
+
+    override fun toString(): String {
+        return loggingName
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalTutorialIndicatorViewBinder.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalTutorialIndicatorViewBinder.kt
index dab6819..4dfc371 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalTutorialIndicatorViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalTutorialIndicatorViewBinder.kt
@@ -44,6 +44,8 @@
                             )
                         }
                     }
+
+                    launch { viewModel.alpha.collect { view.alpha = it } }
                 }
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTutorialIndicatorViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTutorialIndicatorViewModel.kt
index eaf9550..274e61a 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTutorialIndicatorViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTutorialIndicatorViewModel.kt
@@ -17,15 +17,21 @@
 package com.android.systemui.communal.ui.viewmodel
 
 import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor
+import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.distinctUntilChanged
 
 /** View model for communal tutorial indicator on keyguard */
 class CommunalTutorialIndicatorViewModel
 @Inject
 constructor(
     communalTutorialInteractor: CommunalTutorialInteractor,
+    bottomAreaInteractor: KeyguardBottomAreaInteractor,
 ) {
     /** An observable for whether the tutorial indicator view should be visible. */
     val showIndicator: Flow<Boolean> = communalTutorialInteractor.isTutorialAvailable
+
+    /** An observable for the alpha level for the tutorial indicator. */
+    val alpha: Flow<Float> = bottomAreaInteractor.alpha.distinctUntilChanged()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index 390b580..de9b563 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -20,11 +20,13 @@
 import android.content.Context
 import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor
+import com.android.systemui.communal.shared.model.CommunalSceneKey
 import com.android.systemui.communal.ui.model.CommunalContentUiModel
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.map
 
 @SysUISingleton
@@ -33,7 +35,7 @@
 constructor(
     @Application private val context: Context,
     private val appWidgetHost: AppWidgetHost,
-    communalInteractor: CommunalInteractor,
+    private val communalInteractor: CommunalInteractor,
     tutorialInteractor: CommunalTutorialInteractor,
 ) {
     /** Whether communal hub should show tutorial content. */
@@ -54,4 +56,9 @@
                 )
             }
         }
+
+    val currentScene: StateFlow<CommunalSceneKey> = communalInteractor.desiredScene
+    fun onSceneChanged(scene: CommunalSceneKey) {
+        communalInteractor.onSceneChanged(scene)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 1dd4abf..236c5b8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -48,7 +48,6 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.dagger.StartCentralSurfacesModule;
-import com.android.systemui.statusbar.events.StatusBarEventsModule;
 import com.android.systemui.statusbar.phone.DozeServiceHost;
 import com.android.systemui.statusbar.phone.HeadsUpModule;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -99,7 +98,6 @@
         ReferenceScreenshotModule.class,
         RotationLockModule.class,
         SceneContainerFrameworkModule.class,
-        StatusBarEventsModule.class,
         StartCentralSurfacesModule.class,
         VolumeModule.class,
         WallpaperModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index a41bb2f..f3353c7 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -29,7 +29,6 @@
 import com.android.systemui.BootCompleteCacheImpl;
 import com.android.systemui.accessibility.AccessibilityModule;
 import com.android.systemui.accessibility.data.repository.AccessibilityRepositoryModule;
-import com.android.systemui.aconfig.AConfigModule;
 import com.android.systemui.appops.dagger.AppOpsModule;
 import com.android.systemui.assist.AssistModule;
 import com.android.systemui.authentication.AuthenticationModule;
@@ -96,6 +95,7 @@
 import com.android.systemui.statusbar.connectivity.ConnectivityModule;
 import com.android.systemui.statusbar.dagger.StatusBarModule;
 import com.android.systemui.statusbar.disableflags.dagger.DisableFlagsModule;
+import com.android.systemui.statusbar.events.StatusBarEventsModule;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -162,7 +162,6 @@
 @Module(includes = {
         AccessibilityModule.class,
         AccessibilityRepositoryModule.class,
-        AConfigModule.class,
         AppOpsModule.class,
         AssistModule.class,
         AuthenticationModule.class,
@@ -209,6 +208,7 @@
         SettingsUtilModule.class,
         SmartRepliesInflationModule.class,
         SmartspaceModule.class,
+        StatusBarEventsModule.class,
         StatusBarModule.class,
         StatusBarPipelineModule.class,
         StatusBarPolicyModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
index 2ba687b..26c5ea6 100644
--- a/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt
@@ -23,15 +23,15 @@
 import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
 import android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_REMOVED
 import android.os.Handler
-import android.os.Trace
 import android.util.Log
 import android.view.Display
+import com.android.app.tracing.FlowTracing.traceEach
+import com.android.app.tracing.traceSection
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.display.data.DisplayEvent
-import com.android.systemui.tracing.traceSection
 import com.android.systemui.util.Compile
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
@@ -43,10 +43,9 @@
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.filterIsInstance
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.shareIn
 import kotlinx.coroutines.flow.stateIn
@@ -97,7 +96,6 @@
     @Application applicationScope: CoroutineScope,
     @Background backgroundCoroutineDispatcher: CoroutineDispatcher
 ) : DisplayRepository {
-    // Displays are enabled only after receiving them in [onDisplayAdded]
     private val allDisplayEvents: Flow<DisplayEvent> =
         conflatedCallbackFlow {
                 val callback =
@@ -124,16 +122,22 @@
                 awaitClose { displayManager.unregisterDisplayListener(callback) }
             }
             .onStart { emit(DisplayEvent.Changed(Display.DEFAULT_DISPLAY)) }
+            .debugLog("allDisplayEvents")
             .flowOn(backgroundCoroutineDispatcher)
 
     override val displayChangeEvent: Flow<Int> =
-        allDisplayEvents.filter { it is DisplayEvent.Changed }.map { it.displayId }
+        allDisplayEvents.filterIsInstance<DisplayEvent.Changed>().map { event -> event.displayId }
 
     override val displayAdditionEvent: Flow<Display?> =
-        allDisplayEvents
-            .filter { it is DisplayEvent.Added }
-            .map { displayManager.getDisplay(it.displayId) }
+        allDisplayEvents.filterIsInstance<DisplayEvent.Added>().map {
+            displayManager.getDisplay(it.displayId)
+        }
 
+    /**
+     * Represents displays that went though the [DisplayListener.onDisplayAdded] callback.
+     *
+     * Those are commonly the ones provided by [DisplayManager.getDisplays] by default.
+     */
     private val enabledDisplays =
         allDisplayEvents
             .map { getDisplays() }
@@ -143,9 +147,7 @@
     override val displays: Flow<Set<Display>> = enabledDisplays
 
     private fun getDisplays(): Set<Display> =
-        traceSection("DisplayRepository#getDisplays()") {
-            displayManager.displays?.toSet() ?: emptySet()
-        }
+        traceSection("$TAG#getDisplays()") { displayManager.displays?.toSet() ?: emptySet() }
 
     /** Propagate to the listeners only enabled displays */
     private val enabledDisplayIds: Flow<Set<Int>> =
@@ -153,7 +155,8 @@
             .map { enabledDisplaysSet -> enabledDisplaysSet.map { it.displayId }.toSet() }
             .debugLog("enabledDisplayIds")
 
-    private val ignoredDisplayIds = MutableStateFlow<Set<Int>>(emptySet())
+    private val _ignoredDisplayIds = MutableStateFlow<Set<Int>>(emptySet())
+    private val ignoredDisplayIds: Flow<Set<Int>> = _ignoredDisplayIds.debugLog("ignoredDisplayIds")
 
     private fun getInitialConnectedDisplays(): Set<Int> =
         displayManager
@@ -177,7 +180,7 @@
                                 Log.d(TAG, "display with id=$id connected.")
                             }
                             connectedIds += id
-                            ignoredDisplayIds.value -= id
+                            _ignoredDisplayIds.value -= id
                             trySend(connectedIds.toSet())
                         }
 
@@ -186,7 +189,7 @@
                             if (DEBUG) {
                                 Log.d(TAG, "display with id=$id disconnected.")
                             }
-                            ignoredDisplayIds.value -= id
+                            _ignoredDisplayIds.value -= id
                             trySend(connectedIds.toSet())
                         }
                     }
@@ -214,17 +217,23 @@
     private val connectedExternalDisplayIds: Flow<Set<Int>> =
         connectedDisplayIds
             .map { connectedDisplayIds ->
-                connectedDisplayIds
-                    .filter { id -> displayManager.getDisplay(id)?.type == Display.TYPE_EXTERNAL }
-                    .toSet()
+                traceSection("$TAG#filteringExternalDisplays") {
+                    connectedDisplayIds
+                        .filter { id -> getDisplayType(id) == Display.TYPE_EXTERNAL }
+                        .toSet()
+                }
             }
             .flowOn(backgroundCoroutineDispatcher)
             .debugLog("connectedExternalDisplayIds")
 
+    private fun getDisplayType(displayId: Int): Int? =
+        traceSection("$TAG#getDisplayType") { displayManager.getDisplay(displayId)?.type }
+
     /**
-     * Pending displays are the ones connected, but not enabled and not ignored. A connected display
-     * is ignored after the user makes the decision to use it or not. For now, the initial decision
-     * from the user is final and not reversible.
+     * Pending displays are the ones connected, but not enabled and not ignored.
+     *
+     * A connected display is ignored after the user makes the decision to use it or not. For now,
+     * the initial decision from the user is final and not reversible.
      */
     private val pendingDisplayIds: Flow<Set<Int>> =
         combine(enabledDisplayIds, connectedExternalDisplayIds, ignoredDisplayIds) {
@@ -241,12 +250,16 @@
                 }
                 connectedExternalDisplayIds - enabledDisplaysIds - ignoredDisplayIds
             }
-            .debugLog("pendingDisplayIds")
+            .debugLog("allPendingDisplayIds")
+
+    /** Which display id should be enabled among the pending ones. */
+    private val pendingDisplayId: Flow<Int?> =
+        pendingDisplayIds.map { it.maxOrNull() }.distinctUntilChanged().debugLog("pendingDisplayId")
 
     override val pendingDisplay: Flow<DisplayRepository.PendingDisplay?> =
-        pendingDisplayIds
-            .map { pendingDisplayIds ->
-                val id = pendingDisplayIds.maxOrNull() ?: return@map null
+        pendingDisplayId
+            .map { displayId ->
+                val id = displayId ?: return@map null
                 object : DisplayRepository.PendingDisplay {
                     override val id = id
 
@@ -263,7 +276,7 @@
 
                     override suspend fun ignore() {
                         traceSection("DisplayRepository#ignore($id)") {
-                            ignoredDisplayIds.value += id
+                            _ignoredDisplayIds.value += id
                         }
                     }
 
@@ -282,11 +295,7 @@
 
     private fun <T> Flow<T>.debugLog(flowName: String): Flow<T> {
         return if (DEBUG) {
-            this.onEach {
-                Log.d(TAG, "$flowName: $it")
-                Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_APP, "$TAG#$flowName", 0)
-                Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_APP, "$TAG#$flowName", "$it", 0)
-            }
+            traceEach(flowName, logcat = true)
         } else {
             this
         }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
index 1c2ff4b..87c12b4 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
@@ -16,12 +16,15 @@
 
 package com.android.systemui.flags;
 
+import static com.android.systemui.Flags.exampleFlag;
+import static com.android.systemui.Flags.sysuiTeamfood;
 import static com.android.systemui.flags.FlagManager.ACTION_GET_FLAGS;
 import static com.android.systemui.flags.FlagManager.ACTION_SET_FLAG;
 import static com.android.systemui.flags.FlagManager.EXTRA_FLAGS;
 import static com.android.systemui.flags.FlagManager.EXTRA_NAME;
 import static com.android.systemui.flags.FlagManager.EXTRA_VALUE;
 import static com.android.systemui.flags.FlagsCommonModule.ALL_FLAGS;
+import static com.android.systemui.shared.Flags.exampleSharedFlag;
 
 import static java.util.Objects.requireNonNull;
 
@@ -36,13 +39,10 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
-import com.android.systemui.FeatureFlags;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.util.settings.GlobalSettings;
 
-import org.jetbrains.annotations.NotNull;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Map;
@@ -81,7 +81,6 @@
     private final Map<String, Boolean> mBooleanFlagCache = new ConcurrentHashMap<>();
     private final Map<String, String> mStringFlagCache = new ConcurrentHashMap<>();
     private final Map<String, Integer> mIntFlagCache = new ConcurrentHashMap<>();
-    private final FeatureFlags mGantryFlags;
     private final Restarter mRestarter;
 
     private final ServerFlagReader.ChangeListener mOnPropertiesChanged =
@@ -126,7 +125,6 @@
             @Main Resources resources,
             ServerFlagReader serverFlagReader,
             @Named(ALL_FLAGS) Map<String, Flag<?>> allFlags,
-            FeatureFlags gantryFlags,
             Restarter restarter) {
         mFlagManager = flagManager;
         mContext = context;
@@ -135,7 +133,6 @@
         mSystemProperties = systemProperties;
         mServerFlagReader = serverFlagReader;
         mAllFlags = allFlags;
-        mGantryFlags = gantryFlags;
         mRestarter = restarter;
     }
 
@@ -153,16 +150,16 @@
     }
 
     @Override
-    public boolean isEnabled(@NotNull UnreleasedFlag flag) {
+    public boolean isEnabled(@NonNull UnreleasedFlag flag) {
         return isEnabledInternal(flag);
     }
 
     @Override
-    public boolean isEnabled(@NotNull ReleasedFlag flag) {
+    public boolean isEnabled(@NonNull ReleasedFlag flag) {
         return isEnabledInternal(flag);
     }
 
-    private boolean isEnabledInternal(@NotNull BooleanFlag flag) {
+    private boolean isEnabledInternal(@NonNull BooleanFlag flag) {
         String name = flag.getName();
 
         Boolean value = mBooleanFlagCache.get(name);
@@ -264,7 +261,7 @@
                 && !defaultValue
                 && result == null
                 && flag.getTeamfood()) {
-            return mGantryFlags.sysuiTeamfood();
+            return sysuiTeamfood();
         }
 
         return result == null ? mServerFlagReader.readServerOverride(
@@ -537,8 +534,10 @@
     @Override
     public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
         pw.println("can override: true");
-        pw.println("teamfood: " + mGantryFlags.sysuiTeamfood());
+        pw.println("teamfood: " + sysuiTeamfood());
         pw.println("booleans: " + mBooleanFlagCache.size());
+        pw.println("example_flag: " + exampleFlag());
+        pw.println("example_shared_flag: " + exampleSharedFlag());
         // Sort our flags for dumping
         TreeMap<String, Boolean> dumpBooleanMap = new TreeMap<>(mBooleanFlagCache);
         dumpBooleanMap.forEach((key, value) -> pw.println("  sysui_flag_" + key + ": " + value));
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 0c364e1..49b8ee6 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -258,7 +258,7 @@
     // TODO(b/290652751): Tracking bug.
     @JvmField
     val MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA =
-        unreleasedFlag("migrate_split_keyguard_bottom_area", teamfood = true)
+        unreleasedFlag("migrate_split_keyguard_bottom_area")
 
     // TODO(b/297037052): Tracking bug.
     @JvmField
@@ -273,7 +273,7 @@
 
     /** Migrate the lock icon view to the new keyguard root view. */
     // TODO(b/286552209): Tracking bug.
-    @JvmField val MIGRATE_LOCK_ICON = unreleasedFlag("migrate_lock_icon", teamfood = true)
+    @JvmField val MIGRATE_LOCK_ICON = unreleasedFlag("migrate_lock_icon")
 
     // TODO(b/288276738): Tracking bug.
     @JvmField val WIDGET_ON_KEYGUARD = unreleasedFlag("widget_on_keyguard")
@@ -296,11 +296,6 @@
     @JvmField val MIGRATE_CLOCKS_TO_BLUEPRINT =
             unreleasedFlag("migrate_clocks_to_blueprint")
 
-    /** Migrate KeyguardRootView to use composables. */
-    // TODO(b/301969856): Tracking Bug.
-    @JvmField val KEYGUARD_ROOT_VIEW_USE_COMPOSE =
-        unreleasedFlag("keyguard_root_view_use_compose")
-
     /** Enables preview loading animation in the wallpaper picker. */
     // TODO(b/274443705): Tracking Bug
     @JvmField
@@ -409,9 +404,6 @@
     val FILTER_PROVISIONING_NETWORK_SUBSCRIPTIONS =
         releasedFlag("filter_provisioning_network_subscriptions")
 
-    // TODO(b/265892345): Tracking Bug
-    val PLUG_IN_STATUS_BAR_CHIP = releasedFlag("plug_in_status_bar_chip")
-
     // TODO(b/292533677): Tracking Bug
     val WIFI_TRACKER_LIB_FOR_WIFI_ICON = releasedFlag("wifi_tracker_lib_for_wifi_icon")
 
@@ -535,10 +527,9 @@
     @Keep
     @JvmField
     val WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES =
-        unreleasedFlag(
-            name = "screen_record_enterprise_policies",
+        releasedFlag(
+            name = "enable_screen_record_enterprise_policies",
             namespace = DeviceConfig.NAMESPACE_WINDOW_MANAGER,
-            teamfood = false
         )
 
     // TODO(b/293252410) : Tracking Bug
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
index 4b98526..c490ce7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/CustomizationProvider.kt
@@ -30,13 +30,13 @@
 import android.os.Binder
 import android.os.Bundle
 import android.util.Log
+import com.android.app.tracing.TraceUtils.Companion.runBlocking
 import com.android.systemui.SystemUIAppComponentFactoryBase
 import com.android.systemui.SystemUIAppComponentFactoryBase.ContextAvailableCallback
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.domain.interactor.KeyguardQuickAffordanceInteractor
 import com.android.systemui.keyguard.ui.preview.KeyguardRemotePreviewManager
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
-import com.android.systemui.tracing.TraceUtils.Companion.runBlocking
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
index c56dfde..61c8e1bb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewConfigurator.kt
@@ -27,9 +27,10 @@
 import com.android.keyguard.LockIconViewController
 import com.android.keyguard.dagger.KeyguardStatusViewComponent
 import com.android.systemui.CoreStartable
+import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.ui.binder.KeyguardBlueprintViewBinder
 import com.android.systemui.keyguard.ui.binder.KeyguardIndicationAreaBinder
@@ -46,7 +47,7 @@
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.KeyguardIndicationController
 import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
 import dagger.Lazy
 import javax.inject.Inject
@@ -63,14 +64,15 @@
     private val keyguardRootViewModel: KeyguardRootViewModel,
     private val keyguardIndicationAreaViewModel: KeyguardIndicationAreaViewModel,
     private val notificationShadeWindowView: NotificationShadeWindowView,
-    private val featureFlags: FeatureFlags,
+    private val featureFlags: FeatureFlagsClassic,
     private val indicationController: KeyguardIndicationController,
-    private val keyguardStateController: KeyguardStateController,
+    private val screenOffAnimationController: ScreenOffAnimationController,
     private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
     private val chipbarCoordinator: ChipbarCoordinator,
     private val keyguardBlueprintCommandListener: KeyguardBlueprintCommandListener,
     private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel,
     private val keyguardStatusViewComponentFactory: KeyguardStatusViewComponent.Factory,
+    private val configuration: ConfigurationState,
     private val context: Context,
     private val keyguardIndicationController: KeyguardIndicationController,
     private val lockIconViewController: Lazy<LockIconViewController>,
@@ -143,10 +145,11 @@
             KeyguardRootViewBinder.bind(
                 keyguardRootView,
                 keyguardRootViewModel,
+                configuration,
                 featureFlags,
                 occludingAppDeviceEntryMessageViewModel,
                 chipbarCoordinator,
-                keyguardStateController,
+                screenOffAnimationController,
                 shadeInteractor,
                 { keyguardStatusViewController!!.getClockController() },
                 interactionJankMonitor,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt b/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
index 5c1b731..f9b89b1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
@@ -17,7 +17,7 @@
 
 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import javax.inject.Inject
 import javax.inject.Singleton
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index 0e795ae..c4962a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -18,6 +18,7 @@
 
 import android.animation.ValueAnimator
 import com.android.app.animation.Interpolators
+import com.android.app.tracing.TraceUtils.Companion.launch
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.flags.FeatureFlags
@@ -31,7 +32,6 @@
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.shade.data.repository.ShadeRepository
-import com.android.systemui.tracing.TraceUtils.Companion.launch
 import com.android.systemui.util.kotlin.Utils.Companion.toQuad
 import com.android.systemui.util.kotlin.Utils.Companion.toTriple
 import com.android.systemui.util.kotlin.sample
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index fbe92e3..448411e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -22,6 +22,7 @@
 import android.content.Context
 import android.content.Intent
 import android.util.Log
+import com.android.app.tracing.TraceUtils.Companion.withContext
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.animation.DialogLaunchAnimator
 import com.android.systemui.animation.Expandable
@@ -48,7 +49,6 @@
 import com.android.systemui.shared.customization.data.content.CustomizationProviderContract as Contract
 import com.android.systemui.statusbar.phone.SystemUIDialog
 import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.tracing.TraceUtils.Companion.withContext
 import dagger.Lazy
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index 67a12b0..ad48957 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -16,25 +16,31 @@
 
 package com.android.systemui.keyguard.ui.binder
 
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
 import android.annotation.DrawableRes
 import android.view.HapticFeedbackConstants
 import android.view.View
 import android.view.View.OnLayoutChangeListener
 import android.view.ViewGroup
 import android.view.ViewGroup.OnHierarchyChangeListener
+import android.view.ViewPropertyAnimator
 import android.view.WindowInsets
-import android.view.WindowInsets.Type
 import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.lifecycleScope
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.animation.Interpolators
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
 import com.android.keyguard.KeyguardClockSwitch.MISSING_CLOCK_ID
 import com.android.systemui.common.shared.model.Icon
 import com.android.systemui.common.shared.model.Text
 import com.android.systemui.common.shared.model.TintedIcon
+import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
+import com.android.systemui.flags.RefactorFlag
 import com.android.systemui.keyguard.shared.model.TransitionState
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
 import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
@@ -42,29 +48,38 @@
 import com.android.systemui.plugins.ClockController
 import com.android.systemui.res.R
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
+import com.android.systemui.statusbar.CrossFadeHelper
 import com.android.systemui.statusbar.VibratorHelper
-import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.temporarydisplay.ViewPriority
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
 import com.android.systemui.temporarydisplay.chipbar.ChipbarInfo
+import com.android.systemui.util.ui.AnimatedValue
+import com.android.systemui.util.ui.isAnimating
+import com.android.systemui.util.ui.stopAnimating
+import com.android.systemui.util.ui.value
 import javax.inject.Provider
 import kotlinx.coroutines.DisposableHandle
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
 /** Bind occludingAppDeviceEntryMessageViewModel to run whenever the keyguard view is attached. */
-@ExperimentalCoroutinesApi
+@OptIn(ExperimentalCoroutinesApi::class)
 object KeyguardRootViewBinder {
 
     @JvmStatic
     fun bind(
         view: ViewGroup,
         viewModel: KeyguardRootViewModel,
-        featureFlags: FeatureFlags,
+        configuration: ConfigurationState,
+        featureFlags: FeatureFlagsClassic,
         occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
         chipbarCoordinator: ChipbarCoordinator,
-        keyguardStateController: KeyguardStateController,
+        screenOffAnimationController: ScreenOffAnimationController,
         shadeInteractor: ShadeInteractor,
         clockControllerProvider: Provider<ClockController>?,
         interactionJankMonitor: InteractionJankMonitor?,
@@ -149,6 +164,24 @@
                             }
                         }
 
+                        if (NotificationIconContainerRefactor.isEnabled) {
+                            launch {
+                                val iconsAppearTranslationPx =
+                                    configuration
+                                        .getDimensionPixelSize(R.dimen.shelf_appear_translation)
+                                        .stateIn(this)
+                                viewModel.isNotifIconContainerVisible.collect { isVisible ->
+                                    childViews[aodNotificationIconContainerId]
+                                        ?.setAodNotifIconContainerIsVisible(
+                                            isVisible,
+                                            featureFlags,
+                                            iconsAppearTranslationPx.value,
+                                            screenOffAnimationController,
+                                        )
+                                }
+                            }
+                        }
+
                         interactionJankMonitor?.let { jankMonitor ->
                             launch {
                                 viewModel.goneToAodTransition.collect {
@@ -312,5 +345,124 @@
         }
     }
 
+    @JvmStatic
+    fun bindAodIconVisibility(
+        view: View,
+        isVisible: Flow<AnimatedValue<Boolean>>,
+        configuration: ConfigurationState,
+        featureFlags: FeatureFlagsClassic,
+        screenOffAnimationController: ScreenOffAnimationController,
+    ): DisposableHandle? {
+        RefactorFlag(featureFlags, Flags.MIGRATE_KEYGUARD_STATUS_VIEW).assertInLegacyMode()
+        if (NotificationIconContainerRefactor.isUnexpectedlyInLegacyMode()) return null
+        return view.repeatWhenAttached {
+            lifecycleScope.launch {
+                val iconAppearTranslationPx =
+                    configuration
+                        .getDimensionPixelSize(R.dimen.shelf_appear_translation)
+                        .stateIn(this)
+                isVisible.collect { isVisible ->
+                    view.setAodNotifIconContainerIsVisible(
+                        isVisible,
+                        featureFlags,
+                        iconAppearTranslationPx.value,
+                        screenOffAnimationController,
+                    )
+                }
+            }
+        }
+    }
+
+    private fun View.setAodNotifIconContainerIsVisible(
+        isVisible: AnimatedValue<Boolean>,
+        featureFlags: FeatureFlagsClassic,
+        iconsAppearTranslationPx: Int,
+        screenOffAnimationController: ScreenOffAnimationController,
+    ) {
+        val statusViewMigrated = featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)
+        animate().cancel()
+        val animatorListener =
+            object : AnimatorListenerAdapter() {
+                override fun onAnimationEnd(animation: Animator) {
+                    isVisible.stopAnimating()
+                }
+            }
+        when {
+            !isVisible.isAnimating -> {
+                alpha = 1f
+                if (!statusViewMigrated) {
+                    translationY = 0f
+                }
+                visibility = if (isVisible.value) View.VISIBLE else View.INVISIBLE
+            }
+            featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION) -> {
+                animateInIconTranslation(statusViewMigrated)
+                if (isVisible.value) {
+                    CrossFadeHelper.fadeIn(this, animatorListener)
+                } else {
+                    CrossFadeHelper.fadeOut(this, animatorListener)
+                }
+            }
+            !isVisible.value -> {
+                // Let's make sure the icon are translated to 0, since we cancelled it above
+                animateInIconTranslation(statusViewMigrated)
+                CrossFadeHelper.fadeOut(this, animatorListener)
+            }
+            visibility != View.VISIBLE -> {
+                // No fading here, let's just appear the icons instead!
+                visibility = View.VISIBLE
+                alpha = 1f
+                appearIcons(
+                    animate = screenOffAnimationController.shouldAnimateAodIcons(),
+                    iconsAppearTranslationPx,
+                    statusViewMigrated,
+                    animatorListener,
+                )
+            }
+            else -> {
+                // Let's make sure the icons are translated to 0, since we cancelled it above
+                animateInIconTranslation(statusViewMigrated)
+                // We were fading out, let's fade in instead
+                CrossFadeHelper.fadeIn(this, animatorListener)
+            }
+        }
+    }
+
+    private fun View.appearIcons(
+        animate: Boolean,
+        iconAppearTranslation: Int,
+        statusViewMigrated: Boolean,
+        animatorListener: Animator.AnimatorListener,
+    ) {
+        if (animate) {
+            if (!statusViewMigrated) {
+                translationY = -iconAppearTranslation.toFloat()
+            }
+            alpha = 0f
+            animate()
+                .alpha(1f)
+                .setInterpolator(Interpolators.LINEAR)
+                .setDuration(AOD_ICONS_APPEAR_DURATION)
+                .apply { if (statusViewMigrated) animateInIconTranslation() }
+                .setListener(animatorListener)
+                .start()
+        } else {
+            alpha = 1.0f
+            if (!statusViewMigrated) {
+                translationY = 0f
+            }
+        }
+    }
+
+    private fun View.animateInIconTranslation(statusViewMigrated: Boolean) {
+        if (!statusViewMigrated) {
+            animate().animateInIconTranslation().setDuration(AOD_ICONS_APPEAR_DURATION).start()
+        }
+    }
+
+    private fun ViewPropertyAnimator.animateInIconTranslation(): ViewPropertyAnimator =
+        setInterpolator(Interpolators.DECELERATE_QUINT).translationY(0f)
+
     private const val ID = "occluding_app_device_entry_unlock_msg"
+    private const val AOD_ICONS_APPEAR_DURATION: Long = 200
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
index 1acea5c..0bee48a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
@@ -16,19 +16,30 @@
 
 package com.android.systemui.keyguard.ui.binder
 
+import android.animation.ValueAnimator
+import android.graphics.Point
 import com.android.systemui.CoreStartable
 import com.android.systemui.biometrics.SideFpsController
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.ui.view.SideFpsProgressBar
 import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
+import com.android.systemui.log.SideFpsLogger
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.util.kotlin.Quint
+import java.io.PrintWriter
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
 
+private const val spfsProgressBarCommand = "sfps-progress-bar"
+
 @SysUISingleton
 class SideFpsProgressBarViewBinder
 @Inject
@@ -37,38 +48,124 @@
     private val view: SideFpsProgressBar,
     @Application private val applicationScope: CoroutineScope,
     private val sfpsController: dagger.Lazy<SideFpsController>,
+    private val logger: SideFpsLogger,
+    private val commandRegistry: CommandRegistry,
+    private val featureFlagsClassic: FeatureFlagsClassic,
 ) : CoreStartable {
 
     override fun start() {
+        if (!featureFlagsClassic.isEnabled(Flags.REST_TO_UNLOCK)) {
+            return
+        }
+        // When the rest to unlock feature is disabled by the user, stop any coroutines that are
+        // not required.
+        var layoutJob: Job? = null
+        var progressJob: Job? = null
+        commandRegistry.registerCommand(spfsProgressBarCommand) { SfpsProgressBarCommand() }
         applicationScope.launch {
             viewModel.isProlongedTouchRequiredForAuthentication.collectLatest { enabled ->
+                logger.isProlongedTouchRequiredForAuthenticationChanged(enabled)
                 if (enabled) {
-                    launch {
+                    layoutJob = launch {
                         combine(
                                 viewModel.isVisible,
-                                viewModel.sensorLocation,
-                                viewModel.shouldRotate90Degrees,
+                                viewModel.progressBarLocation,
+                                viewModel.rotation,
                                 viewModel.isFingerprintAuthRunning,
-                                viewModel.sensorWidth,
+                                viewModel.progressBarLength,
                                 ::Quint
                             )
-                            .collectLatest {
-                                (visible, location, shouldRotate, fpDetectRunning, sensorWidth) ->
-                                view.updateView(visible, location, shouldRotate, sensorWidth)
-                                // We have to hide the SFPS indicator as the progress bar will
-                                // be shown at the same location
-                                if (visible) {
-                                    sfpsController.get().hideIndicator()
-                                } else if (fpDetectRunning) {
-                                    sfpsController.get().showIndicator()
-                                }
+                            .collectLatest { (visible, location, rotation, fpDetectRunning, length)
+                                ->
+                                updateView(
+                                    visible,
+                                    location,
+                                    fpDetectRunning,
+                                    length,
+                                    viewModel.progressBarThickness,
+                                    rotation,
+                                )
                             }
                     }
-                    launch { viewModel.progress.collectLatest { view.setProgress(it) } }
+                    progressJob = launch {
+                        viewModel.progress.collectLatest { view.setProgress(it) }
+                    }
                 } else {
-                    view.hideOverlay()
+                    view.hide()
+                    layoutJob?.cancel()
+                    progressJob?.cancel()
                 }
             }
         }
     }
+
+    private fun updateView(
+        visible: Boolean,
+        location: Point,
+        fpDetectRunning: Boolean,
+        length: Int,
+        thickness: Int,
+        rotation: Float,
+    ) {
+        logger.sfpsProgressBarStateChanged(visible, location, fpDetectRunning, length, rotation)
+        view.updateView(visible, location, length, thickness, rotation)
+        // We have to hide the SFPS indicator as the progress bar will
+        // be shown at the same location
+        if (visible) {
+            logger.hidingSfpsIndicator()
+            sfpsController.get().hideIndicator()
+        } else if (fpDetectRunning) {
+            logger.showingSfpsIndicator()
+            sfpsController.get().showIndicator()
+        }
+    }
+
+    inner class SfpsProgressBarCommand : Command {
+        private var animator: ValueAnimator? = null
+        override fun execute(pw: PrintWriter, args: List<String>) {
+            if (args.isEmpty() || args[0] == "show" && args.size != 6) {
+                pw.println("invalid command")
+                help(pw)
+            } else {
+                when (args[0]) {
+                    "show" -> {
+                        animator?.cancel()
+                        updateView(
+                            visible = true,
+                            location = Point(Integer.parseInt(args[1]), Integer.parseInt(args[2])),
+                            fpDetectRunning = true,
+                            length = Integer.parseInt(args[3]),
+                            thickness = Integer.parseInt(args[4]),
+                            rotation = Integer.parseInt(args[5]).toFloat(),
+                        )
+                        animator =
+                            ValueAnimator.ofFloat(0.0f, 1.0f).apply {
+                                repeatMode = ValueAnimator.REVERSE
+                                repeatCount = ValueAnimator.INFINITE
+                                addUpdateListener { view.setProgress(it.animatedValue as Float) }
+                            }
+                        animator?.start()
+                    }
+                    "hide" -> {
+                        animator?.cancel()
+                        updateView(
+                            visible = false,
+                            location = Point(0, 0),
+                            fpDetectRunning = false,
+                            length = 0,
+                            thickness = 0,
+                            rotation = 0.0f,
+                        )
+                    }
+                }
+            }
+        }
+
+        override fun help(pw: PrintWriter) {
+            pw.println("Usage: adb shell cmd statusbar $spfsProgressBarCommand <command>")
+            pw.println("Available commands:")
+            pw.println("  show x y width height rotation")
+            pw.println("  hide")
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
index fe6a21e..b797c4b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/preview/KeyguardPreviewRenderer.kt
@@ -44,10 +44,10 @@
 import com.android.systemui.animation.view.LaunchableImageView
 import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
 import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryHapticsInteractor
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.ui.binder.KeyguardPreviewClockViewBinder
 import com.android.systemui.keyguard.ui.binder.KeyguardPreviewSmartspaceViewBinder
@@ -76,7 +76,7 @@
 import com.android.systemui.statusbar.VibratorHelper
 import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController
 import com.android.systemui.statusbar.phone.KeyguardBottomAreaView
-import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedInject
@@ -99,12 +99,13 @@
     private val quickAffordancesCombinedViewModel: KeyguardQuickAffordancesCombinedViewModel,
     displayManager: DisplayManager,
     private val windowManager: WindowManager,
+    private val configuration: ConfigurationState,
     private val clockController: ClockEventController,
     private val clockRegistry: ClockRegistry,
     private val broadcastDispatcher: BroadcastDispatcher,
     private val lockscreenSmartspaceController: LockscreenSmartspaceController,
     private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
-    private val featureFlags: FeatureFlags,
+    private val featureFlags: FeatureFlagsClassic,
     private val falsingManager: FalsingManager,
     private val vibratorHelper: VibratorHelper,
     private val indicationController: KeyguardIndicationController,
@@ -113,9 +114,8 @@
     private val keyguardBlueprintViewModel: KeyguardBlueprintViewModel,
     private val occludingAppDeviceEntryMessageViewModel: OccludingAppDeviceEntryMessageViewModel,
     private val chipbarCoordinator: ChipbarCoordinator,
-    private val keyguardStateController: KeyguardStateController,
+    private val screenOffAnimationController: ScreenOffAnimationController,
     private val shadeInteractor: ShadeInteractor,
-    private val deviceEntryHapticsInteractor: DeviceEntryHapticsInteractor,
 ) {
 
     val hostToken: IBinder? = bundle.getBinder(KEY_HOST_TOKEN)
@@ -341,10 +341,11 @@
             KeyguardRootViewBinder.bind(
                 keyguardRootView,
                 keyguardRootViewModel,
+                configuration,
                 featureFlags,
                 occludingAppDeviceEntryMessageViewModel,
                 chipbarCoordinator,
-                keyguardStateController,
+                screenOffAnimationController,
                 shadeInteractor,
                 null, // clock provider only needed for burn in
                 null, // jank monitor not required for preview mode
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/SideFpsProgressBar.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/SideFpsProgressBar.kt
index f7ab1ee..853f176 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/SideFpsProgressBar.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/SideFpsProgressBar.kt
@@ -22,17 +22,16 @@
 import android.view.Gravity
 import android.view.LayoutInflater
 import android.view.View
+import android.view.ViewGroup.LayoutParams.MATCH_PARENT
 import android.view.WindowManager
 import android.widget.ProgressBar
-import com.android.systemui.biometrics.Utils
+import androidx.core.view.isGone
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.res.R
 import javax.inject.Inject
 
 private const val TAG = "SideFpsProgressBar"
 
-const val progressBarHeight = 100
-
 @SysUISingleton
 class SideFpsProgressBar
 @Inject
@@ -40,31 +39,36 @@
     private val layoutInflater: LayoutInflater,
     private val windowManager: WindowManager,
 ) {
-    private var progressBarWidth = 200
+    private var overlayView: View? = null
+
     fun updateView(
         visible: Boolean,
-        location: Point,
-        shouldRotate90Degrees: Boolean,
-        progressBarWidth: Int
+        viewLeftTopLocation: Point,
+        progressBarWidth: Int,
+        progressBarHeight: Int,
+        rotation: Float,
     ) {
         if (visible) {
-            this.progressBarWidth = progressBarWidth
-            createAndShowOverlay(location, shouldRotate90Degrees)
+            createAndShowOverlay(viewLeftTopLocation, rotation, progressBarWidth, progressBarHeight)
         } else {
-            hideOverlay()
+            hide()
         }
     }
 
-    fun hideOverlay() {
-        overlayView = null
+    fun hide() {
+        progressBar?.isGone = true
     }
 
     private val overlayViewParams =
         WindowManager.LayoutParams(
-                progressBarHeight,
-                progressBarWidth,
+                // overlay is always full screen
+                MATCH_PARENT,
+                MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or
+                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
+                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
+                    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                 PixelFormat.TRANSPARENT
             )
             .apply {
@@ -78,37 +82,31 @@
                         WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
             }
 
-    private var overlayView: View? = null
-        set(value) {
-            field?.let { oldView -> windowManager.removeView(oldView) }
-            field = value
-            field?.let { newView -> windowManager.addView(newView, overlayViewParams) }
-        }
-
     private fun createAndShowOverlay(
-        fingerprintSensorLocation: Point,
-        shouldRotate90Degrees: Boolean
+        viewLeftTop: Point,
+        rotation: Float,
+        progressBarLength: Int,
+        progressBarThickness: Int,
     ) {
         if (overlayView == null) {
             overlayView = layoutInflater.inflate(R.layout.sidefps_progress_bar, null, false)
+            windowManager.addView(overlayView, overlayViewParams)
+            progressBar?.pivotX = 0.0f
+            progressBar?.pivotY = 0.0f
         }
-        overlayViewParams.x = fingerprintSensorLocation.x
-        overlayViewParams.y = fingerprintSensorLocation.y
-        if (shouldRotate90Degrees) {
-            overlayView?.rotation = 270.0f
-            overlayViewParams.width = progressBarHeight
-            overlayViewParams.height = progressBarWidth
-        } else {
-            overlayView?.rotation = 0.0f
-            overlayViewParams.width = progressBarWidth
-            overlayViewParams.height = progressBarHeight
-        }
-        windowManager.updateViewLayout(overlayView, overlayViewParams)
+        progressBar?.layoutParams?.width = progressBarLength
+        progressBar?.layoutParams?.height = progressBarThickness
+        progressBar?.translationX = viewLeftTop.x.toFloat()
+        progressBar?.translationY = viewLeftTop.y.toFloat()
+        progressBar?.rotation = rotation
+        progressBar?.isGone = false
+        overlayView?.requestLayout()
     }
 
     fun setProgress(value: Float) {
-        overlayView
-            ?.findViewById<ProgressBar?>(R.id.side_fps_progress_bar)
-            ?.setProgress((value * 100).toInt(), false)
+        progressBar?.setProgress((value * 100).toInt(), false)
     }
+
+    private val progressBar: ProgressBar?
+        get() = overlayView?.findViewById(R.id.side_fps_progress_bar)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt
index b7fe960..0390077 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt
@@ -31,7 +31,6 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.shared.model.KeyguardSection
 import com.android.systemui.res.R
-import com.android.systemui.shade.NotificationPanelView
 import com.android.systemui.statusbar.notification.icon.ui.viewbinder.AlwaysOnDisplayNotificationIconViewStore
 import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder
 import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel
@@ -39,7 +38,6 @@
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import com.android.systemui.statusbar.phone.NotificationIconContainer
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import javax.inject.Inject
 import kotlinx.coroutines.DisposableHandle
@@ -54,9 +52,7 @@
     private val featureFlags: FeatureFlagsClassic,
     private val nicAodViewModel: NotificationIconContainerAlwaysOnDisplayViewModel,
     private val nicAodIconViewStore: AlwaysOnDisplayNotificationIconViewStore,
-    private val notificationPanelView: NotificationPanelView,
     private val notificationIconAreaController: NotificationIconAreaController,
-    private val screenOffAnimationController: ScreenOffAnimationController,
 ) : KeyguardSection() {
 
     private var nicBindingDisposable: DisposableHandle? = null
@@ -97,8 +93,6 @@
                     configurationState,
                     configurationController,
                     dozeParameters,
-                    featureFlags,
-                    screenOffAnimationController,
                     nicAodIconViewStore,
                 )
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
index e12da53..60f75f0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModel.kt
@@ -22,14 +22,28 @@
 import android.view.View.VISIBLE
 import com.android.app.animation.Interpolators
 import com.android.systemui.common.shared.model.SharedNotificationContainerPosition
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.BurnInModel
+import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.plugins.ClockController
 import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.util.kotlin.pairwise
+import com.android.systemui.util.kotlin.sample
+import com.android.systemui.util.ui.AnimatableEvent
+import com.android.systemui.util.ui.AnimatedValue
+import com.android.systemui.util.ui.toAnimatedValueFlow
+import com.android.systemui.util.ui.zip
 import javax.inject.Inject
 import javax.inject.Provider
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -45,15 +59,21 @@
 import kotlinx.coroutines.flow.onStart
 
 @OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
 class KeyguardRootViewModel
 @Inject
 constructor(
     private val context: Context,
+    private val deviceEntryInteractor: DeviceEntryInteractor,
+    private val dozeParameters: DozeParameters,
+    private val featureFlags: FeatureFlagsClassic,
     private val keyguardInteractor: KeyguardInteractor,
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+    private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor,
     private val burnInInteractor: BurnInInteractor,
     private val goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
     private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
-    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+    screenOffAnimationController: ScreenOffAnimationController,
 ) {
 
     data class PreviewMode(val isInPreviewMode: Boolean = false)
@@ -174,6 +194,47 @@
             }
         }
 
+    /** Is the notification icon container visible? */
+    val isNotifIconContainerVisible: Flow<AnimatedValue<Boolean>> =
+        combine(
+                keyguardTransitionInteractor.finishedKeyguardState.map {
+                    KeyguardState.lockscreenVisibleInState(it)
+                },
+                deviceEntryInteractor.isBypassEnabled,
+                areNotifsFullyHiddenAnimated(),
+                isPulseExpandingAnimated(),
+            ) {
+                onKeyguard: Boolean,
+                isBypassEnabled: Boolean,
+                notifsFullyHidden: AnimatedValue<Boolean>,
+                pulseExpanding: AnimatedValue<Boolean>,
+                ->
+                when {
+                    // Hide the AOD icons if we're not in the KEYGUARD state unless the screen off
+                    // animation is playing, in which case we want them to be visible if we're
+                    // animating in the AOD UI and will be switching to KEYGUARD shortly.
+                    !onKeyguard && !screenOffAnimationController.shouldShowAodIconsWhenShade() ->
+                        AnimatedValue.NotAnimating(false)
+                    else ->
+                        zip(notifsFullyHidden, pulseExpanding) {
+                            areNotifsFullyHidden,
+                            isPulseExpanding,
+                            ->
+                            when {
+                                // If we're bypassing, then we're visible
+                                isBypassEnabled -> true
+                                // If we are pulsing (and not bypassing), then we are hidden
+                                isPulseExpanding -> false
+                                // If notifs are fully gone, then we're visible
+                                areNotifsFullyHidden -> true
+                                // Otherwise, we're hidden
+                                else -> false
+                            }
+                        }
+                }
+            }
+            .distinctUntilChanged()
+
     /**
      * Puts this view-model in "preview mode", which means it's being used for UI that is rendering
      * the lock screen preview in wallpaper picker / settings and not the real experience on the
@@ -191,4 +252,39 @@
         keyguardInteractor.sharedNotificationContainerPosition.value =
             SharedNotificationContainerPosition(top, bottom)
     }
+
+    /** Is there an expanded pulse, are we animating in response? */
+    private fun isPulseExpandingAnimated(): Flow<AnimatedValue<Boolean>> {
+        return notificationsKeyguardInteractor.isPulseExpanding
+            .pairwise(initialValue = null)
+            // If pulsing changes, start animating, unless it's the first emission
+            .map { (prev, expanding) -> AnimatableEvent(expanding, startAnimating = prev != null) }
+            .toAnimatedValueFlow()
+    }
+
+    /** Are notifications completely hidden from view, are we animating in response? */
+    private fun areNotifsFullyHiddenAnimated(): Flow<AnimatedValue<Boolean>> {
+        return notificationsKeyguardInteractor.areNotificationsFullyHidden
+            .pairwise(initialValue = null)
+            .sample(deviceEntryInteractor.isBypassEnabled) { (prev, fullyHidden), bypassEnabled ->
+                val animate =
+                    when {
+                        // Don't animate for the first value
+                        prev == null -> false
+                        // Always animate if bypass is enabled.
+                        bypassEnabled -> true
+                        // If we're not bypassing and we're not going to AOD, then we're not
+                        // animating.
+                        !dozeParameters.alwaysOn -> false
+                        // Don't animate when going to AOD if the display needs blanking.
+                        dozeParameters.displayNeedsBlanking -> false
+                        // We only want the appear animations to happen when the notifications
+                        // get fully hidden, since otherwise the un-hide animation overlaps.
+                        featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION) -> true
+                        else -> fullyHidden
+                    }
+                AnimatableEvent(fullyHidden, animate)
+            }
+            .toAnimatedValueFlow()
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
index 2c3b431..a0f5baf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModel.kt
@@ -17,64 +17,137 @@
 package com.android.systemui.keyguard.ui.viewmodel
 
 import android.animation.ValueAnimator
+import android.content.Context
 import android.graphics.Point
 import androidx.core.animation.doOnEnd
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
+import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.biometrics.shared.model.isDefaultOrientation
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.flags.FeatureFlagsClassic
+import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
 import com.android.systemui.keyguard.shared.model.ErrorFingerprintAuthenticationStatus
 import com.android.systemui.keyguard.shared.model.FailFingerprintAuthenticationStatus
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
+import com.android.systemui.res.R
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onCompletion
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.launch
 
 @SysUISingleton
 class SideFpsProgressBarViewModel
 @Inject
 constructor(
+    private val context: Context,
     private val fpAuthRepository: DeviceEntryFingerprintAuthRepository,
     private val sfpsSensorInteractor: SideFpsSensorInteractor,
     displayStateInteractor: DisplayStateInteractor,
     @Application private val applicationScope: CoroutineScope,
+    private val featureFlagsClassic: FeatureFlagsClassic,
 ) {
     private val _progress = MutableStateFlow(0.0f)
     private val _visible = MutableStateFlow(false)
     private var _animator: ValueAnimator? = null
+    private var animatorJob: Job? = null
 
     private fun onFingerprintCaptureCompleted() {
         _visible.value = false
         _progress.value = 0.0f
     }
 
+    private val additionalSensorLengthPadding =
+        context.resources.getDimension(R.dimen.sfps_progress_bar_length_extra_padding).toInt()
+
     val isVisible: Flow<Boolean> = _visible.asStateFlow()
 
     val progress: Flow<Float> = _progress.asStateFlow()
 
-    val sensorWidth: Flow<Int> = sfpsSensorInteractor.sensorLocation.map { it.width }
+    val progressBarLength: Flow<Int> =
+        sfpsSensorInteractor.sensorLocation
+            .map { it.length + additionalSensorLengthPadding }
+            .distinctUntilChanged()
 
-    val sensorLocation: Flow<Point> =
-        sfpsSensorInteractor.sensorLocation.map { Point(it.left, it.top) }
+    val progressBarThickness =
+        context.resources.getDimension(R.dimen.sfps_progress_bar_thickness).toInt()
+
+    val progressBarLocation =
+        combine(displayStateInteractor.currentRotation, sfpsSensorInteractor.sensorLocation, ::Pair)
+            .map { (rotation, sensorLocation) ->
+                val paddingFromEdge =
+                    context.resources
+                        .getDimension(R.dimen.sfps_progress_bar_padding_from_edge)
+                        .toInt()
+                val lengthOfTheProgressBar = sensorLocation.length + additionalSensorLengthPadding
+                val viewLeftTop = Point(sensorLocation.left, sensorLocation.top)
+                val totalDistanceFromTheEdge = paddingFromEdge + progressBarThickness
+
+                val isSensorVerticalNow =
+                    sensorLocation.isSensorVerticalInDefaultOrientation ==
+                        rotation.isDefaultOrientation()
+                if (isSensorVerticalNow) {
+                    // Sensor is vertical to the current orientation, we rotate it 270 deg
+                    // around the (left,top) point as the pivot. We need to push it down the
+                    // length of the progress bar so that it is still aligned to the sensor
+                    viewLeftTop.y += lengthOfTheProgressBar
+                    val isSensorOnTheNearEdge =
+                        rotation == DisplayRotation.ROTATION_180 ||
+                            rotation == DisplayRotation.ROTATION_90
+                    if (isSensorOnTheNearEdge) {
+                        // Add just the padding from the edge to push the progress bar right
+                        viewLeftTop.x += paddingFromEdge
+                    } else {
+                        // View left top is pushed left from the edge by the progress bar thickness
+                        // and the padding.
+                        viewLeftTop.x -= totalDistanceFromTheEdge
+                    }
+                } else {
+                    // Sensor is horizontal to the current orientation.
+                    val isSensorOnTheNearEdge =
+                        rotation == DisplayRotation.ROTATION_0 ||
+                            rotation == DisplayRotation.ROTATION_90
+                    if (isSensorOnTheNearEdge) {
+                        // Add just the padding from the edge to push the progress bar down
+                        viewLeftTop.y += paddingFromEdge
+                    } else {
+                        // Sensor is now at the bottom edge of the device in the current rotation.
+                        // We want to push it up from the bottom edge by the padding and
+                        // the thickness of the progressbar.
+                        viewLeftTop.y -= totalDistanceFromTheEdge
+                        viewLeftTop.x -= additionalSensorLengthPadding
+                    }
+                }
+                viewLeftTop
+            }
 
     val isFingerprintAuthRunning: Flow<Boolean> = fpAuthRepository.isRunning
 
-    val shouldRotate90Degrees: Flow<Boolean> =
+    val rotation: Flow<Float> =
         combine(displayStateInteractor.currentRotation, sfpsSensorInteractor.sensorLocation, ::Pair)
             .map { (rotation, sensorLocation) ->
-                if (rotation.isDefaultOrientation()) {
-                    sensorLocation.isSensorVerticalInDefaultOrientation
+                if (
+                    rotation.isDefaultOrientation() ==
+                        sensorLocation.isSensorVerticalInDefaultOrientation
+                ) {
+                    // We should rotate the progress bar 270 degrees in the clockwise direction with
+                    // the left top point as the pivot so that it fills up from bottom to top
+                    270.0f
                 } else {
-                    !sensorLocation.isSensorVerticalInDefaultOrientation
+                    0.0f
                 }
             }
 
@@ -82,26 +155,32 @@
         sfpsSensorInteractor.isProlongedTouchRequiredForAuthentication
 
     init {
-        applicationScope.launch {
-            combine(
-                    sfpsSensorInteractor.isProlongedTouchRequiredForAuthentication,
-                    sfpsSensorInteractor.authenticationDuration,
-                    ::Pair
-                )
-                .collectLatest { (enabled, authDuration) ->
-                    if (!enabled) return@collectLatest
+        if (featureFlagsClassic.isEnabled(Flags.REST_TO_UNLOCK)) {
+            launchAnimator()
+        }
+    }
 
-                    launch {
-                        fpAuthRepository.authenticationStatus.collectLatest { authStatus ->
+    private fun launchAnimator() {
+        applicationScope.launch {
+            sfpsSensorInteractor.isProlongedTouchRequiredForAuthentication.collectLatest { enabled
+                ->
+                if (!enabled) {
+                    animatorJob?.cancel()
+                    return@collectLatest
+                }
+                animatorJob =
+                    fpAuthRepository.authenticationStatus
+                        .onEach { authStatus ->
                             when (authStatus) {
                                 is AcquiredFingerprintAuthenticationStatus -> {
                                     if (authStatus.fingerprintCaptureStarted) {
-
                                         _visible.value = true
                                         _animator?.cancel()
                                         _animator =
                                             ValueAnimator.ofFloat(0.0f, 1.0f)
-                                                .setDuration(authDuration)
+                                                .setDuration(
+                                                    sfpsSensorInteractor.authenticationDuration
+                                                )
                                                 .apply {
                                                     addUpdateListener {
                                                         _progress.value = it.animatedValue as Float
@@ -131,8 +210,9 @@
                                 else -> Unit
                             }
                         }
-                    }
-                }
+                        .onCompletion { _animator?.cancel() }
+                        .launchIn(applicationScope)
+            }
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/log/SideFpsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/SideFpsLogger.kt
new file mode 100644
index 0000000..919072a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/SideFpsLogger.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import android.graphics.Point
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.dagger.BouncerLog
+import javax.inject.Inject
+
+private const val TAG = "SideFpsLogger"
+
+/**
+ * Helper class for logging for SFPS related functionality
+ *
+ * To enable logcat echoing for an entire buffer:
+ * ```
+ *   adb shell settings put global systemui/buffer/BouncerLog <logLevel>
+ *
+ * ```
+ */
+@SysUISingleton
+class SideFpsLogger @Inject constructor(@BouncerLog private val buffer: LogBuffer) {
+    fun sfpsProgressBarStateChanged(
+        visible: Boolean,
+        location: Point,
+        fpDetectRunning: Boolean,
+        sensorWidth: Int,
+        rotation: Float,
+    ) {
+        buffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            {
+                bool1 = visible
+                int1 = location.x
+                int2 = location.y
+                str1 = "$rotation"
+                bool3 = fpDetectRunning
+                long1 = sensorWidth.toLong()
+            },
+            {
+                "SFPS progress bar state changed: visible: $bool1, " +
+                    "sensorLocation (x, y): ($int1, $int2), " +
+                    "rotation = $str1, " +
+                    "fpDetectRunning: $bool3, " +
+                    "sensorWidth: $long1"
+            }
+        )
+    }
+
+    fun hidingSfpsIndicator() {
+        buffer.log(TAG, LogLevel.DEBUG, "hiding SFPS indicator to show progress bar")
+    }
+
+    fun showingSfpsIndicator() {
+        buffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            "Requesting show SFPS indicator because progress bar " +
+                "is being hidden and FP detect is currently running"
+        )
+    }
+
+    fun isProlongedTouchRequiredForAuthenticationChanged(enabled: Boolean) {
+        buffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            { bool1 = enabled },
+            { "isProlongedTouchRequiredForAuthentication: $bool1" }
+        )
+    }
+
+    fun sensorLocationStateChanged(
+        pointOnScreenX: Int,
+        pointOnScreenY: Int,
+        sensorLength: Int,
+        isSensorVerticalInDefaultOrientation: Boolean
+    ) {
+        buffer.log(
+            TAG,
+            LogLevel.DEBUG,
+            {
+                int1 = pointOnScreenX
+                int2 = pointOnScreenY
+                str2 = "$sensorLength"
+                bool1 = isSensorVerticalInDefaultOrientation
+            },
+            {
+                "SideFpsSensorLocation state changed: " +
+                    "pointOnScreen: ($int1, $int2), " +
+                    "sensorLength: $str2, " +
+                    "sensorVerticalInDefaultOrientation: $bool1"
+            }
+        )
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
index 601aebe..3e8b49d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt
@@ -56,6 +56,7 @@
 import android.util.Log
 import android.util.Pair as APair
 import androidx.media.utils.MediaConstants
+import com.android.app.tracing.traceSection
 import com.android.internal.annotations.Keep
 import com.android.internal.logging.InstanceId
 import com.android.keyguard.KeyguardUpdateMonitor
@@ -86,7 +87,6 @@
 import com.android.systemui.statusbar.NotificationMediaManager.isConnectingState
 import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
 import com.android.systemui.statusbar.notification.row.HybridGroupManager
-import com.android.systemui.tracing.traceSection
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.util.Assert
 import com.android.systemui.util.Utils
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index d3bc61b..a252470 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -34,6 +34,7 @@
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.tracing.traceSection
 import com.android.internal.logging.InstanceId
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.keyguard.KeyguardUpdateMonitorCallback
@@ -66,7 +67,6 @@
 import com.android.systemui.statusbar.notification.collection.provider.OnReorderingAllowedListener
 import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider
 import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.tracing.traceSection
 import com.android.systemui.util.Utils
 import com.android.systemui.util.animation.UniqueObjectHostView
 import com.android.systemui.util.animation.requiresRemeasuring
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
index f3d41aa..b1ff708 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
@@ -34,8 +34,11 @@
 import android.view.ViewGroupOverlay
 import androidx.annotation.VisibleForTesting
 import com.android.app.animation.Interpolators
+import com.android.app.tracing.traceSection
 import com.android.keyguard.KeyguardViewController
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dreams.DreamOverlayStateController
 import com.android.systemui.keyguard.WakefulnessLifecycle
@@ -53,10 +56,11 @@
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.statusbar.policy.SplitShadeStateController
-import com.android.systemui.tracing.traceSection
 import com.android.systemui.util.animation.UniqueObjectHostView
 import com.android.systemui.util.settings.SecureSettings
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
 
 private val TAG: String = MediaHierarchyManager::class.java.simpleName
 
@@ -96,11 +100,13 @@
     private val mediaManager: MediaDataManager,
     private val keyguardViewController: KeyguardViewController,
     private val dreamOverlayStateController: DreamOverlayStateController,
+    private val communalInteractor: CommunalInteractor,
     configurationController: ConfigurationController,
     wakefulnessLifecycle: WakefulnessLifecycle,
     panelEventsEvents: ShadeStateEvents,
     private val secureSettings: SecureSettings,
     @Main private val handler: Handler,
+    @Application private val coroutineScope: CoroutineScope,
     private val splitShadeStateController: SplitShadeStateController,
     private val logger: MediaViewLogger,
 ) {
@@ -209,7 +215,7 @@
         else result.setIntersect(animationStartClipping, targetClipping)
     }
 
-    private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_DREAM_OVERLAY + 1)
+    private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_COMMUNAL_HUB + 1)
     /**
      * The last location where this view was at before going to the desired location. This is useful
      * for guided transitions.
@@ -401,6 +407,9 @@
             }
         }
 
+    /** Is the communal UI showing */
+    private var isCommunalShowing: Boolean = false
+
     /**
      * The current cross fade progress. 0.5f means it's just switching between the start and the end
      * location and the content is fully faded, while 0.75f means that we're halfway faded in again
@@ -563,6 +572,14 @@
             settingsObserver,
             UserHandle.USER_ALL
         )
+
+        // Listen to the communal UI state.
+        coroutineScope.launch {
+            communalInteractor.isCommunalShowing.collect { value ->
+                isCommunalShowing = value
+                updateDesiredLocation(forceNoAnimation = true)
+            }
+        }
     }
 
     private fun updateConfiguration() {
@@ -1115,6 +1132,9 @@
                 qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
                 onLockscreen && isSplitShadeExpanding() -> LOCATION_QS
                 onLockscreen && isTransformingToFullShadeAndInQQS() -> LOCATION_QQS
+                // TODO(b/308813166): revisit logic once interactions between the hub and
+                //  shade/keyguard state are finalized
+                isCommunalShowing && communalInteractor.isCommunalEnabled -> LOCATION_COMMUNAL_HUB
                 onLockscreen && allowMediaPlayerOnLockScreen -> LOCATION_LOCKSCREEN
                 else -> LOCATION_QQS
             }
@@ -1224,6 +1244,9 @@
         /** Attached on the dream overlay */
         const val LOCATION_DREAM_OVERLAY = 3
 
+        /** Attached to a view in the communal UI grid */
+        const val LOCATION_COMMUNAL_HUB = 4
+
         /** Attached at the root of the hierarchy in an overlay */
         const val IN_OVERLAY = -1000
 
@@ -1261,7 +1284,8 @@
             MediaHierarchyManager.LOCATION_QS,
             MediaHierarchyManager.LOCATION_QQS,
             MediaHierarchyManager.LOCATION_LOCKSCREEN,
-            MediaHierarchyManager.LOCATION_DREAM_OVERLAY
+            MediaHierarchyManager.LOCATION_DREAM_OVERLAY,
+            MediaHierarchyManager.LOCATION_COMMUNAL_HUB
         ]
 )
 @Retention(AnnotationRetention.SOURCE)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHostStatesManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHostStatesManager.kt
index 0129c49..1f711cf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHostStatesManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHostStatesManager.kt
@@ -16,8 +16,8 @@
 
 package com.android.systemui.media.controls.ui
 
+import com.android.app.tracing.traceSection
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.tracing.traceSection
 import com.android.systemui.util.animation.MeasurementOutput
 import javax.inject.Inject
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
index 6b82746..1ec43c5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
@@ -20,6 +20,7 @@
 import android.content.res.Configuration
 import androidx.annotation.VisibleForTesting
 import androidx.constraintlayout.widget.ConstraintSet
+import com.android.app.tracing.traceSection
 import com.android.systemui.media.controls.models.GutsViewHolder
 import com.android.systemui.media.controls.models.player.MediaViewHolder
 import com.android.systemui.media.controls.models.recommendation.RecommendationViewHolder
@@ -27,7 +28,6 @@
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.tracing.traceSection
 import com.android.systemui.util.animation.MeasurementOutput
 import com.android.systemui.util.animation.TransitionLayout
 import com.android.systemui.util.animation.TransitionLayoutController
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaUiEventLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaUiEventLogger.kt
index 20ea60f..16a703a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaUiEventLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaUiEventLogger.kt
@@ -20,11 +20,11 @@
 import com.android.internal.logging.InstanceIdSequence
 import com.android.internal.logging.UiEvent
 import com.android.internal.logging.UiEventLogger
-import com.android.systemui.res.R
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.ui.MediaHierarchyManager
 import com.android.systemui.media.controls.ui.MediaLocation
+import com.android.systemui.res.R
 import java.lang.IllegalArgumentException
 import javax.inject.Inject
 
@@ -154,6 +154,8 @@
                     MediaUiEvent.MEDIA_CAROUSEL_LOCATION_LOCKSCREEN
                 MediaHierarchyManager.LOCATION_DREAM_OVERLAY ->
                     MediaUiEvent.MEDIA_CAROUSEL_LOCATION_DREAM
+                MediaHierarchyManager.LOCATION_COMMUNAL_HUB ->
+                    MediaUiEvent.MEDIA_CAROUSEL_LOCATION_COMMUNAL
                 else -> throw IllegalArgumentException("Unknown media carousel location $location")
             }
         logger.log(event)
@@ -276,6 +278,8 @@
     MEDIA_CAROUSEL_LOCATION_LOCKSCREEN(1039),
     @UiEvent(doc = "The media carousel moved to the dream state")
     MEDIA_CAROUSEL_LOCATION_DREAM(1040),
+    @UiEvent(doc = "The media carousel moved to the communal hub UI")
+    MEDIA_CAROUSEL_LOCATION_COMMUNAL(1520),
     @UiEvent(doc = "A media recommendation card was added to the media carousel")
     MEDIA_RECOMMENDATION_ADDED(1041),
     @UiEvent(doc = "A media recommendation card was removed from the media carousel")
diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
index 888cd0b..8f752e5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
@@ -46,6 +46,7 @@
     String QUICK_QS_PANEL = "media_quick_qs_panel";
     String KEYGUARD = "media_keyguard";
     String DREAM = "dream";
+    String COMMUNAL_HUB = "communal_Hub";
 
     /** */
     @Provides
@@ -87,6 +88,16 @@
         return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
     }
 
+    /** */
+    @Provides
+    @SysUISingleton
+    @Named(COMMUNAL_HUB)
+    static MediaHost providesCommunalMediaHost(MediaHost.MediaHostStateHolder stateHolder,
+            MediaHierarchyManager hierarchyManager, MediaDataManager dataManager,
+            MediaHostStatesManager statesManager) {
+        return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
+    }
+
     /** Provides a logging buffer related to the media tap-to-transfer chip on the sender device. */
     @Provides
     @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerFactory.kt b/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerFactory.kt
index 97ec654..6e3b7b8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerFactory.kt
@@ -31,7 +31,7 @@
     private val logger: MediaMuteAwaitLogger,
     @Main private val mainExecutor: Executor
 ) {
-    private val deviceIconUtil = DeviceIconUtil()
+    private val deviceIconUtil = DeviceIconUtil(context)
 
     /** Creates a [MediaMuteAwaitConnectionManager]. */
     fun create(localMediaManager: LocalMediaManager): MediaMuteAwaitConnectionManager {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index ad1c77d..a985236 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -112,7 +112,6 @@
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.Gefingerpoken;
-import com.android.systemui.res.R;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.DisplayId;
@@ -130,6 +129,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.settings.UserContextProvider;
 import com.android.systemui.settings.UserTracker;
@@ -399,6 +399,11 @@
         }
 
         @Override
+        public void animateNavBarLongPress(boolean isTouchDown, long durationMs) {
+            mView.getHomeHandle().animateLongPress(isTouchDown, durationMs);
+        }
+
+        @Override
         public void onHomeRotationEnabled(boolean enabled) {
             mView.getRotationButtonController().setHomeRotationEnabled(enabled);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
index 10084bd..5fe830e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonDispatcher.java
@@ -247,6 +247,14 @@
         }
     }
 
+    public void animateLongPress(boolean isTouchDown, long durationMs) {
+        for (int i = 0; i < mViews.size(); i++) {
+            if (mViews.get(i) instanceof ButtonInterface) {
+                ((ButtonInterface) mViews.get(i)).animateLongPress(isTouchDown, durationMs);
+            }
+        }
+    }
+
     public void setLongClickable(boolean isLongClickable) {
         mLongClickable = isLongClickable;
         final int N = mViews.size();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
index 8d291dd..356b2f7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/ButtonInterface.java
@@ -30,4 +30,14 @@
     void setDarkIntensity(float intensity);
 
     void setDelayTouchFeedback(boolean shouldDelay);
+
+    /**
+     * Animate the button being long-pressed.
+     *
+     * @param isTouchDown {@code true} if the button is starting to be pressed ({@code false} if
+     *                                released or canceled)
+     * @param durationMs how long the animation should take (for the {@code isTouchDown} case, this
+     *                   should be the same as the amount of time to trigger a long-press)
+     */
+    default void animateLongPress(boolean isTouchDown, long durationMs) {}
 }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
index 5a22c38..5bfc7dc 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationHandle.java
@@ -17,6 +17,7 @@
 package com.android.systemui.navigationbar.gestural;
 
 import android.animation.ArgbEvaluator;
+import android.animation.ObjectAnimator;
 import android.annotation.ColorInt;
 import android.content.Context;
 import android.content.res.Resources;
@@ -24,12 +25,15 @@
 import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.util.FloatProperty;
 import android.view.ContextThemeWrapper;
 import android.view.View;
+import android.view.animation.Interpolator;
 
+import com.android.app.animation.Interpolators;
 import com.android.settingslib.Utils;
-import com.android.systemui.res.R;
 import com.android.systemui.navigationbar.buttons.ButtonInterface;
+import com.android.systemui.res.R;
 
 public class NavigationHandle extends View implements ButtonInterface {
 
@@ -38,8 +42,26 @@
     private @ColorInt final int mDarkColor;
     protected final float mRadius;
     protected final float mBottom;
+    private final float mAdditionalWidthForAnimation;
+    private final float mAdditionalHeightForAnimation;
     private boolean mRequiresInvalidate;
 
+    private ObjectAnimator mPulseAnimator = null;
+    private float mPulseAnimationProgress;
+
+    private static final FloatProperty<NavigationHandle> PULSE_ANIMATION_PROGRESS =
+            new FloatProperty<>("pulseAnimationProgress") {
+                @Override
+                public Float get(NavigationHandle controller) {
+                    return controller.getPulseAnimationProgress();
+                }
+
+                @Override
+                public void setValue(NavigationHandle controller, float progress) {
+                    controller.setPulseAnimationProgress(progress);
+                }
+            };
+
     public NavigationHandle(Context context) {
         this(context, null);
     }
@@ -49,6 +71,10 @@
         final Resources res = context.getResources();
         mRadius = res.getDimension(R.dimen.navigation_handle_radius);
         mBottom = res.getDimension(R.dimen.navigation_handle_bottom);
+        mAdditionalWidthForAnimation =
+                res.getDimension(R.dimen.navigation_home_handle_additional_width_for_animation);
+        mAdditionalHeightForAnimation =
+                res.getDimension(R.dimen.navigation_home_handle_additional_height_for_animation);
 
         final int dualToneDarkTheme = Utils.getThemeAttr(context, R.attr.darkIconTheme);
         final int dualToneLightTheme = Utils.getThemeAttr(context, R.attr.lightIconTheme);
@@ -75,23 +101,24 @@
 
         // Draw that bar
         int navHeight = getHeight();
-        float height = mRadius * 2;
-        int width = getWidth();
-        float y = (navHeight - mBottom - height);
-        canvas.drawRoundRect(0, y, width, y + height, mRadius, mRadius, mPaint);
+        float additionalHeight = mAdditionalHeightForAnimation * mPulseAnimationProgress;
+        float height = mRadius * 2 + additionalHeight;
+        float additionalWidth = mAdditionalWidthForAnimation * mPulseAnimationProgress;
+        float width = getWidth() + additionalWidth;
+        float x = -(additionalWidth / 2);
+        float y = navHeight - mBottom - height - (additionalHeight / 2);
+        float adjustedRadius = height / 2;
+        canvas.drawRoundRect(x, y, width, y + height, adjustedRadius, adjustedRadius, mPaint);
     }
 
     @Override
-    public void setImageDrawable(Drawable drawable) {
-    }
+    public void setImageDrawable(Drawable drawable) {}
 
     @Override
-    public void abortCurrentGesture() {
-    }
+    public void abortCurrentGesture() {}
 
     @Override
-    public void setVertical(boolean vertical) {
-    }
+    public void setVertical(boolean vertical) {}
 
     @Override
     public void setDarkIntensity(float intensity) {
@@ -108,6 +135,43 @@
     }
 
     @Override
-    public void setDelayTouchFeedback(boolean shouldDelay) {
+    public void setDelayTouchFeedback(boolean shouldDelay) {}
+
+    @Override
+    public void animateLongPress(boolean isTouchDown, long durationMs) {
+        if (mPulseAnimator != null) {
+            mPulseAnimator.cancel();
+        }
+
+        Interpolator interpolator;
+        if (isTouchDown) {
+            // For now we animate the navbar expanding and contracting so that the navbar is the
+            // original size by the end of {@code duration}. This is because a screenshot is taken
+            // at that point and we don't want to capture the larger navbar.
+            // TODO(b/306400785): Determine a way to exclude navbar from the screenshot.
+
+            // Fraction of the touch down animation to expand; remaining is used to contract again.
+            float expandFraction = 0.9f;
+            interpolator = t -> t <= expandFraction
+                        ? Interpolators.clampToProgress(Interpolators.LEGACY, t, 0, expandFraction)
+                        : 1 - Interpolators.clampToProgress(
+                                Interpolators.LINEAR, t, expandFraction, 1);
+        } else {
+            interpolator = Interpolators.LEGACY_DECELERATE;
+        }
+
+        mPulseAnimator =
+                ObjectAnimator.ofFloat(this, PULSE_ANIMATION_PROGRESS, isTouchDown ? 1 : 0);
+        mPulseAnimator.setDuration(durationMs).setInterpolator(interpolator);
+        mPulseAnimator.start();
+    }
+
+    private void setPulseAnimationProgress(float pulseAnimationProgress) {
+        mPulseAnimationProgress = pulseAnimationProgress;
+        invalidate();
+    }
+
+    private float getPulseAnimationProgress() {
+        return mPulseAnimationProgress;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/entity/CustomTileDefaults.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/entity/CustomTileDefaults.kt
new file mode 100644
index 0000000..dfeb65b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/entity/CustomTileDefaults.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom.data.entity
+
+import android.graphics.drawable.Icon
+
+sealed interface CustomTileDefaults {
+
+    data object Error : CustomTileDefaults
+    data class Result(
+        val icon: Icon,
+        val label: CharSequence,
+    ) : CustomTileDefaults
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileDefaultsRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileDefaultsRepository.kt
new file mode 100644
index 0000000..1546ec2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileDefaultsRepository.kt
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom.data.repository
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.PackageManager
+import android.content.pm.ServiceInfo
+import android.graphics.drawable.Icon
+import android.os.UserHandle
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.qs.tiles.impl.custom.data.entity.CustomTileDefaults
+import com.android.systemui.qs.tiles.impl.di.QSTileScope
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.BufferOverflow
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.withContext
+
+/** Gets a label and an icon for a custom tile based on its package. */
+interface CustomTileDefaultsRepository {
+
+    /**
+     * Returns [CustomTileDefaults] for a specified [user]. An updated value may be emitted as a
+     * response for [requestNewDefaults].
+     *
+     * @see requestNewDefaults
+     */
+    fun defaults(user: UserHandle): Flow<CustomTileDefaults>
+
+    /**
+     * Requests the new default from the [PackageManager]. The result is cached until the input of
+     * this method changes or [force] == true is passed.
+     *
+     * Listen to [defaults] to get the loaded result
+     */
+    fun requestNewDefaults(
+        user: UserHandle,
+        componentName: ComponentName,
+        force: Boolean = false,
+    )
+}
+
+@QSTileScope
+class CustomTileDefaultsRepositoryImpl
+@Inject
+constructor(
+    private val context: Context,
+    @Application applicationScope: CoroutineScope,
+    @Background private val backgroundDispatcher: CoroutineDispatcher,
+) : CustomTileDefaultsRepository {
+
+    private val defaultsRequests =
+        MutableSharedFlow<DefaultsRequest>(
+            replay = 1,
+            onBufferOverflow = BufferOverflow.DROP_OLDEST
+        )
+
+    private val defaults: SharedFlow<DefaultsResult> =
+        defaultsRequests
+            .distinctUntilChanged { old, new ->
+                if (new.force) {
+                    // force update should always pass
+                    false
+                } else {
+                    old == new
+                }
+            }
+            .map { DefaultsResult(it.user, loadDefaults(it.user, it.componentName)) }
+            .shareIn(applicationScope, SharingStarted.WhileSubscribed(), replay = 1)
+
+    override fun defaults(user: UserHandle): Flow<CustomTileDefaults> =
+        defaults.filter { it.user == user }.map { it.data }
+
+    override fun requestNewDefaults(
+        user: UserHandle,
+        componentName: ComponentName,
+        force: Boolean,
+    ) {
+        defaultsRequests.tryEmit(DefaultsRequest(user, componentName, force))
+    }
+
+    private suspend fun loadDefaults(
+        user: UserHandle,
+        componentName: ComponentName
+    ): CustomTileDefaults =
+        withContext(backgroundDispatcher) {
+            try {
+                val userContext = context.createContextAsUser(user, 0)
+                val info = componentName.getServiceInfo(userContext.packageManager)
+
+                val iconRes = if (info.icon == NO_ICON_RES) info.applicationInfo.icon else info.icon
+                if (iconRes == NO_ICON_RES) {
+                    return@withContext CustomTileDefaults.Error
+                }
+
+                CustomTileDefaults.Result(
+                    Icon.createWithResource(componentName.packageName, iconRes),
+                    info.loadLabel(userContext.packageManager)
+                )
+            } catch (e: PackageManager.NameNotFoundException) {
+                CustomTileDefaults.Error
+            }
+        }
+
+    private fun ComponentName.getServiceInfo(
+        packageManager: PackageManager,
+    ): ServiceInfo {
+        val isSystemApp = packageManager.getApplicationInfo(packageName, 0).isSystemApp
+        var flags =
+            (PackageManager.MATCH_DIRECT_BOOT_UNAWARE or PackageManager.MATCH_DIRECT_BOOT_AWARE)
+        if (isSystemApp) {
+            flags = flags or PackageManager.MATCH_DISABLED_COMPONENTS
+        }
+        return packageManager.getServiceInfo(this, flags)
+    }
+
+    private data class DefaultsRequest(
+        val user: UserHandle,
+        val componentName: ComponentName,
+        val force: Boolean = false,
+    )
+
+    private data class DefaultsResult(val user: UserHandle, val data: CustomTileDefaults)
+
+    private companion object {
+
+        const val NO_ICON_RES = 0
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt
new file mode 100644
index 0000000..6d7d88f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom.data.repository
+
+import android.os.UserHandle
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+import com.android.systemui.qs.external.TileServiceManager
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.qs.tiles.impl.custom.di.bound.CustomTileBoundScope
+import com.android.systemui.qs.tiles.impl.custom.di.bound.CustomTileUser
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.shareIn
+
+interface CustomTilePackageUpdatesRepository {
+
+    val packageChanges: Flow<Unit>
+}
+
+@CustomTileBoundScope
+class CustomTilePackageUpdatesRepositoryImpl
+@Inject
+constructor(
+    tileSpec: TileSpec.CustomTileSpec,
+    @CustomTileUser user: UserHandle,
+    serviceManager: TileServiceManager,
+    defaultsRepository: CustomTileDefaultsRepository,
+    @CustomTileBoundScope boundScope: CoroutineScope,
+) : CustomTilePackageUpdatesRepository {
+
+    override val packageChanges: Flow<Unit> =
+        ConflatedCallbackFlow.conflatedCallbackFlow {
+                serviceManager.setTileChangeListener { changedComponentName ->
+                    if (changedComponentName == tileSpec.componentName) {
+                        trySend(Unit)
+                    }
+                }
+
+                awaitClose { serviceManager.setTileChangeListener(null) }
+            }
+            .onEach { defaultsRepository.requestNewDefaults(user, tileSpec.componentName, true) }
+            .shareIn(boundScope, SharingStarted.WhileSubscribed())
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/CustomTileModule.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/CustomTileModule.kt
index ccff8af..482bf9b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/CustomTileModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/CustomTileModule.kt
@@ -23,6 +23,8 @@
 import com.android.systemui.qs.tiles.impl.custom.CustomTileInteractor
 import com.android.systemui.qs.tiles.impl.custom.CustomTileMapper
 import com.android.systemui.qs.tiles.impl.custom.CustomTileUserActionInteractor
+import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTileDefaultsRepository
+import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTileDefaultsRepositoryImpl
 import com.android.systemui.qs.tiles.impl.custom.di.bound.CustomTileBoundComponent
 import dagger.Binds
 import dagger.Module
@@ -43,4 +45,9 @@
 
     @Binds
     fun bindMapper(customTileMapper: CustomTileMapper): QSTileDataToStateMapper<CustomTileData>
+
+    @Binds
+    fun bindCustomTileDefaultsRepository(
+        impl: CustomTileDefaultsRepositoryImpl
+    ): CustomTileDefaultsRepository
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/bound/CustomTileBoundComponent.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/bound/CustomTileBoundComponent.kt
index e33b3e9..d382d20 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/bound/CustomTileBoundComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/bound/CustomTileBoundComponent.kt
@@ -23,7 +23,7 @@
 
 /** @see CustomTileBoundScope */
 @CustomTileBoundScope
-@Subcomponent
+@Subcomponent(modules = [CustomTileBoundModule::class])
 interface CustomTileBoundComponent {
 
     @Subcomponent.Builder
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/bound/CustomTileBoundModule.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/bound/CustomTileBoundModule.kt
new file mode 100644
index 0000000..889424a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/di/bound/CustomTileBoundModule.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom.di.bound
+
+import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTilePackageUpdatesRepository
+import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTilePackageUpdatesRepositoryImpl
+import dagger.Binds
+import dagger.Module
+
+@Module
+interface CustomTileBoundModule {
+
+    @Binds
+    fun bindCustomTilePackageUpdatesRepository(
+        impl: CustomTilePackageUpdatesRepositoryImpl
+    ): CustomTilePackageUpdatesRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 4465504..1334660 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -245,6 +245,12 @@
         }
 
         @Override
+        public void animateNavBarLongPress(boolean isTouchDown, long durationMs) {
+            verifyCallerAndClearCallingIdentityPostMain("animateNavBarLongPress", () ->
+                    notifyAnimateNavBarLongPress(isTouchDown, durationMs));
+        }
+
+        @Override
         public void onBackPressed() {
             verifyCallerAndClearCallingIdentityPostMain("onBackPressed", () -> {
                 sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
@@ -914,6 +920,12 @@
         }
     }
 
+    private void notifyAnimateNavBarLongPress(boolean isTouchDown, long durationMs) {
+        for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) {
+            mConnectionCallbacks.get(i).animateNavBarLongPress(isTouchDown, durationMs);
+        }
+    }
+
     public void notifyAssistantVisibilityChanged(float visibility) {
         try {
             if (mOverviewProxy != null) {
@@ -1058,6 +1070,7 @@
         default void onAssistantGestureCompletion(float velocity) {}
         default void startAssistant(Bundle bundle) {}
         default void setAssistantOverridesRequested(int[] invocationTypes) {}
+        default void animateNavBarLongPress(boolean isTouchDown, long durationMs) {}
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 7353379..b144003 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -26,9 +26,12 @@
 import com.android.systemui.scene.shared.model.SceneModel
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
@@ -105,6 +108,26 @@
                 initialValue = null,
             )
 
+    /**
+     * Whether user input is ongoing for the current transition. For example, if the user is swiping
+     * their finger to transition between scenes, this value will be true while their finger is on
+     * the screen, then false for the rest of the transition.
+     */
+    @OptIn(ExperimentalCoroutinesApi::class)
+    val isTransitionUserInputOngoing: StateFlow<Boolean> =
+        transitionState
+            .flatMapLatest {
+                when (it) {
+                    is ObservableTransitionState.Transition -> it.isUserInputOngoing
+                    is ObservableTransitionState.Idle -> flowOf(false)
+                }
+            }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false
+            )
+
     /** Whether the scene container is visible. */
     val isVisible: StateFlow<Boolean> = repository.isVisible
 
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
index 9ba02b1..49bceef 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt
@@ -17,8 +17,8 @@
 package com.android.systemui.scene.shared.flag
 
 import androidx.annotation.VisibleForTesting
-import com.android.systemui.FeatureFlags
 import com.android.systemui.Flags as AConfigFlags
+import com.android.systemui.Flags.sceneContainer
 import com.android.systemui.compose.ComposeFacade
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlagsClassic
@@ -50,7 +50,6 @@
 @AssistedInject
 constructor(
     private val featureFlagsClassic: FeatureFlagsClassic,
-    featureFlags: FeatureFlags,
     @Assisted private val isComposeAvailable: Boolean,
 ) : SceneContainerFlags {
 
@@ -72,7 +71,7 @@
         listOf(
             AconfigFlagMustBeEnabled(
                 flagName = AConfigFlags.FLAG_SCENE_CONTAINER,
-                flagValue = featureFlags.sceneContainer(),
+                flagValue = sceneContainer(),
             ),
         ) +
             classicFlagTokens.map { flagToken -> FlagMustBeEnabled(flagToken) } +
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/ObservableTransitionState.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/ObservableTransitionState.kt
index 3927873..f704894 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/ObservableTransitionState.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/ObservableTransitionState.kt
@@ -42,6 +42,13 @@
          * scene, this value will remain true after the pointer is no longer touching the screen and
          * will be true in any transition created to animate back to the original position.
          */
-        val isUserInputDriven: Boolean,
+        val isInitiatedByUserInput: Boolean,
+
+        /**
+         * Whether user input is currently driving the transition. For example, if a user is
+         * dragging a pointer, this emits true. Once they lift their finger, this emits false while
+         * the transition completes/settles.
+         */
+        val isUserInputOngoing: Flow<Boolean>,
     ) : ObservableTransitionState()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
index 1416c10..a950539 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
@@ -29,12 +29,12 @@
 import android.view.RemoteAnimationTarget
 import android.view.WindowManager
 import android.view.WindowManagerGlobal
+import com.android.app.tracing.TraceUtils.Companion.launch
 import com.android.internal.infra.ServiceConnector
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.settings.DisplayTracker
-import com.android.systemui.tracing.TraceUtils.Companion.launch
 import javax.inject.Inject
 import kotlinx.coroutines.CompletableDeferred
 import kotlinx.coroutines.CoroutineDispatcher
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
index 8b3548b..f56f416 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
@@ -20,7 +20,7 @@
 import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.tracing.TraceUtils.Companion.launch
+import com.android.app.tracing.TraceUtils.Companion.launch
 import kotlinx.coroutines.CoroutineScope
 import java.util.function.Consumer
 import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
index c6b2cf5..713ede6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
@@ -25,7 +25,7 @@
 import com.android.systemui.shade.ShadeExpansionStateManager
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
-import com.android.systemui.tracing.TraceUtils.Companion.launch
+import com.android.app.tracing.TraceUtils.Companion.launch
 import kotlinx.coroutines.withContext
 
 /** Provides state from the main SystemUI process on behalf of the Screenshot process. */
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt
index 385c813..38d00f7 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotSoundController.kt
@@ -18,9 +18,9 @@
 
 import android.media.MediaPlayer
 import android.util.Log
+import com.android.app.tracing.TraceUtils.Companion.async
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.tracing.TraceUtils.Companion.async
 import com.google.errorprone.annotations.CanIgnoreReturnValue
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.seconds
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
index ccac533..f6c25e0 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt
@@ -5,6 +5,7 @@
 import android.util.Log
 import android.view.Display
 import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE
+import com.android.app.tracing.TraceUtils.Companion.launch
 import com.android.internal.logging.UiEventLogger
 import com.android.internal.util.ScreenshotRequest
 import com.android.systemui.dagger.SysUISingleton
@@ -13,7 +14,6 @@
 import com.android.systemui.res.R
 import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_CAPTURE_FAILED
 import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback
-import com.android.systemui.tracing.TraceUtils.Companion.launch
 import java.util.function.Consumer
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index a2627ed..a2ca49d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -113,6 +113,7 @@
     private final SysUIKeyEventHandler mSysUIKeyEventHandler;
     private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
     private final AlternateBouncerInteractor mAlternateBouncerInteractor;
+    private final QuickSettingsController mQuickSettingsController;
     private GestureDetector mPulsingWakeupGestureHandler;
     private GestureDetector mDreamingWakeupGestureHandler;
     private View mBrightnessMirror;
@@ -188,6 +189,7 @@
             BouncerMessageInteractor bouncerMessageInteractor,
             BouncerLogger bouncerLogger,
             SysUIKeyEventHandler sysUIKeyEventHandler,
+            QuickSettingsController quickSettingsController,
             PrimaryBouncerInteractor primaryBouncerInteractor,
             AlternateBouncerInteractor alternateBouncerInteractor,
             SelectedUserInteractor selectedUserInteractor) {
@@ -220,6 +222,7 @@
         mSysUIKeyEventHandler = sysUIKeyEventHandler;
         mPrimaryBouncerInteractor = primaryBouncerInteractor;
         mAlternateBouncerInteractor = alternateBouncerInteractor;
+        mQuickSettingsController = quickSettingsController;
 
         // This view is not part of the newly inflated expanded status bar.
         mBrightnessMirror = mView.findViewById(R.id.brightness_mirror_container);
@@ -454,6 +457,16 @@
                         && !bouncerShowing
                         && !mStatusBarStateController.isDozing()) {
                     if (mDragDownHelper.isDragDownEnabled()) {
+                        if (mFeatureFlagsClassic.isEnabled(Flags.MIGRATE_NSSL)) {
+                            // When on lockscreen, if the touch originates at the top of the screen
+                            // go directly to QS and not the shade
+                            if (mQuickSettingsController.shouldQuickSettingsIntercept(
+                                    ev.getX(), ev.getY(), 0)) {
+                                mShadeLogger.d("NSWVC: QS intercepted");
+                                return true;
+                            }
+                        }
+
                         // This handles drag down over lockscreen
                         boolean result = mDragDownHelper.onInterceptTouchEvent(ev);
                         if (mFeatureFlagsClassic.isEnabled(Flags.MIGRATE_NSSL)) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index a4c4503..b2ffeb3 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -275,7 +275,7 @@
                 when (state) {
                     is ObservableTransitionState.Idle -> false
                     is ObservableTransitionState.Transition ->
-                        state.isUserInputDriven &&
+                        state.isInitiatedByUserInput &&
                             (state.toScene == sceneKey || state.fromScene == sceneKey)
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
index 84796f9..ed96482 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
@@ -17,19 +17,11 @@
 package com.android.systemui.statusbar.events
 
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.statusbar.window.StatusBarWindowController
-import com.android.systemui.util.concurrency.DelayableExecutor
-import com.android.systemui.util.time.SystemClock
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
-import kotlinx.coroutines.CoroutineScope
 
 @Module
 interface StatusBarEventsModule {
@@ -42,41 +34,11 @@
         fun provideSystemStatusAnimationSchedulerLogBuffer(factory: LogBufferFactory): LogBuffer {
             return factory.create("SystemStatusAnimationSchedulerLog", 60)
         }
-
-        @Provides
-        @SysUISingleton
-        fun provideSystemStatusAnimationScheduler(
-                featureFlags: FeatureFlags,
-                coordinator: SystemEventCoordinator,
-                chipAnimationController: SystemEventChipAnimationController,
-                statusBarWindowController: StatusBarWindowController,
-                dumpManager: DumpManager,
-                systemClock: SystemClock,
-                @Application coroutineScope: CoroutineScope,
-                @Main executor: DelayableExecutor,
-                logger: SystemStatusAnimationSchedulerLogger
-        ): SystemStatusAnimationScheduler {
-            return if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
-                SystemStatusAnimationSchedulerImpl(
-                        coordinator,
-                        chipAnimationController,
-                        statusBarWindowController,
-                        dumpManager,
-                        systemClock,
-                        coroutineScope,
-                        logger
-                )
-            } else {
-                SystemStatusAnimationSchedulerLegacyImpl(
-                        coordinator,
-                        chipAnimationController,
-                        statusBarWindowController,
-                        dumpManager,
-                        systemClock,
-                        executor
-                )
-            }
-        }
     }
-}
 
+    @Binds
+    @SysUISingleton
+    fun bindSystemStatusAnimationScheduler(
+        systemStatusAnimationSchedulerImpl: SystemStatusAnimationSchedulerImpl
+    ): SystemStatusAnimationScheduler
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
index 73c0bfe..fec1765 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
@@ -32,8 +32,6 @@
 import androidx.core.animation.ValueAnimator
 import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.res.R
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
 import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
 import com.android.systemui.statusbar.window.StatusBarWindowController
@@ -47,8 +45,7 @@
 class SystemEventChipAnimationController @Inject constructor(
     private val context: Context,
     private val statusBarWindowController: StatusBarWindowController,
-    private val contentInsetsProvider: StatusBarContentInsetsProvider,
-    private val featureFlags: FeatureFlags,
+    private val contentInsetsProvider: StatusBarContentInsetsProvider
 ) : SystemStatusAnimationCallback {
 
     private lateinit var animationWindowView: FrameLayout
@@ -317,15 +314,8 @@
                 it.marginEnd = marginEnd
             }
 
-    private fun initializeAnimRect() = if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
-        animRect.set(chipBounds)
-    } else {
-        animRect.set(
-                chipLeft,
-                currentAnimatedView!!.view.top,
-                chipRight,
-                currentAnimatedView!!.view.bottom)
-    }
+    private fun initializeAnimRect() = animRect.set(chipBounds)
+
 
     /**
      * To be called during an animation, sets the width and updates the current animated chip view
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
index e9d5dec..a73d517 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
@@ -24,8 +24,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
+import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State
 import com.android.systemui.privacy.PrivacyChipBuilder
 import com.android.systemui.privacy.PrivacyItem
 import com.android.systemui.privacy.PrivacyItemController
@@ -49,7 +48,6 @@
     private val batteryController: BatteryController,
     private val privacyController: PrivacyItemController,
     private val context: Context,
-    private val featureFlags: FeatureFlags,
     @Application private val appScope: CoroutineScope,
     connectedDisplayInteractor: ConnectedDisplayInteractor
 ) {
@@ -76,9 +74,7 @@
     }
 
     fun notifyPluggedIn(@IntRange(from = 0, to = 100) batteryLevel: Int) {
-        if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
-            scheduler.onStatusEvent(BatteryEvent(batteryLevel))
-        }
+        scheduler.onStatusEvent(BatteryEvent(batteryLevel))
     }
 
     fun notifyPrivacyItemsEmpty() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
deleted file mode 100644
index 6b5a548..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.events
-
-import android.os.Process
-import android.provider.DeviceConfig
-import android.util.Log
-import androidx.core.animation.Animator
-import androidx.core.animation.AnimatorListenerAdapter
-import androidx.core.animation.AnimatorSet
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.window.StatusBarWindowController
-import com.android.systemui.util.Assert
-import com.android.systemui.util.concurrency.DelayableExecutor
-import com.android.systemui.util.time.SystemClock
-import java.io.PrintWriter
-import javax.inject.Inject
-
-/**
- * Dead-simple scheduler for system status events. Obeys the following principles (all values TBD):
- * ```
- *      - Avoiding log spam by only allowing 12 events per minute (1event/5s)
- *      - Waits 100ms to schedule any event for debouncing/prioritization
- *      - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent])
- *      - Only schedules a single event, and throws away lowest priority events
- * ```
- *
- * There are 4 basic stages of animation at play here:
- * ```
- *      1. System chrome animation OUT
- *      2. Chip animation IN
- *      3. Chip animation OUT; potentially into a dot
- *      4. System chrome animation IN
- * ```
- *
- * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
- * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
- * their respective views based on the progress of the animator. Interpolation differences TBD
- */
-open class SystemStatusAnimationSchedulerLegacyImpl
-@Inject
-constructor(
-    private val coordinator: SystemEventCoordinator,
-    private val chipAnimationController: SystemEventChipAnimationController,
-    private val statusBarWindowController: StatusBarWindowController,
-    private val dumpManager: DumpManager,
-    private val systemClock: SystemClock,
-    @Main private val executor: DelayableExecutor
-) : SystemStatusAnimationScheduler {
-
-    companion object {
-        private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator"
-    }
-
-    fun isImmersiveIndicatorEnabled(): Boolean {
-        return DeviceConfig.getBoolean(
-            DeviceConfig.NAMESPACE_PRIVACY,
-            PROPERTY_ENABLE_IMMERSIVE_INDICATOR,
-            true
-        )
-    }
-
-    @SystemAnimationState private var animationState: Int = IDLE
-
-    /** True if the persistent privacy dot should be active */
-    var hasPersistentDot = false
-        protected set
-
-    private var scheduledEvent: StatusEvent? = null
-
-    val listeners = mutableSetOf<SystemStatusAnimationCallback>()
-
-    init {
-        coordinator.attachScheduler(this)
-        dumpManager.registerDumpable(TAG, this)
-    }
-
-    @SystemAnimationState override fun getAnimationState() = animationState
-
-    override fun onStatusEvent(event: StatusEvent) {
-        // Ignore any updates until the system is up and running. However, for important events that
-        // request to be force visible (like privacy), ignore whether it's too early.
-        if ((isTooEarly() && !event.forceVisible) || !isImmersiveIndicatorEnabled()) {
-            return
-        }
-
-        // Don't deal with threading for now (no need let's be honest)
-        Assert.isMainThread()
-        if (
-            (event.priority > (scheduledEvent?.priority ?: -1)) &&
-                animationState != ANIMATING_OUT &&
-                animationState != SHOWING_PERSISTENT_DOT
-        ) {
-            // events can only be scheduled if a higher priority or no other event is in progress
-            if (DEBUG) {
-                Log.d(TAG, "scheduling event $event")
-            }
-
-            scheduleEvent(event)
-        } else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
-            if (DEBUG) {
-                Log.d(TAG, "updating current event from: $event. animationState=$animationState")
-            }
-            scheduledEvent?.updateFromEvent(event)
-            if (event.forceVisible) {
-                hasPersistentDot = true
-                // If we missed the chance to show the persistent dot, do it now
-                if (animationState == IDLE) {
-                    notifyTransitionToPersistentDot()
-                }
-            }
-        } else {
-            if (DEBUG) {
-                Log.d(TAG, "ignoring event $event")
-            }
-        }
-    }
-
-    override fun removePersistentDot() {
-        if (!hasPersistentDot || !isImmersiveIndicatorEnabled()) {
-            return
-        }
-
-        hasPersistentDot = false
-        notifyHidePersistentDot()
-        return
-    }
-
-    fun isTooEarly(): Boolean {
-        return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME
-    }
-
-    /** Clear the scheduled event (if any) and schedule a new one */
-    private fun scheduleEvent(event: StatusEvent) {
-        scheduledEvent = event
-
-        if (event.forceVisible) {
-            hasPersistentDot = true
-        }
-
-        // If animations are turned off, we'll transition directly to the dot
-        if (!event.showAnimation && event.forceVisible) {
-            notifyTransitionToPersistentDot()
-            scheduledEvent = null
-            return
-        }
-
-        chipAnimationController.prepareChipAnimation(scheduledEvent!!.viewCreator)
-        animationState = ANIMATION_QUEUED
-        executor.executeDelayed({ runChipAnimation() }, DEBOUNCE_DELAY)
-    }
-
-    /**
-     * 1. Define a total budget for the chip animation (1500ms)
-     * 2. Send out callbacks to listeners so that they can generate animations locally
-     * 3. Update the scheduler state so that clients know where we are
-     * 4. Maybe: provide scaffolding such as: dot location, margins, etc
-     * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
-     *    collect all of the animators and run them together.
-     */
-    private fun runChipAnimation() {
-        statusBarWindowController.setForceStatusBarVisible(true)
-        animationState = ANIMATING_IN
-
-        val animSet = collectStartAnimations()
-        if (animSet.totalDuration > 500) {
-            throw IllegalStateException(
-                "System animation total length exceeds budget. " +
-                    "Expected: 500, actual: ${animSet.totalDuration}"
-            )
-        }
-        animSet.addListener(
-            object : AnimatorListenerAdapter() {
-                override fun onAnimationEnd(animation: Animator) {
-                    animationState = RUNNING_CHIP_ANIM
-                }
-            }
-        )
-        animSet.start()
-
-        executor.executeDelayed(
-            {
-                val animSet2 = collectFinishAnimations()
-                animationState = ANIMATING_OUT
-                animSet2.addListener(
-                    object : AnimatorListenerAdapter() {
-                        override fun onAnimationEnd(animation: Animator) {
-                            animationState =
-                                if (hasPersistentDot) {
-                                    SHOWING_PERSISTENT_DOT
-                                } else {
-                                    IDLE
-                                }
-
-                            statusBarWindowController.setForceStatusBarVisible(false)
-                        }
-                    }
-                )
-                animSet2.start()
-                scheduledEvent = null
-            },
-            DISPLAY_LENGTH
-        )
-    }
-
-    private fun collectStartAnimations(): AnimatorSet {
-        val animators = mutableListOf<Animator>()
-        listeners.forEach { listener ->
-            listener.onSystemEventAnimationBegin()?.let { anim -> animators.add(anim) }
-        }
-        animators.add(chipAnimationController.onSystemEventAnimationBegin())
-        val animSet = AnimatorSet().also { it.playTogether(animators) }
-
-        return animSet
-    }
-
-    private fun collectFinishAnimations(): AnimatorSet {
-        val animators = mutableListOf<Animator>()
-        listeners.forEach { listener ->
-            listener.onSystemEventAnimationFinish(hasPersistentDot)?.let { anim ->
-                animators.add(anim)
-            }
-        }
-        animators.add(chipAnimationController.onSystemEventAnimationFinish(hasPersistentDot))
-        if (hasPersistentDot) {
-            val dotAnim = notifyTransitionToPersistentDot()
-            if (dotAnim != null) {
-                animators.add(dotAnim)
-            }
-        }
-        val animSet = AnimatorSet().also { it.playTogether(animators) }
-
-        return animSet
-    }
-
-    private fun notifyTransitionToPersistentDot(): Animator? {
-        val anims: List<Animator> =
-            listeners.mapNotNull {
-                it.onSystemStatusAnimationTransitionToPersistentDot(
-                    scheduledEvent?.contentDescription
-                )
-            }
-        if (anims.isNotEmpty()) {
-            val aSet = AnimatorSet()
-            aSet.playTogether(anims)
-            return aSet
-        }
-
-        return null
-    }
-
-    private fun notifyHidePersistentDot(): Animator? {
-        val anims: List<Animator> = listeners.mapNotNull { it.onHidePersistentDot() }
-
-        if (animationState == SHOWING_PERSISTENT_DOT) {
-            animationState = IDLE
-        }
-
-        if (anims.isNotEmpty()) {
-            val aSet = AnimatorSet()
-            aSet.playTogether(anims)
-            return aSet
-        }
-
-        return null
-    }
-
-    override fun addCallback(listener: SystemStatusAnimationCallback) {
-        Assert.isMainThread()
-
-        if (listeners.isEmpty()) {
-            coordinator.startObserving()
-        }
-        listeners.add(listener)
-    }
-
-    override fun removeCallback(listener: SystemStatusAnimationCallback) {
-        Assert.isMainThread()
-
-        listeners.remove(listener)
-        if (listeners.isEmpty()) {
-            coordinator.stopObserving()
-        }
-    }
-
-    override fun dump(pw: PrintWriter, args: Array<out String>) {
-        pw.println("Scheduled event: $scheduledEvent")
-        pw.println("Has persistent privacy dot: $hasPersistentDot")
-        pw.println("Animation state: $animationState")
-        pw.println("Listeners:")
-        if (listeners.isEmpty()) {
-            pw.println("(none)")
-        } else {
-            listeners.forEach { pw.println("  $it") }
-        }
-    }
-}
-
-private const val DEBUG = false
-private const val TAG = "SystemStatusAnimationSchedulerLegacyImpl"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt
index b2bdb72..a1a2ba4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt
@@ -21,7 +21,7 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.util.Assert
 import com.android.systemui.util.ListenerSet
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import java.util.Collections.unmodifiableList
 import java.util.concurrent.Executor
 import java.util.concurrent.atomic.AtomicReference
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
index 860697b..64970e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -26,7 +26,7 @@
 import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
 import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import javax.inject.Inject
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
index e8afac5..3809ea0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
@@ -28,7 +28,7 @@
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.Compile
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import javax.inject.Inject
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
index 1f6f42d..1dd6242 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
@@ -23,7 +23,7 @@
 import com.android.systemui.statusbar.notification.collection.NotifCollection
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.util.NamedListenerSet
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 
 /**
  * Set of classes that represent the various events that [NotifCollection] can dispatch to
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
index ca8e4fe..9fc4e40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
@@ -23,7 +23,7 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
 import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
 import com.android.systemui.util.Compile
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 
 /**
  * Converts a notif list (the output of the ShadeListBuilder) into a NodeSpec, an abstract
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
index c2791a0..9b55210 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
@@ -26,7 +26,7 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import javax.inject.Inject
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
index c6d8500..61e6f65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
@@ -18,7 +18,7 @@
 
 import android.annotation.MainThread
 import android.view.View
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 
 /**
  * Given a "spec" that describes a "tree" of views, adds and removes views from the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
index 2c59ee8..1935866 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
@@ -26,7 +26,7 @@
 import com.android.systemui.statusbar.notification.collection.PipelineDumper
 import com.android.systemui.statusbar.notification.collection.provider.SectionHeaderVisibilityProvider
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
index 8064f04..12ee54d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/data/repository/ActiveNotificationListRepository.kt
@@ -16,6 +16,9 @@
 package com.android.systemui.statusbar.notification.data.repository
 
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore.Key
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationEntryModel
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel
 import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
 import javax.inject.Inject
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -29,13 +32,64 @@
  */
 @SysUISingleton
 class ActiveNotificationListRepository @Inject constructor() {
-    /**
-     * Notifications actively presented to the user in the notification stack.
-     *
-     * @see com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
-     */
-    val activeNotifications = MutableStateFlow(emptyMap<String, ActiveNotificationModel>())
+    /** Notifications actively presented to the user in the notification list. */
+    val activeNotifications = MutableStateFlow(ActiveNotificationsStore())
 
     /** Are any already-seen notifications currently filtered out of the active list? */
     val hasFilteredOutSeenNotifications = MutableStateFlow(false)
 }
+
+/** Represents the notification list, comprised of groups and individual notifications. */
+data class ActiveNotificationsStore(
+    /** Notification groups, stored by key. */
+    val groups: Map<String, ActiveNotificationGroupModel> = emptyMap(),
+    /** All individual notifications, including top-level and group children, stored by key. */
+    val individuals: Map<String, ActiveNotificationModel> = emptyMap(),
+    /**
+     * Ordered top-level list of entries in the notification list (either groups or individual),
+     * represented as [Key]s. The associated [ActiveNotificationEntryModel] can be retrieved by
+     * invoking [get].
+     */
+    val renderList: List<Key> = emptyList(),
+) {
+    operator fun get(key: Key): ActiveNotificationEntryModel? {
+        return when (key) {
+            is Key.Group -> groups[key.key]
+            is Key.Individual -> individuals[key.key]
+        }
+    }
+
+    /** Unique key identifying an [ActiveNotificationEntryModel] in the store. */
+    sealed class Key {
+        data class Individual(val key: String) : Key()
+        data class Group(val key: String) : Key()
+    }
+
+    /** Mutable builder for an [ActiveNotificationsStore]. */
+    class Builder {
+        private val groups = mutableMapOf<String, ActiveNotificationGroupModel>()
+        private val individuals = mutableMapOf<String, ActiveNotificationModel>()
+        private val renderList = mutableListOf<Key>()
+
+        fun build() = ActiveNotificationsStore(groups, individuals, renderList)
+
+        fun addEntry(entry: ActiveNotificationEntryModel) {
+            when (entry) {
+                is ActiveNotificationModel -> addIndividualNotif(entry)
+                is ActiveNotificationGroupModel -> addNotifGroup(entry)
+            }
+        }
+
+        fun addIndividualNotif(notif: ActiveNotificationModel) {
+            renderList.add(Key.Individual(notif.key))
+            individuals[notif.key] = notif
+        }
+
+        fun addNotifGroup(group: ActiveNotificationGroupModel) {
+            renderList.add(Key.Group(group.key))
+            groups[group.key] = group
+            individuals[group.summary.key] = group.summary
+            group.children.forEach { individuals[it.key] = it }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
index bfec60bc..85ba205 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/ActiveNotificationsInteractor.kt
@@ -16,6 +16,7 @@
 package com.android.systemui.statusbar.notification.domain.interactor
 
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel
 import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
@@ -27,6 +28,16 @@
     repository: ActiveNotificationListRepository,
 ) {
     /** Notifications actively presented to the user in the notification stack, in order. */
-    val notifications: Flow<Collection<ActiveNotificationModel>> =
-        repository.activeNotifications.map { it.values }
+    val topLevelRepresentativeNotifications: Flow<List<ActiveNotificationModel>> =
+        repository.activeNotifications.map { store ->
+            store.renderList.map { key ->
+                val entry =
+                    store[key]
+                        ?: error("Could not find notification with key $key in active notif store.")
+                when (entry) {
+                    is ActiveNotificationGroupModel -> entry.summary
+                    is ActiveNotificationModel -> entry
+                }
+            }
+        }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt
index 604ecbc..6f4ed9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt
@@ -16,15 +16,18 @@
 package com.android.systemui.statusbar.notification.domain.interactor
 
 import android.graphics.drawable.Icon
+import com.android.systemui.statusbar.notification.collection.GroupEntry
 import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationEntryModel
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationGroupModel
 import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
 import javax.inject.Inject
 import kotlinx.coroutines.flow.update
 
-private typealias ModelStore = Map<String, ActiveNotificationModel>
-
 /**
  * Logic for passing information from the
  * [com.android.systemui.statusbar.notification.collection.NotifPipeline] to the presentation
@@ -37,106 +40,166 @@
     private val sectionStyleProvider: SectionStyleProvider,
 ) {
     /**
-     * Sets the current list of rendered notification entries as displayed in the notification
-     * stack.
-     *
-     * @see com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository.activeNotifications
+     * Sets the current list of rendered notification entries as displayed in the notification list.
      */
     fun setRenderedList(entries: List<ListEntry>) {
         repository.activeNotifications.update { existingModels ->
-            entries.associateBy(
-                keySelector = { it.key },
-                valueTransform = { it.toModel(existingModels) },
-            )
+            buildActiveNotificationsStore(existingModels, sectionStyleProvider) {
+                entries.forEach(::addListEntry)
+            }
+        }
+    }
+}
+
+private fun buildActiveNotificationsStore(
+    existingModels: ActiveNotificationsStore,
+    sectionStyleProvider: SectionStyleProvider,
+    block: ActiveNotificationsStoreBuilder.() -> Unit
+): ActiveNotificationsStore =
+    ActiveNotificationsStoreBuilder(existingModels, sectionStyleProvider).apply(block).build()
+
+private class ActiveNotificationsStoreBuilder(
+    private val existingModels: ActiveNotificationsStore,
+    private val sectionStyleProvider: SectionStyleProvider,
+) {
+    private val builder = ActiveNotificationsStore.Builder()
+
+    fun build(): ActiveNotificationsStore = builder.build()
+
+    /**
+     * Convert a [ListEntry] into [ActiveNotificationEntryModel]s, and add them to the
+     * [ActiveNotificationsStore]. Special care is taken to avoid re-allocating models if the result
+     * would be identical to an existing model (at the expense of additional computations).
+     */
+    fun addListEntry(entry: ListEntry) {
+        when (entry) {
+            is GroupEntry -> {
+                entry.summary?.let { summary ->
+                    val summaryModel = summary.toModel()
+                    val childModels = entry.children.map { it.toModel() }
+                    builder.addNotifGroup(
+                        existingModels.createOrReuse(
+                            key = entry.key,
+                            summary = summaryModel,
+                            children = childModels
+                        )
+                    )
+                }
+            }
+            else -> {
+                entry.representativeEntry?.let { notifEntry ->
+                    builder.addIndividualNotif(notifEntry.toModel())
+                }
+            }
         }
     }
 
-    private fun ListEntry.toModel(
-        existingModels: ModelStore,
-    ): ActiveNotificationModel =
+    private fun NotificationEntry.toModel(): ActiveNotificationModel =
         existingModels.createOrReuse(
             key = key,
-            groupKey = representativeEntry?.sbn?.groupKey,
+            groupKey = sbn.groupKey,
             isAmbient = sectionStyleProvider.isMinimized(this),
-            isRowDismissed = representativeEntry?.isRowDismissed == true,
+            isRowDismissed = isRowDismissed,
             isSilent = sectionStyleProvider.isSilent(this),
-            isLastMessageFromReply = representativeEntry?.isLastMessageFromReply == true,
-            isSuppressedFromStatusBar = representativeEntry?.shouldSuppressStatusBar() == true,
-            isPulsing = representativeEntry?.showingPulsing() == true,
-            aodIcon = representativeEntry?.icons?.aodIcon?.sourceIcon,
-            shelfIcon = representativeEntry?.icons?.shelfIcon?.sourceIcon,
-            statusBarIcon = representativeEntry?.icons?.statusBarIcon?.sourceIcon,
+            isLastMessageFromReply = isLastMessageFromReply,
+            isSuppressedFromStatusBar = shouldSuppressStatusBar(),
+            isPulsing = showingPulsing(),
+            aodIcon = icons.aodIcon?.sourceIcon,
+            shelfIcon = icons.shelfIcon?.sourceIcon,
+            statusBarIcon = icons.statusBarIcon?.sourceIcon,
         )
+}
 
-    private fun ModelStore.createOrReuse(
-        key: String,
-        groupKey: String?,
-        isAmbient: Boolean,
-        isRowDismissed: Boolean,
-        isSilent: Boolean,
-        isLastMessageFromReply: Boolean,
-        isSuppressedFromStatusBar: Boolean,
-        isPulsing: Boolean,
-        aodIcon: Icon?,
-        shelfIcon: Icon?,
-        statusBarIcon: Icon?
-    ): ActiveNotificationModel {
-        return this[key]?.takeIf {
-            it.isCurrent(
-                key = key,
-                groupKey = groupKey,
-                isAmbient = isAmbient,
-                isRowDismissed = isRowDismissed,
-                isSilent = isSilent,
-                isLastMessageFromReply = isLastMessageFromReply,
-                isSuppressedFromStatusBar = isSuppressedFromStatusBar,
-                isPulsing = isPulsing,
-                aodIcon = aodIcon,
-                shelfIcon = shelfIcon,
-                statusBarIcon = statusBarIcon
-            )
-        }
-            ?: ActiveNotificationModel(
-                key = key,
-                groupKey = groupKey,
-                isAmbient = isAmbient,
-                isRowDismissed = isRowDismissed,
-                isSilent = isSilent,
-                isLastMessageFromReply = isLastMessageFromReply,
-                isSuppressedFromStatusBar = isSuppressedFromStatusBar,
-                isPulsing = isPulsing,
-                aodIcon = aodIcon,
-                shelfIcon = shelfIcon,
-                statusBarIcon = statusBarIcon,
-            )
+private fun ActiveNotificationsStore.createOrReuse(
+    key: String,
+    groupKey: String?,
+    isAmbient: Boolean,
+    isRowDismissed: Boolean,
+    isSilent: Boolean,
+    isLastMessageFromReply: Boolean,
+    isSuppressedFromStatusBar: Boolean,
+    isPulsing: Boolean,
+    aodIcon: Icon?,
+    shelfIcon: Icon?,
+    statusBarIcon: Icon?
+): ActiveNotificationModel {
+    return individuals[key]?.takeIf {
+        it.isCurrent(
+            key = key,
+            groupKey = groupKey,
+            isAmbient = isAmbient,
+            isRowDismissed = isRowDismissed,
+            isSilent = isSilent,
+            isLastMessageFromReply = isLastMessageFromReply,
+            isSuppressedFromStatusBar = isSuppressedFromStatusBar,
+            isPulsing = isPulsing,
+            aodIcon = aodIcon,
+            shelfIcon = shelfIcon,
+            statusBarIcon = statusBarIcon
+        )
     }
+        ?: ActiveNotificationModel(
+            key = key,
+            groupKey = groupKey,
+            isAmbient = isAmbient,
+            isRowDismissed = isRowDismissed,
+            isSilent = isSilent,
+            isLastMessageFromReply = isLastMessageFromReply,
+            isSuppressedFromStatusBar = isSuppressedFromStatusBar,
+            isPulsing = isPulsing,
+            aodIcon = aodIcon,
+            shelfIcon = shelfIcon,
+            statusBarIcon = statusBarIcon,
+        )
+}
 
-    private fun ActiveNotificationModel.isCurrent(
-        key: String,
-        groupKey: String?,
-        isAmbient: Boolean,
-        isRowDismissed: Boolean,
-        isSilent: Boolean,
-        isLastMessageFromReply: Boolean,
-        isSuppressedFromStatusBar: Boolean,
-        isPulsing: Boolean,
-        aodIcon: Icon?,
-        shelfIcon: Icon?,
-        statusBarIcon: Icon?
-    ): Boolean {
-        return when {
-            key != this.key -> false
-            groupKey != this.groupKey -> false
-            isAmbient != this.isAmbient -> false
-            isRowDismissed != this.isRowDismissed -> false
-            isSilent != this.isSilent -> false
-            isLastMessageFromReply != this.isLastMessageFromReply -> false
-            isSuppressedFromStatusBar != this.isSuppressedFromStatusBar -> false
-            isPulsing != this.isPulsing -> false
-            aodIcon != this.aodIcon -> false
-            shelfIcon != this.shelfIcon -> false
-            statusBarIcon != this.statusBarIcon -> false
-            else -> true
-        }
+private fun ActiveNotificationModel.isCurrent(
+    key: String,
+    groupKey: String?,
+    isAmbient: Boolean,
+    isRowDismissed: Boolean,
+    isSilent: Boolean,
+    isLastMessageFromReply: Boolean,
+    isSuppressedFromStatusBar: Boolean,
+    isPulsing: Boolean,
+    aodIcon: Icon?,
+    shelfIcon: Icon?,
+    statusBarIcon: Icon?
+): Boolean {
+    return when {
+        key != this.key -> false
+        groupKey != this.groupKey -> false
+        isAmbient != this.isAmbient -> false
+        isRowDismissed != this.isRowDismissed -> false
+        isSilent != this.isSilent -> false
+        isLastMessageFromReply != this.isLastMessageFromReply -> false
+        isSuppressedFromStatusBar != this.isSuppressedFromStatusBar -> false
+        isPulsing != this.isPulsing -> false
+        aodIcon != this.aodIcon -> false
+        shelfIcon != this.shelfIcon -> false
+        statusBarIcon != this.statusBarIcon -> false
+        else -> true
+    }
+}
+
+private fun ActiveNotificationsStore.createOrReuse(
+    key: String,
+    summary: ActiveNotificationModel,
+    children: List<ActiveNotificationModel>,
+): ActiveNotificationGroupModel {
+    return groups[key]?.takeIf { it.isCurrent(key, summary, children) }
+        ?: ActiveNotificationGroupModel(key, summary, children)
+}
+
+private fun ActiveNotificationGroupModel.isCurrent(
+    key: String,
+    summary: ActiveNotificationModel,
+    children: List<ActiveNotificationModel>,
+): Boolean {
+    return when {
+        key != this.key -> false
+        summary != this.summary -> false
+        children != this.children -> false
+        else -> true
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
index 05c88e0..9e8654a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
@@ -34,7 +34,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import javax.inject.Inject
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt
index 00d873e..30e2f0e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractor.kt
@@ -48,7 +48,7 @@
         showPulsing: Boolean = true,
     ): Flow<Set<ActiveNotificationModel>> {
         return combine(
-            activeNotificationsInteractor.notifications,
+            activeNotificationsInteractor.topLevelRepresentativeNotifications,
             keyguardViewStateRepository.areNotificationsFullyHidden,
         ) { notifications, notifsFullyHidden ->
             notifications
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
index c1f728a..db0fa99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/NotificationIconContainerViewBinder.kt
@@ -15,26 +15,19 @@
  */
 package com.android.systemui.statusbar.notification.icon.ui.viewbinder
 
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
 import android.graphics.Color
 import android.graphics.Rect
 import android.view.View
 import android.view.ViewGroup
-import android.view.ViewPropertyAnimator
 import android.widget.FrameLayout
 import androidx.annotation.ColorInt
 import androidx.collection.ArrayMap
 import androidx.lifecycle.lifecycleScope
-import com.android.app.animation.Interpolators
 import com.android.internal.policy.SystemBarUtils
 import com.android.internal.util.ContrastColorUtil
 import com.android.systemui.common.ui.ConfigurationState
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.res.R
-import com.android.systemui.statusbar.CrossFadeHelper
 import com.android.systemui.statusbar.StatusBarIconView
 import com.android.systemui.statusbar.notification.NotificationUtils
 import com.android.systemui.statusbar.notification.collection.NotifCollection
@@ -47,7 +40,6 @@
 import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconsViewData
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.NotificationIconContainer
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.onConfigChanged
 import com.android.systemui.util.children
@@ -65,7 +57,6 @@
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.mapNotNull
-import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
 /** Binds a view-model to a [NotificationIconContainer]. */
@@ -118,8 +109,6 @@
         configuration: ConfigurationState,
         configurationController: ConfigurationController,
         dozeParameters: DozeParameters,
-        featureFlags: FeatureFlagsClassic,
-        screenOffAnimationController: ScreenOffAnimationController,
         viewStore: IconViewStore,
     ): DisposableHandle {
         return view.repeatWhenAttached {
@@ -134,16 +123,6 @@
                 }
                 launch { viewModel.animationsEnabled.bindAnimationsEnabled(view) }
                 launch { viewModel.isDozing.bindIsDozing(view, dozeParameters) }
-                // TODO(b/278765923): this should live where AOD is bound, not inside of the NIC
-                //  view-binder
-                launch {
-                    viewModel.isVisible.bindIsVisible(
-                        view,
-                        configuration,
-                        featureFlags,
-                        screenOffAnimationController,
-                    )
-                }
                 launch {
                     configuration
                         .getColorAttr(R.attr.wallpaperTextColor, DEFAULT_AOD_ICON_COLOR)
@@ -333,106 +312,11 @@
         setDecorColor(iconColors.tint)
     }
 
-    private suspend fun Flow<AnimatedValue<Boolean>>.bindIsVisible(
-        view: NotificationIconContainer,
-        configuration: ConfigurationState,
-        featureFlags: FeatureFlagsClassic,
-        screenOffAnimationController: ScreenOffAnimationController,
-    ): Unit = coroutineScope {
-        val iconAppearTranslation =
-            configuration.getDimensionPixelSize(R.dimen.shelf_appear_translation).stateIn(this)
-        val statusViewMigrated = featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)
-        collect { isVisible ->
-            view.animate().cancel()
-            val animatorListener =
-                object : AnimatorListenerAdapter() {
-                    override fun onAnimationEnd(animation: Animator) {
-                        isVisible.stopAnimating()
-                    }
-                }
-            when {
-                !isVisible.isAnimating -> {
-                    view.alpha = 1f
-                    if (!statusViewMigrated) {
-                        view.translationY = 0f
-                    }
-                    view.visibility = if (isVisible.value) View.VISIBLE else View.INVISIBLE
-                }
-                featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION) -> {
-                    view.animateInIconTranslation(statusViewMigrated)
-                    if (isVisible.value) {
-                        CrossFadeHelper.fadeIn(view, animatorListener)
-                    } else {
-                        CrossFadeHelper.fadeOut(view, animatorListener)
-                    }
-                }
-                !isVisible.value -> {
-                    // Let's make sure the icon are translated to 0, since we cancelled it above
-                    view.animateInIconTranslation(statusViewMigrated)
-                    CrossFadeHelper.fadeOut(view, animatorListener)
-                }
-                view.visibility != View.VISIBLE -> {
-                    // No fading here, let's just appear the icons instead!
-                    view.visibility = View.VISIBLE
-                    view.alpha = 1f
-                    view.appearIcons(
-                        animate = screenOffAnimationController.shouldAnimateAodIcons(),
-                        iconAppearTranslation.value,
-                        statusViewMigrated,
-                        animatorListener,
-                    )
-                }
-                else -> {
-                    // Let's make sure the icons are translated to 0, since we cancelled it above
-                    view.animateInIconTranslation(statusViewMigrated)
-                    // We were fading out, let's fade in instead
-                    CrossFadeHelper.fadeIn(view, animatorListener)
-                }
-            }
-        }
-    }
-
-    private fun View.appearIcons(
-        animate: Boolean,
-        iconAppearTranslation: Int,
-        statusViewMigrated: Boolean,
-        animatorListener: Animator.AnimatorListener,
-    ) {
-        if (animate) {
-            if (!statusViewMigrated) {
-                translationY = -iconAppearTranslation.toFloat()
-            }
-            alpha = 0f
-            animate()
-                .alpha(1f)
-                .setInterpolator(Interpolators.LINEAR)
-                .setDuration(AOD_ICONS_APPEAR_DURATION)
-                .apply { if (statusViewMigrated) animateInIconTranslation() }
-                .setListener(animatorListener)
-                .start()
-        } else {
-            alpha = 1.0f
-            if (!statusViewMigrated) {
-                translationY = 0f
-            }
-        }
-    }
-
-    private fun View.animateInIconTranslation(statusViewMigrated: Boolean) {
-        if (!statusViewMigrated) {
-            animate().animateInIconTranslation().setDuration(AOD_ICONS_APPEAR_DURATION).start()
-        }
-    }
-
-    private fun ViewPropertyAnimator.animateInIconTranslation(): ViewPropertyAnimator =
-        setInterpolator(Interpolators.DECELERATE_QUINT).translationY(0f)
-
     /** External storage for [StatusBarIconView] instances. */
     fun interface IconViewStore {
         fun iconView(key: String): StatusBarIconView?
     }
 
-    private const val AOD_ICONS_APPEAR_DURATION: Long = 200
     @ColorInt private val DEFAULT_AOD_ICON_COLOR = Color.WHITE
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
index 611ed89..835c059 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModel.kt
@@ -15,26 +15,16 @@
  */
 package com.android.systemui.statusbar.notification.icon.ui.viewmodel
 
-import android.graphics.Rect
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
 import com.android.systemui.statusbar.notification.icon.domain.interactor.AlwaysOnDisplayNotificationIconsInteractor
-import com.android.systemui.statusbar.phone.DozeParameters
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController
-import com.android.systemui.util.kotlin.pairwise
-import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.ui.AnimatableEvent
 import com.android.systemui.util.ui.AnimatedValue
 import com.android.systemui.util.ui.toAnimatedValueFlow
-import com.android.systemui.util.ui.zip
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
@@ -46,14 +36,9 @@
 class NotificationIconContainerAlwaysOnDisplayViewModel
 @Inject
 constructor(
-    private val deviceEntryInteractor: DeviceEntryInteractor,
-    private val dozeParameters: DozeParameters,
-    private val featureFlags: FeatureFlagsClassic,
     iconsInteractor: AlwaysOnDisplayNotificationIconsInteractor,
     keyguardInteractor: KeyguardInteractor,
     keyguardTransitionInteractor: KeyguardTransitionInteractor,
-    private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor,
-    screenOffAnimationController: ScreenOffAnimationController,
     shadeInteractor: ShadeInteractor,
 ) {
 
@@ -84,45 +69,6 @@
             .distinctUntilChanged()
             .toAnimatedValueFlow()
 
-    /** Is the icon container visible? */
-    val isVisible: Flow<AnimatedValue<Boolean>> =
-        combine(
-                keyguardTransitionInteractor.finishedKeyguardState.map { it != KeyguardState.GONE },
-                deviceEntryInteractor.isBypassEnabled,
-                areNotifsFullyHiddenAnimated(),
-                isPulseExpandingAnimated(),
-            ) {
-                onKeyguard: Boolean,
-                isBypassEnabled: Boolean,
-                notifsFullyHidden: AnimatedValue<Boolean>,
-                pulseExpanding: AnimatedValue<Boolean>,
-                ->
-                when {
-                    // Hide the AOD icons if we're not in the KEYGUARD state unless the screen off
-                    // animation is playing, in which case we want them to be visible if we're
-                    // animating in the AOD UI and will be switching to KEYGUARD shortly.
-                    !onKeyguard && !screenOffAnimationController.shouldShowAodIconsWhenShade() ->
-                        AnimatedValue.NotAnimating(false)
-                    else ->
-                        zip(notifsFullyHidden, pulseExpanding) {
-                            areNotifsFullyHidden,
-                            isPulseExpanding,
-                            ->
-                            when {
-                                // If we're bypassing, then we're visible
-                                isBypassEnabled -> true
-                                // If we are pulsing (and not bypassing), then we are hidden
-                                isPulseExpanding -> false
-                                // If notifs are fully gone, then we're visible
-                                areNotifsFullyHidden -> true
-                                // Otherwise, we're hidden
-                                else -> false
-                            }
-                        }
-                }
-            }
-            .distinctUntilChanged()
-
     /** [NotificationIconsViewData] indicating which icons to display in the view. */
     val icons: Flow<NotificationIconsViewData> =
         iconsInteractor.aodNotifs.map { entries ->
@@ -130,43 +76,4 @@
                 visibleKeys = entries.mapNotNull { it.toIconInfo(it.aodIcon) },
             )
         }
-
-    /** Is there an expanded pulse, are we animating in response? */
-    private fun isPulseExpandingAnimated(): Flow<AnimatedValue<Boolean>> {
-        return notificationsKeyguardInteractor.isPulseExpanding
-            .pairwise(initialValue = null)
-            // If pulsing changes, start animating, unless it's the first emission
-            .map { (prev, expanding) -> AnimatableEvent(expanding, startAnimating = prev != null) }
-            .toAnimatedValueFlow()
-    }
-
-    /** Are notifications completely hidden from view, are we animating in response? */
-    private fun areNotifsFullyHiddenAnimated(): Flow<AnimatedValue<Boolean>> {
-        return notificationsKeyguardInteractor.areNotificationsFullyHidden
-            .pairwise(initialValue = null)
-            .sample(deviceEntryInteractor.isBypassEnabled) { (prev, fullyHidden), bypassEnabled ->
-                val animate =
-                    when {
-                        // Don't animate for the first value
-                        prev == null -> false
-                        // Always animate if bypass is enabled.
-                        bypassEnabled -> true
-                        // If we're not bypassing and we're not going to AOD, then we're not
-                        // animating.
-                        !dozeParameters.alwaysOn -> false
-                        // Don't animate when going to AOD if the display needs blanking.
-                        dozeParameters.displayNeedsBlanking -> false
-                        // We only want the appear animations to happen when the notifications
-                        // get fully hidden, since otherwise the un-hide animation overlaps.
-                        featureFlags.isEnabled(Flags.NEW_AOD_TRANSITION) -> true
-                        else -> fullyHidden
-                    }
-                AnimatableEvent(fullyHidden, animate)
-            }
-            .toAnimatedValueFlow()
-    }
-
-    private class IconColorsImpl(override val tint: Int) : NotificationIconColors {
-        override fun staticDrawableColor(viewBounds: Rect, isColorized: Boolean): Int = tint
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
index 53631e3..82626acc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModel.kt
@@ -61,7 +61,7 @@
             darkIconInteractor.tintAreas,
             darkIconInteractor.tintColor,
             // Included so that tints are re-applied after entries are changed.
-            notificationsInteractor.notifications,
+            notificationsInteractor.topLevelRepresentativeNotifications,
         ) { areas, tint, _ ->
             NotificationIconColorLookup { viewBounds: Rect ->
                 if (DarkIconDispatcher.isInAreas(areas, viewBounds)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
index 75e0484..538be14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/CommonVisualInterruptionSuppressors.kt
@@ -16,18 +16,29 @@
 
 package com.android.systemui.statusbar.notification.interruption
 
+import android.app.Notification.BubbleMetadata
+import android.app.Notification.VISIBILITY_PRIVATE
+import android.app.NotificationManager.IMPORTANCE_DEFAULT
+import android.app.NotificationManager.IMPORTANCE_HIGH
 import android.database.ContentObserver
 import android.hardware.display.AmbientDisplayConfiguration
 import android.os.Handler
+import android.os.PowerManager
 import android.provider.Settings.Global.HEADS_UP_NOTIFICATIONS_ENABLED
 import android.provider.Settings.Global.HEADS_UP_OFF
 import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.StatusBarState.SHADE
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.MAX_HUN_WHEN_AGE_MS
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.BUBBLE
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PEEK
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PULSE
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.util.time.SystemClock
 
 class PeekDisabledSuppressor(
     private val globalSettings: GlobalSettings,
@@ -88,3 +99,121 @@
     ) {
     override fun shouldSuppress() = batteryController.isAodPowerSave()
 }
+
+class PeekPackageSnoozedSuppressor(private val headsUpManager: HeadsUpManager) :
+    VisualInterruptionFilter(types = setOf(PEEK), reason = "package snoozed") {
+    override fun shouldSuppress(entry: NotificationEntry) =
+        when {
+            // Assume any notification with an FSI is time-sensitive (like an alarm or incoming
+            // call) and ignore whether HUNs have been snoozed for the package.
+            entry.sbn.notification.fullScreenIntent != null -> false
+
+            // Otherwise, check if the package is snoozed.
+            else -> headsUpManager.isSnoozed(entry.sbn.packageName)
+        }
+}
+
+class PeekAlreadyBubbledSuppressor(private val statusBarStateController: StatusBarStateController) :
+    VisualInterruptionFilter(types = setOf(PEEK), reason = "already bubbled") {
+    override fun shouldSuppress(entry: NotificationEntry) =
+        when {
+            statusBarStateController.state != SHADE -> false
+            else -> entry.isBubble
+        }
+}
+
+class PeekDndSuppressor() :
+    VisualInterruptionFilter(types = setOf(PEEK), reason = "suppressed by DND") {
+    override fun shouldSuppress(entry: NotificationEntry) = entry.shouldSuppressPeek()
+}
+
+class PeekNotImportantSuppressor() :
+    VisualInterruptionFilter(types = setOf(PEEK), reason = "not important") {
+    override fun shouldSuppress(entry: NotificationEntry) = entry.importance < IMPORTANCE_HIGH
+}
+
+class PeekDeviceNotInUseSuppressor(
+    private val powerManager: PowerManager,
+    private val statusBarStateController: StatusBarStateController
+) : VisualInterruptionCondition(types = setOf(PEEK), reason = "not in use") {
+    override fun shouldSuppress() =
+        when {
+            !powerManager.isScreenOn || statusBarStateController.isDreaming -> true
+            else -> false
+        }
+}
+
+class PeekOldWhenSuppressor(private val systemClock: SystemClock) :
+    VisualInterruptionFilter(types = setOf(PEEK), reason = "old when") {
+    private fun whenAge(entry: NotificationEntry) =
+        systemClock.currentTimeMillis() - entry.sbn.notification.`when`
+
+    override fun shouldSuppress(entry: NotificationEntry): Boolean =
+        when {
+            // Ignore a "when" of 0, as it is unlikely to be a meaningful timestamp.
+            entry.sbn.notification.`when` <= 0L -> false
+
+            // Assume all HUNs with FSIs, foreground services, or user-initiated jobs are
+            // time-sensitive, regardless of their "when".
+            entry.sbn.notification.fullScreenIntent != null ||
+                entry.sbn.notification.isForegroundService ||
+                entry.sbn.notification.isUserInitiatedJob -> false
+
+            // Otherwise, check if the HUN's "when" is too old.
+            else -> whenAge(entry) >= MAX_HUN_WHEN_AGE_MS
+        }
+}
+
+class PulseEffectSuppressor() :
+    VisualInterruptionFilter(types = setOf(PULSE), reason = "ambient effect suppressed") {
+    override fun shouldSuppress(entry: NotificationEntry) = entry.shouldSuppressAmbient()
+}
+
+class PulseLockscreenVisibilityPrivateSuppressor() :
+    VisualInterruptionFilter(
+        types = setOf(PULSE),
+        reason = "notification hidden on lock screen by override"
+    ) {
+    override fun shouldSuppress(entry: NotificationEntry) =
+        entry.ranking.lockscreenVisibilityOverride == VISIBILITY_PRIVATE
+}
+
+class PulseLowImportanceSuppressor() :
+    VisualInterruptionFilter(types = setOf(PULSE), reason = "importance less than DEFAULT") {
+    override fun shouldSuppress(entry: NotificationEntry) = entry.importance < IMPORTANCE_DEFAULT
+}
+
+class HunGroupAlertBehaviorSuppressor() :
+    VisualInterruptionFilter(
+        types = setOf(PEEK, PULSE),
+        reason = "suppressive group alert behavior"
+    ) {
+    override fun shouldSuppress(entry: NotificationEntry) =
+        entry.sbn.let { it.isGroup && it.notification.suppressAlertingDueToGrouping() }
+}
+
+class HunJustLaunchedFsiSuppressor() :
+    VisualInterruptionFilter(types = setOf(PEEK, PULSE), reason = "just launched FSI") {
+    override fun shouldSuppress(entry: NotificationEntry) = entry.hasJustLaunchedFullScreenIntent()
+}
+
+class BubbleNotAllowedSuppressor() :
+    VisualInterruptionFilter(types = setOf(BUBBLE), reason = "not allowed") {
+    override fun shouldSuppress(entry: NotificationEntry) = !entry.canBubble()
+}
+
+class BubbleNoMetadataSuppressor() :
+    VisualInterruptionFilter(types = setOf(BUBBLE), reason = "no bubble metadata") {
+
+    private fun isValidMetadata(metadata: BubbleMetadata?) =
+        metadata != null && (metadata.intent != null || metadata.shortcutId != null)
+
+    override fun shouldSuppress(entry: NotificationEntry) = !isValidMetadata(entry.bubbleMetadata)
+}
+
+class AlertKeyguardVisibilitySuppressor(
+    private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider
+) : VisualInterruptionFilter(types = setOf(PEEK, PULSE, BUBBLE), reason = "hidden on keyguard") {
+    override fun shouldSuppress(entry: NotificationEntry) =
+        keyguardNotificationVisibilityProvider.shouldHideNotification(entry)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
index bae7134..2730683 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
@@ -19,6 +19,7 @@
 import android.os.Handler
 import android.os.PowerManager
 import android.util.Log
+import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.settings.UserTracker
@@ -41,6 +42,7 @@
     private val batteryController: BatteryController,
     private val globalSettings: GlobalSettings,
     private val headsUpManager: HeadsUpManager,
+    private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider,
     private val logger: NotificationInterruptLogger,
     @Main private val mainHandler: Handler,
     private val powerManager: PowerManager,
@@ -56,6 +58,20 @@
         addCondition(PeekDisabledSuppressor(globalSettings, headsUpManager, logger, mainHandler))
         addCondition(PulseDisabledSuppressor(ambientDisplayConfiguration, userTracker))
         addCondition(PulseBatterySaverSuppressor(batteryController))
+        addFilter(PeekPackageSnoozedSuppressor(headsUpManager))
+        addFilter(PeekAlreadyBubbledSuppressor(statusBarStateController))
+        addFilter(PeekDndSuppressor())
+        addFilter(PeekNotImportantSuppressor())
+        addCondition(PeekDeviceNotInUseSuppressor(powerManager, statusBarStateController))
+        addFilter(PeekOldWhenSuppressor(systemClock))
+        addFilter(PulseEffectSuppressor())
+        addFilter(PulseLockscreenVisibilityPrivateSuppressor())
+        addFilter(PulseLowImportanceSuppressor())
+        addFilter(BubbleNotAllowedSuppressor())
+        addFilter(BubbleNoMetadataSuppressor())
+        addFilter(HunGroupAlertBehaviorSuppressor())
+        addFilter(HunJustLaunchedFsiSuppressor())
+        addFilter(AlertKeyguardVisibilitySuppressor(keyguardNotificationVisibilityProvider))
 
         started = true
     }
@@ -91,11 +107,21 @@
         condition.start()
     }
 
+    @VisibleForTesting
+    fun removeCondition(condition: VisualInterruptionCondition) {
+        conditions.remove(condition)
+    }
+
     fun addFilter(filter: VisualInterruptionFilter) {
         filters.add(filter)
         filter.start()
     }
 
+    @VisibleForTesting
+    fun removeFilter(filter: VisualInterruptionFilter) {
+        filters.remove(filter)
+    }
+
     override fun makeUnloggedHeadsUpDecision(entry: NotificationEntry): Decision {
         check(started)
         return makeHeadsUpDecision(entry)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
index c89f2fa..f096dd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
@@ -21,12 +21,12 @@
 import android.util.Log
 import android.util.StatsEvent
 import androidx.annotation.VisibleForTesting
+import com.android.app.tracing.traceSection
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.shared.system.SysUiStatsLog
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
-import com.android.systemui.tracing.traceSection
 import java.lang.Exception
 import java.util.concurrent.Executor
 import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt
index 78370ba..eb1c1ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/ActiveNotificationModel.kt
@@ -17,9 +17,17 @@
 
 import android.graphics.drawable.Icon
 
-/** Model for entries in the notification stack. */
+/**
+ * Model for a top-level "entry" in the notification list, either an
+ * [individual notification][ActiveNotificationModel], or a [group][ActiveNotificationGroupModel].
+ */
+sealed class ActiveNotificationEntryModel
+
+/**
+ * Model for an individual notification in the notification list. These can appear as either an
+ * individual top-level notification, or as a child or summary of a [ActiveNotificationGroupModel].
+ */
 data class ActiveNotificationModel(
-    /** Notification key associated with this entry. */
     val key: String,
     /** Notification group key associated with this entry. */
     val groupKey: String?,
@@ -47,4 +55,11 @@
     val shelfIcon: Icon?,
     /** Icon to display in the status bar. */
     val statusBarIcon: Icon?,
-)
+) : ActiveNotificationEntryModel()
+
+/** Model for a group of notifications. */
+data class ActiveNotificationGroupModel(
+    val key: String,
+    val summary: ActiveNotificationModel,
+    val children: List<ActiveNotificationModel>,
+) : ActiveNotificationEntryModel()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
index a98efba..af2ca26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationListViewBinder.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.stack.ui.viewbinder
 
 import android.view.LayoutInflater
+import com.android.app.tracing.traceSection
 import com.android.systemui.common.ui.ConfigurationState
 import com.android.systemui.common.ui.reinflateAndBindLatest
 import com.android.systemui.lifecycle.repeatWhenAttached
@@ -31,7 +32,6 @@
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel
 import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import com.android.systemui.statusbar.policy.ConfigurationController
-import com.android.systemui.tracing.traceSection
 
 /** Binds a [NotificationStackScrollLayout] to its [view model][NotificationListViewModel]. */
 object NotificationListViewBinder {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
index 2d125462..e1fba2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt
@@ -494,7 +494,7 @@
                     // this runnable is called right after the keyguard is solved, so we tell
                     // WM that we should dismiss it to avoid flickers when opening an activity
                     // that can also be shown over the keyguard.
-                    options.setDismissKeyguard()
+                    options.setDismissKeyguardIfInsecure()
                     options.setDisallowEnterPictureInPictureWhileLaunching(
                         disallowEnterPictureInPictureWhileLaunching
                     )
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index ae70384..c207324 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -25,6 +25,7 @@
 import android.util.TimeUtils;
 
 import com.android.app.animation.Interpolators;
+import com.android.internal.policy.GestureNavigationSettingsObserver;
 import com.android.systemui.Dumpable;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shared.system.QuickStepContract;
@@ -95,6 +96,7 @@
     private final KeyguardStateController mKeyguardStateController;
     private final StatusBarStateController mStatusBarStateController;
     private final CommandQueue mCommandQueue;
+    private final GestureNavigationSettingsObserver mGestureNavigationSettingsObserver;
 
     private boolean mTransitionDeferring;
     private long mTransitionDeferringStartTime;
@@ -134,6 +136,8 @@
         mDozeAmount = mStatusBarStateController.getDozeAmount();
         mContext = context;
         mDisplayId = mContext.getDisplayId();
+        mGestureNavigationSettingsObserver = new GestureNavigationSettingsObserver(
+                mHandler, mContext, null);
     }
 
     /** Call to cleanup the LightBarTransitionsController when done with it. */
@@ -279,7 +283,8 @@
      */
     public boolean supportsIconTintForNavMode(int navigationMode) {
         // In gesture mode, we already do region sampling to update tint based on content beneath.
-        return !QuickStepContract.isGesturalMode(navigationMode);
+        return !QuickStepContract.isGesturalMode(navigationMode)
+                || mGestureNavigationSettingsObserver.areNavigationButtonForcedVisible();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
index 894549d..cba72d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
@@ -38,7 +38,7 @@
 import com.android.systemui.util.leak.RotationUtils.Rotation
 import com.android.systemui.util.leak.RotationUtils.getExactRotation
 import com.android.systemui.util.leak.RotationUtils.getResourcesForRotation
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import java.io.PrintWriter
 import java.lang.Math.max
 import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 1eea348..fb586ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -31,7 +31,7 @@
 import com.android.systemui.statusbar.notification.stack.AnimationProperties
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator
 import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.tracing.TraceUtils
+import com.android.app.tracing.TraceUtils
 import com.android.systemui.util.settings.GlobalSettings
 import javax.inject.Inject
 import com.android.systemui.flags.FeatureFlags
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index fa9256f..2797b8d 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -162,6 +162,7 @@
                 .setContentText(context.getString(R.string.stylus_battery_low_subtitle))
                 .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                 .setLocalOnly(true)
+                .setOnlyAlertOnce(true)
                 .setAutoCancel(true)
                 .build()
 
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
index c3c0291..2afb435 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
@@ -48,7 +48,7 @@
 import com.android.systemui.unfold.updates.RotationChangeProvider
 import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider.Companion.areAnimationsEnabled
 import com.android.systemui.util.concurrency.ThreadFactory
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import com.android.wm.shell.displayareahelper.DisplayAreaHelper
 import java.util.Optional
 import java.util.concurrent.Executor
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
index dfff7c4..12b8845 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTraceLogger.kt
@@ -17,10 +17,10 @@
 
 import android.content.Context
 import android.os.Trace
+import com.android.app.tracing.TraceStateLogger
 import com.android.systemui.CoreStartable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.tracing.TraceStateLogger
 import com.android.systemui.unfold.system.DeviceStateRepository
 import com.android.systemui.unfold.updates.FoldStateRepository
 import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/util/NamedListenerSet.kt b/packages/SystemUI/src/com/android/systemui/util/NamedListenerSet.kt
index 1e0f420..45d742f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NamedListenerSet.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/NamedListenerSet.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.util
 
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import java.util.concurrent.CopyOnWriteArrayList
 import java.util.function.Consumer
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/NoRemeasureMotionLayout.kt b/packages/SystemUI/src/com/android/systemui/util/NoRemeasureMotionLayout.kt
index cec9580..f49d616 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NoRemeasureMotionLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/NoRemeasureMotionLayout.kt
@@ -20,7 +20,7 @@
 import android.util.AttributeSet
 import android.view.Choreographer
 import androidx.constraintlayout.motion.widget.MotionLayout
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 
 /**
  * [MotionLayout] that avoids remeasuring with the same inputs in the same frame.
diff --git a/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt b/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
index afd2360..de92318 100644
--- a/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
@@ -13,7 +13,7 @@
 import android.graphics.drawable.Drawable
 import android.util.Log
 import androidx.annotation.Px
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 
 class DrawableSize {
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
index 5396bca..81737c7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
@@ -7,8 +7,8 @@
 import com.android.systemui.dagger.qualifiers.Tracing
 import com.android.systemui.flags.FeatureFlagsClassic
 import com.android.systemui.flags.Flags
-import com.android.systemui.tracing.TraceUtils.Companion.coroutineTracingIsEnabled
-import com.android.systemui.tracing.TraceContextElement
+import com.android.app.tracing.TraceUtils.Companion.coroutineTracingIsEnabled
+import com.android.app.tracing.TraceContextElement
 import dagger.Module
 import dagger.Provides
 import kotlinx.coroutines.CoroutineDispatcher
diff --git a/packages/SystemUI/src/com/android/systemui/util/wrapper/LottieViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/util/wrapper/LottieViewWrapper.kt
index 2e355bd..eefd849 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wrapper/LottieViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/wrapper/LottieViewWrapper.kt
@@ -18,7 +18,7 @@
 import android.content.Context
 import android.util.AttributeSet
 import com.airbnb.lottie.LottieAnimationView
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 
 /** LottieAnimationView that traces each call to invalidate. */
 open class LottieViewWrapper : LottieAnimationView {
diff --git a/packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt b/packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
index 8f320a3..059ff56 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
@@ -21,7 +21,7 @@
 import com.android.internal.view.RotationPolicy
 import com.android.internal.view.RotationPolicy.RotationPolicyListener
 import com.android.systemui.util.settings.SecureSettings
-import com.android.systemui.tracing.traceSection
+import com.android.app.tracing.traceSection
 import javax.inject.Inject
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
index a453726..d261b08 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
@@ -57,7 +57,7 @@
     public static final String VOLUME_SILENT_DO_NOT_DISTURB = "sysui_do_not_disturb";
 
     private final boolean mDefaultVolumeDownToEnterSilent;
-    public static final boolean DEFAULT_VOLUME_UP_TO_EXIT_SILENT = false;
+    public final boolean mDefaultVolumeUpToExitSilent;
     public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false;
 
     private static final Intent ZEN_SETTINGS =
@@ -107,10 +107,12 @@
 
         mDefaultVolumeDownToEnterSilent = mContext.getResources()
                 .getBoolean(R.bool.config_volume_down_to_enter_silent);
+        mDefaultVolumeUpToExitSilent = mContext.getResources()
+                .getBoolean(R.bool.config_volume_up_to_exit_silent);
 
         mVolumePolicy = new VolumePolicy(
                 mDefaultVolumeDownToEnterSilent,  // volumeDownToEnterSilent
-                DEFAULT_VOLUME_UP_TO_EXIT_SILENT,  // volumeUpToExitSilent
+                mDefaultVolumeUpToExitSilent,  // volumeUpToExitSilent
                 DEFAULT_DO_NOT_DISTURB_WHEN_SILENT,  // doNotDisturbWhenSilent
                 400    // vibrateToSilentDebounce
         );
@@ -133,7 +135,7 @@
                 TunerService.parseIntegerSwitch(newValue, mDefaultVolumeDownToEnterSilent);
         } else if (VOLUME_UP_SILENT.equals(key)) {
             volumeUpToExitSilent =
-                TunerService.parseIntegerSwitch(newValue, DEFAULT_VOLUME_UP_TO_EXIT_SILENT);
+                TunerService.parseIntegerSwitch(newValue, mDefaultVolumeUpToExitSilent);
         } else if (VOLUME_SILENT_DO_NOT_DISTURB.equals(key)) {
             doNotDisturbWhenSilent =
                 TunerService.parseIntegerSwitch(newValue, DEFAULT_DO_NOT_DISTURB_WHEN_SILENT);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
index 603d548..4a799d8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java
@@ -41,6 +41,7 @@
 import com.android.systemui.flags.FakeFeatureFlags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel;
 import com.android.systemui.log.LogBuffer;
 import com.android.systemui.plugins.ClockAnimations;
 import com.android.systemui.plugins.ClockController;
@@ -191,6 +192,7 @@
                 mClockEventController,
                 mLogBuffer,
                 mock(NotificationIconContainerAlwaysOnDisplayViewModel.class),
+                mock(KeyguardRootViewModel.class),
                 mock(ConfigurationState.class),
                 mock(DozeParameters.class),
                 mock(AlwaysOnDisplayNotificationIconViewStore.class),
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index fda4133..225f125 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -810,6 +810,7 @@
                     SceneKey.Bouncer,
                     flowOf(.5f),
                     false,
+                    isUserInputOngoing = flowOf(false),
                 )
             runCurrent()
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
@@ -825,7 +826,8 @@
                     SceneKey.Bouncer,
                     SceneKey.Gone,
                     flowOf(.5f),
-                    false
+                    false,
+                    isUserInputOngoing = flowOf(false),
                 )
             runCurrent()
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
@@ -842,7 +844,8 @@
                     SceneKey.Gone,
                     SceneKey.Bouncer,
                     flowOf(.5f),
-                    false
+                    false,
+                    isUserInputOngoing = flowOf(false),
                 )
             runCurrent()
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer, null), "reason")
@@ -860,7 +863,8 @@
                     SceneKey.Bouncer,
                     SceneKey.Gone,
                     flowOf(.5f),
-                    false
+                    false,
+                    isUserInputOngoing = flowOf(false),
                 )
             runCurrent()
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
@@ -876,6 +880,7 @@
                     SceneKey.Lockscreen,
                     flowOf(.5f),
                     false,
+                    isUserInputOngoing = flowOf(false),
                 )
             runCurrent()
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Lockscreen, null), "reason")
@@ -893,6 +898,7 @@
                     SceneKey.Gone,
                     flowOf(.5f),
                     false,
+                    isUserInputOngoing = flowOf(false),
                 )
             runCurrent()
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone, null), "reason")
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 6099ece1..776799e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -870,6 +870,23 @@
     }
 
     @Test
+    public void whenDetectFingerprint_detectError() {
+        ArgumentCaptor<FingerprintManager.FingerprintDetectionCallback> fpDetectCallbackCaptor =
+                ArgumentCaptor.forClass(FingerprintManager.FingerprintDetectionCallback.class);
+
+        givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+        verify(mFingerprintManager).detectFingerprint(
+                any(), fpDetectCallbackCaptor.capture(), any());
+        fpDetectCallbackCaptor.getValue().onDetectionError(/* msgId */ 10);
+
+        // THEN verify keyguardUpdateMonitorCallback receives a biometric error
+        verify(mTestCallback).onBiometricError(
+                eq(10), eq(""), eq(BiometricSourceType.FINGERPRINT));
+        verify(mTestCallback, never()).onBiometricAuthenticated(
+                anyInt(), any(), anyBoolean());
+    }
+
+    @Test
     public void whenDetectFace_biometricDetectCallback() throws RemoteException {
         ArgumentCaptor<FaceManager.FaceDetectionCallback> faceDetectCallbackCaptor =
                 ArgumentCaptor.forClass(FaceManager.FaceDetectionCallback.class);
@@ -1212,6 +1229,34 @@
     }
 
     @Test
+    public void fpStopsListeningWhenBiometricPromptShows_resumesOnBpHidden() {
+        // verify AuthController.Callback is added:
+        ArgumentCaptor<AuthController.Callback> captor = ArgumentCaptor.forClass(
+                AuthController.Callback.class);
+        verify(mAuthController).addCallback(captor.capture());
+        AuthController.Callback callback = captor.getValue();
+
+        // GIVEN keyguard showing
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mKeyguardUpdateMonitor.setKeyguardShowing(true, false);
+
+        // THEN fingerprint should listen
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isTrue();
+
+        // WHEN biometric prompt is shown
+        callback.onBiometricPromptShown();
+
+        // THEN shouldn't listen for fingerprint
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isFalse();
+
+        // WHEN biometric prompt is dismissed
+        callback.onBiometricPromptDismissed();
+
+        // THEN we should listen for fingerprint
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(false)).isTrue();
+    }
+
+    @Test
     public void testTriesToAuthenticate_whenTrustOnAgentKeyguard_ifBypass() {
         mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
         mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
index 728102d..837a130 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.accessibility;
 
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -29,7 +31,6 @@
 
 import android.animation.ValueAnimator;
 import android.annotation.Nullable;
-import android.app.Instrumentation;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Handler;
@@ -42,7 +43,7 @@
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
 import android.view.animation.AccelerateInterpolator;
 
-import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
 
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
@@ -67,6 +68,7 @@
 
 @LargeTest
 @RunWith(AndroidTestingRunner.class)
+@FlakyTest(bugId = 308501761)
 public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
 
     @Rule
@@ -101,7 +103,7 @@
     private SpyWindowMagnificationController mController;
     private WindowMagnificationController mSpyController;
     private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
-    private Instrumentation mInstrumentation;
+
     private long mWaitAnimationDuration;
     private long mWaitPartialAnimationDuration;
 
@@ -111,7 +113,6 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mInstrumentation = InstrumentationRegistry.getInstrumentation();
         final WindowManager wm = mContext.getSystemService(WindowManager.class);
         mWindowManager = spy(new TestableWindowManager(wm));
         mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
@@ -133,7 +134,7 @@
 
     @After
     public void tearDown() throws Exception {
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mController.deleteWindowMagnification();
         });
     }
@@ -197,7 +198,7 @@
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
         resetMockObjects();
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                     targetCenterX, targetCenterY, mAnimationCallback2);
             mCurrentScale.set(mController.getScale());
@@ -250,7 +251,7 @@
         final float targetCenterY = mirrorView.getHeight() / 2.0f;
 
         Mockito.reset(mSpyController);
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                     targetCenterX, targetCenterY, mAnimationCallback);
             mCurrentScale.set(mController.getScale());
@@ -286,7 +287,7 @@
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
         Mockito.reset(mSpyController);
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                     targetCenterX, targetCenterY, mAnimationCallback);
             mCurrentScale.set(mController.getScale());
@@ -374,7 +375,7 @@
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
         Mockito.reset(mSpyController);
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                     targetCenterX, targetCenterY, mAnimationCallback2);
             mCurrentScale.set(mController.getScale());
@@ -386,7 +387,7 @@
         verify(mAnimationCallback2, never()).onResult(anyBoolean());
         verify(mAnimationCallback).onResult(false);
 
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             // ValueAnimator.reverse() could not work correctly with the AnimatorTestRule since it
             // is using SystemClock in reverse() (b/305731398). Therefore, we call end() on the
             // animator directly to verify the result of animation is correct instead of querying
@@ -454,7 +455,7 @@
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
 
         Mockito.reset(mSpyController);
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.enableWindowMagnification(targetScale,
                     targetCenterX, targetCenterY, mAnimationCallback2);
             mCurrentScale.set(mController.getScale());
@@ -482,7 +483,7 @@
         final Rect windowBounds = new Rect(mWindowManager.getCurrentWindowMetrics().getBounds());
 
         Mockito.reset(mSpyController);
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
                     windowBounds.exactCenterX(), windowBounds.exactCenterY(),
                     offsetRatio, offsetRatio, mAnimationCallback);
@@ -510,7 +511,7 @@
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
         enableWindowMagnificationWithoutAnimation();
 
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
                     targetCenterX, targetCenterY, mAnimationCallback);
             advanceTimeBy(mWaitAnimationDuration);
@@ -526,7 +527,7 @@
             throws RemoteException {
         enableWindowMagnificationWithoutAnimation();
 
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
                     DEFAULT_CENTER_X + 10, DEFAULT_CENTER_Y + 10, mAnimationCallback);
             mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
@@ -554,7 +555,7 @@
         enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
 
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
                     targetCenterX, targetCenterY, mAnimationCallback2);
             advanceTimeBy(mWaitAnimationDuration);
@@ -574,7 +575,7 @@
         enableWindowMagnificationAndWaitAnimating(mWaitPartialAnimationDuration,
                 mAnimationCallback);
 
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.moveWindowMagnifierToPosition(
                     Float.NaN, Float.NaN, mAnimationCallback2);
             advanceTimeBy(mWaitAnimationDuration);
@@ -646,7 +647,7 @@
                 mAnimationCallback);
 
         Mockito.reset(mSpyController);
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.deleteWindowMagnification(
                     mAnimationCallback2);
             mCurrentScale.set(mController.getScale());
@@ -734,7 +735,7 @@
         final float offsetY =
                 (float) Math.ceil(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE)
                         + 1.0f;
-        mInstrumentation.runOnMainSync(()-> mController.moveWindowMagnifier(offsetX, offsetY));
+        getInstrumentation().runOnMainSync(()-> mController.moveWindowMagnifier(offsetX, offsetY));
 
         verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y + offsetY);
@@ -749,7 +750,7 @@
         final float offsetY =
                 (float) Math.floor(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE)
                         - 1.0f;
-        mInstrumentation.runOnMainSync(() ->
+        getInstrumentation().runOnMainSync(() ->
                 mController.moveWindowMagnifier(offsetX, offsetY));
 
         verify(mSpyController).moveWindowMagnifier(offsetX, offsetY);
@@ -765,7 +766,7 @@
                 (float) Math.ceil(offsetX * WindowMagnificationController.HORIZONTAL_LOCK_BASE);
         // while diagonal scrolling enabled,
         //  should move with both offsetX and offsetY without regrading offsetY/offsetX
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mController.setDiagonalScrolling(true);
             mController.moveWindowMagnifier(offsetX, offsetY);
         });
@@ -780,7 +781,7 @@
         final float targetCenterY = DEFAULT_CENTER_Y + 100;
         enableWindowMagnificationWithoutAnimation();
 
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mController.moveWindowMagnifierToPosition(targetCenterX, targetCenterY,
                     mAnimationCallback);
             advanceTimeBy(mWaitAnimationDuration);
@@ -807,7 +808,7 @@
 
     private void enableWindowMagnificationWithoutAnimation(
             float targetScale, float targetCenterX, float targetCenterY) {
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.enableWindowMagnification(
                     targetScale, targetCenterX, targetCenterY, null);
         });
@@ -825,7 +826,7 @@
             float targetCenterX,
             float targetCenterY,
             @Nullable IRemoteMagnificationAnimationCallback callback) {
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.enableWindowMagnification(
                     targetScale, targetCenterX, targetCenterY, callback);
             advanceTimeBy(duration);
@@ -833,14 +834,14 @@
     }
 
     private void deleteWindowMagnificationWithoutAnimation() {
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.deleteWindowMagnification(null);
         });
     }
 
     private void deleteWindowMagnificationAndWaitAnimating(long duration,
             @Nullable IRemoteMagnificationAnimationCallback callback) {
-        mInstrumentation.runOnMainSync(() -> {
+        getInstrumentation().runOnMainSync(() -> {
             mWindowMagnificationAnimationController.deleteWindowMagnification(callback);
             advanceTimeBy(duration);
         });
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
index 5e7b857..2d95b09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
@@ -54,6 +54,7 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.WakefulnessLifecycle
 import com.android.systemui.statusbar.VibratorHelper
+import com.android.systemui.statusbar.events.ANIMATING_OUT
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -211,6 +212,16 @@
     }
 
     @Test
+    fun testIgnoresAnimatedInWhenDialogAnimatingOut() {
+        val container = initializeFingerprintContainer(addToView = false)
+        container.mContainerState = ANIMATING_OUT
+        container.addToView()
+        waitForIdleSync()
+
+        verify(callback, never()).onDialogAnimatedIn(anyLong(), anyBoolean())
+    }
+
+    @Test
     fun testDismissBeforeIntroEnd() {
         val container = initializeFingerprintContainer()
         waitForIdleSync()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractorTest.kt
index 99501c42..67d3a20 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/SideFpsSensorInteractorTest.kt
@@ -26,6 +26,7 @@
 import android.view.WindowMetrics
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
 import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
 import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.biometrics.shared.model.DisplayRotation.ROTATION_0
@@ -35,11 +36,12 @@
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.android.systemui.biometrics.shared.model.SensorStrength
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags.REST_TO_UNLOCK
+import com.android.systemui.dump.logcatLogBuffer
+import com.android.systemui.log.SideFpsLogger
 import com.android.systemui.res.R
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
+import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.test.StandardTestDispatcher
@@ -62,7 +64,7 @@
 class SideFpsSensorInteractorTest : SysuiTestCase() {
 
     @JvmField @Rule var mockitoRule = MockitoJUnit.rule()
-    private lateinit var testScope: TestScope
+    private val testScope = TestScope(StandardTestDispatcher())
 
     private val fingerprintRepository = FakeFingerprintPropertyRepository()
 
@@ -70,32 +72,36 @@
 
     @Mock private lateinit var windowManager: WindowManager
     @Mock private lateinit var displayStateInteractor: DisplayStateInteractor
-
+    @Mock
+    private lateinit var fingerprintInteractiveToAuthProvider: FingerprintInteractiveToAuthProvider
+    private val isRestToUnlockEnabled = MutableStateFlow(false)
     private val contextDisplayInfo = DisplayInfo()
     private val displayChangeEvent = MutableStateFlow(0)
     private val currentRotation = MutableStateFlow(ROTATION_0)
 
     @Before
     fun setup() {
-        testScope = TestScope(StandardTestDispatcher())
         mContext = spy(mContext)
 
-        val displayManager = mock(DisplayManagerGlobal::class.java)
         val resources = mContext.resources
         whenever(mContext.display)
-            .thenReturn(Display(displayManager, 1, contextDisplayInfo, resources))
+            .thenReturn(
+                Display(mock(DisplayManagerGlobal::class.java), 1, contextDisplayInfo, resources)
+            )
         whenever(displayStateInteractor.displayChanges).thenReturn(displayChangeEvent)
         whenever(displayStateInteractor.currentRotation).thenReturn(currentRotation)
 
         contextDisplayInfo.uniqueId = "current-display"
-
+        whenever(fingerprintInteractiveToAuthProvider.enabledForCurrentUser)
+            .thenReturn(isRestToUnlockEnabled)
         underTest =
             SideFpsSensorInteractor(
                 mContext,
                 fingerprintRepository,
                 windowManager,
                 displayStateInteractor,
-                FakeFeatureFlagsClassic().apply { set(REST_TO_UNLOCK, true) }
+                Optional.of(fingerprintInteractiveToAuthProvider),
+                SideFpsLogger(logcatLogBuffer("SfpsLogger"))
             )
     }
 
@@ -126,7 +132,7 @@
     @Test
     fun authenticationDurationIsAvailableWhenSFPSSensorIsAvailable() =
         testScope.runTest {
-            assertThat(collectLastValue(underTest.authenticationDuration)())
+            assertThat(underTest.authenticationDuration)
                 .isEqualTo(context.resources.getInteger(R.integer.config_restToUnlockDuration))
         }
 
@@ -155,7 +161,7 @@
             assertThat(sensorLocation!!.left).isEqualTo(1000)
             assertThat(sensorLocation!!.top).isEqualTo(200)
             assertThat(sensorLocation!!.isSensorVerticalInDefaultOrientation).isEqualTo(true)
-            assertThat(sensorLocation!!.width).isEqualTo(100)
+            assertThat(sensorLocation!!.length).isEqualTo(100)
         }
 
     @Test
@@ -183,7 +189,7 @@
             assertThat(sensorLocation!!.left).isEqualTo(500)
             assertThat(sensorLocation!!.top).isEqualTo(1000)
             assertThat(sensorLocation!!.isSensorVerticalInDefaultOrientation).isEqualTo(true)
-            assertThat(sensorLocation!!.width).isEqualTo(100)
+            assertThat(sensorLocation!!.length).isEqualTo(100)
         }
 
     @Test
@@ -211,7 +217,7 @@
             assertThat(sensorLocation!!.left).isEqualTo(200)
             assertThat(sensorLocation!!.top).isEqualTo(0)
             assertThat(sensorLocation!!.isSensorVerticalInDefaultOrientation).isEqualTo(true)
-            assertThat(sensorLocation!!.width).isEqualTo(100)
+            assertThat(sensorLocation!!.length).isEqualTo(100)
         }
 
     @Test
@@ -264,7 +270,7 @@
             assertThat(sensorLocation!!.left).isEqualTo(500)
             assertThat(sensorLocation!!.top).isEqualTo(0)
             assertThat(sensorLocation!!.isSensorVerticalInDefaultOrientation).isEqualTo(false)
-            assertThat(sensorLocation!!.width).isEqualTo(100)
+            assertThat(sensorLocation!!.length).isEqualTo(100)
         }
 
     @Test
@@ -291,7 +297,7 @@
             assertThat(sensorLocation!!.left).isEqualTo(0)
             assertThat(sensorLocation!!.top).isEqualTo(400)
             assertThat(sensorLocation!!.isSensorVerticalInDefaultOrientation).isEqualTo(false)
-            assertThat(sensorLocation!!.width).isEqualTo(100)
+            assertThat(sensorLocation!!.length).isEqualTo(100)
         }
 
     @Test
@@ -318,7 +324,7 @@
             assertThat(sensorLocation!!.left).isEqualTo(400)
             assertThat(sensorLocation!!.top).isEqualTo(800)
             assertThat(sensorLocation!!.isSensorVerticalInDefaultOrientation).isEqualTo(false)
-            assertThat(sensorLocation!!.width).isEqualTo(100)
+            assertThat(sensorLocation!!.length).isEqualTo(100)
         }
 
     @Test
@@ -345,7 +351,22 @@
             assertThat(sensorLocation!!.left).isEqualTo(800)
             assertThat(sensorLocation!!.top).isEqualTo(500)
             assertThat(sensorLocation!!.isSensorVerticalInDefaultOrientation).isEqualTo(false)
-            assertThat(sensorLocation!!.width).isEqualTo(100)
+            assertThat(sensorLocation!!.length).isEqualTo(100)
+        }
+
+    @Test
+    fun isProlongedTouchRequiredForAuthentication_dependsOnSettingsToggle() =
+        testScope.runTest {
+            val isEnabled by collectLastValue(underTest.isProlongedTouchRequiredForAuthentication)
+            setupFingerprint(FingerprintSensorType.POWER_BUTTON)
+
+            isRestToUnlockEnabled.value = true
+            runCurrent()
+            assertThat(isEnabled).isTrue()
+
+            isRestToUnlockEnabled.value = false
+            runCurrent()
+            assertThat(isEnabled).isFalse()
         }
 
     private suspend fun TestScope.setupFPLocationAndDisplaySize(
@@ -356,10 +377,14 @@
         rotation: DisplayRotation,
         sensorWidth: Int
     ) {
-        overrideResource(R.integer.config_sfpsSensorWidth, sensorWidth)
         setupDisplayDimensions(width, height)
         currentRotation.value = rotation
-        setupFingerprint(x = sensorLocationX, y = sensorLocationY, displayId = "expanded_display")
+        setupFingerprint(
+            x = sensorLocationX,
+            y = sensorLocationY,
+            displayId = "expanded_display",
+            sensorRadius = sensorWidth / 2
+        )
     }
 
     private fun setupDisplayDimensions(displayWidth: Int, displayHeight: Int) {
@@ -367,7 +392,7 @@
             .thenReturn(
                 WindowMetrics(
                     Rect(0, 0, displayWidth, displayHeight),
-                    mock(WindowInsets::class.java)
+                    mock(WindowInsets::class.java),
                 )
             )
     }
@@ -376,7 +401,8 @@
         fingerprintSensorType: FingerprintSensorType = FingerprintSensorType.POWER_BUTTON,
         x: Int = 0,
         y: Int = 0,
-        displayId: String = "display_id_1"
+        displayId: String = "display_id_1",
+        sensorRadius: Int = 150
     ) {
         contextDisplayInfo.uniqueId = displayId
         fingerprintRepository.setProperties(
@@ -390,14 +416,14 @@
                             "someOtherDisplayId",
                             x + 100,
                             y + 100,
-                            0,
+                            sensorRadius,
                         ),
                     displayId to
                         SensorLocationInternal(
                             displayId,
                             x,
                             y,
-                            0,
+                            sensorRadius,
                         )
                 )
         )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
index 8e21f29..2f17b6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
@@ -23,6 +23,7 @@
 import com.android.systemui.communal.data.repository.FakeCommunalRepository
 import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository
 import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo
+import com.android.systemui.communal.shared.model.CommunalSceneKey
 import com.android.systemui.coroutines.collectLastValue
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -86,4 +87,48 @@
             val interactor = CommunalInteractor(communalRepository, widgetRepository)
             assertThat(interactor.isCommunalEnabled).isFalse()
         }
+
+    @Test
+    fun listensToSceneChange() =
+        testScope.runTest {
+            val interactor = CommunalInteractor(communalRepository, widgetRepository)
+            var desiredScene = collectLastValue(interactor.desiredScene)
+            runCurrent()
+            assertThat(desiredScene()).isEqualTo(CommunalSceneKey.Blank)
+
+            val targetScene = CommunalSceneKey.Communal
+            communalRepository.setDesiredScene(targetScene)
+            desiredScene = collectLastValue(interactor.desiredScene)
+            runCurrent()
+            assertThat(desiredScene()).isEqualTo(targetScene)
+        }
+
+    @Test
+    fun updatesScene() =
+        testScope.runTest {
+            val interactor = CommunalInteractor(communalRepository, widgetRepository)
+            val targetScene = CommunalSceneKey.Communal
+
+            interactor.onSceneChanged(targetScene)
+
+            val desiredScene = collectLastValue(communalRepository.desiredScene)
+            runCurrent()
+            assertThat(desiredScene()).isEqualTo(targetScene)
+        }
+
+    @Test
+    fun isCommunalShowing() =
+        testScope.runTest {
+            val interactor = CommunalInteractor(communalRepository, widgetRepository)
+
+            var isCommunalShowing = collectLastValue(interactor.isCommunalShowing)
+            runCurrent()
+            assertThat(isCommunalShowing()).isEqualTo(false)
+
+            interactor.onSceneChanged(CommunalSceneKey.Communal)
+
+            isCommunalShowing = collectLastValue(interactor.isCommunalShowing)
+            runCurrent()
+            assertThat(isCommunalShowing()).isEqualTo(true)
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
index 0a9a15e..61d1502 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
@@ -21,16 +21,23 @@
 import android.provider.Settings.Secure.HUB_MODE_TUTORIAL_STARTED
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.repository.FakeCommunalRepository
 import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository
+import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository
+import com.android.systemui.communal.shared.model.CommunalSceneKey
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
+import com.android.systemui.scene.SceneTestUtils
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags
+import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.scene.shared.model.SceneModel
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -46,18 +53,28 @@
 
     @Mock private lateinit var userTracker: UserTracker
 
-    private val testDispatcher = StandardTestDispatcher()
-    private val testScope = TestScope(testDispatcher)
-
+    private lateinit var testScope: TestScope
     private lateinit var underTest: CommunalTutorialInteractor
     private lateinit var keyguardRepository: FakeKeyguardRepository
     private lateinit var keyguardInteractor: KeyguardInteractor
     private lateinit var communalTutorialRepository: FakeCommunalTutorialRepository
+    private lateinit var sceneContainerFlags: FakeSceneContainerFlags
+    private lateinit var communalInteractor: CommunalInteractor
+    private lateinit var communalRepository: FakeCommunalRepository
+
+    private val utils = SceneTestUtils(this)
+    private lateinit var sceneInteractor: SceneInteractor
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
+        sceneInteractor = utils.sceneInteractor()
+        testScope = utils.testScope
+        sceneContainerFlags = utils.sceneContainerFlags.apply { enabled = false }
+        communalRepository = FakeCommunalRepository(isCommunalEnabled = true)
+        communalInteractor = CommunalInteractor(communalRepository, FakeCommunalWidgetRepository())
+
         val withDeps = KeyguardInteractorFactory.create()
         keyguardInteractor = withDeps.keyguardInteractor
         keyguardRepository = withDeps.repository
@@ -65,8 +82,12 @@
 
         underTest =
             CommunalTutorialInteractor(
-                keyguardInteractor = keyguardInteractor,
+                scope = testScope.backgroundScope,
                 communalTutorialRepository = communalTutorialRepository,
+                keyguardInteractor = keyguardInteractor,
+                communalInteractor = communalInteractor,
+                sceneContainerFlags = sceneContainerFlags,
+                sceneInteractor = sceneInteractor,
             )
 
         whenever(userTracker.userHandle).thenReturn(mock())
@@ -87,6 +108,7 @@
             val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable)
             keyguardRepository.setKeyguardShowing(true)
             keyguardRepository.setKeyguardOccluded(false)
+            communalInteractor.onSceneChanged(CommunalSceneKey.Blank)
             communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
             assertThat(isTutorialAvailable).isFalse()
         }
@@ -97,6 +119,7 @@
             val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable)
             keyguardRepository.setKeyguardShowing(true)
             keyguardRepository.setKeyguardOccluded(false)
+            communalInteractor.onSceneChanged(CommunalSceneKey.Blank)
             communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED)
             assertThat(isTutorialAvailable).isTrue()
         }
@@ -107,7 +130,188 @@
             val isTutorialAvailable by collectLastValue(underTest.isTutorialAvailable)
             keyguardRepository.setKeyguardShowing(true)
             keyguardRepository.setKeyguardOccluded(false)
+            communalInteractor.onSceneChanged(CommunalSceneKey.Communal)
             communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED)
             assertThat(isTutorialAvailable).isTrue()
         }
+
+    /* Testing tutorial states with transitions when flexiglass off */
+    @Test
+    fun tutorialState_notStartedAndCommunalSceneShowing_tutorialStarted() =
+        testScope.runTest {
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(communalInteractor.desiredScene)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED)
+
+            communalInteractor.onSceneChanged(CommunalSceneKey.Communal)
+
+            assertThat(currentScene).isEqualTo(CommunalSceneKey.Communal)
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_STARTED)
+        }
+
+    @Test
+    fun tutorialState_startedAndCommunalSceneShowing_stateWillNotUpdate() =
+        testScope.runTest {
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(communalInteractor.desiredScene)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED)
+
+            communalInteractor.onSceneChanged(CommunalSceneKey.Communal)
+
+            assertThat(currentScene).isEqualTo(CommunalSceneKey.Communal)
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_STARTED)
+        }
+
+    @Test
+    fun tutorialState_completedAndCommunalSceneShowing_stateWillNotUpdate() =
+        testScope.runTest {
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(communalInteractor.desiredScene)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
+
+            communalInteractor.onSceneChanged(CommunalSceneKey.Communal)
+
+            assertThat(currentScene).isEqualTo(CommunalSceneKey.Communal)
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED)
+        }
+
+    @Test
+    fun tutorialState_notStartedAndCommunalSceneNotShowing_stateWillNotUpdate() =
+        testScope.runTest {
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(communalInteractor.desiredScene)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED)
+
+            communalInteractor.onSceneChanged(CommunalSceneKey.Blank)
+
+            assertThat(currentScene).isEqualTo(CommunalSceneKey.Blank)
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_NOT_STARTED)
+        }
+
+    @Test
+    fun tutorialState_startedAndCommunalSceneNotShowing_tutorialCompleted() =
+        testScope.runTest {
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(communalInteractor.desiredScene)
+            communalInteractor.onSceneChanged(CommunalSceneKey.Communal)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED)
+
+            communalInteractor.onSceneChanged(CommunalSceneKey.Blank)
+
+            assertThat(currentScene).isEqualTo(CommunalSceneKey.Blank)
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED)
+        }
+
+    @Test
+    fun tutorialState_completedAndCommunalSceneNotShowing_stateWillNotUpdate() =
+        testScope.runTest {
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(communalInteractor.desiredScene)
+            communalInteractor.onSceneChanged(CommunalSceneKey.Communal)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
+
+            communalInteractor.onSceneChanged(CommunalSceneKey.Blank)
+
+            assertThat(currentScene).isEqualTo(CommunalSceneKey.Blank)
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED)
+        }
+
+    /* Testing tutorial states with transitions when flexiglass on */
+    @Test
+    fun tutorialState_notStartedCommunalSceneShowingAndFlexiglassOn_tutorialStarted() =
+        testScope.runTest {
+            sceneContainerFlags.enabled = true
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED)
+
+            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Communal), "reason")
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Communal))
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_STARTED)
+        }
+
+    @Test
+    fun tutorialState_startedCommunalSceneShowingAndFlexiglassOn_stateWillNotUpdate() =
+        testScope.runTest {
+            sceneContainerFlags.enabled = true
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED)
+
+            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Communal), "reason")
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Communal))
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_STARTED)
+        }
+
+    @Test
+    fun tutorialState_completedCommunalSceneShowingAndFlexiglassOn_stateWillNotUpdate() =
+        testScope.runTest {
+            sceneContainerFlags.enabled = true
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
+
+            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Communal), "reason")
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Communal))
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED)
+        }
+
+    @Test
+    fun tutorialState_notStartedCommunalSceneNotShowingAndFlexiglassOn_stateWillNotUpdate() =
+        testScope.runTest {
+            sceneContainerFlags.enabled = true
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED)
+
+            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Lockscreen), "reason")
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_NOT_STARTED)
+        }
+
+    @Test
+    fun tutorialState_startedCommunalSceneNotShowingAndFlexiglassOn_tutorialCompleted() =
+        testScope.runTest {
+            sceneContainerFlags.enabled = true
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Communal), "reason")
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED)
+
+            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Lockscreen), "reason")
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED)
+        }
+
+    @Test
+    fun tutorialState_completedCommunalSceneNotShowingAndFlexiglassOn_stateWillNotUpdate() =
+        testScope.runTest {
+            sceneContainerFlags.enabled = true
+            val tutorialSettingState by
+                collectLastValue(communalTutorialRepository.tutorialSettingState)
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Communal), "reason")
+            communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
+
+            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Lockscreen), "reason")
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+            assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED)
+        }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
index d80dd76..806930d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt
@@ -380,6 +380,32 @@
         }
 
     @Test
+    fun pendingDisplay_afterConfigChanged_doesNotChange() =
+        testScope.runTest {
+            val pendingDisplay by lastPendingDisplay()
+
+            sendOnDisplayConnected(1, TYPE_EXTERNAL)
+            val initialPendingDisplay: DisplayRepository.PendingDisplay? = pendingDisplay
+            assertThat(pendingDisplay).isNotNull()
+            sendOnDisplayChanged(1)
+
+            assertThat(initialPendingDisplay).isEqualTo(pendingDisplay)
+        }
+
+    @Test
+    fun pendingDisplay_afterNewHigherDisplayConnected_changes() =
+        testScope.runTest {
+            val pendingDisplay by lastPendingDisplay()
+
+            sendOnDisplayConnected(1, TYPE_EXTERNAL)
+            val initialPendingDisplay: DisplayRepository.PendingDisplay? = pendingDisplay
+            assertThat(pendingDisplay).isNotNull()
+            sendOnDisplayConnected(2, TYPE_EXTERNAL)
+
+            assertThat(initialPendingDisplay).isNotEqualTo(pendingDisplay)
+        }
+
+    @Test
     fun onPendingDisplay_OneInternalAndOneExternalDisplay_internalIgnored() =
         testScope.runTest {
             val pendingDisplay by lastPendingDisplay()
@@ -466,6 +492,10 @@
         connectedDisplayListener.value.onDisplayConnected(id)
     }
 
+    private fun sendOnDisplayChanged(id: Int) {
+        connectedDisplayListener.value.onDisplayChanged(id)
+    }
+
     private fun setDisplays(displays: List<Display>) {
         whenever(displayManager.displays).thenReturn(displays.toTypedArray())
         displays.forEach { display ->
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
index f51745b..b589a2a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsClassicDebugTest.kt
@@ -22,7 +22,6 @@
 import android.content.res.Resources
 import android.content.res.Resources.NotFoundException
 import android.test.suitebuilder.annotation.SmallTest
-import com.android.systemui.FakeFeatureFlagsImpl
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
@@ -66,7 +65,6 @@
     private lateinit var broadcastReceiver: BroadcastReceiver
     private lateinit var clearCacheAction: Consumer<String>
     private val serverFlagReader = ServerFlagReaderFake()
-    private val fakeGantryFlags = FakeFeatureFlagsImpl()
 
     private val teamfoodableFlagA = UnreleasedFlag(name = "a", namespace = "test", teamfood = true)
     private val teamfoodableFlagB = ReleasedFlag(name = "b", namespace = "test", teamfood = true)
@@ -74,7 +72,6 @@
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        fakeGantryFlags.setFlag("com.android.systemui.sysui_teamfood", false)
         flagMap.put(teamfoodableFlagA.name, teamfoodableFlagA)
         flagMap.put(teamfoodableFlagB.name, teamfoodableFlagB)
         mFeatureFlagsClassicDebug =
@@ -86,7 +83,6 @@
                 resources,
                 serverFlagReader,
                 flagMap,
-                fakeGantryFlags,
                 restarter
             )
         mFeatureFlagsClassicDebug.init()
@@ -134,7 +130,7 @@
 
     @Test
     fun teamFoodFlag_True() {
-        fakeGantryFlags.setFlag("com.android.systemui.sysui_teamfood", true)
+        mSetFlagsRule.enableFlags(com.android.systemui.Flags.FLAG_SYSUI_TEAMFOOD)
         assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagA)).isTrue()
         assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagB)).isTrue()
 
@@ -149,7 +145,7 @@
             .thenReturn(true)
         whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.name), any()))
             .thenReturn(false)
-        fakeGantryFlags.setFlag("com.android.systemui.sysui_teamfood", true)
+        mSetFlagsRule.enableFlags(com.android.systemui.Flags.FLAG_SYSUI_TEAMFOOD)
         assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagA)).isTrue()
         assertThat(mFeatureFlagsClassicDebug.isEnabled(teamfoodableFlagB)).isFalse()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 27325d3..ad2ec72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -203,7 +203,8 @@
                     fromScene = SceneKey.Gone,
                     toScene = SceneKey.Lockscreen,
                     progress = flowOf(0f),
-                    isUserInputDriven = false,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
                 )
             runCurrent()
             assertThat(isAnimate).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
index b80771f..4a1386e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardRootViewModelTest.kt
@@ -15,16 +15,24 @@
  *
  */
 
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
 package com.android.systemui.keyguard.ui.viewmodel
 
 import android.view.View
 import androidx.test.filters.SmallTest
+import com.android.SysUITestModule
+import com.android.TestMocksModule
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
+import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory
@@ -33,14 +41,25 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.plugins.ClockController
+import com.android.systemui.statusbar.notification.data.repository.FakeNotificationsKeyguardViewStateRepository
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.ui.isAnimating
+import com.android.systemui.util.ui.stopAnimating
+import com.android.systemui.util.ui.value
 import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
 import javax.inject.Provider
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -48,7 +67,10 @@
 import org.junit.runners.JUnit4
 import org.mockito.Answers
 import org.mockito.Mock
+import org.mockito.Mockito.RETURNS_DEEP_STUBS
 import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.withSettings
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -81,7 +103,7 @@
         MockitoAnnotations.initMocks(this)
 
         val featureFlags =
-            FakeFeatureFlags().apply {
+            FakeFeatureFlagsClassic().apply {
                 set(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA, true)
                 set(Flags.FACE_AUTH_REFACTOR, true)
             }
@@ -107,11 +129,21 @@
         underTest =
             KeyguardRootViewModel(
                 context,
+                deviceEntryInteractor =
+                    mock { whenever(isBypassEnabled).thenReturn(MutableStateFlow(false)) },
+                dozeParameters = mock(),
+                featureFlags,
                 keyguardInteractor,
+                keyguardTransitionInteractor,
+                notificationsKeyguardInteractor =
+                    mock {
+                        whenever(areNotificationsFullyHidden).thenReturn(emptyFlow())
+                        whenever(isPulseExpanding).thenReturn(emptyFlow())
+                    },
                 burnInInteractor,
                 goneToAodTransitionViewModel,
                 aodToLockscreenTransitionViewModel,
-                keyguardTransitionInteractor,
+                screenOffAnimationController = mock(),
             )
         underTest.clockControllerProvider = Provider { clockController }
     }
@@ -281,3 +313,169 @@
             assertThat(burnInLayerAlpha).isEqualTo(1f)
         }
 }
+
+@SmallTest
+class KeyguardRootViewModelTestWithFakes : SysuiTestCase() {
+
+    @Component(modules = [SysUITestModule::class])
+    @SysUISingleton
+    interface TestComponent {
+        val underTest: KeyguardRootViewModel
+        val deviceEntryRepository: FakeDeviceEntryRepository
+        val notifsKeyguardRepository: FakeNotificationsKeyguardViewStateRepository
+        val repository: FakeKeyguardRepository
+        val testScope: TestScope
+        val transitionRepository: FakeKeyguardTransitionRepository
+
+        @Component.Factory
+        interface Factory {
+            fun create(
+                @BindsInstance test: SysuiTestCase,
+                featureFlags: FakeFeatureFlagsClassicModule,
+                mocks: TestMocksModule,
+            ): TestComponent
+        }
+    }
+
+    private val clockController: ClockController =
+        mock(withSettings().defaultAnswer(RETURNS_DEEP_STUBS))
+    private val dozeParams: DozeParameters = mock()
+    private val screenOffAnimController: ScreenOffAnimationController = mock()
+
+    private fun runTest(block: suspend TestComponent.() -> Unit): Unit =
+        DaggerKeyguardRootViewModelTestWithFakes_TestComponent.factory()
+            .create(
+                test = this,
+                featureFlags =
+                    FakeFeatureFlagsClassicModule {
+                        setDefault(Flags.NEW_AOD_TRANSITION)
+                        set(Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA, true)
+                        set(Flags.FACE_AUTH_REFACTOR, true)
+                    },
+                mocks =
+                    TestMocksModule(
+                        dozeParameters = dozeParams,
+                        screenOffAnimationController = screenOffAnimController,
+                    )
+            )
+            .run {
+                reset(clockController)
+                underTest.clockControllerProvider = Provider { clockController }
+                testScope.runTest {
+                    runCurrent()
+                    block()
+                }
+            }
+
+    @Test
+    fun iconContainer_isNotVisible_notOnKeyguard_dontShowAodIconsWhenShade() = runTest {
+        val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible)
+        testScope.runCurrent()
+        transitionRepository.sendTransitionSteps(
+            from = KeyguardState.OFF,
+            to = KeyguardState.GONE,
+            testScope,
+        )
+        whenever(screenOffAnimController.shouldShowAodIconsWhenShade()).thenReturn(false)
+        testScope.runCurrent()
+
+        assertThat(isVisible?.value).isFalse()
+        assertThat(isVisible?.isAnimating).isFalse()
+    }
+
+    @Test
+    fun iconContainer_isVisible_bypassEnabled() = runTest {
+        val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible)
+        testScope.runCurrent()
+        deviceEntryRepository.setBypassEnabled(true)
+        testScope.runCurrent()
+
+        assertThat(isVisible?.value).isTrue()
+    }
+
+    @Test
+    fun iconContainer_isNotVisible_pulseExpanding_notBypassing() = runTest {
+        val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible)
+        testScope.runCurrent()
+        notifsKeyguardRepository.setPulseExpanding(true)
+        deviceEntryRepository.setBypassEnabled(false)
+        testScope.runCurrent()
+
+        assertThat(isVisible?.value).isEqualTo(false)
+    }
+
+    @Test
+    fun iconContainer_isVisible_notifsFullyHidden_bypassEnabled() = runTest {
+        val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible)
+        testScope.runCurrent()
+        notifsKeyguardRepository.setPulseExpanding(false)
+        deviceEntryRepository.setBypassEnabled(true)
+        notifsKeyguardRepository.setNotificationsFullyHidden(true)
+        testScope.runCurrent()
+
+        assertThat(isVisible?.value).isTrue()
+        assertThat(isVisible?.isAnimating).isTrue()
+    }
+
+    @Test
+    fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled_aodDisabled() = runTest {
+        val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible)
+        testScope.runCurrent()
+        notifsKeyguardRepository.setPulseExpanding(false)
+        deviceEntryRepository.setBypassEnabled(false)
+        whenever(dozeParams.alwaysOn).thenReturn(false)
+        notifsKeyguardRepository.setNotificationsFullyHidden(true)
+        testScope.runCurrent()
+
+        assertThat(isVisible?.value).isTrue()
+        assertThat(isVisible?.isAnimating).isFalse()
+    }
+
+    @Test
+    fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled_displayNeedsBlanking() = runTest {
+        val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible)
+        testScope.runCurrent()
+        notifsKeyguardRepository.setPulseExpanding(false)
+        deviceEntryRepository.setBypassEnabled(false)
+        whenever(dozeParams.alwaysOn).thenReturn(true)
+        whenever(dozeParams.displayNeedsBlanking).thenReturn(true)
+        notifsKeyguardRepository.setNotificationsFullyHidden(true)
+        testScope.runCurrent()
+
+        assertThat(isVisible?.value).isTrue()
+        assertThat(isVisible?.isAnimating).isFalse()
+    }
+
+    @Test
+    fun iconContainer_isVisible_notifsFullyHidden_bypassDisabled() = runTest {
+        val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible)
+        testScope.runCurrent()
+        notifsKeyguardRepository.setPulseExpanding(false)
+        deviceEntryRepository.setBypassEnabled(false)
+        whenever(dozeParams.alwaysOn).thenReturn(true)
+        whenever(dozeParams.displayNeedsBlanking).thenReturn(false)
+        notifsKeyguardRepository.setNotificationsFullyHidden(true)
+        testScope.runCurrent()
+
+        assertThat(isVisible?.value).isTrue()
+        assertThat(isVisible?.isAnimating).isTrue()
+    }
+
+    @Test
+    fun isIconContainerVisible_stopAnimation() = runTest {
+        val isVisible by testScope.collectLastValue(underTest.isNotifIconContainerVisible)
+        testScope.runCurrent()
+        notifsKeyguardRepository.setPulseExpanding(false)
+        deviceEntryRepository.setBypassEnabled(false)
+        whenever(dozeParams.alwaysOn).thenReturn(true)
+        whenever(dozeParams.displayNeedsBlanking).thenReturn(false)
+        notifsKeyguardRepository.setNotificationsFullyHidden(true)
+        testScope.runCurrent()
+
+        assertThat(isVisible?.isAnimating).isEqualTo(true)
+        isVisible?.stopAnimating()
+        testScope.runCurrent()
+
+        assertThat(isVisible?.isAnimating).isEqualTo(false)
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
index 5296f1a..5bfe569 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaHierarchyManagerTest.kt
@@ -25,6 +25,10 @@
 import androidx.test.filters.SmallTest
 import com.android.keyguard.KeyguardViewController
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.repository.FakeCommunalRepository
+import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.shared.model.CommunalSceneKey
 import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
 import com.android.systemui.dreams.DreamOverlayStateController
 import com.android.systemui.keyguard.WakefulnessLifecycle
@@ -46,6 +50,11 @@
 import com.android.systemui.util.settings.FakeSettings
 import com.android.systemui.utils.os.FakeHandler
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
 import org.junit.Assert.assertNotNull
 import org.junit.Before
 import org.junit.Rule
@@ -63,6 +72,7 @@
 import org.mockito.Mockito.`when` as whenever
 import org.mockito.junit.MockitoJUnit
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper
@@ -71,6 +81,7 @@
     @Mock private lateinit var lockHost: MediaHost
     @Mock private lateinit var qsHost: MediaHost
     @Mock private lateinit var qqsHost: MediaHost
+    @Mock private lateinit var hubModeHost: MediaHost
     @Mock private lateinit var bypassController: KeyguardBypassController
     @Mock private lateinit var keyguardStateController: KeyguardStateController
     @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
@@ -93,10 +104,15 @@
     private lateinit var mediaHierarchyManager: MediaHierarchyManager
     private lateinit var mediaFrame: ViewGroup
     private val configurationController = FakeConfigurationController()
+    private val communalRepository = FakeCommunalRepository(isCommunalEnabled = true)
+    private val communalInteractor =
+        CommunalInteractor(communalRepository, FakeCommunalWidgetRepository())
     private val notifPanelEvents = ShadeExpansionStateManager()
     private val settings = FakeSettings()
     private lateinit var testableLooper: TestableLooper
     private lateinit var fakeHandler: FakeHandler
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
 
     @Before
     fun setup() {
@@ -117,11 +133,13 @@
                 mediaDataManager,
                 keyguardViewController,
                 dreamOverlayStateController,
+                communalInteractor,
                 configurationController,
                 wakefulnessLifecycle,
                 notifPanelEvents,
                 settings,
                 fakeHandler,
+                testScope.backgroundScope,
                 ResourcesSplitShadeStateController(),
                 logger,
             )
@@ -131,6 +149,7 @@
         setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN, LOCKSCREEN_TOP)
         setupHost(qsHost, MediaHierarchyManager.LOCATION_QS, QS_TOP)
         setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS, QQS_TOP)
+        setupHost(hubModeHost, MediaHierarchyManager.LOCATION_COMMUNAL_HUB, COMMUNAL_TOP)
         whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
         whenever(mediaDataManager.hasActiveMedia()).thenReturn(true)
         whenever(mediaCarouselController.mediaCarouselScrollHandler)
@@ -475,6 +494,33 @@
     }
 
     @Test
+    fun testCommunalLocation() =
+        testScope.runTest {
+            communalInteractor.onSceneChanged(CommunalSceneKey.Communal)
+            runCurrent()
+            verify(mediaCarouselController)
+                .onDesiredLocationChanged(
+                    eq(MediaHierarchyManager.LOCATION_COMMUNAL_HUB),
+                    nullable(),
+                    eq(false),
+                    anyLong(),
+                    anyLong()
+                )
+            clearInvocations(mediaCarouselController)
+
+            communalInteractor.onSceneChanged(CommunalSceneKey.Blank)
+            runCurrent()
+            verify(mediaCarouselController)
+                .onDesiredLocationChanged(
+                    eq(MediaHierarchyManager.LOCATION_QQS),
+                    any(MediaHostState::class.java),
+                    eq(false),
+                    anyLong(),
+                    anyLong()
+                )
+        }
+
+    @Test
     fun testQsExpandedChanged_noQqsMedia() {
         // When we are looking at QQS with active media
         whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
@@ -538,5 +584,6 @@
         private const val QQS_TOP = 123
         private const val QS_TOP = 456
         private const val LOCKSCREEN_TOP = 789
+        private const val COMMUNAL_TOP = 111
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTileDefaultsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTileDefaultsRepositoryTest.kt
new file mode 100644
index 0000000..89ba69f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTileDefaultsRepositoryTest.kt
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom
+
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
+import android.content.pm.ServiceInfo
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.qs.tiles.impl.custom.data.entity.CustomTileDefaults
+import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTileDefaultsRepository
+import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTileDefaultsRepositoryImpl
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class CustomTileDefaultsRepositoryTest : SysuiTestCase() {
+
+    @Mock private lateinit var sysuiContext: Context
+    @Mock private lateinit var user1Context: Context
+    @Mock private lateinit var user2Context: Context
+    @Mock private lateinit var packageManager1: PackageManager
+    @Mock private lateinit var packageManager2: PackageManager
+
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+
+    private lateinit var underTest: CustomTileDefaultsRepository
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+
+        whenever(sysuiContext.createContextAsUser(eq(USER_1), any())).thenReturn(user1Context)
+        whenever(user1Context.packageManager).thenReturn(packageManager1)
+        packageManager1.setupApp1()
+
+        whenever(sysuiContext.createContextAsUser(eq(USER_2), any())).thenReturn(user2Context)
+        whenever(user2Context.packageManager).thenReturn(packageManager2)
+        packageManager2.setupApp2()
+
+        underTest =
+            CustomTileDefaultsRepositoryImpl(
+                sysuiContext,
+                testScope.backgroundScope,
+                testDispatcher,
+            )
+    }
+
+    @Test
+    fun regularRequestingEmitsTheNewDefault() =
+        testScope.runTest {
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+
+            runCurrent()
+
+            val default = underTest.defaults(USER_1).first() as CustomTileDefaults.Result
+            assertThat(default.label).isEqualTo(APP_LABEL_1)
+            assertThat(default.icon.resId).isEqualTo(SERVICE_ICON_1)
+            assertThat(default.icon.resPackage).isEqualTo(COMPONENT_NAME_1.packageName)
+        }
+
+    @Test
+    fun requestingSystemAppEmitsTheNewDefault() =
+        testScope.runTest {
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+
+            runCurrent()
+
+            val default = underTest.defaults(USER_1).first() as CustomTileDefaults.Result
+            assertThat(default.label).isEqualTo(APP_LABEL_1)
+            assertThat(default.icon.resId).isEqualTo(SERVICE_ICON_1)
+            assertThat(default.icon.resPackage).isEqualTo(COMPONENT_NAME_1.packageName)
+        }
+
+    @Test
+    fun requestingForcesTheNewEmit() =
+        testScope.runTest {
+            val defaults = mutableListOf<CustomTileDefaults.Result>()
+            backgroundScope.launch {
+                underTest
+                    .defaults(USER_1)
+                    .map { it as CustomTileDefaults.Result }
+                    .collect { defaults.add(it) }
+            }
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+            // the same request should be skipped. This leads to 2 result in assertions
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+            runCurrent()
+
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, true)
+            runCurrent()
+
+            assertThat(defaults).hasSize(2)
+            assertThat(defaults.last().label).isEqualTo(APP_LABEL_1)
+            assertThat(defaults.last().icon.resId).isEqualTo(SERVICE_ICON_1)
+            assertThat(defaults.last().icon.resPackage).isEqualTo(COMPONENT_NAME_1.packageName)
+        }
+
+    @Test
+    fun userChangeForcesTheNewEmit() =
+        testScope.runTest {
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+            runCurrent()
+
+            underTest.requestNewDefaults(USER_2, COMPONENT_NAME_2, false)
+            runCurrent()
+
+            val default = underTest.defaults(USER_2).first() as CustomTileDefaults.Result
+            assertThat(default.label).isEqualTo(APP_LABEL_2)
+            assertThat(default.icon.resId).isEqualTo(SERVICE_ICON_2)
+            assertThat(default.icon.resPackage).isEqualTo(COMPONENT_NAME_2.packageName)
+        }
+
+    @Test
+    fun componentNameChangeForcesTheNewEmit() =
+        testScope.runTest {
+            packageManager1.setupApp2(false)
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+            runCurrent()
+
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_2, false)
+            runCurrent()
+
+            val default = underTest.defaults(USER_1).first() as CustomTileDefaults.Result
+            assertThat(default.label).isEqualTo(APP_LABEL_2)
+            assertThat(default.icon.resId).isEqualTo(SERVICE_ICON_2)
+            assertThat(default.icon.resPackage).isEqualTo(COMPONENT_NAME_2.packageName)
+        }
+
+    @Test
+    fun noIconIsAnError() =
+        testScope.runTest {
+            packageManager1.setupApp(
+                componentName = COMPONENT_NAME_1,
+                appLabel = "",
+                serviceIcon = 0,
+                appInfoIcon = 0,
+                isSystemApp = false,
+            )
+            underTest.requestNewDefaults(USER_1, COMPONENT_NAME_1, false)
+
+            runCurrent()
+
+            assertThat(underTest.defaults(USER_1).first())
+                .isInstanceOf(CustomTileDefaults.Error::class.java)
+        }
+
+    @Test
+    fun applicationScopeIsFreedWhileNotSubscribed() =
+        testScope.runTest {
+            val listenJob = underTest.defaults(USER_1).launchIn(backgroundScope)
+            listenJob.cancel()
+            assertThat(this.coroutineContext[Job]!!.children.toList()).isEmpty()
+        }
+
+    private fun PackageManager.setupApp1(isSystemApp: Boolean = false) =
+        setupApp(
+            componentName = COMPONENT_NAME_1,
+            serviceIcon = SERVICE_ICON_1,
+            appLabel = APP_LABEL_1,
+            appInfoIcon = APP_INFO_ICON_1,
+            isSystemApp = isSystemApp,
+        )
+    private fun PackageManager.setupApp2(isSystemApp: Boolean = false) =
+        setupApp(
+            componentName = COMPONENT_NAME_2,
+            serviceIcon = SERVICE_ICON_2,
+            appLabel = APP_LABEL_2,
+            appInfoIcon = APP_INFO_ICON_2,
+            isSystemApp = isSystemApp,
+        )
+
+    private fun PackageManager.setupApp(
+        componentName: ComponentName,
+        serviceIcon: Int,
+        appLabel: CharSequence,
+        appInfoIcon: Int = serviceIcon,
+        isSystemApp: Boolean = false,
+    ) {
+        val appInfo =
+            object : ApplicationInfo() {
+                    override fun isSystemApp(): Boolean = isSystemApp
+                }
+                .apply { icon = appInfoIcon }
+        whenever(getApplicationInfo(eq(componentName.packageName), any<Int>())).thenReturn(appInfo)
+
+        // set of desired flags is different for system and a regular app.
+        var serviceFlags =
+            (PackageManager.MATCH_DIRECT_BOOT_UNAWARE or PackageManager.MATCH_DIRECT_BOOT_AWARE)
+        if (isSystemApp) {
+            serviceFlags = serviceFlags or PackageManager.MATCH_DISABLED_COMPONENTS
+        }
+
+        val serviceInfo =
+            object : ServiceInfo() {
+                    override fun loadLabel(pm: PackageManager): CharSequence = appLabel
+                }
+                .apply {
+                    applicationInfo = appInfo
+                    icon = serviceIcon
+                }
+        whenever(getServiceInfo(eq(componentName), eq(serviceFlags))).thenReturn(serviceInfo)
+    }
+
+    private companion object {
+        val USER_1 = UserHandle(1)
+        val USER_2 = UserHandle(2)
+
+        val COMPONENT_NAME_1 = ComponentName("pkg.test_1", "cls")
+        const val SERVICE_ICON_1 = 11
+        const val APP_INFO_ICON_1 = 12
+        const val APP_LABEL_1 = "app_1"
+
+        val COMPONENT_NAME_2 = ComponentName("pkg.test_2", "cls")
+        const val SERVICE_ICON_2 = 21
+        const val APP_INFO_ICON_2 = 22
+        const val APP_LABEL_2 = "app_2"
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt
new file mode 100644
index 0000000..4a22113
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/impl/custom/CustomTilePackageUpdatesRepositoryTest.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom
+
+import android.content.ComponentName
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.qs.external.TileLifecycleManager
+import com.android.systemui.qs.external.TileServiceManager
+import com.android.systemui.qs.pipeline.shared.TileSpec
+import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTilePackageUpdatesRepository
+import com.android.systemui.qs.tiles.impl.custom.data.repository.CustomTilePackageUpdatesRepositoryImpl
+import com.android.systemui.qs.tiles.impl.custom.data.repository.FakeCustomTileDefaultsRepository
+import com.android.systemui.qs.tiles.impl.custom.data.repository.FakeCustomTileDefaultsRepository.DefaultsRequest
+import com.android.systemui.util.mockito.capture
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CustomTilePackageUpdatesRepositoryTest : SysuiTestCase() {
+
+    @Mock private lateinit var tileServiceManager: TileServiceManager
+
+    @Captor
+    private lateinit var listenerCaptor: ArgumentCaptor<TileLifecycleManager.TileChangeListener>
+
+    private val defaultsRepository = FakeCustomTileDefaultsRepository()
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
+
+    private lateinit var underTest: CustomTilePackageUpdatesRepository
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+
+        underTest =
+            CustomTilePackageUpdatesRepositoryImpl(
+                TileSpec.create(COMPONENT_1),
+                USER,
+                tileServiceManager,
+                defaultsRepository,
+                testScope.backgroundScope,
+            )
+    }
+
+    @Test
+    fun packageChangesUpdatesDefaults() =
+        testScope.runTest {
+            val events = mutableListOf<Unit>()
+            underTest.packageChanges.onEach { events.add(it) }.launchIn(backgroundScope)
+            runCurrent()
+            verify(tileServiceManager).setTileChangeListener(capture(listenerCaptor))
+
+            emitPackageChange()
+            runCurrent()
+
+            assertThat(events).hasSize(1)
+            assertThat(defaultsRepository.defaultsRequests).isNotEmpty()
+            assertThat(defaultsRepository.defaultsRequests.last())
+                .isEqualTo(DefaultsRequest(USER, COMPONENT_1, true))
+        }
+
+    @Test
+    fun packageChangesEmittedOnlyForTheTile() =
+        testScope.runTest {
+            val events = mutableListOf<Unit>()
+            underTest.packageChanges.onEach { events.add(it) }.launchIn(backgroundScope)
+            runCurrent()
+            verify(tileServiceManager).setTileChangeListener(capture(listenerCaptor))
+
+            emitPackageChange(COMPONENT_2)
+            runCurrent()
+
+            assertThat(events).isEmpty()
+        }
+
+    private fun emitPackageChange(componentName: ComponentName = COMPONENT_1) {
+        listenerCaptor.value.onTileChanged(componentName)
+    }
+
+    private companion object {
+        val USER = UserHandle(0)
+        val COMPONENT_1 = ComponentName("pkg.test.1", "cls.test")
+        val COMPONENT_2 = ComponentName("pkg.test.2", "cls.test")
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 88a5c17..9c0456c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -54,6 +54,7 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
@@ -466,7 +467,8 @@
                 fromScene = getCurrentSceneInUi(),
                 toScene = to.key,
                 progress = progressFlow,
-                isUserInputDriven = false,
+                isInitiatedByUserInput = false,
+                isUserInputOngoing = flowOf(false),
             )
         runCurrent()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
index 432bd0f..d669006 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
@@ -29,6 +29,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -51,6 +52,7 @@
                     SceneKey.Lockscreen,
                     SceneKey.Bouncer,
                     SceneKey.Gone,
+                    SceneKey.Communal,
                 )
             )
     }
@@ -119,7 +121,8 @@
                     fromScene = SceneKey.Lockscreen,
                     toScene = SceneKey.Shade,
                     progress = progress,
-                    isUserInputDriven = false,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
                 )
             assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index 8b23d18..3f032a4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -83,7 +83,8 @@
                     fromScene = SceneKey.Lockscreen,
                     toScene = SceneKey.Shade,
                     progress = progress,
-                    isUserInputDriven = false,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
                 )
             assertThat(reflectedTransitionState).isEqualTo(transitionState.value)
 
@@ -121,7 +122,8 @@
                     fromScene = underTest.desiredScene.value.key,
                     toScene = SceneKey.Shade,
                     progress = progress,
-                    isUserInputDriven = false,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
                 )
             assertThat(transitionTo).isEqualTo(SceneKey.Shade)
 
@@ -158,7 +160,8 @@
                         fromScene = SceneKey.Gone,
                         toScene = SceneKey.Lockscreen,
                         progress = flowOf(0.5f),
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             val transitioning by
@@ -177,7 +180,8 @@
                         fromScene = SceneKey.Shade,
                         toScene = SceneKey.QuickSettings,
                         progress = flowOf(0.5f),
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             underTest.setTransitionState(transitionState)
@@ -194,7 +198,8 @@
                         fromScene = SceneKey.Shade,
                         toScene = SceneKey.Lockscreen,
                         progress = flowOf(0.5f),
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             val transitioning by
@@ -222,7 +227,8 @@
                     fromScene = SceneKey.Shade,
                     toScene = SceneKey.Lockscreen,
                     progress = flowOf(0.5f),
-                    isUserInputDriven = false,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
                 )
             assertThat(transitioning).isTrue()
 
@@ -231,6 +237,95 @@
         }
 
     @Test
+    fun isTransitionUserInputOngoing_idle_false() =
+        testScope.runTest {
+            val transitionState =
+                MutableStateFlow<ObservableTransitionState>(
+                    ObservableTransitionState.Idle(SceneKey.Shade)
+                )
+            val isTransitionUserInputOngoing by
+                collectLastValue(underTest.isTransitionUserInputOngoing)
+            underTest.setTransitionState(transitionState)
+
+            assertThat(isTransitionUserInputOngoing).isFalse()
+        }
+
+    @Test
+    fun isTransitionUserInputOngoing_transition_true() =
+        testScope.runTest {
+            val transitionState =
+                MutableStateFlow<ObservableTransitionState>(
+                    ObservableTransitionState.Transition(
+                        fromScene = SceneKey.Shade,
+                        toScene = SceneKey.Lockscreen,
+                        progress = flowOf(0.5f),
+                        isInitiatedByUserInput = true,
+                        isUserInputOngoing = flowOf(true),
+                    )
+                )
+            val isTransitionUserInputOngoing by
+                collectLastValue(underTest.isTransitionUserInputOngoing)
+            underTest.setTransitionState(transitionState)
+
+            assertThat(isTransitionUserInputOngoing).isTrue()
+        }
+
+    @Test
+    fun isTransitionUserInputOngoing_updateMidTransition_false() =
+        testScope.runTest {
+            val transitionState =
+                MutableStateFlow<ObservableTransitionState>(
+                    ObservableTransitionState.Transition(
+                        fromScene = SceneKey.Shade,
+                        toScene = SceneKey.Lockscreen,
+                        progress = flowOf(0.5f),
+                        isInitiatedByUserInput = true,
+                        isUserInputOngoing = flowOf(true),
+                    )
+                )
+            val isTransitionUserInputOngoing by
+                collectLastValue(underTest.isTransitionUserInputOngoing)
+            underTest.setTransitionState(transitionState)
+
+            assertThat(isTransitionUserInputOngoing).isTrue()
+
+            transitionState.value =
+                ObservableTransitionState.Transition(
+                    fromScene = SceneKey.Shade,
+                    toScene = SceneKey.Lockscreen,
+                    progress = flowOf(0.6f),
+                    isInitiatedByUserInput = true,
+                    isUserInputOngoing = flowOf(false),
+                )
+
+            assertThat(isTransitionUserInputOngoing).isFalse()
+        }
+
+    @Test
+    fun isTransitionUserInputOngoing_updateOnIdle_false() =
+        testScope.runTest {
+            val transitionState =
+                MutableStateFlow<ObservableTransitionState>(
+                    ObservableTransitionState.Transition(
+                        fromScene = SceneKey.Shade,
+                        toScene = SceneKey.Lockscreen,
+                        progress = flowOf(0.5f),
+                        isInitiatedByUserInput = true,
+                        isUserInputOngoing = flowOf(true),
+                    )
+                )
+            val isTransitionUserInputOngoing by
+                collectLastValue(underTest.isTransitionUserInputOngoing)
+            underTest.setTransitionState(transitionState)
+
+            assertThat(isTransitionUserInputOngoing).isTrue()
+
+            transitionState.value = ObservableTransitionState.Idle(scene = SceneKey.Lockscreen)
+
+            assertThat(isTransitionUserInputOngoing).isFalse()
+        }
+
+    @Test
     fun isVisible() =
         testScope.runTest {
             val isVisible by collectLastValue(underTest.isVisible)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index c1f2d0c..c0b5861 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -115,7 +115,8 @@
                     fromScene = SceneKey.Gone,
                     toScene = SceneKey.Shade,
                     progress = flowOf(0.5f),
-                    isUserInputDriven = false,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
                 )
             assertThat(isVisible).isTrue()
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Shade), "reason")
@@ -128,7 +129,8 @@
                     fromScene = SceneKey.Shade,
                     toScene = SceneKey.Gone,
                     progress = flowOf(0.5f),
-                    isUserInputDriven = false,
+                    isInitiatedByUserInput = false,
+                    isUserInputOngoing = flowOf(false),
                 )
             assertThat(isVisible).isTrue()
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone), "reason")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
index 0bed4d0..32a38bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt
@@ -76,7 +76,6 @@
         underTest =
             SceneContainerFlagsImpl(
                 featureFlagsClassic = featureFlags,
-                featureFlags = aconfigFlags,
                 isComposeAvailable = testCase.isComposeAvailable,
             )
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index 4e3e165..5459779 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -97,6 +97,7 @@
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
+import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.test.TestScope
@@ -111,9 +112,8 @@
 import org.mockito.Mockito.never
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-import java.util.Optional
 import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
@@ -140,6 +140,7 @@
     @Mock private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
     @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
     @Mock private lateinit var statusBarWindowStateController: StatusBarWindowStateController
+    @Mock private lateinit var quickSettingsController: QuickSettingsController
     @Mock
     private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
     @Mock private lateinit var lockIconViewController: LockIconViewController
@@ -166,7 +167,7 @@
     @Mock lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
     private val notificationLaunchAnimationRepository = NotificationLaunchAnimationRepository()
     private val notificationLaunchAnimationInteractor =
-            NotificationLaunchAnimationInteractor(notificationLaunchAnimationRepository)
+        NotificationLaunchAnimationInteractor(notificationLaunchAnimationRepository)
 
     private lateinit var fakeClock: FakeSystemClock
     private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
@@ -274,6 +275,7 @@
                 ),
                 BouncerLogger(logcatLogBuffer("BouncerLog")),
                 sysUIKeyEventHandler,
+                quickSettingsController,
                 primaryBouncerInteractor,
                 alternateBouncerInteractor,
                 mSelectedUserInteractor,
@@ -460,9 +462,11 @@
         // AND alternate bouncer doesn't want the touch
         whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
             .thenReturn(false)
+        // AND quick settings controller doesn't want it
+        whenever(quickSettingsController.shouldQuickSettingsIntercept(any(), any(), any()))
+            .thenReturn(false)
         // AND the lock icon wants the touch
-        whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT))
-                .thenReturn(true)
+        whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT)).thenReturn(true)
 
         featureFlagsClassic.set(MIGRATE_NSSL, true)
 
@@ -476,10 +480,31 @@
         whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
         // AND alternate bouncer doesn't want the touch
         whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
-                .thenReturn(false)
+            .thenReturn(false)
         // AND the lock icon does NOT want the touch
-        whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT))
-                .thenReturn(false)
+        whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT)).thenReturn(false)
+        // AND quick settings controller doesn't want it
+        whenever(quickSettingsController.shouldQuickSettingsIntercept(any(), any(), any()))
+            .thenReturn(false)
+
+        featureFlagsClassic.set(MIGRATE_NSSL, true)
+
+        // THEN touch should NOT be intercepted by NotificationShade
+        assertThat(interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)).isTrue()
+    }
+
+    @Test
+    fun shouldInterceptTouchEvent_dozing_touchInStatusBar_touchIntercepted() {
+        // GIVEN dozing
+        whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
+        // AND alternate bouncer doesn't want the touch
+        whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
+            .thenReturn(false)
+        // AND the lock icon does NOT want the touch
+        whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT)).thenReturn(false)
+        // AND quick settings controller DOES want it
+        whenever(quickSettingsController.shouldQuickSettingsIntercept(any(), any(), any()))
+            .thenReturn(true)
 
         featureFlagsClassic.set(MIGRATE_NSSL, true)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
index 3d5d26a..a6ab6a5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.kt
@@ -121,6 +121,7 @@
     @Mock private lateinit var notificationStackScrollLayout: NotificationStackScrollLayout
     @Mock private lateinit var notificationShadeDepthController: NotificationShadeDepthController
     @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
+    @Mock private lateinit var quickSettingsController: QuickSettingsController
     @Mock
     private lateinit var notificationStackScrollLayoutController:
         NotificationStackScrollLayoutController
@@ -264,6 +265,7 @@
                 ),
                 BouncerLogger(logcatLogBuffer("BouncerLog")),
                 Mockito.mock(SysUIKeyEventHandler::class.java),
+                quickSettingsController,
                 primaryBouncerInteractor,
                 alternateBouncerInteractor,
                 mSelectedUserInteractor,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
index 3a260ae..8b8a625 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeInteractorTest.kt
@@ -60,6 +60,7 @@
 import dagger.Component
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
@@ -495,7 +496,8 @@
                         fromScene = SceneKey.Lockscreen,
                         toScene = key,
                         progress = progress,
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             sceneInteractor.setTransitionState(transitionState)
@@ -532,7 +534,8 @@
                         fromScene = key,
                         toScene = SceneKey.Lockscreen,
                         progress = progress,
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             sceneInteractor.setTransitionState(transitionState)
@@ -568,7 +571,8 @@
                         fromScene = SceneKey.Lockscreen,
                         toScene = SceneKey.Shade,
                         progress = progress,
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             sceneInteractor.setTransitionState(transitionState)
@@ -844,7 +848,8 @@
                         fromScene = SceneKey.Lockscreen,
                         toScene = key,
                         progress = progress,
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             sceneInteractor.setTransitionState(transitionState)
@@ -881,7 +886,8 @@
                         fromScene = SceneKey.Lockscreen,
                         toScene = key,
                         progress = progress,
-                        isUserInputDriven = true,
+                        isInitiatedByUserInput = true,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             sceneInteractor.setTransitionState(transitionState)
@@ -918,7 +924,8 @@
                         fromScene = key,
                         toScene = SceneKey.Lockscreen,
                         progress = progress,
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             sceneInteractor.setTransitionState(transitionState)
@@ -955,7 +962,8 @@
                         fromScene = key,
                         toScene = SceneKey.Lockscreen,
                         progress = progress,
-                        isUserInputDriven = true,
+                        isInitiatedByUserInput = true,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             sceneInteractor.setTransitionState(transitionState)
@@ -990,8 +998,9 @@
                     ObservableTransitionState.Transition(
                         fromScene = SceneKey.Lockscreen,
                         toScene = SceneKey.QuickSettings,
-                        progress = progress,
-                        isUserInputDriven = true,
+                        progress = MutableStateFlow(0f),
+                        isInitiatedByUserInput = true,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             sceneInteractor.setTransitionState(transitionState)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
index f98267b..02d15de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeHeaderViewModelTest.kt
@@ -20,6 +20,7 @@
 import com.android.systemui.util.mockito.mock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -89,7 +90,8 @@
                         fromScene = SceneKey.Shade,
                         toScene = SceneKey.QuickSettings,
                         progress = MutableStateFlow(0.5f),
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             )
@@ -107,7 +109,8 @@
                         fromScene = SceneKey.QuickSettings,
                         toScene = SceneKey.Shade,
                         progress = MutableStateFlow(0.5f),
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             )
@@ -125,7 +128,8 @@
                         fromScene = SceneKey.Gone,
                         toScene = SceneKey.Shade,
                         progress = MutableStateFlow(0.5f),
-                        isUserInputDriven = false,
+                        isInitiatedByUserInput = false,
+                        isUserInputOngoing = flowOf(false),
                     )
                 )
             )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
index 2e223f6..df257ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventChipAnimationControllerTest.kt
@@ -27,7 +27,6 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.AnimatorTestRule
-import com.android.systemui.flags.FakeFeatureFlags
 import com.android.systemui.statusbar.phone.StatusBarContentInsetsChangedListener
 import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
 import com.android.systemui.statusbar.window.StatusBarWindowController
@@ -88,8 +87,7 @@
             SystemEventChipAnimationController(
                 context = mContext,
                 statusBarWindowController = sbWindowController,
-                contentInsetsProvider = insetsProvider,
-                featureFlags = FakeFeatureFlags(),
+                contentInsetsProvider = insetsProvider
             )
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventCoordinatorTest.kt
index c289ff3..bbc63f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemEventCoordinatorTest.kt
@@ -21,7 +21,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor
 import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State.CONNECTED
 import com.android.systemui.privacy.PrivacyItemController
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.util.mockito.any
@@ -48,7 +48,6 @@
 class SystemEventCoordinatorTest : SysuiTestCase() {
 
     private val fakeSystemClock = FakeSystemClock()
-    private val featureFlags = FakeFeatureFlags()
     private val testScope = TestScope(UnconfinedTestDispatcher())
     private val connectedDisplayInteractor = FakeConnectedDisplayInteractor()
 
@@ -66,7 +65,6 @@
                     batteryController,
                     privacyController,
                     context,
-                    featureFlags,
                     TestScope(UnconfinedTestDispatcher()),
                     connectedDisplayInteractor
                 )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
index fee8b82..5f01b5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImplTest.kt
@@ -26,8 +26,6 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.AnimatorTestRule
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.privacy.OngoingPrivacyChip
 import com.android.systemui.statusbar.BatteryStatusChip
 import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
@@ -76,7 +74,6 @@
     private lateinit var systemClock: FakeSystemClock
     private lateinit var chipAnimationController: SystemEventChipAnimationController
     private lateinit var systemStatusAnimationScheduler: SystemStatusAnimationScheduler
-    private val fakeFeatureFlags = FakeFeatureFlags()
 
     @get:Rule val animatorTestRule = AnimatorTestRule()
 
@@ -84,15 +81,12 @@
     fun setup() {
         MockitoAnnotations.initMocks(this)
 
-        fakeFeatureFlags.set(Flags.PLUG_IN_STATUS_BAR_CHIP, true)
-
         systemClock = FakeSystemClock()
         chipAnimationController =
             SystemEventChipAnimationController(
                 mContext,
                 statusBarWindowController,
-                statusBarContentInsetProvider,
-                fakeFeatureFlags
+                statusBarContentInsetProvider
             )
 
         // StatusBarContentInsetProvider is mocked. Ensure that it returns some mocked values.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
index ca8ea4e..b86f841 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationsListInteractorTest.kt
@@ -19,6 +19,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
 import com.android.systemui.statusbar.notification.shared.byKey
 import com.android.systemui.util.mockito.mock
@@ -40,9 +41,19 @@
 
     @Test
     fun setRenderedList_preservesOrdering() = runTest {
-        val notifs by collectLastValue(notifsInteractor.notifications)
+        val notifs by collectLastValue(notifsInteractor.topLevelRepresentativeNotifications)
         val keys = (1..50).shuffled().map { "$it" }
-        val entries = keys.map { mock<ListEntry> { whenever(key).thenReturn(it) } }
+        val entries =
+            keys.map {
+                mock<ListEntry> {
+                    val mockRep = mock<NotificationEntry> {
+                        whenever(key).thenReturn(it)
+                        whenever(sbn).thenReturn(mock())
+                        whenever(icons).thenReturn(mock())
+                    }
+                    whenever(representativeEntry).thenReturn(mockRep)
+                }
+            }
         underTest.setRenderedList(entries)
         assertThat(notifs).comparingElementsUsing(byKey).containsExactlyElementsIn(keys).inOrder()
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
index ec80e5f..f8252a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
 import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
 import com.android.systemui.statusbar.notification.data.repository.FakeNotificationsKeyguardViewStateRepository
 import com.android.systemui.statusbar.notification.shared.activeNotificationModel
 import com.android.systemui.statusbar.notification.shared.byIsAmbient
@@ -77,7 +78,9 @@
     fun setup() =
         with(testComponent) {
             activeNotificationListRepository.activeNotifications.value =
-                testIcons.associateBy { it.key }
+                ActiveNotificationsStore.Builder()
+                    .apply { testIcons.forEach(::addIndividualNotif) }
+                    .build()
         }
 
     @Test
@@ -196,7 +199,9 @@
     fun setup() =
         with(testComponent) {
             activeNotificationListRepository.activeNotifications.value =
-                testIcons.associateBy { it.key }
+                ActiveNotificationsStore.Builder()
+                    .apply { testIcons.forEach(::addIndividualNotif) }
+                    .build()
         }
 
     @Test
@@ -318,7 +323,9 @@
     fun setup() =
         with(testComponent) {
             activeNotificationListRepository.activeNotifications.value =
-                testIcons.associateBy { it.key }
+                ActiveNotificationsStore.Builder()
+                    .apply { testIcons.forEach(::addIndividualNotif) }
+                    .build()
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
index 14d188c..49e1493 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
 import com.android.systemui.flags.FakeFeatureFlagsClassicModule
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
@@ -38,7 +37,6 @@
 import com.android.systemui.power.data.repository.FakePowerRepository
 import com.android.systemui.power.shared.model.WakeSleepReason
 import com.android.systemui.power.shared.model.WakefulnessState
-import com.android.systemui.statusbar.notification.data.repository.FakeNotificationsKeyguardViewStateRepository
 import com.android.systemui.statusbar.phone.DozeParameters
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController
 import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
@@ -70,16 +68,12 @@
     private lateinit var testComponent: TestComponent
     private val underTest: NotificationIconContainerAlwaysOnDisplayViewModel
         get() = testComponent.underTest
-    private val deviceEntryRepository: FakeDeviceEntryRepository
-        get() = testComponent.deviceEntryRepository
     private val deviceProvisioningRepository: FakeDeviceProvisioningRepository
         get() = testComponent.deviceProvisioningRepository
     private val keyguardRepository: FakeKeyguardRepository
         get() = testComponent.keyguardRepository
     private val keyguardTransitionRepository: FakeKeyguardTransitionRepository
         get() = testComponent.keyguardTransitionRepository
-    private val notifsKeyguardRepository: FakeNotificationsKeyguardViewStateRepository
-        get() = testComponent.notifsKeyguardRepository
     private val powerRepository: FakePowerRepository
         get() = testComponent.powerRepository
     private val scope: TestScope
@@ -354,137 +348,6 @@
             assertThat(isDozing?.isAnimating).isEqualTo(false)
         }
 
-    @Test
-    fun isNotVisible_pulseExpanding() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            notifsKeyguardRepository.setPulseExpanding(true)
-            runCurrent()
-
-            assertThat(isVisible?.value).isFalse()
-        }
-
-    @Test
-    fun isNotVisible_notOnKeyguard_dontShowAodIconsWhenShade() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            keyguardTransitionRepository.sendTransitionSteps(
-                from = KeyguardState.OFF,
-                to = KeyguardState.GONE,
-                scope,
-            )
-            whenever(screenOffAnimController.shouldShowAodIconsWhenShade()).thenReturn(false)
-            runCurrent()
-
-            assertThat(isVisible?.value).isFalse()
-            assertThat(isVisible?.isAnimating).isFalse()
-        }
-
-    @Test
-    fun isVisible_bypassEnabled() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            deviceEntryRepository.setBypassEnabled(true)
-            runCurrent()
-
-            assertThat(isVisible?.value).isTrue()
-        }
-
-    @Test
-    fun isNotVisible_pulseExpanding_notBypassing() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            notifsKeyguardRepository.setPulseExpanding(true)
-            deviceEntryRepository.setBypassEnabled(false)
-            runCurrent()
-
-            assertThat(isVisible?.value).isEqualTo(false)
-        }
-
-    @Test
-    fun isVisible_notifsFullyHidden_bypassEnabled() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            notifsKeyguardRepository.setPulseExpanding(false)
-            deviceEntryRepository.setBypassEnabled(true)
-            notifsKeyguardRepository.setNotificationsFullyHidden(true)
-            runCurrent()
-
-            assertThat(isVisible?.value).isTrue()
-            assertThat(isVisible?.isAnimating).isTrue()
-        }
-
-    @Test
-    fun isVisible_notifsFullyHidden_bypassDisabled_aodDisabled() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            notifsKeyguardRepository.setPulseExpanding(false)
-            deviceEntryRepository.setBypassEnabled(false)
-            whenever(dozeParams.alwaysOn).thenReturn(false)
-            notifsKeyguardRepository.setNotificationsFullyHidden(true)
-            runCurrent()
-
-            assertThat(isVisible?.value).isTrue()
-            assertThat(isVisible?.isAnimating).isFalse()
-        }
-
-    @Test
-    fun isVisible_notifsFullyHidden_bypassDisabled_displayNeedsBlanking() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            notifsKeyguardRepository.setPulseExpanding(false)
-            deviceEntryRepository.setBypassEnabled(false)
-            whenever(dozeParams.alwaysOn).thenReturn(true)
-            whenever(dozeParams.displayNeedsBlanking).thenReturn(true)
-            notifsKeyguardRepository.setNotificationsFullyHidden(true)
-            runCurrent()
-
-            assertThat(isVisible?.value).isTrue()
-            assertThat(isVisible?.isAnimating).isFalse()
-        }
-
-    @Test
-    fun isVisible_notifsFullyHidden_bypassDisabled() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            notifsKeyguardRepository.setPulseExpanding(false)
-            deviceEntryRepository.setBypassEnabled(false)
-            whenever(dozeParams.alwaysOn).thenReturn(true)
-            whenever(dozeParams.displayNeedsBlanking).thenReturn(false)
-            notifsKeyguardRepository.setNotificationsFullyHidden(true)
-            runCurrent()
-
-            assertThat(isVisible?.value).isTrue()
-            assertThat(isVisible?.isAnimating).isTrue()
-        }
-
-    @Test
-    fun isVisible_stopAnimation() =
-        scope.runTest {
-            val isVisible by collectLastValue(underTest.isVisible)
-            runCurrent()
-            notifsKeyguardRepository.setPulseExpanding(false)
-            deviceEntryRepository.setBypassEnabled(false)
-            whenever(dozeParams.alwaysOn).thenReturn(true)
-            whenever(dozeParams.displayNeedsBlanking).thenReturn(false)
-            notifsKeyguardRepository.setNotificationsFullyHidden(true)
-            runCurrent()
-
-            assertThat(isVisible?.isAnimating).isEqualTo(true)
-            isVisible?.stopAnimating()
-            runCurrent()
-
-            assertThat(isVisible?.isAnimating).isEqualTo(false)
-        }
-
     @SysUISingleton
     @Component(
         modules =
@@ -498,11 +361,9 @@
 
         val underTest: NotificationIconContainerAlwaysOnDisplayViewModel
 
-        val deviceEntryRepository: FakeDeviceEntryRepository
         val deviceProvisioningRepository: FakeDeviceProvisioningRepository
         val keyguardRepository: FakeKeyguardRepository
         val keyguardTransitionRepository: FakeKeyguardTransitionRepository
-        val notifsKeyguardRepository: FakeNotificationsKeyguardViewStateRepository
         val powerRepository: FakePowerRepository
         val scope: TestScope
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
index ba68fbb..44acac8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerStatusBarViewModelTest.kt
@@ -42,6 +42,7 @@
 import com.android.systemui.power.shared.model.WakefulnessState
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
 import com.android.systemui.statusbar.notification.data.repository.HeadsUpNotificationIconViewStateRepository
 import com.android.systemui.statusbar.notification.shared.activeNotificationModel
 import com.android.systemui.statusbar.phone.DozeParameters
@@ -342,14 +343,17 @@
                 val icon: Icon = mock()
                 shadeRepository.setLegacyShadeExpansion(0f)
                 activeNotificationsRepository.activeNotifications.value =
-                    listOf(
-                            activeNotificationModel(
-                                key = "notif1",
-                                groupKey = "group",
-                                statusBarIcon = icon
+                    ActiveNotificationsStore.Builder()
+                        .apply {
+                            addIndividualNotif(
+                                activeNotificationModel(
+                                    key = "notif1",
+                                    groupKey = "group",
+                                    statusBarIcon = icon
+                                )
                             )
-                        )
-                        .associateBy { it.key }
+                        }
+                        .build()
                 val isolatedIcon by collectLastValue(underTest.isolatedIcon)
                 runCurrent()
 
@@ -368,14 +372,17 @@
                 val icon: Icon = mock()
                 shadeRepository.setLegacyShadeExpansion(.5f)
                 activeNotificationsRepository.activeNotifications.value =
-                    listOf(
-                            activeNotificationModel(
-                                key = "notif1",
-                                groupKey = "group",
-                                statusBarIcon = icon
+                    ActiveNotificationsStore.Builder()
+                        .apply {
+                            addIndividualNotif(
+                                activeNotificationModel(
+                                    key = "notif1",
+                                    groupKey = "group",
+                                    statusBarIcon = icon
+                                )
                             )
-                        )
-                        .associateBy { it.key }
+                        }
+                        .build()
                 val isolatedIcon by collectLastValue(underTest.isolatedIcon)
                 runCurrent()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
index ff89bdb..80d941a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
@@ -18,6 +18,11 @@
 
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.BUBBLE
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PEEK
+import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PULSE
+import org.junit.Test
 import org.junit.runner.RunWith
 
 @SmallTest
@@ -29,6 +34,7 @@
             batteryController,
             globalSettings,
             headsUpManager,
+            keyguardNotificationVisibilityProvider,
             logger,
             mainHandler,
             powerManager,
@@ -37,4 +43,179 @@
             userTracker,
         )
     }
+
+    @Test
+    fun testNothingCondition_suppressesNothing() {
+        withCondition(TestCondition(types = emptySet()) { true }) {
+            assertPeekNotSuppressed()
+            assertPulseNotSuppressed()
+            assertBubbleNotSuppressed()
+        }
+    }
+
+    @Test
+    fun testNothingFilter_suppressesNothing() {
+        withFilter(TestFilter(types = emptySet()) { true }) {
+            assertPeekNotSuppressed()
+            assertPulseNotSuppressed()
+            assertBubbleNotSuppressed()
+        }
+    }
+
+    @Test
+    fun testPeekCondition_suppressesOnlyPeek() {
+        withCondition(TestCondition(types = setOf(PEEK)) { true }) {
+            assertPeekSuppressed()
+            assertPulseNotSuppressed()
+            assertBubbleNotSuppressed()
+        }
+    }
+
+    @Test
+    fun testPeekFilter_suppressesOnlyPeek() {
+        withFilter(TestFilter(types = setOf(PEEK)) { true }) {
+            assertPeekSuppressed()
+            assertPulseNotSuppressed()
+            assertBubbleNotSuppressed()
+        }
+    }
+
+    @Test
+    fun testPulseCondition_suppressesOnlyPulse() {
+        withCondition(TestCondition(types = setOf(PULSE)) { true }) {
+            assertPeekNotSuppressed()
+            assertPulseSuppressed()
+            assertBubbleNotSuppressed()
+        }
+    }
+
+    @Test
+    fun testPulseFilter_suppressesOnlyPulse() {
+        withFilter(TestFilter(types = setOf(PULSE)) { true }) {
+            assertPeekNotSuppressed()
+            assertPulseSuppressed()
+            assertBubbleNotSuppressed()
+        }
+    }
+
+    @Test
+    fun testBubbleCondition_suppressesOnlyBubble() {
+        withCondition(TestCondition(types = setOf(BUBBLE)) { true }) {
+            assertPeekNotSuppressed()
+            assertPulseNotSuppressed()
+            assertBubbleSuppressed()
+        }
+    }
+
+    @Test
+    fun testBubbleFilter_suppressesOnlyBubble() {
+        withFilter(TestFilter(types = setOf(BUBBLE)) { true }) {
+            assertPeekNotSuppressed()
+            assertPulseNotSuppressed()
+            assertBubbleSuppressed()
+        }
+    }
+
+    @Test
+    fun testCondition_differentState() {
+        ensurePeekState()
+        val entry = buildPeekEntry()
+
+        var stateShouldSuppress = false
+        withCondition(TestCondition(types = setOf(PEEK)) { stateShouldSuppress }) {
+            assertShouldHeadsUp(entry)
+
+            stateShouldSuppress = true
+            assertShouldNotHeadsUp(entry)
+
+            stateShouldSuppress = false
+            assertShouldHeadsUp(entry)
+        }
+    }
+
+    @Test
+    fun testFilter_differentState() {
+        ensurePeekState()
+        val entry = buildPeekEntry()
+
+        var stateShouldSuppress = false
+        withFilter(TestFilter(types = setOf(PEEK)) { stateShouldSuppress }) {
+            assertShouldHeadsUp(entry)
+
+            stateShouldSuppress = true
+            assertShouldNotHeadsUp(entry)
+
+            stateShouldSuppress = false
+            assertShouldHeadsUp(entry)
+        }
+    }
+
+    @Test
+    fun testFilter_differentNotif() {
+        ensurePeekState()
+
+        val suppressedEntry = buildPeekEntry()
+        val unsuppressedEntry = buildPeekEntry()
+
+        withFilter(TestFilter(types = setOf(PEEK)) { it == suppressedEntry }) {
+            assertShouldNotHeadsUp(suppressedEntry)
+            assertShouldHeadsUp(unsuppressedEntry)
+        }
+    }
+
+    private fun assertPeekSuppressed() {
+        ensurePeekState()
+        assertShouldNotHeadsUp(buildPeekEntry())
+    }
+
+    private fun assertPeekNotSuppressed() {
+        ensurePeekState()
+        assertShouldHeadsUp(buildPeekEntry())
+    }
+
+    private fun assertPulseSuppressed() {
+        ensurePulseState()
+        assertShouldNotHeadsUp(buildPulseEntry())
+    }
+
+    private fun assertPulseNotSuppressed() {
+        ensurePulseState()
+        assertShouldHeadsUp(buildPulseEntry())
+    }
+
+    private fun assertBubbleSuppressed() {
+        ensureBubbleState()
+        assertShouldNotBubble(buildBubbleEntry())
+    }
+
+    private fun assertBubbleNotSuppressed() {
+        ensureBubbleState()
+        assertShouldBubble(buildBubbleEntry())
+    }
+
+    private fun withCondition(condition: VisualInterruptionCondition, block: () -> Unit) {
+        provider.addCondition(condition)
+        block()
+        provider.removeCondition(condition)
+    }
+
+    private fun withFilter(filter: VisualInterruptionFilter, block: () -> Unit) {
+        provider.addFilter(filter)
+        block()
+        provider.removeFilter(filter)
+    }
+
+    private class TestCondition(
+        types: Set<VisualInterruptionType>,
+        val onShouldSuppress: () -> Boolean
+    ) : VisualInterruptionCondition(types = types, reason = "") {
+        override fun shouldSuppress(): Boolean = onShouldSuppress()
+    }
+
+    private class TestFilter(
+        types: Set<VisualInterruptionType>,
+        val onShouldSuppress: (NotificationEntry) -> Boolean = { true }
+    ) : VisualInterruptionFilter(types = types, reason = "") {
+        override fun shouldSuppress(entry: NotificationEntry) = onShouldSuppress(entry)
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
index 5511194..7f12b22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
@@ -19,9 +19,17 @@
 import android.app.ActivityManager
 import android.app.Notification
 import android.app.Notification.BubbleMetadata
+import android.app.Notification.FLAG_BUBBLE
+import android.app.Notification.GROUP_ALERT_ALL
+import android.app.Notification.GROUP_ALERT_CHILDREN
+import android.app.Notification.GROUP_ALERT_SUMMARY
+import android.app.Notification.VISIBILITY_PRIVATE
 import android.app.NotificationChannel
 import android.app.NotificationManager.IMPORTANCE_DEFAULT
 import android.app.NotificationManager.IMPORTANCE_HIGH
+import android.app.NotificationManager.IMPORTANCE_LOW
+import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT
+import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK
 import android.app.NotificationManager.VISIBILITY_NO_OVERRIDE
 import android.app.PendingIntent
 import android.app.PendingIntent.FLAG_MUTABLE
@@ -43,9 +51,11 @@
 import com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking
 import com.android.systemui.statusbar.StatusBarState.KEYGUARD
 import com.android.systemui.statusbar.StatusBarState.SHADE
+import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
 import com.android.systemui.statusbar.notification.NotifPipelineFlags
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.MAX_HUN_WHEN_AGE_MS
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -127,6 +137,84 @@
     }
 
     @Test
+    fun testShouldNotPeek_packageSnoozed() {
+        ensurePeekState { hunSnoozed = true }
+        assertShouldNotHeadsUp(buildPeekEntry())
+    }
+
+    @Test
+    fun testShouldPeek_packageSnoozedButFsi() {
+        ensurePeekState { hunSnoozed = true }
+        assertShouldHeadsUp(buildFsiEntry())
+    }
+
+    @Test
+    fun testShouldNotPeek_alreadyBubbled() {
+        ensurePeekState { statusBarState = SHADE }
+        assertShouldNotHeadsUp(buildPeekEntry { isBubble = true })
+    }
+
+    @Test
+    fun testShouldPeek_isBubble_shadeLocked() {
+        ensurePeekState { statusBarState = SHADE_LOCKED }
+        assertShouldHeadsUp(buildPeekEntry { isBubble = true })
+    }
+
+    @Test
+    fun testShouldPeek_isBubble_keyguard() {
+        ensurePeekState { statusBarState = KEYGUARD }
+        assertShouldHeadsUp(buildPeekEntry { isBubble = true })
+    }
+
+    @Test
+    fun testShouldNotPeek_dnd() {
+        ensurePeekState()
+        assertShouldNotHeadsUp(buildPeekEntry { suppressedVisualEffects = SUPPRESSED_EFFECT_PEEK })
+    }
+
+    @Test
+    fun testShouldNotPeek_notImportant() {
+        ensurePeekState()
+        assertShouldNotHeadsUp(buildPeekEntry { importance = IMPORTANCE_DEFAULT })
+    }
+
+    @Test
+    fun testShouldNotPeek_screenOff() {
+        ensurePeekState { isScreenOn = false }
+        assertShouldNotHeadsUp(buildPeekEntry())
+    }
+
+    @Test
+    fun testShouldNotPeek_dreaming() {
+        ensurePeekState { isDreaming = true }
+        assertShouldNotHeadsUp(buildPeekEntry())
+    }
+
+    @Test
+    fun testShouldNotPeek_oldWhen() {
+        ensurePeekState()
+        assertShouldNotHeadsUp(buildPeekEntry { whenMs = whenAgo(MAX_HUN_WHEN_AGE_MS) })
+    }
+
+    @Test
+    fun testShouldPeek_notQuiteOldEnoughWhen() {
+        ensurePeekState()
+        assertShouldHeadsUp(buildPeekEntry { whenMs = whenAgo(MAX_HUN_WHEN_AGE_MS - 1) })
+    }
+
+    @Test
+    fun testShouldPeek_zeroWhen() {
+        ensurePeekState()
+        assertShouldHeadsUp(buildPeekEntry { whenMs = 0L })
+    }
+
+    @Test
+    fun testShouldPeek_oldWhenButFsi() {
+        ensurePeekState()
+        assertShouldHeadsUp(buildFsiEntry { whenMs = whenAgo(MAX_HUN_WHEN_AGE_MS) })
+    }
+
+    @Test
     fun testShouldPeek_defaultLegacySuppressor() {
         ensurePeekState()
         provider.addLegacySuppressor(neverSuppresses)
@@ -201,9 +289,151 @@
     }
 
     @Test
-    fun testShouldBubble() {
+    fun testShouldNotPulse_effectSuppressed() {
+        ensurePulseState()
+        assertShouldNotHeadsUp(
+            buildPulseEntry { suppressedVisualEffects = SUPPRESSED_EFFECT_AMBIENT }
+        )
+    }
+
+    @Test
+    fun testShouldNotPulse_visibilityOverridePrivate() {
+        ensurePulseState()
+        assertShouldNotHeadsUp(buildPulseEntry { visibilityOverride = VISIBILITY_PRIVATE })
+    }
+
+    @Test
+    fun testShouldNotPulse_importanceLow() {
+        ensurePulseState()
+        assertShouldNotHeadsUp(buildPulseEntry { importance = IMPORTANCE_LOW })
+    }
+
+    private fun withPeekAndPulseEntry(
+        extendEntry: EntryBuilder.() -> Unit,
+        block: (NotificationEntry) -> Unit
+    ) {
+        ensurePeekState()
+        block(buildPeekEntry(extendEntry))
+
+        ensurePulseState()
+        block(buildPulseEntry(extendEntry))
+    }
+
+    @Test
+    fun testShouldHeadsUp_groupedSummaryNotif_groupAlertAll() {
+        withPeekAndPulseEntry({
+            isGrouped = true
+            isGroupSummary = true
+            groupAlertBehavior = GROUP_ALERT_ALL
+        }) {
+            assertShouldHeadsUp(it)
+        }
+    }
+
+    @Test
+    fun testShouldHeadsUp_groupedSummaryNotif_groupAlertSummary() {
+        withPeekAndPulseEntry({
+            isGrouped = true
+            isGroupSummary = true
+            groupAlertBehavior = GROUP_ALERT_SUMMARY
+        }) {
+            assertShouldHeadsUp(it)
+        }
+    }
+
+    @Test
+    fun testShouldNotHeadsUp_groupedSummaryNotif_groupAlertChildren() {
+        withPeekAndPulseEntry({
+            isGrouped = true
+            isGroupSummary = true
+            groupAlertBehavior = GROUP_ALERT_CHILDREN
+        }) {
+            assertShouldNotHeadsUp(it)
+        }
+    }
+
+    @Test
+    fun testShouldHeadsUp_ungroupedSummaryNotif_groupAlertChildren() {
+        withPeekAndPulseEntry({
+            isGrouped = false
+            isGroupSummary = true
+            groupAlertBehavior = GROUP_ALERT_CHILDREN
+        }) {
+            assertShouldHeadsUp(it)
+        }
+    }
+
+    @Test
+    fun testShouldHeadsUp_groupedChildNotif_groupAlertAll() {
+        withPeekAndPulseEntry({
+            isGrouped = true
+            isGroupSummary = false
+            groupAlertBehavior = GROUP_ALERT_ALL
+        }) {
+            assertShouldHeadsUp(it)
+        }
+    }
+
+    @Test
+    fun testShouldHeadsUp_groupedChildNotif_groupAlertChildren() {
+        withPeekAndPulseEntry({
+            isGrouped = true
+            isGroupSummary = false
+            groupAlertBehavior = GROUP_ALERT_CHILDREN
+        }) {
+            assertShouldHeadsUp(it)
+        }
+    }
+
+    @Test
+    fun testShouldNotHeadsUp_groupedChildNotif_groupAlertSummary() {
+        withPeekAndPulseEntry({
+            isGrouped = true
+            isGroupSummary = false
+            groupAlertBehavior = GROUP_ALERT_SUMMARY
+        }) {
+            assertShouldNotHeadsUp(it)
+        }
+    }
+
+    @Test
+    fun testShouldHeadsUp_ungroupedChildNotif_groupAlertSummary() {
+        withPeekAndPulseEntry({
+            isGrouped = false
+            isGroupSummary = false
+            groupAlertBehavior = GROUP_ALERT_SUMMARY
+        }) {
+            assertShouldHeadsUp(it)
+        }
+    }
+
+    @Test
+    fun testShouldNotHeadsUp_justLaunchedFsi() {
+        withPeekAndPulseEntry({ hasJustLaunchedFsi = true }) { assertShouldNotHeadsUp(it) }
+    }
+
+    @Test
+    fun testShouldBubble_withIntentAndIcon() {
         ensureBubbleState()
-        assertShouldBubble(buildBubbleEntry())
+        assertShouldBubble(buildBubbleEntry { bubbleIsShortcut = false })
+    }
+
+    @Test
+    fun testShouldBubble_withShortcut() {
+        ensureBubbleState()
+        assertShouldBubble(buildBubbleEntry { bubbleIsShortcut = true })
+    }
+
+    @Test
+    fun testShouldNotBubble_notAllowed() {
+        ensureBubbleState()
+        assertShouldNotBubble(buildBubbleEntry { canBubble = false })
+    }
+
+    @Test
+    fun testShouldNotBubble_noBubbleMetadata() {
+        ensureBubbleState()
+        assertShouldNotBubble(buildBubbleEntry { hasBubbleMetadata = false })
     }
 
     @Test
@@ -235,6 +465,18 @@
     }
 
     @Test
+    fun testShouldNotAlert_hiddenOnKeyguard() {
+        ensurePeekState({ keyguardShouldHideNotification = true })
+        assertShouldNotHeadsUp(buildPeekEntry())
+
+        ensurePulseState({ keyguardShouldHideNotification = true })
+        assertShouldNotHeadsUp(buildPulseEntry())
+
+        ensureBubbleState({ keyguardShouldHideNotification = true })
+        assertShouldNotBubble(buildBubbleEntry())
+    }
+
+    @Test
     fun testShouldFsi_notInteractive() {
         ensureNotInteractiveFsiState()
         assertShouldFsi(buildFsiEntry())
@@ -252,7 +494,7 @@
         assertShouldFsi(buildFsiEntry())
     }
 
-    private data class State(
+    protected data class State(
         var hunSettingEnabled: Boolean? = null,
         var hunSnoozed: Boolean? = null,
         var isAodPowerSave: Boolean? = null,
@@ -265,7 +507,7 @@
         var statusBarState: Int? = null,
     )
 
-    private fun setState(state: State): Unit =
+    protected fun setState(state: State): Unit =
         state.run {
             hunSettingEnabled?.let {
                 val newSetting = if (it) HEADS_UP_ON else HEADS_UP_OFF
@@ -296,7 +538,7 @@
             statusBarState?.let { statusBarStateController.state = it }
         }
 
-    private fun ensureState(block: State.() -> Unit) =
+    protected fun ensureState(block: State.() -> Unit) =
         State()
             .apply {
                 keyguardShouldHideNotification = false
@@ -304,7 +546,7 @@
             }
             .run(this::setState)
 
-    private fun ensurePeekState(block: State.() -> Unit = {}) = ensureState {
+    protected fun ensurePeekState(block: State.() -> Unit = {}) = ensureState {
         hunSettingEnabled = true
         hunSnoozed = false
         isDozing = false
@@ -313,88 +555,102 @@
         run(block)
     }
 
-    private fun ensurePulseState(block: State.() -> Unit = {}) = ensureState {
+    protected fun ensurePulseState(block: State.() -> Unit = {}) = ensureState {
         isAodPowerSave = false
         isDozing = true
         pulseOnNotificationsEnabled = true
         run(block)
     }
 
-    private fun ensureBubbleState(block: State.() -> Unit = {}) = ensureState(block)
+    protected fun ensureBubbleState(block: State.() -> Unit = {}) = ensureState(block)
 
-    private fun ensureNotInteractiveFsiState(block: State.() -> Unit = {}) = ensureState {
+    protected fun ensureNotInteractiveFsiState(block: State.() -> Unit = {}) = ensureState {
         isDreaming = false
         isInteractive = false
         statusBarState = SHADE
         run(block)
     }
 
-    private fun ensureDreamingFsiState(block: State.() -> Unit = {}) = ensureState {
+    protected fun ensureDreamingFsiState(block: State.() -> Unit = {}) = ensureState {
         isDreaming = true
         isInteractive = true
         statusBarState = SHADE
         run(block)
     }
 
-    private fun ensureKeyguardFsiState(block: State.() -> Unit = {}) = ensureState {
+    protected fun ensureKeyguardFsiState(block: State.() -> Unit = {}) = ensureState {
         isDreaming = false
         isInteractive = true
         statusBarState = KEYGUARD
         run(block)
     }
 
-    private fun assertShouldHeadsUp(entry: NotificationEntry) =
+    protected fun assertShouldHeadsUp(entry: NotificationEntry) =
         provider.makeUnloggedHeadsUpDecision(entry).let {
             assertTrue("unexpected suppressed HUN: ${it.logReason}", it.shouldInterrupt)
         }
 
-    private fun assertShouldNotHeadsUp(entry: NotificationEntry) =
+    protected fun assertShouldNotHeadsUp(entry: NotificationEntry) =
         provider.makeUnloggedHeadsUpDecision(entry).let {
             assertFalse("unexpected unsuppressed HUN: ${it.logReason}", it.shouldInterrupt)
         }
 
-    private fun assertShouldBubble(entry: NotificationEntry) =
+    protected fun assertShouldBubble(entry: NotificationEntry) =
         provider.makeAndLogBubbleDecision(entry).let {
             assertTrue("unexpected suppressed bubble: ${it.logReason}", it.shouldInterrupt)
         }
 
-    private fun assertShouldNotBubble(entry: NotificationEntry) =
+    protected fun assertShouldNotBubble(entry: NotificationEntry) =
         provider.makeAndLogBubbleDecision(entry).let {
             assertFalse("unexpected unsuppressed bubble: ${it.logReason}", it.shouldInterrupt)
         }
 
-    private fun assertShouldFsi(entry: NotificationEntry) =
+    protected fun assertShouldFsi(entry: NotificationEntry) =
         provider.makeUnloggedFullScreenIntentDecision(entry).let {
             assertTrue("unexpected suppressed FSI: ${it.logReason}", it.shouldInterrupt)
         }
 
-    private fun assertShouldNotFsi(entry: NotificationEntry) =
+    protected fun assertShouldNotFsi(entry: NotificationEntry) =
         provider.makeUnloggedFullScreenIntentDecision(entry).let {
             assertFalse("unexpected unsuppressed FSI: ${it.logReason}", it.shouldInterrupt)
         }
 
-    private class EntryBuilder(val context: Context) {
+    protected class EntryBuilder(val context: Context) {
         var importance = IMPORTANCE_DEFAULT
         var suppressedVisualEffects: Int? = null
         var whenMs: Long? = null
         var visibilityOverride: Int? = null
         var hasFsi = false
         var canBubble: Boolean? = null
+        var isBubble = false
         var hasBubbleMetadata = false
-        var bubbleSuppressNotification: Boolean? = null
+        var bubbleIsShortcut = false
+        var bubbleSuppressesNotification: Boolean? = null
+        var isGrouped = false
+        var isGroupSummary: Boolean? = null
+        var groupAlertBehavior: Int? = null
+        var hasJustLaunchedFsi = false
 
-        private fun buildBubbleMetadata() =
-            BubbleMetadata.Builder(
-                    PendingIntent.getActivity(
-                        context,
-                        /* requestCode = */ 0,
-                        Intent().setPackage(context.packageName),
-                        FLAG_MUTABLE
-                    ),
-                    Icon.createWithResource(context.resources, R.drawable.android)
-                )
-                .apply { bubbleSuppressNotification?.let { setSuppressNotification(it) } }
-                .build()
+        private fun buildBubbleMetadata(): BubbleMetadata {
+            val builder =
+                if (bubbleIsShortcut) {
+                    BubbleMetadata.Builder(context.packageName + ":test_shortcut_id")
+                } else {
+                    BubbleMetadata.Builder(
+                        PendingIntent.getActivity(
+                            context,
+                            /* requestCode = */ 0,
+                            Intent().setPackage(context.packageName),
+                            FLAG_MUTABLE
+                        ),
+                        Icon.createWithResource(context.resources, R.drawable.android)
+                    )
+                }
+
+            bubbleSuppressesNotification?.let { builder.setSuppressNotification(it) }
+
+            return builder.build()
+        }
 
         fun build() =
             Notification.Builder(context, TEST_CHANNEL_ID)
@@ -411,8 +667,21 @@
                     if (hasBubbleMetadata) {
                         setBubbleMetadata(buildBubbleMetadata())
                     }
+
+                    if (isGrouped) {
+                        setGroup(TEST_GROUP_KEY)
+                    }
+
+                    isGroupSummary?.let { setGroupSummary(it) }
+
+                    groupAlertBehavior?.let { setGroupAlertBehavior(it) }
                 }
                 .build()
+                .apply {
+                    if (isBubble) {
+                        flags = flags or FLAG_BUBBLE
+                    }
+                }
                 .let { NotificationEntryBuilder().setNotification(it) }
                 .apply {
                     setPkg(TEST_PACKAGE)
@@ -426,6 +695,10 @@
                 }
                 .build()!!
                 .also {
+                    if (hasJustLaunchedFsi) {
+                        it.notifyFullScreenIntentLaunched()
+                    }
+
                     modifyRanking(it)
                         .apply {
                             suppressedVisualEffects?.let { setSuppressedVisualEffects(it) }
@@ -435,29 +708,29 @@
                 }
     }
 
-    private fun buildEntry(block: EntryBuilder.() -> Unit) =
+    protected fun buildEntry(block: EntryBuilder.() -> Unit) =
         EntryBuilder(context).also(block).build()
 
-    private fun buildPeekEntry(block: EntryBuilder.() -> Unit = {}) = buildEntry {
+    protected fun buildPeekEntry(block: EntryBuilder.() -> Unit = {}) = buildEntry {
         importance = IMPORTANCE_HIGH
         run(block)
     }
 
-    private fun buildPulseEntry(block: EntryBuilder.() -> Unit = {}) = buildEntry {
+    protected fun buildPulseEntry(block: EntryBuilder.() -> Unit = {}) = buildEntry {
         importance = IMPORTANCE_DEFAULT
         visibilityOverride = VISIBILITY_NO_OVERRIDE
         run(block)
     }
 
-    private fun buildFsiEntry(block: EntryBuilder.() -> Unit = {}) = buildEntry {
-        importance = IMPORTANCE_HIGH
-        hasFsi = true
+    protected fun buildBubbleEntry(block: EntryBuilder.() -> Unit = {}) = buildEntry {
+        canBubble = true
+        hasBubbleMetadata = true
         run(block)
     }
 
-    private fun buildBubbleEntry(block: EntryBuilder.() -> Unit = {}) = buildEntry {
-        canBubble = true
-        hasBubbleMetadata = true
+    protected fun buildFsiEntry(block: EntryBuilder.() -> Unit = {}) = buildEntry {
+        importance = IMPORTANCE_HIGH
+        hasFsi = true
         run(block)
     }
 
@@ -470,3 +743,4 @@
 private const val TEST_CHANNEL_NAME = "Test Channel"
 private const val TEST_PACKAGE = "test_package"
 private const val TEST_TAG = "test_tag"
+private const val TEST_GROUP_KEY = "test_group_key"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/tracing/TraceUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/tracing/TraceUtilsTest.kt
index 8fb5ff8..ba34ce6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/tracing/TraceUtilsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/tracing/TraceUtilsTest.kt
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.tracing
+package com.android.app.tracing
 
 import android.os.Handler
 import android.os.Looper
@@ -76,7 +76,7 @@
     @Test
     fun testLongTraceSection_doesNotThrow_whenUsingHelper() {
         traceSection(SECTION_NAME_THATS_TOO_LONG) {
-            Log.v(TAG, "com.android.systemui.tracing.traceSection() block.")
+            Log.v(TAG, "com.android.app.tracing.traceSection() block.")
         }
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
index e1c6dde..799bb40 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalRepository.kt
@@ -1,8 +1,17 @@
 package com.android.systemui.communal.data.repository
 
+import com.android.systemui.communal.shared.model.CommunalSceneKey
+import kotlinx.coroutines.flow.MutableStateFlow
+
 /** Fake implementation of [CommunalRepository]. */
-class FakeCommunalRepository : CommunalRepository {
-    override var isCommunalEnabled = false
+class FakeCommunalRepository(
+    override var isCommunalEnabled: Boolean = false,
+    override val desiredScene: MutableStateFlow<CommunalSceneKey> =
+        MutableStateFlow(CommunalSceneKey.Blank)
+) : CommunalRepository {
+    override fun setDesiredScene(desiredScene: CommunalSceneKey) {
+        this.desiredScene.value = desiredScene
+    }
 
     fun setIsCommunalEnabled(value: Boolean) {
         isCommunalEnabled = value
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTileDefaultsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTileDefaultsRepository.kt
new file mode 100644
index 0000000..13910fd
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTileDefaultsRepository.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom.data.repository
+
+import android.content.ComponentName
+import android.os.UserHandle
+import com.android.systemui.qs.tiles.impl.custom.data.entity.CustomTileDefaults
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+
+class FakeCustomTileDefaultsRepository : CustomTileDefaultsRepository {
+
+    private val defaults: MutableMap<DefaultsKey, CustomTileDefaults> = mutableMapOf()
+    private val defaultsFlow = MutableSharedFlow<DefaultsRequest>()
+
+    private val mutableDefaultsRequests: MutableList<DefaultsRequest> = mutableListOf()
+    val defaultsRequests: List<DefaultsRequest> = mutableDefaultsRequests
+
+    override fun defaults(user: UserHandle): Flow<CustomTileDefaults> =
+        defaultsFlow
+            .distinctUntilChanged { old, new ->
+                if (new.force) {
+                    false
+                } else {
+                    old == new
+                }
+            }
+            .map { defaults[DefaultsKey(it.user, it.componentName)]!! }
+
+    override fun requestNewDefaults(
+        user: UserHandle,
+        componentName: ComponentName,
+        force: Boolean
+    ) {
+        val request = DefaultsRequest(user, componentName, force)
+        mutableDefaultsRequests.add(request)
+        defaultsFlow.tryEmit(request)
+    }
+
+    fun putDefaults(
+        user: UserHandle,
+        componentName: ComponentName,
+        customTileDefaults: CustomTileDefaults,
+    ) {
+        defaults[DefaultsKey(user, componentName)] = customTileDefaults
+    }
+
+    fun removeDefaults(user: UserHandle, componentName: ComponentName) {
+        defaults.remove(DefaultsKey(user, componentName))
+    }
+
+    data class DefaultsRequest(
+        val user: UserHandle,
+        val componentName: ComponentName,
+        val force: Boolean = false,
+    )
+
+    private data class DefaultsKey(val user: UserHandle, val componentName: ComponentName)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTilePackageUpdatesRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTilePackageUpdatesRepository.kt
new file mode 100644
index 0000000..8f972f5
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/tiles/impl/custom/data/repository/FakeCustomTilePackageUpdatesRepository.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles.impl.custom.data.repository
+
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+
+class FakeCustomTilePackageUpdatesRepository : CustomTilePackageUpdatesRepository {
+
+    private val mutablePackageChanges = MutableSharedFlow<Unit>()
+
+    override val packageChanges: Flow<Unit>
+        get() = mutablePackageChanges
+
+    suspend fun emitPackageChange() {
+        mutablePackageChanges.emit(Unit)
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index bdddc04..6beb513 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -131,6 +131,7 @@
             SceneKey.Lockscreen,
             SceneKey.Bouncer,
             SceneKey.Gone,
+            SceneKey.Communal,
         )
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
index 7e0632b..efccafc 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
@@ -22,47 +22,47 @@
  * be null"). To fix this, we can use methods that modify the return type to be nullable. This
  * causes Kotlin to skip the null checks.
  */
-
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatcher
+import org.mockito.MockSettings
 import org.mockito.Mockito
 import org.mockito.Mockito.`when`
+import org.mockito.Mockito.withSettings
 import org.mockito.stubbing.OngoingStubbing
 import org.mockito.stubbing.Stubber
 
 /**
- * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when
- * null is returned.
+ * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when null is
+ * returned.
  *
  * Generic T is nullable because implicitly bounded by Any?.
  */
 fun <T> eq(obj: T): T = Mockito.eq<T>(obj) ?: obj
 
 /**
- * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when
- * null is returned.
+ * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when null is
+ * returned.
  *
  * Generic T is nullable because implicitly bounded by Any?.
  */
 fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
+
 inline fun <reified T> any(): T = any(T::class.java)
 
 /**
- * Returns Mockito.argThat() as nullable type to avoid java.lang.IllegalStateException when
- * null is returned.
+ * Returns Mockito.argThat() as nullable type to avoid java.lang.IllegalStateException when null is
+ * returned.
  *
  * Generic T is nullable because implicitly bounded by Any?.
  */
 fun <T> argThat(matcher: ArgumentMatcher<T>): T = Mockito.argThat(matcher)
 
-/**
- * Kotlin type-inferred version of Mockito.nullable()
- */
+/** Kotlin type-inferred version of Mockito.nullable() */
 inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java)
 
 /**
- * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException
- * when null is returned.
+ * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException when
+ * null is returned.
  *
  * Generic T is nullable because implicitly bounded by Any?.
  */
@@ -74,7 +74,7 @@
  * Generic T is nullable because implicitly bounded by Any?.
  */
 inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
-        ArgumentCaptor.forClass(T::class.java)
+    ArgumentCaptor.forClass(T::class.java)
 
 /**
  * Helper function for creating new mocks, without the need to pass in a [Class] instance.
@@ -83,8 +83,8 @@
  *
  * @param apply builder function to simplify stub configuration by improving type inference.
  */
-inline fun <reified T : Any> mock(apply: T.() -> Unit = {}): T = Mockito.mock(T::class.java)
-        .apply(apply)
+inline fun <reified T : Any> mock(settings: MockSettings? = null, apply: T.() -> Unit = {}): T =
+    Mockito.mock(T::class.java, settings ?: withSettings()).apply(apply)
 
 /**
  * Helper function for stubbing methods without the need to use backticks.
@@ -92,6 +92,7 @@
  * @see Mockito.when
  */
 fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall)
+
 fun <T> Stubber.whenever(mock: T): T = `when`(mock)
 
 /**
@@ -115,34 +116,32 @@
  * Generic T is nullable because implicitly bounded by Any?.
  */
 inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> =
-        KotlinArgumentCaptor(T::class.java)
+    KotlinArgumentCaptor(T::class.java)
 
 /**
  * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
  *
- *    val captor = argumentCaptor<Foo>()
- *    verify(...).someMethod(captor.capture())
- *    val captured = captor.value
+ * val captor = argumentCaptor<Foo>() verify(...).someMethod(captor.capture()) val captured =
+ * captor.value
  *
  * becomes:
  *
- *    val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
+ * val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
  *
  * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
  */
 inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
-        kotlinArgumentCaptor<T>().apply { block() }.value
+    kotlinArgumentCaptor<T>().apply { block() }.value
 
 /**
  * Variant of [withArgCaptor] for capturing multiple arguments.
  *
- *    val captor = argumentCaptor<Foo>()
- *    verify(...).someMethod(captor.capture())
- *    val captured: List<Foo> = captor.allValues
+ * val captor = argumentCaptor<Foo>() verify(...).someMethod(captor.capture()) val captured:
+ * List<Foo> = captor.allValues
  *
  * becomes:
  *
- *    val capturedList = captureMany<Foo> { verify(...).someMethod(capture()) }
+ * val capturedList = captureMany<Foo> { verify(...).someMethod(capture()) }
  */
 inline fun <reified T : Any> captureMany(block: KotlinArgumentCaptor<T>.() -> Unit): List<T> =
-        kotlinArgumentCaptor<T>().apply{ block() }.allValues
+    kotlinArgumentCaptor<T>().apply { block() }.allValues
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index cfe2af9..5953d0d 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -39,9 +39,12 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.accessibility.AccessibilityTraceManager;
 import com.android.server.accessibility.EventStreamTransformation;
+import com.android.server.accessibility.Flags;
+import com.android.server.accessibility.gestures.GestureMatcher;
 import com.android.server.accessibility.gestures.MultiTap;
 import com.android.server.accessibility.gestures.MultiTapAndHold;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -453,20 +456,45 @@
         private final MagnificationGesturesObserver mGesturesObserver;
 
         DetectingState(@UiContext Context context) {
-            final MultiTap multiTap = new MultiTap(context, mDetectSingleFingerTripleTap ? 3 : 1,
-                    mDetectSingleFingerTripleTap
-                            ? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP
-                            : MagnificationGestureMatcher.GESTURE_SINGLE_TAP, null);
-            final MultiTapAndHold multiTapAndHold = new MultiTapAndHold(context,
-                    mDetectSingleFingerTripleTap ? 3 : 1,
-                    mDetectSingleFingerTripleTap
-                            ? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD
-                            : MagnificationGestureMatcher.GESTURE_SINGLE_TAP_AND_HOLD, null);
-            mGesturesObserver = new MagnificationGesturesObserver(this,
-                    new SimpleSwipe(context),
-                    multiTap,
-                    multiTapAndHold,
-                    new TwoFingersDownOrSwipe(context));
+            if (Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
+                final List<GestureMatcher> mGestureMatchers = new ArrayList<>();
+
+                mGestureMatchers.add(new SimpleSwipe(context));
+                // Observe single tap and single tap and hold to reduce response time when the
+                // user performs these two gestures inside the window magnifier.
+                mGestureMatchers.add(new MultiTap(context,
+                        mDetectSingleFingerTripleTap ? 3 : 1,
+                        mDetectSingleFingerTripleTap
+                                ? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP
+                                : MagnificationGestureMatcher.GESTURE_SINGLE_TAP,
+                        null));
+                mGestureMatchers.add(new MultiTapAndHold(context,
+                        mDetectSingleFingerTripleTap ? 3 : 1,
+                        mDetectSingleFingerTripleTap
+                                ? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD
+                                : MagnificationGestureMatcher.GESTURE_SINGLE_TAP_AND_HOLD,
+                        null));
+                mGestureMatchers.add(new TwoFingersDownOrSwipe(context));
+
+                mGesturesObserver = new MagnificationGesturesObserver(this,
+                        mGestureMatchers.toArray(new GestureMatcher[mGestureMatchers.size()]));
+            } else {
+                final MultiTap multiTap = new MultiTap(context,
+                        mDetectSingleFingerTripleTap ? 3 : 1,
+                        mDetectSingleFingerTripleTap
+                                ? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP
+                                : MagnificationGestureMatcher.GESTURE_SINGLE_TAP, null);
+                final MultiTapAndHold multiTapAndHold = new MultiTapAndHold(context,
+                        mDetectSingleFingerTripleTap ? 3 : 1,
+                        mDetectSingleFingerTripleTap
+                                ? MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD
+                                : MagnificationGestureMatcher.GESTURE_SINGLE_TAP_AND_HOLD, null);
+                mGesturesObserver = new MagnificationGesturesObserver(this,
+                        new SimpleSwipe(context),
+                        multiTap,
+                        multiTapAndHold,
+                        new TwoFingersDownOrSwipe(context));
+            }
         }
 
         @Override
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index a036383..ae8fddf 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -23,6 +23,7 @@
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_ACTIVITY;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
 import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS;
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
@@ -665,6 +666,13 @@
                     }
                 }
                 break;
+            case POLICY_TYPE_CLIPBOARD:
+                if (Flags.crossDeviceClipboard()) {
+                    synchronized (mVirtualDeviceLock) {
+                        mDevicePolicies.put(policyType, devicePolicy);
+                    }
+                }
+                break;
             default:
                 throw new IllegalArgumentException("Device policy " + policyType
                         + " cannot be changed at runtime. ");
diff --git a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionAllowlistManager.java b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionAllowlistManager.java
index f77430d..bfb3a38 100644
--- a/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionAllowlistManager.java
+++ b/services/contentcapture/java/com/android/server/contentprotection/ContentProtectionAllowlistManager.java
@@ -22,6 +22,8 @@
 import android.annotation.Nullable;
 import android.os.Handler;
 import android.os.UserHandle;
+import android.service.contentcapture.IContentProtectionAllowlistCallback;
+import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -52,6 +54,10 @@
     @NonNull
     final PackageMonitor mPackageMonitor;
 
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    @NonNull
+    final IContentProtectionAllowlistCallback mAllowlistCallback;
+
     private final Object mHandlerToken = new Object();
 
     private final Object mLock = new Object();
@@ -74,6 +80,7 @@
         mHandler = handler;
         mTimeoutMs = timeoutMs;
         mPackageMonitor = createPackageMonitor();
+        mAllowlistCallback = createAllowlistCallback();
     }
 
     /** Starts the manager. */
@@ -107,7 +114,7 @@
         return allowedPackages.contains(packageName);
     }
 
-    private void setAllowlist(@NonNull List<String> packages) {
+    private void handleUpdateAllowlistResponse(@NonNull List<String> packages) {
         synchronized (mLock) {
             mAllowedPackages = packages.stream().collect(Collectors.toUnmodifiableSet());
         }
@@ -115,14 +122,14 @@
     }
 
     private void handleInitialUpdate() {
-        handleUpdate();
+        handlePackagesChanged();
 
         // Initial update done, start listening to package updates now
         mPackageMonitor.register(
                 mContentCaptureManagerService.getContext(), UserHandle.ALL, mHandler);
     }
 
-    private void handleUpdate() {
+    private void handlePackagesChanged() {
         if (!blocklistUpdateEnabled()) {
             return;
         }
@@ -145,6 +152,12 @@
         // If there are any pending updates queued already, they can be removed immediately
         mHandler.removeCallbacksAndMessages(mHandlerToken);
         mUpdatePendingUntil = Instant.now().plusMillis(mTimeoutMs);
+
+        try {
+            remoteContentProtectionService.onUpdateAllowlistRequest(mAllowlistCallback);
+        } catch (Exception ex) {
+            Slog.e(TAG, "Failed to call remote service", ex);
+        }
     }
 
     /** @hide */
@@ -154,12 +167,28 @@
         return new ContentProtectionPackageMonitor();
     }
 
+    /** @hide */
+    @NonNull
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected IContentProtectionAllowlistCallback createAllowlistCallback() {
+        return new ContentProtectionAllowlistCallback();
+    }
+
     private final class ContentProtectionPackageMonitor extends PackageMonitor {
 
         // This callback might be invoked multiple times, for more info refer to the comment above
         @Override
         public void onSomePackagesChanged() {
-            handleUpdate();
+            handlePackagesChanged();
+        }
+    }
+
+    private final class ContentProtectionAllowlistCallback
+            extends IContentProtectionAllowlistCallback.Stub {
+
+        @Override
+        public void setAllowlist(List<String> packages) {
+            mHandler.post(() -> handleUpdateAllowlistResponse(packages));
         }
     }
 }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 7dbf61b..a14f3fe 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -183,6 +183,7 @@
         "android.hardware.power.stats-V2-java",
         "android.hidl.manager-V1.2-java",
         "cbor-java",
+        "com.android.media.audio-aconfig-java",
         "dropbox_flags_lib",
         "icu4j_calendar_astronomer",
         "android.security.aaid_aidl-java",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 638abdb..4f32220 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -300,14 +300,6 @@
             @UserIdInt int userId, @NonNull String[] packageNames, boolean suspended);
 
     /**
-     * Suspend or unsuspend packages in a profile when quiet mode is toggled.
-     *
-     * @param userId The target user.
-     * @param suspended Whether the packages should be suspended or unsuspended.
-     */
-    public abstract void setPackagesSuspendedForQuietMode(@UserIdInt int userId, boolean suspended);
-
-    /**
      * Get the information describing the dialog to be shown to the user when they try to launch a
      * suspended application.
      *
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index db89cac..c4cb816 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -179,6 +179,15 @@
 3130 pm_snapshot_stats (build_count|1|1),(reuse_count|1|1),(big_builds|1|1),(short_lived|1|1),(max_build_time|1|3),(cumm_build_time|2|3)
 # Snapshot rebuild instance
 3131 pm_snapshot_rebuild (build_time|1|3),(lifetime|1|3)
+# Caller information to clear application data
+1003160 pm_clear_app_data_caller (pid|1),(uid|1),(package|3)
+# ---------------------------
+# Installer.java
+# ---------------------------
+# Caller Information to clear application data
+1003200 installer_clear_app_data_caller (pid|1),(uid|1),(package|3),(flags|1)
+# Call stack to clear application data
+1003201 installer_clear_app_data_call_stack (method|3),(class|3),(file|3),(line|1)
 
 # ---------------------------
 # InputMethodManagerService.java
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index 5a15f17..2b30c01 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -88,6 +88,9 @@
         mWipeEsims = intent.getBooleanExtra(Intent.EXTRA_WIPE_ESIMS, false);
         final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false)
                 || intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false);
+        // This is ONLY used by TestHarnessService within System Server, so we don't add a proper
+        // API constant in Intent for this.
+        final boolean keepMemtagMode = intent.getBooleanExtra("keep_memtag_mode", false);
 
         // TODO(b/189938391): properly handle factory reset on headless system user mode.
         final int sendingUserId = getSendingUserId();
@@ -110,9 +113,11 @@
                 try {
                     Slog.i(TAG, "Calling RecoverySystem.rebootWipeUserData(context, "
                             + "shutdown=" + shutdown + ", reason=" + reason
-                            + ", forceWipe=" + forceWipe + ", wipeEsims=" + mWipeEsims + ")");
+                            + ", forceWipe=" + forceWipe + ", wipeEsims=" + mWipeEsims
+                            + ", keepMemtagMode=" + keepMemtagMode + ")");
                     RecoverySystem
-                            .rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims);
+                            .rebootWipeUserData(
+                                context, shutdown, reason, forceWipe, mWipeEsims, keepMemtagMode);
                     Slog.wtf(TAG, "Still running after master clear?!");
                 } catch (IOException e) {
                     Slog.e(TAG, "Can't perform master clear/factory reset", e);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index bdda95e..8a801d8 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -93,6 +93,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.stats.devicepolicy.DevicePolicyEnums;
 import android.text.TextUtils;
 import android.util.EventLog;
@@ -2346,6 +2347,18 @@
             }
             return;
         }
+        if (isFirstAccountRemovalDisabled(account)) {
+            try {
+                response.onError(
+                        AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
+                        "User cannot remove the first "
+                                + account.type
+                                + " account on the device.");
+            } catch (RemoteException re) {
+                Log.w(TAG, "RemoteException while removing account", re);
+            }
+            return;
+        }
         final long identityToken = clearCallingIdentity();
         UserAccounts accounts = getUserAccounts(userId);
         cancelNotification(getSigninRequiredNotificationId(accounts, account), accounts);
@@ -2395,6 +2408,10 @@
                     account.type);
             throw new SecurityException(msg);
         }
+        if (isFirstAccountRemovalDisabled(account)) {
+            Log.e(TAG, "Cannot remove the first " + account.type + " account on the device.");
+            return false;
+        }
         UserAccounts accounts = getUserAccountsForCaller();
         final long accountId = accounts.accountsDb.findDeAccountId(account);
         logRecord(
@@ -6426,6 +6443,48 @@
         }
     }
 
+    /**
+     * Returns true if the config_canRemoveOrRenameFirstUser is false, and the given account type
+     * matches the one provided by config_accountTypeToKeepFirstUser.
+     */
+    private boolean isFirstAccountRemovalDisabled(Account account) {
+        // Skip if not targeting the first user.
+        int userId = UserHandle.getCallingUserId();
+        if (userId != 0) {
+            return false;
+        }
+
+        // Skip if we are allowed to remove/rename first account.
+        if (mContext.getResources()
+                .getBoolean(com.android.internal.R.bool.config_canRemoveFirstAccount)) {
+            return false;
+        }
+
+        // Skip if needed for testing.
+        if (Settings.Secure.getIntForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.ALLOW_PRIMARY_GAIA_ACCOUNT_REMOVAL_FOR_TESTS,
+                0 /* default */,
+                0 /* userHandle */) != 0) {
+            return false;
+        }
+
+        // Skip if not targeting desired account.
+        String typeToKeep =
+                mContext.getResources()
+                        .getString(
+                                com.android.internal.R.string.config_accountTypeToKeepFirstAccount);
+        if (typeToKeep.isEmpty() || !typeToKeep.equals(account.type)) {
+            return false;
+        }
+
+        // Only restrict first account.
+        UserAccounts accounts = getUserAccounts(0 /* userId */);
+        Account[] accountsOfType = getAccountsFromCache(accounts, typeToKeep,
+                Process.SYSTEM_UID, "android" /* packageName */, false);
+        return accountsOfType.length > 0 && accountsOfType[0].equals(account);
+    }
+
     private final class AccountManagerInternalImpl extends AccountManagerInternal {
         private final Object mLock = new Object();
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 88bb66f..1566113 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1886,7 +1886,7 @@
                     int exitInfoReason = (int) args.arg3;
                     args.recycle();
                     forceStopPackageLocked(pkg, appId, false, false, true, false,
-                            false, userId, reason, exitInfoReason);
+                            false, false, userId, reason, exitInfoReason);
                 }
             } break;
 
@@ -3548,6 +3548,7 @@
         enforceNotIsolatedCaller("clearApplicationUserData");
         int uid = Binder.getCallingUid();
         int pid = Binder.getCallingPid();
+        EventLog.writeEvent(EventLogTags.AM_CLEAR_APP_DATA_CALLER, pid, uid, packageName);
         final int resolvedUserId = mUserController.handleIncomingUser(pid, uid, userId, false,
                 ALLOW_FULL_ONLY, "clearApplicationUserData", null);
 
@@ -3914,7 +3915,10 @@
                                 + packageName + ": " + e);
                     }
                     if (mUserController.isUserRunning(user, userRunningFlags)) {
-                        forceStopPackageLocked(packageName, pkgUid,
+                        forceStopPackageLocked(packageName, UserHandle.getAppId(pkgUid),
+                                false /* callerWillRestart */, false /* purgeCache */,
+                                true /* doIt */, false /* evenPersistent */,
+                                false /* uninstalling */, true /* packageStateStopped */, user,
                                 reason == null ? ("from pid " + callingPid) : reason);
                         finishForceStopPackageLocked(packageName, pkgUid);
                     }
@@ -4163,7 +4167,7 @@
     @GuardedBy("this")
     private void forceStopPackageLocked(final String packageName, int uid, String reason) {
         forceStopPackageLocked(packageName, UserHandle.getAppId(uid), false,
-                false, true, false, false, UserHandle.getUserId(uid), reason);
+                false, true, false, false, false, UserHandle.getUserId(uid), reason);
     }
 
     @GuardedBy("this")
@@ -4349,20 +4353,20 @@
     @GuardedBy("this")
     final boolean forceStopPackageLocked(String packageName, int appId,
             boolean callerWillRestart, boolean purgeCache, boolean doit,
-            boolean evenPersistent, boolean uninstalling, int userId, String reasonString) {
-
+            boolean evenPersistent, boolean uninstalling, boolean packageStateStopped,
+            int userId, String reasonString) {
         int reason = packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
                 : ApplicationExitInfo.REASON_USER_REQUESTED;
         return forceStopPackageLocked(packageName, appId, callerWillRestart, purgeCache, doit,
-                evenPersistent, uninstalling, userId, reasonString, reason);
+                evenPersistent, uninstalling, packageStateStopped, userId, reasonString, reason);
 
     }
 
     @GuardedBy("this")
     final boolean forceStopPackageLocked(String packageName, int appId,
             boolean callerWillRestart, boolean purgeCache, boolean doit,
-            boolean evenPersistent, boolean uninstalling, int userId, String reasonString,
-            int reason) {
+            boolean evenPersistent, boolean uninstalling, boolean packageStateStopped,
+            int userId, String reasonString, int reason) {
         int i;
 
         if (userId == UserHandle.USER_ALL && packageName == null) {
@@ -4443,7 +4447,7 @@
             }
         }
 
-        if (packageName == null || uninstalling) {
+        if (packageName == null || uninstalling || packageStateStopped) {
             didSomething |= mPendingIntentController.removePendingIntentsForPackage(
                     packageName, userId, appId, doit);
         }
@@ -5148,7 +5152,7 @@
                     for (String pkg : pkgs) {
                         synchronized (ActivityManagerService.this) {
                             if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
-                                    0, "query restart")) {
+                                    false, 0, "query restart")) {
                                 setResultCode(Activity.RESULT_OK);
                                 return;
                             }
@@ -7342,7 +7346,7 @@
                 mDebugTransient = !persistent;
                 if (packageName != null) {
                     forceStopPackageLocked(packageName, -1, false, false, true, true,
-                            false, UserHandle.USER_ALL, "set debug app");
+                            false, false, UserHandle.USER_ALL, "set debug app");
                 }
             }
         } finally {
@@ -14918,7 +14922,7 @@
                             if (list != null && list.length > 0) {
                                 for (int i = 0; i < list.length; i++) {
                                     forceStopPackageLocked(list[i], -1, false, true, true,
-                                            false, false, userId, "storage unmount");
+                                            false, false, false, userId, "storage unmount");
                                 }
                                 mAtmInternal.cleanupRecentTasksForUser(UserHandle.USER_ALL);
                                 sendPackageBroadcastLocked(
@@ -14945,8 +14949,8 @@
                                     if (killProcess) {
                                         forceStopPackageLocked(ssp, UserHandle.getAppId(
                                                 intent.getIntExtra(Intent.EXTRA_UID, -1)),
-                                                false, true, true, false, fullUninstall, userId,
-                                                "pkg removed");
+                                                false, true, true, false, fullUninstall, false,
+                                                userId, "pkg removed");
                                         getPackageManagerInternal()
                                                 .onPackageProcessKilledForUninstall(ssp);
                                     } else {
@@ -15864,7 +15868,7 @@
                 } else {
                     // Instrumentation can kill and relaunch even persistent processes
                     forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, false,
-                            userId, "start instr");
+                            false, userId, "start instr");
                     // Inform usage stats to make the target package active
                     if (mUsageStatsService != null) {
                         mUsageStatsService.reportEvent(ii.targetPackage, userId,
@@ -15993,6 +15997,7 @@
                         /* doIt= */ true,
                         /* evenPersistent= */ true,
                         /* uninstalling= */ false,
+                        /* packageStateStopped= */ false,
                         userId,
                         "start instr");
 
@@ -16163,8 +16168,7 @@
                 }
             } else if (!instr.mNoRestart) {
                 forceStopPackageLocked(app.info.packageName, -1, false, false, true, true, false,
-                        app.userId,
-                        "finished inst");
+                        false, app.userId, "finished inst");
             }
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 26b23ff..a95ddf3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -205,7 +205,7 @@
     private boolean mAsync;
     private BroadcastOptions mBroadcastOptions;
     private boolean mShowSplashScreen;
-    private boolean mDismissKeyguard;
+    private boolean mDismissKeyguardIfInsecure;
 
     final boolean mDumping;
 
@@ -552,8 +552,8 @@
                     mAsync = true;
                 } else if (opt.equals("--splashscreen-show-icon")) {
                     mShowSplashScreen = true;
-                } else if (opt.equals("--dismiss-keyguard")) {
-                    mDismissKeyguard = true;
+                } else if (opt.equals("--dismiss-keyguard-if-insecure")) {
+                    mDismissKeyguardIfInsecure = true;
                 } else {
                     return false;
                 }
@@ -714,11 +714,11 @@
                 }
                 options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
             }
-            if (mDismissKeyguard) {
+            if (mDismissKeyguardIfInsecure) {
                 if (options == null) {
                     options = ActivityOptions.makeBasic();
                 }
-                options.setDismissKeyguard();
+                options.setDismissKeyguardIfInsecure();
             }
             if (mWaitOption) {
                 result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, null, intent,
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 9e9db6a..931914f 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -129,3 +129,6 @@
 
 # Intent Sender redirect for UserHandle.USER_CURRENT
 30110 am_intent_sender_redirect_user (userId|1|5)
+
+# Caller information to clear application data
+1030002 am_clear_app_data_caller (pid|1),(uid|1),(package|3)
diff --git a/services/core/java/com/android/server/am/LmkdStatsReporter.java b/services/core/java/com/android/server/am/LmkdStatsReporter.java
index 4380b42..507fd9e 100644
--- a/services/core/java/com/android/server/am/LmkdStatsReporter.java
+++ b/services/core/java/com/android/server/am/LmkdStatsReporter.java
@@ -44,6 +44,7 @@
     private static final int DIRECT_RECL_AND_THRASHING = 5;
     private static final int LOW_MEM_AND_SWAP_UTIL = 6;
     private static final int LOW_FILECACHE_AFTER_THRASHING = 7;
+    private static final int LOW_MEM = 8;
 
     /**
      * Processes the LMK_KILL_OCCURRED packet data
@@ -106,6 +107,8 @@
                 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_SWAP_UTIL;
             case LOW_FILECACHE_AFTER_THRASHING:
                 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_FILECACHE_AFTER_THRASHING;
+            case LOW_MEM:
+                return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM;
             default:
                 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__UNKNOWN;
         }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 0f9c64e..2efac12 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -36,6 +36,7 @@
 import static android.os.Process.startWebView;
 import static android.system.OsConstants.*;
 
+import static com.android.sdksandbox.flags.Flags.selinuxSdkSandboxAudit;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
@@ -183,6 +184,7 @@
     static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
             "persist.sys.vold_app_data_isolation_enabled";
 
+    private static final String APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS = ":isSdkSandboxAudit";
     private static final String APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS = ":isSdkSandboxNext";
 
     // OOM adjustments for processes in various states:
@@ -549,6 +551,10 @@
 
     ActivityManagerGlobalLock mProcLock;
 
+    private static final String PROPERTY_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS =
+            "apply_sdk_sandbox_audit_restrictions";
+    private static final boolean DEFAULT_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS = false;
+
     private static final String PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS =
             "apply_sdk_sandbox_next_restrictions";
     private static final boolean DEFAULT_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS = false;
@@ -573,6 +579,13 @@
         private final Object mLock = new Object();
 
         @GuardedBy("mLock")
+        private boolean mSdkSandboxApplyRestrictionsAudit =
+                DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_ADSERVICES,
+                PROPERTY_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS,
+                DEFAULT_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS);
+
+        @GuardedBy("mLock")
         private boolean mSdkSandboxApplyRestrictionsNext =
                 DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_ADSERVICES,
@@ -593,6 +606,12 @@
             DeviceConfig.removeOnPropertiesChangedListener(this);
         }
 
+        boolean applySdkSandboxRestrictionsAudit() {
+            synchronized (mLock) {
+                return mSdkSandboxApplyRestrictionsAudit;
+            }
+        }
+
         boolean applySdkSandboxRestrictionsNext() {
             synchronized (mLock) {
                 return mSdkSandboxApplyRestrictionsNext;
@@ -608,6 +627,12 @@
                     }
 
                     switch (name) {
+                        case PROPERTY_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS:
+                            mSdkSandboxApplyRestrictionsAudit =
+                                properties.getBoolean(
+                                    PROPERTY_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS,
+                                    DEFAULT_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS);
+                            break;
                         case PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS:
                             mSdkSandboxApplyRestrictionsNext =
                                 properties.getBoolean(
@@ -2015,7 +2040,7 @@
             // the package was initially frozen through KILL_APPLICATION_MSG, so
             // it doesn't hurt to use it again.)
             mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
-                    false, false, true, false, false, app.userId, "start failure");
+                    false, false, true, false, false, false, app.userId, "start failure");
             return false;
         }
     }
@@ -2025,10 +2050,14 @@
     String updateSeInfo(ProcessRecord app) {
         String extraInfo = "";
         // By the time the first the SDK sandbox process is started, device config service
-        // should be available.
-        if (app.isSdkSandbox
-                && getProcessListSettingsListener().applySdkSandboxRestrictionsNext()) {
-            extraInfo = APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS;
+        // should be available. If both Next and Audit are enabled, Next takes precedence.
+        if (app.isSdkSandbox) {
+            if (getProcessListSettingsListener().applySdkSandboxRestrictionsNext()) {
+                extraInfo = APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS;
+            } else if (selinuxSdkSandboxAudit()
+                    && getProcessListSettingsListener().applySdkSandboxRestrictionsAudit()) {
+                extraInfo = APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS;
+            }
         }
 
         return app.info.seInfo
@@ -2086,7 +2115,7 @@
                         + app.processName, e);
                 app.setPendingStart(false);
                 mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
-                        false, false, true, false, false, app.userId, "start failure");
+                        false, false, true, false, false, false, app.userId, "start failure");
             }
             return app.getPid() > 0;
         }
@@ -2119,7 +2148,7 @@
                     app.setPendingStart(false);
                     mService.forceStopPackageLocked(app.info.packageName,
                             UserHandle.getAppId(app.uid),
-                            false, false, true, false, false, app.userId, "start failure");
+                            false, false, true, false, false, false, app.userId, "start failure");
                 }
             }
         };
@@ -3279,12 +3308,17 @@
 
         // Check if we should mark the processrecord for first launch after force-stopping
         if ((r.getApplicationInfo().flags & ApplicationInfo.FLAG_STOPPED) != 0) {
-            final boolean wasPackageEverLaunched = mService.getPackageManagerInternal()
-                    .wasPackageEverLaunched(r.getApplicationInfo().packageName, r.userId);
-            // If the package was launched in the past but is currently stopped, only then it
-            // should be considered as stopped after use. Do not mark it if it's the first launch.
-            if (wasPackageEverLaunched) {
-                r.setWasForceStopped(true);
+            try {
+                final boolean wasPackageEverLaunched = mService.getPackageManagerInternal()
+                        .wasPackageEverLaunched(r.getApplicationInfo().packageName, r.userId);
+                // If the package was launched in the past but is currently stopped, only then it
+                // should be considered as stopped after use. Do not mark it if it's the
+                // first launch.
+                if (wasPackageEverLaunched) {
+                    r.setWasForceStopped(true);
+                }
+            } catch (IllegalArgumentException e) {
+                // App doesn't have state yet, so wasn't forcestopped
             }
         }
 
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index c1a2482..e6cdbb5 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -128,6 +128,7 @@
         "biometrics",
         "biometrics_framework",
         "biometrics_integration",
+        "camera_hal",
         "camera_platform",
         "car_framework",
         "car_perception",
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 728bace..87633e9 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -76,7 +76,6 @@
 import android.app.IStopUserCallback;
 import android.app.IUserSwitchObserver;
 import android.app.KeyguardManager;
-import android.app.admin.DevicePolicyManagerInternal;
 import android.app.usage.UsageEvents;
 import android.appwidget.AppWidgetManagerInternal;
 import android.content.Context;
@@ -1497,10 +1496,8 @@
 
     private boolean shouldStartWithParent(UserInfo user) {
         final UserProperties properties = getUserProperties(user.id);
-        DevicePolicyManagerInternal dpmi =
-                LocalServices.getService(DevicePolicyManagerInternal.class);
         return (properties != null && properties.getStartWithParent())
-                && (!user.isQuietModeEnabled() || dpmi.isKeepProfilesRunningEnabled());
+                && !user.isQuietModeEnabled();
     }
 
     /**
@@ -1999,25 +1996,26 @@
         EventLog.writeEvent(EventLogTags.UC_SWITCH_USER, targetUserId);
         int currentUserId = getCurrentUserId();
         UserInfo targetUserInfo = getUserInfo(targetUserId);
-        if (targetUserId == currentUserId) {
-            Slogf.i(TAG, "user #" + targetUserId + " is already the current user");
-            return true;
-        }
-        if (targetUserInfo == null) {
-            Slogf.w(TAG, "No user info for user #" + targetUserId);
-            return false;
-        }
-        if (!targetUserInfo.supportsSwitchTo()) {
-            Slogf.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
-            return false;
-        }
-        if (FactoryResetter.isFactoryResetting()) {
-            Slogf.w(TAG, "Cannot switch to User #" + targetUserId + ": factory reset in progress");
-            return false;
-        }
-
         boolean userSwitchUiEnabled;
         synchronized (mLock) {
+            if (targetUserId == currentUserId && mTargetUserId == UserHandle.USER_NULL) {
+                Slogf.i(TAG, "user #" + targetUserId + " is already the current user");
+                return true;
+            }
+            if (targetUserInfo == null) {
+                Slogf.w(TAG, "No user info for user #" + targetUserId);
+                return false;
+            }
+            if (!targetUserInfo.supportsSwitchTo()) {
+                Slogf.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported");
+                return false;
+            }
+            if (FactoryResetter.isFactoryResetting()) {
+                Slogf.w(TAG, "Cannot switch to User #" + targetUserId
+                        + ": factory reset in progress");
+                return false;
+            }
+
             if (!mInitialized) {
                 Slogf.e(TAG, "Cannot switch to User #" + targetUserId
                         + ": UserController not ready yet");
@@ -3628,7 +3626,7 @@
 
         void activityManagerForceStopPackage(@UserIdInt int userId, String reason) {
             synchronized (mService) {
-                mService.forceStopPackageLocked(null, -1, false, false, true, false, false,
+                mService.forceStopPackageLocked(null, -1, false, false, true, false, false, false,
                         userId, reason);
             }
         };
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index cbaf05b..a770b66 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -22,3 +22,10 @@
     description: "Detect abusive FGS behavior for certain types (camera, mic, media, location)."
     bug: "295545575"
 }
+
+flag {
+    name: "fgs_boot_completed"
+    namespace: "backstage_power"
+    description: "Disable BOOT_COMPLETED broadcast FGS start for certain types"
+    bug: "296558535"
+}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 2336753..2897075 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1765,6 +1765,14 @@
                     synchronized (mSetModeLock) {
                         synchronized (mDeviceStateLock) {
                             final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
+                            if (btInfo.mState == BluetoothProfile.STATE_CONNECTED
+                                    && !mBtHelper.isProfilePoxyConnected(btInfo.mProfile)) {
+                                AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
+                                        "msg: MSG_L_SET_BT_ACTIVE_DEVICE "
+                                            + "received with null profile proxy: "
+                                            + btInfo)).printLog(TAG));
+                                return;
+                            }
                             @AudioSystem.AudioFormatNativeEnumForBtCodec final int codec =
                                     mBtHelper.getA2dpCodecWithFallbackToSBC(
                                             btInfo.mDevice, "MSG_L_SET_BT_ACTIVE_DEVICE");
@@ -1909,7 +1917,7 @@
                     final BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj;
                     if (btInfo.mDevice == null) break;
                     AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
-                            "msg: onBluetoothActiveDeviceChange " + btInfo)).printLog(TAG));
+                            "msg: MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT " + btInfo)).printLog(TAG));
                     synchronized (mDeviceStateLock) {
                         mDeviceInventory.setBluetoothActiveDevice(btInfo);
                     }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index d707689..e59fd77 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -1628,11 +1628,6 @@
                 Log.i(TAG, "setBluetoothActiveDevice " + info.toString() + " delay(ms): " + delay);
             }
             mDeviceBroker.postBluetoothActiveDevice(info, delay);
-            if (info.mProfile == BluetoothProfile.HEARING_AID
-                    && info.mState == BluetoothProfile.STATE_CONNECTED) {
-                mDeviceBroker.setForceUse_Async(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE,
-                                "HEARING_AID set to CONNECTED");
-            }
         }
         return delay;
     }
@@ -2013,6 +2008,9 @@
         final int hearingAidVolIndex = mDeviceBroker.getVssVolumeForDevice(streamType,
                 AudioSystem.DEVICE_OUT_HEARING_AID);
         mDeviceBroker.postSetHearingAidVolumeIndex(hearingAidVolIndex, streamType);
+
+        mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
+
         AudioDeviceAttributes ada = new AudioDeviceAttributes(
                 AudioSystem.DEVICE_OUT_HEARING_AID, address, name);
         mAudioSystem.setDeviceConnectionState(ada,
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a8fa313..b209fb0 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -37,6 +37,7 @@
 import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
 import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
 
+import static com.android.media.audio.Flags.bluetoothMacAddressAnonymization;
 import static com.android.server.audio.SoundDoseHelper.ACTION_CHECK_MUSIC_ACTIVE;
 import static com.android.server.utils.EventLogger.Event.ALOGE;
 import static com.android.server.utils.EventLogger.Event.ALOGI;
@@ -203,7 +204,6 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
-import com.android.media.audio.flags.Flags;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -10509,7 +10509,7 @@
     }
 
     private boolean isBluetoothPrividged() {
-        if (!Flags.bluetoothMacAddressAnonymization()) {
+        if (!bluetoothMacAddressAnonymization()) {
             return true;
         }
         return PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 7d7e6d0..cce6bd2 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -43,7 +43,6 @@
 import com.android.server.utils.EventLogger;
 
 import java.io.PrintWriter;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -288,6 +287,13 @@
         if (action.equals(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED)) {
             BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE,
                     android.bluetooth.BluetoothDevice.class);
+            if (btDevice != null && !isProfilePoxyConnected(BluetoothProfile.HEADSET)) {
+                AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
+                        "onReceiveBtEvent ACTION_ACTIVE_DEVICE_CHANGED "
+                                + "received with null profile proxy for device: "
+                                + btDevice)).printLog(TAG));
+                return;
+            }
             onSetBtScoActiveDevice(btDevice);
         } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
             int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
@@ -465,7 +471,8 @@
     @GuardedBy("AudioDeviceBroker.this.mDeviceStateLock")
     /*package*/ synchronized void onBtProfileDisconnected(int profile) {
         AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
-                "BT profile " + BluetoothProfile.getProfileName(profile) + " disconnected"));
+                "BT profile " + BluetoothProfile.getProfileName(profile)
+                + " disconnected").printLog(TAG));
         switch (profile) {
             case BluetoothProfile.HEADSET:
                 mBluetoothHeadset = null;
@@ -496,7 +503,11 @@
     /*package*/ synchronized void onBtProfileConnected(int profile, BluetoothProfile proxy) {
         AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
                 "BT profile " + BluetoothProfile.getProfileName(profile) + " connected to proxy "
-                + proxy));
+                + proxy).printLog(TAG));
+        if (proxy == null) {
+            Log.e(TAG, "onBtProfileConnected: null proxy for profile: " + profile);
+            return;
+        }
         switch (profile) {
             case BluetoothProfile.HEADSET:
                 onHeadsetProfileConnected((BluetoothHeadset) proxy);
@@ -522,36 +533,64 @@
         }
 
         // this part is only for A2DP, LE Audio unicast and Hearing aid
-        final List<BluetoothDevice> deviceList = proxy.getConnectedDevices();
-        if (deviceList.isEmpty()) {
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter == null) {
+            Log.e(TAG, "onBtProfileConnected: Null BluetoothAdapter when connecting profile: "
+                    + BluetoothProfile.getProfileName(profile));
             return;
         }
-        final BluetoothDevice btDevice = deviceList.get(0);
-        if (proxy.getConnectionState(btDevice) == BluetoothProfile.STATE_CONNECTED) {
-            mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
-                    new AudioDeviceBroker.BtDeviceChangedData(btDevice, null,
-                        new BluetoothProfileConnectionInfo(profile),
-                        "mBluetoothProfileServiceListener"));
-        } else {
-            mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
-                    new AudioDeviceBroker.BtDeviceChangedData(null, btDevice,
-                        new BluetoothProfileConnectionInfo(profile),
-                        "mBluetoothProfileServiceListener"));
+        List<BluetoothDevice> activeDevices = adapter.getActiveDevices(profile);
+        if (activeDevices.isEmpty() || activeDevices.get(0) == null) {
+            return;
+        }
+        AudioDeviceBroker.BtDeviceChangedData data = new AudioDeviceBroker.BtDeviceChangedData(
+                activeDevices.get(0), null, new BluetoothProfileConnectionInfo(profile),
+                "mBluetoothProfileServiceListener");
+        AudioDeviceBroker.BtDeviceInfo info =
+                mDeviceBroker.createBtDeviceInfo(data, activeDevices.get(0),
+                        BluetoothProfile.STATE_CONNECTED);
+        mDeviceBroker.postBluetoothActiveDevice(info, 0 /* delay */);
+    }
+
+    // @GuardedBy("mDeviceBroker.mSetModeLock")
+    @GuardedBy("AudioDeviceBroker.this.mDeviceStateLock")
+    /*package*/ synchronized boolean isProfilePoxyConnected(int profile) {
+        switch (profile) {
+            case BluetoothProfile.HEADSET:
+                return mBluetoothHeadset != null;
+            case BluetoothProfile.A2DP:
+                return mA2dp != null;
+            case BluetoothProfile.HEARING_AID:
+                return mHearingAid != null;
+            case BluetoothProfile.LE_AUDIO:
+                return mLeAudio != null;
+            case BluetoothProfile.A2DP_SINK:
+            case BluetoothProfile.LE_AUDIO_BROADCAST:
+            default:
+                // return true for profiles that are not managed by the BtHelper because
+                // the fact that the profile proxy is not connected does not affect
+                // the device connection handling.
+                return true;
         }
     }
 
     // @GuardedBy("mDeviceBroker.mSetModeLock")
     @GuardedBy("AudioDeviceBroker.this.mDeviceStateLock")
-    private void onHeadsetProfileConnected(BluetoothHeadset headset) {
+    private void onHeadsetProfileConnected(@NonNull BluetoothHeadset headset) {
         // Discard timeout message
         mDeviceBroker.handleCancelFailureToConnectToBtHeadsetService();
         mBluetoothHeadset = headset;
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-        List<BluetoothDevice> activeDevices = Collections.emptyList();
         if (adapter != null) {
-            activeDevices = adapter.getActiveDevices(BluetoothProfile.HEADSET);
+            List<BluetoothDevice> activeDevices =
+                    adapter.getActiveDevices(BluetoothProfile.HEADSET);
+            if (activeDevices.size() > 0 && activeDevices.get(0) != null) {
+                onSetBtScoActiveDevice(activeDevices.get(0));
+            }
+        } else {
+            Log.e(TAG, "onHeadsetProfileConnected: Null BluetoothAdapter");
         }
-        onSetBtScoActiveDevice((activeDevices.size() > 0) ? activeDevices.get(0) : null);
+
         // Refresh SCO audio state
         checkScoAudioState();
         if (mScoAudioState != SCO_STATE_ACTIVATE_REQ
@@ -559,7 +598,7 @@
             return;
         }
         boolean status = false;
-        if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
+        if (mBluetoothHeadsetDevice != null) {
             switch (mScoAudioState) {
                 case SCO_STATE_ACTIVATE_REQ:
                     status = connectBluetoothScoAudioHelper(
@@ -715,7 +754,8 @@
                         case BluetoothProfile.LE_AUDIO_BROADCAST:
                             AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
                                     "BT profile service: connecting "
-                                    + BluetoothProfile.getProfileName(profile) + " profile"));
+                                    + BluetoothProfile.getProfileName(profile)
+                                    + " profile").printLog(TAG));
                             mDeviceBroker.postBtProfileConnected(profile, proxy);
                             break;
 
@@ -734,7 +774,8 @@
                         case BluetoothProfile.LE_AUDIO_BROADCAST:
                             AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
                                     "BT profile service: disconnecting "
-                                        + BluetoothProfile.getProfileName(profile) + " profile"));
+                                        + BluetoothProfile.getProfileName(profile)
+                                        + " profile").printLog(TAG));
                             mDeviceBroker.postBtProfileDisconnected(profile);
                             break;
 
diff --git a/services/core/java/com/android/server/audio/HardeningEnforcer.java b/services/core/java/com/android/server/audio/HardeningEnforcer.java
index c7556da..4ceb83b2 100644
--- a/services/core/java/com/android/server/audio/HardeningEnforcer.java
+++ b/services/core/java/com/android/server/audio/HardeningEnforcer.java
@@ -15,7 +15,7 @@
  */
 package com.android.server.audio;
 
-import static com.android.media.audio.flags.Flags.autoPublicVolumeApiHardening;
+import static android.media.audio.Flags.autoPublicVolumeApiHardening;
 
 import android.Manifest;
 import android.content.Context;
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 4538cad..0629e637 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -39,6 +39,7 @@
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.ComponentInfoInternal;
+import android.hardware.biometrics.Flags;
 import android.hardware.biometrics.IAuthService;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricService;
@@ -333,6 +334,33 @@
         }
 
         @Override
+        public long getLastAuthenticationTime(int userId,
+                @Authenticators.Types int authenticators) throws RemoteException {
+            // Only allow internal clients to call getLastAuthenticationTime with a different
+            // userId.
+            final int callingUserId = UserHandle.getCallingUserId();
+
+            if (userId != callingUserId) {
+                checkInternalPermission();
+            } else {
+                checkPermission();
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                // We can't do this above because we need the READ_DEVICE_CONFIG permission, which
+                // the calling user may not possess.
+                if (!Flags.lastAuthenticationTime()) {
+                    throw new UnsupportedOperationException();
+                }
+
+                return mBiometricService.getLastAuthenticationTime(userId, authenticators);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public boolean hasEnrolledBiometrics(int userId, String opPackageName)
                 throws RemoteException {
             checkInternalPermission();
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 1898b80..91a68ea 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -20,6 +20,7 @@
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricManager.Authenticators;
+import static android.hardware.biometrics.BiometricManager.BIOMETRIC_NO_AUTHENTICATION;
 
 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_IDLE;
 
@@ -39,6 +40,7 @@
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.Flags;
 import android.hardware.biometrics.IBiometricAuthenticator;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricSensorReceiver;
@@ -53,6 +55,7 @@
 import android.hardware.camera2.CameraManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.security.keymint.HardwareAuthenticatorType;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -62,10 +65,16 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.security.Authorization;
+import android.security.GateKeeper;
 import android.security.KeyStore;
+import android.security.authorization.IKeystoreAuthorization;
+import android.security.authorization.ResponseCode;
+import android.service.gatekeeper.IGateKeeperService;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Pair;
@@ -79,6 +88,7 @@
 import com.android.internal.util.DumpUtils;
 import com.android.server.SystemService;
 import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.utils.Slogf;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -116,6 +126,10 @@
     KeyStore mKeyStore;
     @VisibleForTesting
     ITrustManager mTrustManager;
+    @VisibleForTesting
+    IKeystoreAuthorization mKeystoreAuthorization;
+    @VisibleForTesting
+    IGateKeeperService mGateKeeper;
 
     // Get and cache the available biometric authenticators and their associated info.
     final ArrayList<BiometricSensor> mSensors = new ArrayList<>();
@@ -616,6 +630,64 @@
         }
 
         @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
+        @Override // Binder call
+        public long getLastAuthenticationTime(
+                int userId, @Authenticators.Types int authenticators) {
+            super.getLastAuthenticationTime_enforcePermission();
+
+            if (!Flags.lastAuthenticationTime()) {
+                throw new UnsupportedOperationException();
+            }
+
+            Slogf.d(TAG, "getLastAuthenticationTime(userId=%d, authenticators=0x%x)",
+                    userId, authenticators);
+
+            final long secureUserId;
+            try {
+                secureUserId = mGateKeeper.getSecureUserId(userId);
+            } catch (RemoteException e) {
+                Slogf.w(TAG, "Failed to get secure user id for " + userId, e);
+                return BIOMETRIC_NO_AUTHENTICATION;
+            }
+
+            if (secureUserId == GateKeeper.INVALID_SECURE_USER_ID) {
+                Slogf.w(TAG, "No secure user id for " + userId);
+                return BIOMETRIC_NO_AUTHENTICATION;
+            }
+
+            ArrayList<Integer> hardwareAuthenticators = new ArrayList<>(2);
+
+            if ((authenticators & Authenticators.DEVICE_CREDENTIAL) != 0) {
+                hardwareAuthenticators.add(HardwareAuthenticatorType.PASSWORD);
+            }
+
+            if ((authenticators & Authenticators.BIOMETRIC_STRONG) != 0) {
+                hardwareAuthenticators.add(HardwareAuthenticatorType.FINGERPRINT);
+            }
+
+            if (hardwareAuthenticators.isEmpty()) {
+                throw new IllegalArgumentException("authenticators must not be empty");
+            }
+
+            int[] authTypesArray = hardwareAuthenticators.stream()
+                    .mapToInt(Integer::intValue)
+                    .toArray();
+            try {
+                return mKeystoreAuthorization.getLastAuthTime(secureUserId, authTypesArray);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Error getting last auth time: " + e);
+                return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
+            } catch (ServiceSpecificException e) {
+                // This is returned when the feature flag test fails in keystore2
+                if (e.errorCode == ResponseCode.PERMISSION_DENIED) {
+                    throw new UnsupportedOperationException();
+                }
+
+                return BiometricConstants.BIOMETRIC_NO_AUTHENTICATION;
+            }
+        }
+
+        @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
         @Override
         public boolean hasEnrolledBiometrics(int userId, String opPackageName) {
 
@@ -937,6 +1009,14 @@
             return ActivityManager.getService();
         }
 
+        public IKeystoreAuthorization getKeystoreAuthorizationService() {
+            return Authorization.getService();
+        }
+
+        public IGateKeeperService getGateKeeperService() {
+            return GateKeeper.getService();
+        }
+
         public ITrustManager getTrustManager() {
             return ITrustManager.Stub.asInterface(ServiceManager.getService(Context.TRUST_SERVICE));
         }
@@ -1050,6 +1130,8 @@
         mBiometricContext = injector.getBiometricContext(context);
         mUserManager = injector.getUserManager(context);
         mBiometricCameraManager = injector.getBiometricCameraManager(context);
+        mKeystoreAuthorization = injector.getKeystoreAuthorizationService();
+        mGateKeeper = injector.getGateKeeperService();
 
         try {
             injector.getActivityManagerService().registerUserSwitchObserver(
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index e3c0cf7..b394fb5 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -19,6 +19,8 @@
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED;
 import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
 import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.content.Context.DEVICE_ID_INVALID;
 
@@ -409,7 +411,7 @@
 
     /**
      * Determines which deviceId to use for selecting a Clipboard, depending on where a given app
-     * is running.
+     * is running and the device's clipboard policy.
      *
      * @param requestedDeviceId the requested deviceId passed in from the client side
      * @param uid the intended app uid
@@ -431,28 +433,47 @@
             }
         }
 
-        if (requestedDeviceId != DEVICE_ID_DEFAULT) {
-            // Privileged apps that own the VirtualDevices, or regular apps running on it, can
-            // request it by id.
-            if (mVdmInternal.getDeviceOwnerUid(requestedDeviceId) == uid
-                    || virtualDeviceIds.contains(requestedDeviceId)) {
-                return requestedDeviceId;
+        // If an app is running on any VirtualDevice, it isn't clear which clipboard they
+        // should use, unless all of the devices share the default device's clipboard.
+        boolean allDevicesHaveDefaultClipboard = true;
+        for (int deviceId : virtualDeviceIds) {
+            if (!deviceUsesDefaultClipboard(deviceId)) {
+                allDevicesHaveDefaultClipboard = false;
+                break;
             }
-            return DEVICE_ID_INVALID;
         }
 
-        // The common case is apps running normally (not on a VirtualDevice).
-        if (virtualDeviceIds.isEmpty()) {
-            return DEVICE_ID_DEFAULT;
+        // Apps running on a virtual device may get the default clipboard if all the devices the app
+        // runs on share that clipboard. Otherwise it's not clear which clipboard to use.
+        if (requestedDeviceId == DEVICE_ID_DEFAULT) {
+            return allDevicesHaveDefaultClipboard ? DEVICE_ID_DEFAULT : DEVICE_ID_INVALID;
         }
 
-        // If an app is running on more than one VirtualDevice, it isn't clear which clipboard they
-        // should use.
-        if (virtualDeviceIds.size() > 1) {
-            return DEVICE_ID_INVALID;
+        // At this point the app wants to access a virtual device clipboard. It may do so if:
+        //  1. The app owns the VirtualDevice
+        //  2. The app is present on the VirtualDevice
+        //  3. The VirtualDevice shares the default device clipboard and all virtual devices that
+        //     the app is running on do the same.
+        int clipboardDeviceId = deviceUsesDefaultClipboard(requestedDeviceId)
+                ? DEVICE_ID_DEFAULT
+                : requestedDeviceId;
+
+        if (mVdmInternal.getDeviceOwnerUid(requestedDeviceId) == uid
+                || virtualDeviceIds.contains(requestedDeviceId)
+                || (clipboardDeviceId == DEVICE_ID_DEFAULT && allDevicesHaveDefaultClipboard)) {
+            return clipboardDeviceId;
         }
 
-        return virtualDeviceIds.valueAt(0);
+        // Fallback to the device where the app is running, unless it uses the default clipboard.
+        int fallbackDeviceId = virtualDeviceIds.valueAt(0);
+        return deviceUsesDefaultClipboard(fallbackDeviceId) ? DEVICE_ID_DEFAULT : fallbackDeviceId;
+    }
+
+    private boolean deviceUsesDefaultClipboard(int deviceId) {
+        if (deviceId == DEVICE_ID_DEFAULT || mVdm == null) {
+            return true;
+        }
+        return mVdm.getDevicePolicy(deviceId, POLICY_TYPE_CLIPBOARD) == DEVICE_POLICY_CUSTOM;
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index e475fe6..ff12ca2 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -102,6 +102,7 @@
 import android.media.projection.IMediaProjectionManager;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.IBinder;
@@ -239,6 +240,10 @@
     private static final String FORCE_WIFI_DISPLAY_ENABLE = "persist.debug.wfd.enable";
 
     private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";
+
+    @VisibleForTesting
+    static final String ENABLE_ON_CONNECT =
+            "persist.sys.display.enable_on_connect.external";
     private static final long WAIT_FOR_DEFAULT_DISPLAY_TIMEOUT = 10000;
     // This value needs to be in sync with the threshold
     // in RefreshRateConfigs::getFrameRateDivisor.
@@ -1530,8 +1535,8 @@
                 throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
                         + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
                         + "MediaProjection token in order to create a screen sharing virtual "
-                        + "display. In order to create a virtual display that does not perform"
-                        + "screen sharing (mirroring), please use the flag"
+                        + "display. In order to create a virtual display that does not perform "
+                        + "screen sharing (mirroring), please use the flag "
                         + "VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY.");
             }
         }
@@ -1942,10 +1947,14 @@
         }
 
         setupLogicalDisplay(display);
-
         // TODO(b/292196201) Remove when the display can be disabled before DPC is created.
         if (display.getDisplayInfoLocked().type == Display.TYPE_EXTERNAL) {
-            display.setEnabledLocked(false);
+            if ((Build.IS_ENG || Build.IS_USERDEBUG)
+                    && SystemProperties.getBoolean(ENABLE_ON_CONNECT, false)) {
+                Slog.w(TAG, "External display is enabled by default, bypassing user consent.");
+            } else {
+                display.setEnabledLocked(false);
+            }
         }
 
         sendDisplayEventLocked(display, DisplayManagerGlobal.EVENT_DISPLAY_CONNECTED);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 915f5db..d8ac52e 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1978,6 +1978,11 @@
                         || !isDisplayContentVisible || brightnessIsTemporary;
                 if (!skipAnimation && BrightnessSynchronizer.floatEquals(
                         sdrAnimateValue, currentSdrBrightness)) {
+                    // SDR brightness is unchanged, so animate quickly as this is only impacting
+                    // a likely minority amount of display content
+                    // ie, the highlights of an HDR video or UltraHDR image
+                    slowChange = false;
+
                     // Going from HDR to no HDR; visually this should be a "no-op" anyway
                     // as the remaining SDR content's brightness should be holding steady
                     // due to the sdr brightness not shifting
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index fc596dc..a6155da 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -1601,6 +1601,11 @@
                         || !isDisplayContentVisible || brightnessIsTemporary;
                 if (!skipAnimation && BrightnessSynchronizer.floatEquals(
                         sdrAnimateValue, currentSdrBrightness)) {
+                    // SDR brightness is unchanged, so animate quickly as this is only impacting
+                    // a likely minority amount of display content
+                    // ie, the highlights of an HDR video or UltraHDR image
+                    slowChange = false;
+
                     // Going from HDR to no HDR; visually this should be a "no-op" anyway
                     // as the remaining SDR content's brightness should be holding steady
                     // due to the sdr brightness not shifting
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index 3cf0786..330818e 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -27,6 +27,7 @@
 import android.content.ServiceConnection;
 import android.media.IMediaRoute2ProviderService;
 import android.media.IMediaRoute2ProviderServiceCallback;
+import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
 import android.media.MediaRoute2ProviderService;
 import android.media.RouteDiscoveryPreference;
@@ -641,6 +642,15 @@
 
         @Override
         public void notifyProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
+            for (MediaRoute2Info route : providerInfo.getRoutes()) {
+                if (route.isSystemRoute()) {
+                    throw new SecurityException(
+                            "Only the system is allowed to publish system routes. "
+                                    + "Disallowed route: "
+                                    + route);
+                }
+            }
+
             Connection connection = mConnectionRef.get();
             if (connection != null) {
                 connection.postProviderUpdated(providerInfo);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index b2f00a2..1bdd402 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -128,12 +128,12 @@
 import static com.android.server.am.PendingIntentRecord.FLAG_ACTIVITY_SENDER;
 import static com.android.server.am.PendingIntentRecord.FLAG_BROADCAST_SENDER;
 import static com.android.server.am.PendingIntentRecord.FLAG_SERVICE_SENDER;
+import static com.android.server.notification.Flags.expireBitmaps;
 import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_ANIM_BUFFER;
 import static com.android.server.policy.PhoneWindowManager.TOAST_WINDOW_TIMEOUT;
 import static com.android.server.utils.PriorityDump.PRIORITY_ARG;
 import static com.android.server.utils.PriorityDump.PRIORITY_ARG_CRITICAL;
 import static com.android.server.utils.PriorityDump.PRIORITY_ARG_NORMAL;
-import static com.android.server.notification.Flags.expireBitmaps;
 
 import android.Manifest;
 import android.Manifest.permission;
@@ -178,7 +178,6 @@
 import android.app.role.OnRoleHoldersChangedListener;
 import android.app.role.RoleManager;
 import android.app.usage.UsageEvents;
-import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.companion.ICompanionDeviceManager;
 import android.compat.annotation.ChangeId;
@@ -206,8 +205,6 @@
 import android.content.pm.VersionedPackage;
 import android.content.res.Resources;
 import android.database.ContentObserver;
-import android.graphics.Bitmap;
-import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
@@ -320,7 +317,6 @@
 import com.android.server.job.JobSchedulerInternal;
 import com.android.server.lights.LightsManager;
 import com.android.server.lights.LogicalLight;
-import com.android.server.notification.Flags;
 import com.android.server.notification.ManagedServices.ManagedServiceInfo;
 import com.android.server.notification.ManagedServices.UserProfiles;
 import com.android.server.notification.toast.CustomToastRecord;
@@ -1935,7 +1931,7 @@
             } else if (
                     isProfileUnavailable(action)) {
                 int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
-                if (userHandle >= 0 && !mDpm.isKeepProfilesRunningEnabled()) {
+                if (userHandle >= 0) {
                     cancelAllNotificationsInt(MY_UID, MY_PID, null, null, 0, 0, userHandle,
                             REASON_PROFILE_TURNED_OFF);
                     mSnoozeHelper.clearData(userHandle);
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 40d3ef0..a52870e 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -112,6 +112,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ArchivedPackageParcel;
 import android.content.pm.DataLoaderType;
+import android.content.pm.Flags;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageInstaller;
@@ -159,6 +160,7 @@
 import com.android.server.EventLogTags;
 import com.android.server.LocalManagerRegistry;
 import com.android.server.SystemConfig;
+import com.android.server.art.model.ArtFlags;
 import com.android.server.art.model.DexoptParams;
 import com.android.server.art.model.DexoptResult;
 import com.android.server.pm.Installer.LegacyDexoptDisabledException;
@@ -1867,7 +1869,8 @@
 
         final File targetDir = resolveTargetDir(request.getInstallFlags(), request.getCodeFile());
         final File beforeCodeFile = request.getCodeFile();
-        final File afterCodeFile = PackageManagerServiceUtils.getNextCodePath(targetDir);
+        final File afterCodeFile = PackageManagerServiceUtils.getNextCodePath(targetDir,
+                parsedPackage.getPackageName());
 
         if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
         final boolean onIncremental = mPm.mIncrementalManager != null
@@ -2523,8 +2526,15 @@
                             LocalManagerRegistry.getManager(PackageManagerLocal.class);
                     try (PackageManagerLocal.FilteredSnapshot snapshot =
                                     packageManagerLocal.withFilteredSnapshot()) {
-                        DexoptParams params =
-                                dexoptOptions.convertToDexoptParams(0 /* extraFlags */);
+                        boolean ignoreDexoptProfile =
+                                (installRequest.getInstallFlags()
+                                        & PackageManager.INSTALL_IGNORE_DEXOPT_PROFILE)
+                                != 0;
+                        /*@DexoptFlags*/ int extraFlags =
+                                ignoreDexoptProfile && Flags.useArtServiceV2()
+                                ? ArtFlags.FLAG_IGNORE_PROFILE
+                                : 0;
+                        DexoptParams params = dexoptOptions.convertToDexoptParams(extraFlags);
                         DexoptResult dexOptResult = DexOptHelper.getArtManagerLocal().dexoptPackage(
                                 snapshot, packageName, params);
                         installRequest.onDexoptFinished(dexOptResult);
@@ -3098,7 +3108,8 @@
             return null;
         }
         final File dstCodePath =
-                PackageManagerServiceUtils.getNextCodePath(Environment.getDataAppDirectory(null));
+                PackageManagerServiceUtils.getNextCodePath(Environment.getDataAppDirectory(null),
+                        packageName);
         int ret = PackageManagerServiceUtils.decompressFiles(codePath, dstCodePath, packageName);
         if (ret == PackageManager.INSTALL_SUCCEEDED) {
             ret = PackageManagerServiceUtils.extractNativeBinaries(dstCodePath, packageName);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 4ed3163..d5471cb0 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -24,6 +24,7 @@
 import android.annotation.UserIdInt;
 import android.content.Context;
 import android.content.pm.PackageStats;
+import android.os.Binder;
 import android.os.Build;
 import android.os.CreateAppDataArgs;
 import android.os.CreateAppDataResult;
@@ -35,9 +36,11 @@
 import android.os.ServiceManager;
 import android.os.storage.CrateMetadata;
 import android.text.format.DateUtils;
+import android.util.EventLog;
 import android.util.Slog;
 
 import com.android.internal.os.BackgroundThread;
+import com.android.server.EventLogTags;
 import com.android.server.SystemService;
 
 import dalvik.system.BlockGuard;
@@ -441,6 +444,26 @@
         if (!checkBeforeRemote()) return;
         try {
             mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode);
+
+            final StackTraceElement[] elements = Thread.currentThread().getStackTrace();
+            String className;
+            String methodName;
+            String fileName;
+            int lineNumber;
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            EventLog.writeEvent(EventLogTags.INSTALLER_CLEAR_APP_DATA_CALLER, pid, uid, packageName,
+                    flags);
+            // Skip the first two elements since they are always the same, ie
+            // Thread#getStackTrace() and VMStack#getThreadStackTrace()
+            for (int i = 2; i < elements.length; i++) {
+                className = elements[i].getClassName();
+                methodName = elements[i].getMethodName();
+                fileName = elements[i].getFileName();
+                lineNumber = elements[i].getLineNumber();
+                EventLog.writeEvent(EventLogTags.INSTALLER_CLEAR_APP_DATA_CALL_STACK, methodName,
+                        className, fileName, lineNumber);
+            }
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
diff --git a/services/core/java/com/android/server/pm/PackageArchiver.java b/services/core/java/com/android/server/pm/PackageArchiver.java
index 5cd6287..d5dacce 100644
--- a/services/core/java/com/android/server/pm/PackageArchiver.java
+++ b/services/core/java/com/android/server/pm/PackageArchiver.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED;
 import static android.content.pm.ArchivedActivityInfo.bytesFromBitmap;
 import static android.content.pm.ArchivedActivityInfo.drawableToBitmap;
@@ -106,6 +107,9 @@
     @Nullable
     private LauncherApps mLauncherApps;
 
+    @Nullable
+    private AppOpsManager mAppOpsManager;
+
     PackageArchiver(Context context, PackageManagerService mPm) {
         this.mContext = context;
         this.mPm = mPm;
@@ -178,6 +182,8 @@
                 Binder.getCallingUid(), userId);
         String responsibleInstallerPackage = getResponsibleInstallerPackage(ps);
         verifyInstaller(responsibleInstallerPackage, userId);
+        verifyOptOutStatus(packageName,
+                UserHandle.getUid(userId, UserHandle.getUid(userId, ps.getAppId())));
 
         List<LauncherActivityInfo> mainActivities = getLauncherActivityInfos(ps.getPackageName(),
                 userId);
@@ -308,6 +314,59 @@
         return intentReceivers != null && !intentReceivers.getList().isEmpty();
     }
 
+    /**
+     * Returns true if the app is archivable.
+     */
+    // TODO(b/299299569) Exclude system apps
+    public boolean isAppArchivable(@NonNull String packageName, @NonNull UserHandle user) {
+        Objects.requireNonNull(packageName);
+        Objects.requireNonNull(user);
+
+        Computer snapshot = mPm.snapshotComputer();
+        int userId = user.getIdentifier();
+        int binderUid = Binder.getCallingUid();
+        snapshot.enforceCrossUserPermission(binderUid, userId, true, true,
+                "isAppArchivable");
+        PackageStateInternal ps;
+        try {
+            ps = getPackageState(packageName, mPm.snapshotComputer(),
+                    Binder.getCallingUid(), userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new ParcelableException(e);
+        }
+
+        if (isAppOptedOutOfArchiving(packageName, ps.getAppId())) {
+            return false;
+        }
+
+        try {
+            verifyInstaller(getResponsibleInstallerPackage(ps), userId);
+            getLauncherActivityInfos(packageName, userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * Returns true if user has opted the app out of archiving through system settings.
+     */
+    // TODO(b/304256918) Switch this to a separate OP code for archiving.
+    private boolean isAppOptedOutOfArchiving(String packageName, int uid) {
+        return Binder.withCleanCallingIdentity(() ->
+                getAppOpsManager().checkOp(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
+                        uid, packageName) == MODE_IGNORED);
+    }
+
+    private void verifyOptOutStatus(String packageName, int uid)
+            throws PackageManager.NameNotFoundException {
+        if (isAppOptedOutOfArchiving(packageName, uid)) {
+            throw new PackageManager.NameNotFoundException(
+                    TextUtils.formatSimple("The app %s is opted out of archiving.", packageName));
+        }
+    }
+
     void requestUnarchive(
             @NonNull String packageName,
             @NonNull String callerPackageName,
@@ -510,6 +569,13 @@
         return mLauncherApps;
     }
 
+    private AppOpsManager getAppOpsManager() {
+        if (mAppOpsManager == null) {
+            mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
+        }
+        return mAppOpsManager;
+    }
+
     private void storeArchiveState(String packageName, ArchiveState archiveState, int userId)
             throws PackageManager.NameNotFoundException {
         synchronized (mPm.mLock) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 305e353..a4d8632 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -58,6 +58,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.VersionedPackage;
+import android.content.pm.parsing.FrameworkParsingPackageUtils;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
@@ -666,17 +667,22 @@
 
         // App package name and label length is restricted so that really long strings aren't
         // written to disk.
-        if (params.appPackageName != null
-                && params.appPackageName.length() > SessionParams.MAX_PACKAGE_NAME_LENGTH) {
+        if (params.appPackageName != null && !isValidPackageName(params.appPackageName)) {
             params.appPackageName = null;
         }
 
         params.appLabel = TextUtils.trimToSize(params.appLabel,
                 PackageItemInfo.MAX_SAFE_LABEL_LENGTH);
 
-        String requestedInstallerPackageName = (params.installerPackageName != null
-                && params.installerPackageName.length() < SessionParams.MAX_PACKAGE_NAME_LENGTH)
-                ? params.installerPackageName : installerPackageName;
+        // Validate installer package name.
+        if (params.installerPackageName != null && !isValidPackageName(
+                params.installerPackageName)) {
+            params.installerPackageName = null;
+        }
+
+        var requestedInstallerPackageName =
+                params.installerPackageName != null ? params.installerPackageName
+                        : installerPackageName;
 
         if (PackageManagerServiceUtils.isRootOrShell(callingUid)
                 || PackageInstallerSession.isSystemDataLoaderInstallation(params)
@@ -1105,6 +1111,19 @@
         return Integer.parseInt(sessionId);
     }
 
+    private static boolean isValidPackageName(@NonNull String packageName) {
+        if (packageName.length() > SessionParams.MAX_PACKAGE_NAME_LENGTH) {
+            return false;
+        }
+        // "android" is a valid package name
+        var errorMessage = FrameworkParsingPackageUtils.validateName(
+                packageName, /* requireSeparator= */ false, /* requireFilename */ true);
+        if (errorMessage != null) {
+            return false;
+        }
+        return true;
+    }
+
     private File getTmpSessionDir(String volumeUuid) {
         return Environment.getDataAppDirectory(volumeUuid);
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c9303f2..e5f7962 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2085,8 +2085,8 @@
                 mUserNeedsBadging, () -> mResolveInfo, () -> mInstantAppInstallerActivity,
                 injector.getBackgroundHandler());
         mDexOptHelper = new DexOptHelper(this);
-        mSuspendPackageHelper = new SuspendPackageHelper(this, mInjector, mUserManager,
-                mBroadcastHelper, mProtectedPackages);
+        mSuspendPackageHelper = new SuspendPackageHelper(this, mInjector, mBroadcastHelper,
+                mProtectedPackages);
         mDistractingPackageHelper = new DistractingPackageHelper(this, mBroadcastHelper,
                 mSuspendPackageHelper);
         mStorageEventHelper = new StorageEventHelper(this, mDeletePackageHelper,
@@ -4658,6 +4658,9 @@
                 throw new SecurityException("Cannot clear data for a protected package: "
                         + packageName);
             }
+            final int callingPid = Binder.getCallingPid();
+            EventLog.writeEvent(EventLogTags.PM_CLEAR_APP_DATA_CALLER, callingPid, callingUid,
+                    packageName);
 
             // Queue up an async operation since the package deletion may take a little while.
             mHandler.post(new Runnable() {
@@ -4791,6 +4794,9 @@
                     /* checkShell= */ false, "delete application cache files");
             final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission(
                     android.Manifest.permission.ACCESS_INSTANT_APPS);
+            final int callingPid = Binder.getCallingPid();
+            EventLog.writeEvent(EventLogTags.PM_CLEAR_APP_DATA_CALLER, callingPid, callingUid,
+                    packageName);
 
             // Queue up an async operation since the package deletion may take a little while.
             mHandler.post(() -> {
@@ -6145,7 +6151,7 @@
             }
             return mSuspendPackageHelper.setPackagesSuspended(snapshot, packageNames, suspended,
                     appExtras, launcherExtras, dialogInfo, callingPackage, userId, callingUid,
-                    false /* forQuietMode */, quarantined);
+                    quarantined);
         }
 
         @Override
@@ -6310,6 +6316,11 @@
             return mInstallerService.mPackageArchiver.getArchivedAppIcon(packageName, user);
         }
 
+        @Override
+        public boolean isAppArchivable(@NonNull String packageName, @NonNull UserHandle user) {
+            return mInstallerService.mPackageArchiver.isAppArchivable(packageName, user);
+        }
+
         /**
          * Wait for the handler to finish handling all pending messages.
          * @param timeoutMillis Maximum time in milliseconds to wait.
@@ -6597,12 +6608,6 @@
         }
 
         @Override
-        public void setPackagesSuspendedForQuietMode(int userId, boolean suspended) {
-            mSuspendPackageHelper.setPackagesSuspendedForQuietMode(
-                    snapshotComputer(), userId, suspended);
-        }
-
-        @Override
         public void setDeviceAndProfileOwnerPackages(
                 int deviceOwnerUserId, String deviceOwnerPackage,
                 SparseArray<String> profileOwnerPackages) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index f8e909e..bcb7bde 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -30,6 +30,7 @@
 import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
 import static com.android.server.pm.PackageManagerService.DEBUG_INTENT_MATCHING;
 import static com.android.server.pm.PackageManagerService.DEBUG_PREFERRED;
+import static com.android.server.pm.PackageManagerService.RANDOM_CODEPATH_PREFIX;
 import static com.android.server.pm.PackageManagerService.RANDOM_DIR_PREFIX;
 import static com.android.server.pm.PackageManagerService.SHELL_PACKAGE_NAME;
 import static com.android.server.pm.PackageManagerService.STUB_SUFFIX;
@@ -1298,15 +1299,16 @@
     }
 
     /**
-     * Given {@code targetDir}, returns {@code targetDir/~~[randomStrA]/[randomStrB].}
+     * Given {@code targetDir}, returns {@code targetDir/~~[randomStrA]/[packageName]-[randomStrB].}
      * Makes sure that {@code targetDir/~~[randomStrA]} directory doesn't exist.
      * Notice that this method doesn't actually create any directory.
      *
      * @param targetDir Directory that is two-levels up from the result directory.
-     *
-     * @return File object for the directory that should hold the code files.
+     * @param packageName Name of the package whose code files are to be installed under the result
+     *                    directory.
+     * @return File object for the directory that should hold the code files of {@code packageName}.
      */
-    public static File getNextCodePath(File targetDir) {
+    public static File getNextCodePath(File targetDir, String packageName) {
         SecureRandom random = new SecureRandom();
         byte[] bytes = new byte[16];
         File firstLevelDir;
@@ -1318,8 +1320,22 @@
         } while (firstLevelDir.exists());
 
         random.nextBytes(bytes);
-        String dirName = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP);
-        return new File(firstLevelDir, dirName);
+        String dirName = packageName + RANDOM_CODEPATH_PREFIX + Base64.encodeToString(bytes,
+                Base64.URL_SAFE | Base64.NO_WRAP);
+        final File result = new File(firstLevelDir, dirName);
+        if (DEBUG && !Objects.equals(tryParsePackageName(result.getName()), packageName)) {
+            throw new RuntimeException(
+                    "codepath is off: " + result.getName() + " (" + packageName + ")");
+        }
+        return result;
+    }
+
+    static String tryParsePackageName(@NonNull String codePath) throws IllegalArgumentException {
+        int packageNameEnds = codePath.indexOf(RANDOM_CODEPATH_PREFIX);
+        if (packageNameEnds == -1) {
+            throw new IllegalArgumentException("Not a valid package folder name");
+        }
+        return codePath.substring(0, packageNameEnds);
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 7264e2e..d4abad8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -3703,6 +3703,9 @@
                     sessionParams.installFlags |=
                             PackageManager.INSTALL_BYPASS_LOW_TARGET_SDK_BLOCK;
                     break;
+                case "--ignore-dexopt-profile":
+                    sessionParams.installFlags |= PackageManager.INSTALL_IGNORE_DEXOPT_PROFILE;
+                    break;
                 default:
                     throw new IllegalArgumentException("Unknown option " + opt);
             }
@@ -4799,7 +4802,7 @@
         pw.println("       [--enable-rollback]");
         pw.println("       [--force-uuid internal|UUID] [--pkg PACKAGE] [-S BYTES]");
         pw.println("       [--apex] [--non-staged] [--force-non-staged]");
-        pw.println("       [--staged-ready-timeout TIMEOUT]");
+        pw.println("       [--staged-ready-timeout TIMEOUT] [--ignore-dexopt-profile]");
         pw.println("       [PATH [SPLIT...]|-]");
         pw.println("    Install an application.  Must provide the apk data to install, either as");
         pw.println("    file path(s) or '-' to read from stdin.  Options are:");
@@ -4839,6 +4842,13 @@
         pw.println("          milliseconds for pre-reboot verification to complete when");
         pw.println("          performing staged install. This flag is used to alter the waiting");
         pw.println("          time. You can skip the waiting time by specifying a TIMEOUT of '0'");
+        pw.println("      --ignore-dexopt-profile: If set, all profiles are ignored by dexopt");
+        pw.println("          during the installation, including the profile in the DM file and");
+        pw.println("          the profile embedded in the APK file. If an invalid profile is");
+        pw.println("          provided during installation, no warning will be reported by `adb");
+        pw.println("          install`.");
+        pw.println("          This option does not affect later dexopt operations (e.g.,");
+        pw.println("          background dexopt and manual `pm compile` invocations).");
         pw.println("");
         pw.println("  install-existing [--user USER_ID|all|current]");
         pw.println("       [--instant] [--full] [--wait] [--restrict-permissions] PACKAGE");
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index e8cebef..71f6c0d 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.server.pm;
 
-import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
-import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.os.Process.SYSTEM_UID;
 
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
@@ -27,9 +25,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.AppOpsManager;
-import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Intent;
-import android.content.pm.PackageInfo;
 import android.content.pm.SuspendDialogInfo;
 import android.os.Binder;
 import android.os.Bundle;
@@ -45,7 +41,6 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.CollectionUtils;
-import com.android.server.LocalServices;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
 import com.android.server.pm.pkg.PackageUserStateInternal;
@@ -54,10 +49,8 @@
 import com.android.server.utils.WatchedArrayMap;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
-import java.util.Set;
 import java.util.function.Predicate;
 
 public final class SuspendPackageHelper {
@@ -68,7 +61,6 @@
     private final PackageManagerService mPm;
     private final PackageManagerServiceInjector mInjector;
 
-    private final UserManagerService mUserManager;
     private final BroadcastHelper mBroadcastHelper;
     private final ProtectedPackages mProtectedPackages;
 
@@ -76,10 +68,8 @@
      * Constructor for {@link PackageManagerService}.
      */
     SuspendPackageHelper(PackageManagerService pm, PackageManagerServiceInjector injector,
-            UserManagerService userManager, BroadcastHelper broadcastHelper,
-            ProtectedPackages protectedPackages) {
+            BroadcastHelper broadcastHelper, ProtectedPackages protectedPackages) {
         mPm = pm;
-        mUserManager = userManager;
         mInjector = injector;
         mBroadcastHelper = broadcastHelper;
         mProtectedPackages = protectedPackages;
@@ -102,7 +92,6 @@
      * @param callingPackage The caller's package name.
      * @param userId The user where packages reside.
      * @param callingUid The caller's uid.
-     * @param forQuietMode Whether suspension is for quiet mode, in which case no apps are exempt.
      * @return The names of failed packages.
      */
     @Nullable
@@ -110,11 +99,11 @@
             boolean suspended, @Nullable PersistableBundle appExtras,
             @Nullable PersistableBundle launcherExtras, @Nullable SuspendDialogInfo dialogInfo,
             @NonNull String callingPackage, @UserIdInt int userId, int callingUid,
-            boolean forQuietMode, boolean quarantined) {
+            boolean quarantined) {
         if (ArrayUtils.isEmpty(packageNames)) {
             return packageNames;
         }
-        if (suspended && !quarantined && !forQuietMode && !isSuspendAllowedForUser(snapshot, userId,
+        if (suspended && !quarantined && !isSuspendAllowedForUser(snapshot, userId,
                 callingUid)) {
             Slog.w(TAG, "Cannot suspend due to restrictions on user " + userId);
             return packageNames;
@@ -130,7 +119,7 @@
         final ArraySet<String> changedPackagesList = new ArraySet<>(packageNames.length);
         final IntArray changedUids = new IntArray(packageNames.length);
 
-        final boolean[] canSuspend = suspended && !forQuietMode
+        final boolean[] canSuspend = suspended
                 ? canSuspendPackageForUser(snapshot, packageNames, userId, callingUid)
                 : null;
         for (int i = 0; i < packageNames.length; i++) {
@@ -620,92 +609,10 @@
      */
     public String[] setPackagesSuspendedByAdmin(
             Computer snapshot, int userId, String[] packageNames, boolean suspend) {
-        final Set<String> toSuspend = new ArraySet<>(packageNames);
-        List<String> unsuspendable = new ArrayList<>();
-
-        if (mUserManager.isQuietModeEnabled(userId)) {
-            // If the user is in quiet mode, most apps will already be suspended, we shouldn't
-            // re-suspend or unsuspend them.
-            final Set<String> quiet = packagesToSuspendInQuietMode(snapshot, userId);
-            quiet.retainAll(toSuspend);
-            if (!quiet.isEmpty()) {
-                Slog.i(TAG, "Ignoring quiet packages: " + String.join(", ", quiet));
-                toSuspend.removeAll(quiet);
-            }
-
-            // Some of the already suspended packages might not be suspendable by the admin
-            // (e.g. current dialer package), we need to report it back as unsuspendable the same
-            // way as if quiet mode wasn't enabled. In that latter case they'd be returned by
-            // setPackagesSuspended below after unsuccessful attempt to suspend them.
-            if (suspend) {
-                unsuspendable = getUnsuspendablePackages(snapshot, userId, quiet);
-            }
-        }
-        if (!toSuspend.isEmpty()) {
-            unsuspendable.addAll(Arrays.asList(
-                    setPackagesSuspended(
-                            snapshot, toSuspend.toArray(new String[0]), suspend,
-                            null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */,
-                            PackageManagerService.PLATFORM_PACKAGE_NAME, userId, Process.SYSTEM_UID,
-                            false /* forQuietMode */, false /* quarantined */)));
-        }
-        return unsuspendable.toArray(String[]::new);
-    }
-
-    private List<String> getUnsuspendablePackages(
-            Computer snapshot, int userId, Set<String> packages) {
-        final String[] toSuspendArray = packages.toArray(String[]::new);
-        final boolean[] mask =
-                canSuspendPackageForUser(snapshot, toSuspendArray, userId, Process.SYSTEM_UID);
-        final List<String> result = new ArrayList<>();
-        for (int i = 0; i < mask.length; i++) {
-            if (!mask[i]) {
-                result.add(toSuspendArray[i]);
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Suspends or unsuspends all packages in the given user when quiet mode is toggled to prevent
-     * usage while quiet mode is enabled.
-     */
-    public void setPackagesSuspendedForQuietMode(
-            Computer snapshot, int userId, boolean suspend) {
-        final Set<String> toSuspend = packagesToSuspendInQuietMode(snapshot, userId);
-        if (!suspend) {
-            final DevicePolicyManagerInternal dpm =
-                    LocalServices.getService(DevicePolicyManagerInternal.class);
-            if (dpm != null) {
-                toSuspend.removeAll(dpm.getPackagesSuspendedByAdmin(userId));
-            } else {
-                Slog.wtf(TAG,
-                        "DevicePolicyManager unavailable while suspending apps for quiet mode");
-            }
-        }
-
-        if (toSuspend.isEmpty()) {
-            return;
-        }
-
-        setPackagesSuspended(snapshot, toSuspend.toArray(new String[0]),
-                suspend, null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */,
+        return setPackagesSuspended(snapshot, packageNames, suspend,
+                null /* appExtras */, null /* launcherExtras */, null /* dialogInfo */,
                 PackageManagerService.PLATFORM_PACKAGE_NAME, userId, Process.SYSTEM_UID,
-                true /* forQuietMode */, false /* quarantined */);
-    }
-
-    private Set<String> packagesToSuspendInQuietMode(Computer snapshot, int userId) {
-        final List<PackageInfo> pkgInfos = snapshot.getInstalledPackages(
-                MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId).getList();
-        final Set<String> result = new ArraySet<>();
-        for (PackageInfo info : pkgInfos) {
-            result.add(info.packageName);
-        }
-
-        // Role holder may be null, but ArraySet handles it correctly.
-        result.remove(mPm.getDevicePolicyManagementRoleHolderPackageName(userId));
-
-        return result;
+                false /* quarantined */);
     }
 
     private String getKnownPackageName(@NonNull Computer snapshot,
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index c97fbda..81a570f 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -46,7 +46,6 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityManagerNative;
-import android.app.AppOpsManager;
 import android.app.BroadcastOptions;
 import android.app.IActivityManager;
 import android.app.IStopUserCallback;
@@ -55,7 +54,6 @@
 import android.app.StatsManager;
 import android.app.admin.DevicePolicyEventLogger;
 import android.app.admin.DevicePolicyManagerInternal;
-import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.IIntentReceiver;
@@ -302,19 +300,6 @@
     private static final String TRON_USER_CREATED = "users_user_created";
     private static final String TRON_DEMO_CREATED = "users_demo_created";
 
-    // App ops that should be restricted in quiet mode
-    private static final int[] QUIET_MODE_RESTRICTED_APP_OPS = {
-            AppOpsManager.OP_COARSE_LOCATION,
-            AppOpsManager.OP_FINE_LOCATION,
-            AppOpsManager.OP_GPS,
-            AppOpsManager.OP_BODY_SENSORS,
-            AppOpsManager.OP_ACTIVITY_RECOGNITION,
-            AppOpsManager.OP_BLUETOOTH_SCAN,
-            AppOpsManager.OP_NEARBY_WIFI_DEVICES,
-            AppOpsManager.OP_RECORD_AUDIO,
-            AppOpsManager.OP_CAMERA,
-    };
-
     private final Context mContext;
     private final PackageManagerService mPm;
 
@@ -339,7 +324,6 @@
     private final File mUserListFile;
 
     private final IBinder mUserRestrictionToken = new Binder();
-    private final IBinder mQuietModeToken = new Binder();
 
     /** Installs system packages based on user-type. */
     private final UserSystemPackageInstaller mSystemPackageInstaller;
@@ -702,7 +686,6 @@
 
         @Override
         public void onUserStarting(@NonNull TargetUser targetUser) {
-            boolean isProfileInQuietMode = false;
             synchronized (mUms.mUsersLock) {
                 final UserData user = mUms.getUserDataLU(targetUser.getUserIdentifier());
                 if (user != null) {
@@ -710,14 +693,9 @@
                     if (targetUser.getUserIdentifier() == UserHandle.USER_SYSTEM
                             && targetUser.isFull()) {
                         mUms.setLastEnteredForegroundTimeToNow(user);
-                    } else if (user.info.isManagedProfile() && user.info.isQuietModeEnabled()) {
-                        isProfileInQuietMode = true;
                     }
                 }
             }
-            if (isProfileInQuietMode) {
-                mUms.setAppOpsRestrictedForQuietMode(targetUser.getUserIdentifier(), true);
-            }
         }
 
         @Override
@@ -1516,43 +1494,21 @@
         synchronized (mPackagesLock) {
             writeUserLP(profileUserData);
         }
-        if (getDevicePolicyManagerInternal().isKeepProfilesRunningEnabled()) {
-            // New behavior: when quiet mode is enabled, profile user is running, but apps are
-            // suspended.
-            getPackageManagerInternal().setPackagesSuspendedForQuietMode(userId, enableQuietMode);
-            setAppOpsRestrictedForQuietMode(userId, enableQuietMode);
 
-            if (enableQuietMode
-                    && !mLockPatternUtils.isManagedProfileWithUnifiedChallenge(userId)) {
-                mContext.getSystemService(TrustManager.class).setDeviceLockedForUser(userId, true);
+        try {
+            if (enableQuietMode) {
+                ActivityManager.getService().stopUser(userId, /* force= */ true, null);
+                LocalServices.getService(ActivityManagerInternal.class)
+                        .killForegroundAppsForUser(userId);
+            } else {
+                IProgressListener callback = target != null
+                        ? new DisableQuietModeUserUnlockedCallback(target)
+                        : null;
+                ActivityManager.getService().startProfileWithListener(userId, callback);
             }
-
-            if (!enableQuietMode && target != null) {
-                try {
-                    mContext.startIntentSender(target, null, 0, 0, 0);
-                } catch (IntentSender.SendIntentException e) {
-                    Slog.e(LOG_TAG, "Failed to start intent after disabling quiet mode", e);
-                }
-            }
-        } else {
-            // Old behavior: when quiet is enabled, profile user is stopped.
-            // Old quiet mode behavior: profile user is stopped.
-            // TODO(b/265683382) Remove once rollout complete.
-            try {
-                if (enableQuietMode) {
-                    ActivityManager.getService().stopUser(userId, /* force= */ true, null);
-                    LocalServices.getService(ActivityManagerInternal.class)
-                            .killForegroundAppsForUser(userId);
-                } else {
-                    IProgressListener callback = target != null
-                            ? new DisableQuietModeUserUnlockedCallback(target)
-                            : null;
-                    ActivityManager.getService().startProfileWithListener(userId, callback);
-                }
-            } catch (RemoteException e) {
-                // Should not happen, same process.
-                e.rethrowAsRuntimeException();
-            }
+        } catch (RemoteException e) {
+            // Should not happen, same process.
+            e.rethrowAsRuntimeException();
         }
 
         logQuietModeEnabled(userId, enableQuietMode, callingPackage);
@@ -1569,17 +1525,6 @@
         }
     }
 
-    private void setAppOpsRestrictedForQuietMode(@UserIdInt int userId, boolean restrict) {
-        for (int opCode : QUIET_MODE_RESTRICTED_APP_OPS) {
-            try {
-                mAppOpsService.setUserRestriction(
-                        opCode, restrict, mQuietModeToken, userId, /* excludedPackageTags= */ null);
-            } catch (RemoteException e) {
-                Slog.w(LOG_TAG, "Unable to limit app ops", e);
-            }
-        }
-    }
-
     private void logQuietModeEnabled(@UserIdInt int userId, boolean enableQuietMode,
             @Nullable String callingPackage) {
         Slogf.i(LOG_TAG,
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index 2ad8bcf..9e20805 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -379,10 +379,7 @@
         ai.privateFlags |= flag(state.isInstantApp(), ApplicationInfo.PRIVATE_FLAG_INSTANT)
                 | flag(state.isVirtualPreload(), ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
                 | flag(state.isHidden(), ApplicationInfo.PRIVATE_FLAG_HIDDEN);
-        if ((flags & PackageManager.MATCH_QUARANTINED_COMPONENTS) == 0
-                && state.isQuarantined()) {
-            ai.enabled = false;
-        } else  if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+        if (state.getEnabledState() == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
             ai.enabled = true;
         } else if (state.getEnabledState()
                 == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index a6558e0..eea13f1 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -14575,9 +14575,10 @@
                     mModStepMode = 0;
                 }
             } else {
-                if (level >= 90) {
-                    // If the battery level is at least 90%, always consider the device to be
-                    // charging even if it happens to go down a level.
+                if (level >= mConstants.BATTERY_CHARGING_ENFORCE_LEVEL) {
+                    // If the battery level is at least Constants.BATTERY_CHARGING_ENFORCE_LEVEL,
+                    // always consider the device to be charging even if it happens to go down a
+                    // level.
                     changed |= setChargingLocked(true);
                 } else if (!mCharging) {
                     if (mLastChargeStepLevel < level) {
@@ -15313,6 +15314,8 @@
         public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
         public static final String KEY_BATTERY_CHARGED_DELAY_MS =
                 "battery_charged_delay_ms";
+        public static final String KEY_BATTERY_CHARGING_ENFORCE_LEVEL =
+                "battery_charging_enforce_level";
         public static final String KEY_PER_UID_MODEM_POWER_MODEL =
                 "per_uid_modem_power_model";
         public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
@@ -15363,6 +15366,7 @@
         private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
         private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
         private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
+        private static final int DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL = 90;
         @PerUidModemPowerModel
         private static final int DEFAULT_PER_UID_MODEM_MODEL =
                 PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
@@ -15384,6 +15388,7 @@
         public int MAX_HISTORY_FILES;
         public int MAX_HISTORY_BUFFER; /*Bytes*/
         public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
+        public int BATTERY_CHARGING_ENFORCE_LEVEL = DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL;
         public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
         public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
                 DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
@@ -15412,6 +15417,9 @@
             mResolver.registerContentObserver(
                     Settings.Global.getUriFor(Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY),
                     false /* notifyForDescendants */, this);
+            mResolver.registerContentObserver(Settings.Global.getUriFor(
+                            Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL),
+                    false /* notifyForDescendants */, this);
             updateConstants();
         }
 
@@ -15424,6 +15432,12 @@
                     updateBatteryChargedDelayMsLocked();
                 }
                 return;
+            } else if (uri.equals(Settings.Global.getUriFor(
+                    Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL))) {
+                synchronized (BatteryStatsImpl.this) {
+                    updateBatteryChargingEnforceLevelLocked();
+                }
+                return;
             }
             updateConstants();
         }
@@ -15477,6 +15491,7 @@
                         DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
 
                 updateBatteryChargedDelayMsLocked();
+                updateBatteryChargingEnforceLevelLocked();
 
                 onChange();
             }
@@ -15507,6 +15522,21 @@
             }
         }
 
+        private void updateBatteryChargingEnforceLevelLocked() {
+            int lastChargingEnforceLevel = BATTERY_CHARGING_ENFORCE_LEVEL;
+            final int level = Settings.Global.getInt(mResolver,
+                    Settings.Global.BATTERY_CHARGING_STATE_ENFORCE_LEVEL,
+                    -1);
+
+            BATTERY_CHARGING_ENFORCE_LEVEL = level >= 0 ? level : mParser.getInt(
+                    KEY_BATTERY_CHARGING_ENFORCE_LEVEL, DEFAULT_BATTERY_CHARGING_ENFORCE_LEVEL);
+
+            if (BATTERY_CHARGING_ENFORCE_LEVEL <= mLastChargeStepLevel
+                    && mLastChargeStepLevel < lastChargingEnforceLevel) {
+                setChargingLocked(true);
+            }
+        }
+
         private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
             KERNEL_UID_READERS_THROTTLE_TIME = newTimeMs;
             if (oldTimeMs != newTimeMs) {
@@ -15541,6 +15571,8 @@
             pw.println(MAX_HISTORY_BUFFER/1024);
             pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
             pw.println(BATTERY_CHARGED_DELAY_MS);
+            pw.print(KEY_BATTERY_CHARGING_ENFORCE_LEVEL); pw.print("=");
+            pw.println(BATTERY_CHARGING_ENFORCE_LEVEL);
             pw.print(KEY_PER_UID_MODEM_POWER_MODEL); pw.print("=");
             pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
             pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 4ebd402..5fd787a 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -126,10 +126,10 @@
                 connection = new StorageUserConnection(mContext, userId, this);
                 mConnections.put(userId, connection);
             }
-            Slog.i(TAG, "Creating and starting session with id: " + sessionId);
-            connection.startSession(sessionId, deviceFd, vol.getPath().getPath(),
-                    vol.getInternalPath().getPath());
         }
+        Slog.i(TAG, "Creating and starting session with id: " + sessionId);
+        connection.startSession(sessionId, deviceFd, vol.getPath().getPath(),
+                vol.getInternalPath().getPath());
     }
 
     /**
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index 9a9b836..1f884ba 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -71,6 +71,7 @@
 public class TestHarnessModeService extends SystemService {
     public static final String TEST_HARNESS_MODE_PROPERTY = "persist.sys.test_harness";
     private static final String TAG = TestHarnessModeService.class.getSimpleName();
+    private boolean mEnableKeepMemtagMode = false;
 
     private PersistentDataBlockManagerInternal mPersistentDataBlockManagerInternal;
 
@@ -298,6 +299,18 @@
             switch (cmd) {
                 case "enable":
                 case "restore":
+                    String opt;
+                    while ((opt = getNextOption()) != null) {
+                        switch (opt) {
+                        case "--keep-memtag":
+                            mEnableKeepMemtagMode = true;
+                            break;
+                        default:
+                            getErrPrintWriter().println("Invalid option: " + opt);
+                            return 1;
+                        }
+                    }
+
                     checkPermissions();
                     final long originalId = Binder.clearCallingIdentity();
                     try {
@@ -357,6 +370,7 @@
             i.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
             i.putExtra(Intent.EXTRA_REASON, TAG);
             i.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, true);
+            i.putExtra("keep_memtag_mode", mEnableKeepMemtagMode);
             getContext().sendBroadcastAsUser(i, UserHandle.SYSTEM);
             return 0;
         }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index bdab4d4..d6637e1 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -913,7 +913,7 @@
 
     boolean mEnteringAnimation;
     boolean mOverrideTaskTransition;
-    boolean mDismissKeyguard;
+    boolean mDismissKeyguardIfInsecure;
     boolean mShareIdentity;
 
     /** True if the activity has reported stopped; False if the activity becomes visible. */
@@ -2098,7 +2098,7 @@
             }
 
             mOverrideTaskTransition = options.getOverrideTaskTransition();
-            mDismissKeyguard = options.getDismissKeyguard();
+            mDismissKeyguardIfInsecure = options.getDismissKeyguardIfInsecure();
             mShareIdentity = options.isShareIdentityEnabled();
         }
 
@@ -2448,7 +2448,7 @@
         final int typeParameter = StartingSurfaceController
                 .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
                         allowTaskSnapshot, activityCreated, isSimple, useLegacy, activityAllDrawn,
-                        type, packageName, mUserId);
+                        type, isIconStylePreferred(resolvedTheme), packageName, mUserId);
 
         if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
             if (isActivityTypeHome()) {
@@ -2887,7 +2887,6 @@
         }
 
         final StartingSurfaceController.StartingSurface surface;
-        final WindowState startingWindow = mStartingWindow;
         final boolean animate;
         if (mStartingData != null) {
             if (mStartingData.mWaitForSyncTransactionCommit
@@ -4545,7 +4544,7 @@
                     mTransitionChangeFlags |= FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
                 }
                 // Post cleanup after the visibility and animation are transferred.
-                fromActivity.postWindowRemoveStartingWindowCleanup();
+                fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
                 fromActivity.mVisibleSetFromTransferredStartingWindow = false;
 
                 mWmService.updateFocusedWindowLocked(
@@ -7461,7 +7460,12 @@
         }
     }
 
-    void postWindowRemoveStartingWindowCleanup() {
+    void postWindowRemoveStartingWindowCleanup(@NonNull WindowState win) {
+        if (mStartingWindow == win) {
+            // This could only happen when the window is removed from hierarchy. So do not keep its
+            // reference anymore.
+            mStartingWindow = null;
+        }
         if (mChildren.size() == 0 && mVisibleSetFromTransferredStartingWindow) {
             // We set the visible state to true for the token from a transferred starting
             // window. We now reset it back to false since the starting window was the last
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index 25c42b4..f9d344b 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -285,10 +285,6 @@
             return false;
         }
 
-        if (isKeepProfilesRunningEnabled() && !isPackageSuspended()) {
-            return false;
-        }
-
         IntentSender target = createIntentSenderForOriginalIntent(mCallingUid,
                 FLAG_CANCEL_CURRENT | FLAG_ONE_SHOT);
 
@@ -521,12 +517,6 @@
                 && (mAInfo.applicationInfo.flags & FLAG_SUSPENDED) != 0;
     }
 
-    private static boolean isKeepProfilesRunningEnabled() {
-        DevicePolicyManagerInternal dpmi =
-                LocalServices.getService(DevicePolicyManagerInternal.class);
-        return dpmi == null || dpmi.isKeepProfilesRunningEnabled();
-    }
-
     /**
      * Called when an activity is successfully launched.
      */
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c021785..f0698be 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -69,6 +69,7 @@
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
 import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
+
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DREAM;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
@@ -124,6 +125,7 @@
 import static com.android.server.wm.Task.REPARENT_KEEP_ROOT_TASK_AT_FRONT;
 import static com.android.server.wm.WindowManagerService.MY_PID;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
+import static com.android.sdksandbox.flags.Flags.sandboxActivitySdkBasedContext;
 
 import android.Manifest;
 import android.annotation.IntDef;
@@ -164,6 +166,7 @@
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.app.compat.CompatChanges;
+import android.app.sdksandbox.sandboxactivity.SdkSandboxActivityAuthority;
 import android.app.usage.UsageStatsManagerInternal;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
@@ -1257,6 +1260,13 @@
                 true /*validateIncomingUser*/);
     }
 
+    static boolean isSdkSandboxActivity(Context context, Intent intent) {
+        return intent != null
+                && (sandboxActivitySdkBasedContext()
+                        ? SdkSandboxActivityAuthority.isSdkSandboxActivity(context, intent)
+                        : intent.isSandboxActivity(context));
+    }
+
     private int startActivityAsUser(IApplicationThread caller, String callingPackage,
             @Nullable String callingFeatureId, Intent intent, String resolvedType,
             IBinder resultTo, String resultWho, int requestCode, int startFlags,
@@ -1267,7 +1277,7 @@
         assertPackageMatchesCallingUid(callingPackage);
         enforceNotIsolatedCaller("startActivityAsUser");
 
-        if (intent != null && intent.isSandboxActivity(mContext)) {
+        if (isSdkSandboxActivity(mContext, intent)) {
             SdkSandboxManagerLocal sdkSandboxManagerLocal = LocalManagerRegistry.getManager(
                     SdkSandboxManagerLocal.class);
             sdkSandboxManagerLocal.enforceAllowedToHostSandboxedActivity(
@@ -3825,8 +3835,7 @@
     }
 
     @Override
-    public TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution,
-            boolean takeSnapshotIfNeeded) {
+    public TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution) {
         mAmInternal.enforceCallingPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -3840,12 +3849,8 @@
                 }
             }
             // Don't call this while holding the lock as this operation might hit the disk.
-            TaskSnapshot taskSnapshot = mWindowManager.mTaskSnapshotController.getSnapshot(taskId,
+            return mWindowManager.mTaskSnapshotController.getSnapshot(taskId,
                     task.mUserId, true /* restoreFromDisk */, isLowResolution);
-            if (taskSnapshot == null && takeSnapshotIfNeeded) {
-                taskSnapshot = takeTaskSnapshot(taskId, false /* updateCache */);
-            }
-            return taskSnapshot;
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -7064,8 +7069,7 @@
         @Override
         public TaskSnapshot getTaskSnapshotBlocking(
                 int taskId, boolean isLowResolution) {
-            return ActivityTaskManagerService.this.getTaskSnapshot(taskId, isLowResolution,
-                    false /* takeSnapshotIfNeeded */);
+            return ActivityTaskManagerService.this.getTaskSnapshot(taskId, isLowResolution);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 777b5cd..e5eb303 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -1089,7 +1089,7 @@
             // Remove the process record so it won't be considered as alive.
             mService.mProcessNames.remove(wpc.mName, wpc.mUid);
             mService.mProcessMap.remove(wpc.getPid());
-        } else if (r.intent.isSandboxActivity(mService.mContext)) {
+        } else if (ActivityTaskManagerService.isSdkSandboxActivity(mService.mContext, r.intent)) {
             Slog.e(TAG, "Abort sandbox activity launching as no sandbox process to host it.");
             r.finishIfPossible("No sandbox process for the activity", false /* oomAdj */);
             r.launchFailed = true;
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 4579cc1..68082df 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -28,6 +28,7 @@
 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
 import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
 import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel;
+import static com.android.window.flags.Flags.balShowToasts;
 import static com.android.server.wm.PendingRemoteAnimationRegistry.TIMEOUT_MS;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -74,6 +75,7 @@
 
     private static final long ASM_GRACEPERIOD_TIMEOUT_MS = TIMEOUT_MS;
     private static final int ASM_GRACEPERIOD_MAX_REPEATS = 5;
+    private static final int NO_PROCESS_UID = -1;
     public static final ActivityOptions ACTIVITY_OPTIONS_SYSTEM_DEFINED =
             ActivityOptions.makeBasic()
                     .setPendingIntentBackgroundActivityStartMode(
@@ -291,6 +293,10 @@
             return name + "[debugOnly]";
         }
 
+        private boolean callerIsRealCaller() {
+            return mCallingUid == mRealCallingUid;
+        }
+
         private String dump(BalVerdict resultIfPiCreatorAllowsBal,
                            BalVerdict resultIfPiSenderAllowsBal) {
             return " [callingPackage: " + getDebugPackageName(mCallingPackage, mCallingUid)
@@ -422,7 +428,7 @@
         }
 
         BalVerdict resultForCaller = checkBackgroundActivityStartAllowedByCaller(state);
-        BalVerdict resultForRealCaller = callingUid == realCallingUid && resultForCaller.allows()
+        BalVerdict resultForRealCaller = state.callerIsRealCaller() && resultForCaller.allows()
                 ? resultForCaller // no need to calculate again
                 // otherwise we might need to recalculate because the logic is not the same
                 : checkBackgroundActivityStartAllowedBySender(state, checkedOptions);
@@ -455,6 +461,7 @@
                     "With Android 15 BAL hardening this activity start would be blocked"
                             + " (missing opt in by PI creator)! "
                             + state.dump(resultForCaller, resultForRealCaller));
+            showBalToast("BAL would be blocked", state);
             // return the realCaller result for backwards compatibility
             return statsLog(resultForRealCaller, state);
         }
@@ -466,6 +473,7 @@
                     "With Android 15 BAL hardening this activity start would be blocked"
                             + " (missing opt in by PI creator)! "
                             + state.dump(resultForCaller, resultForRealCaller));
+            showBalToast("BAL would be blocked", state);
             return statsLog(resultForCaller, state);
         }
         if (resultForRealCaller.allows()
@@ -477,6 +485,7 @@
                         "With Android 14 BAL hardening this activity start would be blocked"
                                 + " (missing opt in by PI sender)! "
                                 + state.dump(resultForCaller, resultForRealCaller));
+                showBalToast("BAL would be blocked", state);
                 return statsLog(resultForRealCaller, state);
             }
             Slog.wtf(TAG, "Without Android 14 BAL hardening this activity start would be allowed"
@@ -484,6 +493,7 @@
                     + state.dump(resultForCaller, resultForRealCaller));
             // fall through
         }
+        showBalToast("BAL blocked", state);
         // anything that has fallen through would currently be aborted
         Slog.w(TAG, "Background activity launch blocked"
                 + state.dump(resultForCaller, resultForRealCaller));
@@ -636,16 +646,14 @@
     BalVerdict checkBackgroundActivityStartAllowedBySender(
             BalState state,
             ActivityOptions checkedOptions) {
-        int realCallingUid = state.mRealCallingUid;
-        BackgroundStartPrivileges backgroundStartPrivileges = state.mBackgroundStartPrivileges;
 
         if (PendingIntentRecord.isPendingIntentBalAllowedByPermission(checkedOptions)
                 && ActivityManager.checkComponentPermission(
                 android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
-                realCallingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
+                state.mRealCallingUid, NO_PROCESS_UID, true) == PackageManager.PERMISSION_GRANTED) {
             return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
                     /*background*/ false,
-                    "realCallingUid has BAL permission. realCallingUid: " + realCallingUid);
+                    "realCallingUid has BAL permission.");
         }
 
         // don't abort if the realCallingUid has a visible window
@@ -653,26 +661,23 @@
         if (state.mRealCallingUidHasAnyVisibleWindow) {
             return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
                     /*background*/ false,
-                    "realCallingUid has visible (non-toast) window. realCallingUid: "
-                            + realCallingUid);
+                    "realCallingUid has visible (non-toast) window.");
         }
         // if the realCallingUid is a persistent system process, abort if the IntentSender
         // wasn't allowed to start an activity
         if (state.mIsRealCallingUidPersistentSystemProcess
-                && backgroundStartPrivileges.allowsBackgroundActivityStarts()) {
+                && state.mBackgroundStartPrivileges.allowsBackgroundActivityStarts()) {
             return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
                     /*background*/ false,
                     "realCallingUid is persistent system process AND intent "
-                            + "sender allowed (allowBackgroundActivityStart = true). "
-                            + "realCallingUid: " + realCallingUid);
+                            + "sender allowed (allowBackgroundActivityStart = true).");
         }
         // don't abort if the realCallingUid is an associated companion app
         if (mService.isAssociatedCompanionApp(
-                UserHandle.getUserId(realCallingUid), realCallingUid)) {
+                UserHandle.getUserId(state.mRealCallingUid), state.mRealCallingUid)) {
             return new BalVerdict(BAL_ALLOW_PENDING_INTENT,
                     /*background*/ false,
-                    "realCallingUid is a companion app. "
-                            + "realCallingUid: " + realCallingUid);
+                    "realCallingUid is a companion app.");
         }
 
         // don't abort if the callerApp or other processes of that uid are allowed in any way
@@ -830,7 +835,7 @@
                 /* caller_activity_class_name */
                 sourceRecord != null ? sourceRecord.info.name : null,
                 /* target_task_top_activity_uid */
-                targetTopActivity != null ? targetTopActivity.getUid() : -1,
+                targetTopActivity != null ? targetTopActivity.getUid() : NO_PROCESS_UID,
                 /* target_task_top_activity_class_name */
                 targetTopActivity != null ? targetTopActivity.info.name : null,
                 /* target_task_is_different */
@@ -863,8 +868,7 @@
                     + (blockActivityStartAndFeatureEnabled ? " blocked " : " would block ")
                     + getApplicationLabel(mService.mContext.getPackageManager(),
                     launchedFromPackageName);
-            UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
-                    toastText, Toast.LENGTH_LONG).show());
+            showToast(toastText);
 
             Slog.i(TAG, asmDebugInfo);
         }
@@ -883,6 +887,19 @@
         return true;
     }
 
+    private void showBalToast(String toastText, BalState state) {
+        if (balShowToasts()) {
+            showToast(toastText
+                    + " caller:" + state.mCallingPackage
+                    + " realCaller:" + state.mRealCallingPackage);
+        }
+    }
+
+    private void showToast(String toastText) {
+        UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
+                toastText, Toast.LENGTH_LONG).show());
+    }
+
     /**
      * If the top activity uid does not match the launching or launched activity, and the launch was
      * not requested from the top uid, we want to clear out all non matching activities to prevent
@@ -931,12 +948,10 @@
 
         if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)
                 && (!shouldBlockActivityStart || finishCount[0] > 0)) {
-            UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
-                    (shouldBlockActivityStart
-                            ? "Top activities cleared by "
-                            : "Top activities would be cleared by ")
-                            + ActivitySecurityModelFeatureFlags.DOC_LINK,
-                    Toast.LENGTH_LONG).show());
+            showToast((shouldBlockActivityStart
+                    ? "Top activities cleared by "
+                    : "Top activities would be cleared by ")
+                    + ActivitySecurityModelFeatureFlags.DOC_LINK);
 
             Slog.i(TAG, getDebugInfoForActivitySecurity("Clear Top", sourceRecord, targetRecord,
                     targetTask, targetTaskTop, realCallingUid, balCode, shouldBlockActivityStart,
@@ -974,13 +989,13 @@
                 /* caller_activity_class_name */
                 callerActivityClassName,
                 /* target_task_top_activity_uid */
-                topActivity == null ? -1 : topActivity.getUid(),
+                topActivity == null ? NO_PROCESS_UID : topActivity.getUid(),
                 /* target_task_top_activity_class_name */
                 topActivity == null ? null : topActivity.info.name,
                 /* target_task_is_different */
                 false,
                 /* target_activity_uid */
-                -1,
+                NO_PROCESS_UID,
                 /* target_activity_class_name */
                 null,
                 /* target_intent_action */
@@ -1014,11 +1029,10 @@
         }
 
         if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
-            UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
-                    (ActivitySecurityModelFeatureFlags.DOC_LINK
-                            + (restrictActivitySwitch ? " returned home due to "
-                            : " would return home due to ")
-                            + callingLabel), Toast.LENGTH_LONG).show());
+            showToast((ActivitySecurityModelFeatureFlags.DOC_LINK
+                    + (restrictActivitySwitch ? " returned home due to "
+                    : " would return home due to ")
+                    + callingLabel));
         }
 
         // If the activity switch should be restricted, return home rather than the
diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
index 275396f..1462878 100644
--- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java
+++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java
@@ -150,8 +150,8 @@
 
         /**
          * A unique token associated with the embedded window that can be used by the host window
-         * to request focus transfer to the embedded. This is not the input token since we don't
-         * want to give clients access to each others input token.
+         * to request focus transfer and gesture transfer to the embedded. This is not the input
+         * token since we don't want to give clients access to each others input token.
          */
         private final IBinder mInputTransferToken;
 
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index fa2c94a..ccaa3b0 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -665,12 +665,14 @@
                     mTopTurnScreenOnActivity = top;
                 }
 
-                if (top.mDismissKeyguard && mKeyguardShowing) {
+                final boolean isKeyguardSecure = controller.mWindowManager.isKeyguardSecure(
+                        controller.mService.getCurrentUserId());
+                if (top.mDismissKeyguardIfInsecure && mKeyguardShowing && !isKeyguardSecure) {
                     mKeyguardGoingAway = true;
                 } else if (top.canShowWhenLocked()) {
                     mTopOccludesActivity = top;
                 }
-                top.mDismissKeyguard = false;
+                top.mDismissKeyguardIfInsecure = false;
 
                 // Only the top activity may control occluded, as we can't occlude the Keyguard
                 // if the top app doesn't want to occlude it.
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index b1c1fd6..e82f322 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -174,10 +174,14 @@
 
     private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
     private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
+    private static final int MSG_SEND_SLEEP_TRANSITION = 3;
+
     static final String TAG_TASKS = TAG + POSTFIX_TASKS;
     static final String TAG_STATES = TAG + POSTFIX_STATES;
     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
 
+    private static final long SLEEP_TRANSITION_WAIT_MILLIS = 1000L;
+
     private Object mLastWindowFreezeSource = null;
     private float mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
     private long mUserActivityTimeout = -1;
@@ -1132,6 +1136,11 @@
                     mWmService.mPowerManagerInternal.
                             setUserActivityTimeoutOverrideFromWindowManager((Long) msg.obj);
                     break;
+                case MSG_SEND_SLEEP_TRANSITION:
+                    synchronized (mService.mGlobalLock) {
+                        sendSleepTransition((DisplayContent) msg.obj);
+                    }
+                    break;
                 default:
                     break;
             }
@@ -2442,8 +2451,38 @@
         return result;
     }
 
+    void sendSleepTransition(final DisplayContent display) {
+        // We don't actually care about collecting anything here. We really just want
+        // this as a signal to the transition-player.
+        final Transition transition = new Transition(TRANSIT_SLEEP, 0 /* flags */,
+                display.mTransitionController, mWmService.mSyncEngine);
+        final TransitionController.OnStartCollect sendSleepTransition = (deferred) -> {
+            if (deferred && !display.shouldSleep()) {
+                transition.abort();
+            } else {
+                display.mTransitionController.requestStartTransition(transition,
+                        null /* trigger */, null /* remote */, null /* display */);
+                // Force playing immediately so that unrelated ops can't be collected.
+                transition.playNow();
+            }
+        };
+        if (!display.mTransitionController.isCollecting()) {
+            // Since this bypasses sync, submit directly ignoring whether sync-engine
+            // is active.
+            if (mWindowManager.mSyncEngine.hasActiveSync()) {
+                Slog.w(TAG, "Ongoing sync outside of a transition.");
+            }
+            display.mTransitionController.moveToCollecting(transition);
+            sendSleepTransition.onCollectStarted(false /* deferred */);
+        } else {
+            display.mTransitionController.startCollectOrQueue(transition,
+                    sendSleepTransition);
+        }
+    }
+
     void applySleepTokens(boolean applyToRootTasks) {
-        boolean builtSleepTransition = false;
+        boolean scheduledSleepTransition = false;
+
         for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
             // Set the sleeping state of the display.
             final DisplayContent display = getChildAt(displayNdx);
@@ -2453,35 +2492,16 @@
             }
             display.setIsSleeping(displayShouldSleep);
 
-            if (display.mTransitionController.isShellTransitionsEnabled() && !builtSleepTransition
+            if (display.mTransitionController.isShellTransitionsEnabled()
+                    && !scheduledSleepTransition
                     // Only care if there are actual sleep tokens.
                     && displayShouldSleep && !display.mAllSleepTokens.isEmpty()) {
-                builtSleepTransition = true;
-                // We don't actually care about collecting anything here. We really just want
-                // this as a signal to the transition-player.
-                final Transition transition = new Transition(TRANSIT_SLEEP, 0 /* flags */,
-                        display.mTransitionController, mWmService.mSyncEngine);
-                final TransitionController.OnStartCollect sendSleepTransition = (deferred) -> {
-                    if (deferred && !display.shouldSleep()) {
-                        transition.abort();
-                    } else {
-                        display.mTransitionController.requestStartTransition(transition,
-                                null /* trigger */, null /* remote */, null /* display */);
-                        // Force playing immediately so that unrelated ops can't be collected.
-                        transition.playNow();
-                    }
-                };
-                if (!display.mTransitionController.isCollecting()) {
-                    // Since this bypasses sync, submit directly ignoring whether sync-engine
-                    // is active.
-                    if (mWindowManager.mSyncEngine.hasActiveSync()) {
-                        Slog.w(TAG, "Ongoing sync outside of a transition.");
-                    }
-                    display.mTransitionController.moveToCollecting(transition);
-                    sendSleepTransition.onCollectStarted(false /* deferred */);
-                } else {
-                    display.mTransitionController.startCollectOrQueue(transition,
-                            sendSleepTransition);
+                scheduledSleepTransition = true;
+
+                if (!mHandler.hasMessages(MSG_SEND_SLEEP_TRANSITION)) {
+                    mHandler.sendMessageDelayed(
+                            mHandler.obtainMessage(MSG_SEND_SLEEP_TRANSITION, display),
+                            SLEEP_TRANSITION_WAIT_MILLIS);
                 }
             }
 
@@ -2535,6 +2555,10 @@
                 }
             });
         }
+
+        if (!scheduledSleepTransition) {
+            mHandler.removeMessages(MSG_SEND_SLEEP_TRANSITION);
+        }
     }
 
     protected Task getRootTask(int rooTaskId) {
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index 6418148..4ced5d5 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -343,14 +343,14 @@
         }
 
         // Check if the caller is allowed to dismiss keyguard.
-        final boolean dismissKeyguard = options.getDismissKeyguard();
-        if (aInfo != null && dismissKeyguard) {
+        final boolean dismissKeyguardIfInsecure = options.getDismissKeyguardIfInsecure();
+        if (aInfo != null && dismissKeyguardIfInsecure) {
             final int controlKeyguardPerm = ActivityTaskManagerService.checkPermission(
                     CONTROL_KEYGUARD, callingPid, callingUid);
             if (controlKeyguardPerm != PERMISSION_GRANTED) {
                 final String msg = "Permission Denial: starting " + getIntentString(intent)
                         + " from " + callerApp + " (pid=" + callingPid
-                        + ", uid=" + callingUid + ") with dismissKeyguard=true";
+                        + ", uid=" + callingUid + ") with dismissKeyguardIfInsecure=true";
                 Slog.w(TAG, msg);
                 throw new SecurityException(msg);
             }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index a756847..0c55d8a 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -964,6 +964,23 @@
     }
 
     @Override
+    public boolean transferHostTouchGestureToEmbedded(IWindow hostWindow,
+            IBinder inputTransferToken) {
+        if (hostWindow == null) {
+            return false;
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        boolean didTransfer;
+        try {
+            didTransfer = mService.transferHostTouchGestureToEmbedded(this, hostWindow,
+                    inputTransferToken);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return didTransfer;
+    }
+    @Override
     public void generateDisplayHash(IWindow window, Rect boundsInWindow, String hashAlgorithm,
             RemoteCallback callback) {
         final long origId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index a55c232..28a35b9 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -20,6 +20,7 @@
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_DRAWN;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_HANDLE_SOLID_COLOR_SCREEN;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_APP_PREFERS_ICON;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
@@ -103,7 +104,7 @@
     static int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
             boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
             boolean isSolidColor, boolean useLegacy, boolean activityDrawn, int startingWindowType,
-            String packageName, int userId) {
+            boolean appPrefersIcon, String packageName, int userId) {
         int parameter = 0;
         if (newTask) {
             parameter |= TYPE_PARAMETER_NEW_TASK;
@@ -134,6 +135,9 @@
                 UserHandle.of(userId))) {
             parameter |= TYPE_PARAMETER_ALLOW_HANDLE_SOLID_COLOR_SCREEN;
         }
+        if (appPrefersIcon) {
+            parameter |= TYPE_PARAMETER_APP_PREFERS_ICON;
+        }
         return parameter;
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 5c5a1e1..f348928 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3508,10 +3508,13 @@
                         top.mLetterboxUiController.getLetterboxPositionForVerticalReachability();
             }
         }
-        // User Aspect Ratio Settings is enabled if the app is not in SCM
+        // User Aspect Ratio Settings button is enabled if the app is not in SCM and has
+        // launchable activities
         info.topActivityEligibleForUserAspectRatioButton = top != null
                 && !info.topActivityInSizeCompat
-                && top.mLetterboxUiController.shouldEnableUserAspectRatioSettings();
+                && top.mLetterboxUiController.shouldEnableUserAspectRatioSettings()
+                && mAtmService.mContext.getPackageManager()
+                    .getLaunchIntentForPackage(getBasePackageName()) != null;
         info.topActivityBoundsLetterboxed = top != null && top.areBoundsLetterboxed();
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 8f884d2f..f6c431f 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1106,7 +1106,7 @@
         return mInsetsSourceProviders;
     }
 
-    public DisplayContent getDisplayContent() {
+    public final DisplayContent getDisplayContent() {
         return mDisplayContent;
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9fb7e8d..6e3d24b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2020,7 +2020,7 @@
         }
 
         if (win.mActivityRecord != null) {
-            win.mActivityRecord.postWindowRemoveStartingWindowCleanup();
+            win.mActivityRecord.postWindowRemoveStartingWindowCleanup(win);
         }
 
         if (win.mAttrs.type == TYPE_WALLPAPER) {
@@ -8960,6 +8960,43 @@
         }
     }
 
+    boolean transferHostTouchGestureToEmbedded(Session session, IWindow hostWindow,
+            IBinder inputTransferToken) {
+        final IBinder hostInputChannel, embeddedInputChannel;
+        synchronized (mGlobalLock) {
+            final WindowState hostWindowState = windowForClientLocked(session, hostWindow, false);
+            if (hostWindowState == null) {
+                Slog.w(TAG, "Attempt to transfer touch gesture with invalid host window");
+                return false;
+            }
+
+            final EmbeddedWindowController.EmbeddedWindow ew =
+                    mEmbeddedWindowController.getByInputTransferToken(inputTransferToken);
+            if (ew == null || ew.mHostWindowState == null) {
+                Slog.w(TAG, "Attempt to transfer touch gesture to non-existent embedded window");
+                return false;
+            }
+            if (ew.mHostWindowState.mClient.asBinder() != hostWindow.asBinder()) {
+                Slog.w(TAG, "Attempt to transfer touch gesture to embedded window not associated"
+                        + " with host window");
+                return false;
+            }
+            embeddedInputChannel = ew.getInputChannelToken();
+            if (embeddedInputChannel == null) {
+                Slog.w(TAG, "Attempt to transfer touch focus from embedded window with no input"
+                        + " channel");
+                return false;
+            }
+            hostInputChannel = hostWindowState.mInputChannelToken;
+            if (hostInputChannel == null) {
+                Slog.w(TAG,
+                        "Attempt to transfer touch focus to a host window with no input channel");
+                return false;
+            }
+            return mInputManager.transferTouchFocus(hostInputChannel, embeddedInputChannel);
+        }
+    }
+
     private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
             int displayId, SurfaceControl surface, String name,
             InputApplicationHandle applicationHandle, int flags,
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 3497353..95e2515 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -1144,16 +1144,12 @@
                 if (pipTask == null) {
                     break;
                 }
-                ActivityRecord[] pipActivity = new ActivityRecord[1];
-                pipTask.forAllActivities((activity) -> {
-                    if (activity.pictureInPictureArgs != null) {
-                        pipActivity[0] = activity;
-                    }
-                });
+                ActivityRecord pipActivity = pipTask.getActivity(
+                        (activity) -> activity.pictureInPictureArgs != null);
 
                 Rect entryBounds = hop.getBounds();
                 mService.mRootWindowContainer.moveActivityToPinnedRootTask(
-                        pipActivity[0], null /* launchIntoPipHostActivity */,
+                        pipActivity, null /* launchIntoPipHostActivity */,
                         "moveActivityToPinnedRootTask", null /* transition */, entryBounds);
                 effects |= TRANSACT_EFFECTS_LIFECYCLE;
                 break;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f14a6f9..34cf436 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1089,6 +1089,7 @@
         mClient = c;
         mAppOp = appOp;
         mToken = token;
+        mDisplayContent = token.mDisplayContent;
         mActivityRecord = mToken.asActivityRecord();
         mOwnerUid = ownerId;
         mShowUserId = showUserId;
@@ -1565,11 +1566,6 @@
     }
 
     @Override
-    public DisplayContent getDisplayContent() {
-        return mToken.getDisplayContent();
-    }
-
-    @Override
     void onDisplayChanged(DisplayContent dc) {
         if (dc != null && mDisplayContent != null && dc != mDisplayContent
                 && mDisplayContent.getImeInputTarget() == this) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 33751b9..209d934 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -28,7 +28,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowSurfaceControllerProto.LAYER;
 import static com.android.server.wm.WindowSurfaceControllerProto.SHOWN;
 
 import android.os.Debug;
@@ -53,18 +52,6 @@
 
     // Should only be set from within setShown().
     private boolean mSurfaceShown = false;
-    private float mSurfaceX = 0;
-    private float mSurfaceY = 0;
-
-    // Initialize to the identity matrix.
-    private float mLastDsdx = 1;
-    private float mLastDtdx = 0;
-    private float mLastDsdy = 0;
-    private float mLastDtdy = 1;
-
-    private float mSurfaceAlpha = 0;
-
-    private int mSurfaceLayer = 0;
 
     private final String title;
 
@@ -73,8 +60,6 @@
     private final int mWindowType;
     private final Session mWindowSession;
 
-    // Used to track whether we have called detach children on the way to invisibility.
-    boolean mChildrenDetached;
 
     WindowSurfaceController(String name, int format, int flags, WindowStateAnimator animator,
             int windowType) {
@@ -157,44 +142,11 @@
         }
     }
 
-    void setPosition(SurfaceControl.Transaction t, float left, float top) {
-        final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
-        if (!surfaceMoved) {
-            return;
-        }
-
-        mSurfaceX = left;
-        mSurfaceY = top;
-
-        ProtoLog.i(WM_SHOW_TRANSACTIONS,
-                "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", left, top, title);
-
-        t.setPosition(mSurfaceControl, left, top);
-    }
-
-    void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, float dtdy, float dsdy) {
-        final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx ||
-                                      mLastDtdy != dtdy || mLastDsdy != dsdy;
-        if (!matrixChanged) {
-            return;
-        }
-
-        mLastDsdx = dsdx;
-        mLastDtdx = dtdx;
-        mLastDtdy = dtdy;
-        mLastDsdy = dsdy;
-
-        ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE MATRIX [%f,%f,%f,%f]: %s",
-                dsdx, dtdx, dtdy, dsdy, title);
-        t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy);
-    }
-
     boolean prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha) {
         if (mSurfaceControl == null) {
             return false;
         }
 
-        mSurfaceAlpha = alpha;
         t.setAlpha(mSurfaceControl, alpha);
         return true;
     }
@@ -305,7 +257,6 @@
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(SHOWN, mSurfaceShown);
-        proto.write(LAYER, mSurfaceLayer);
         proto.end(token);
     }
 
@@ -314,13 +265,6 @@
             pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
         }
         pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
-        pw.print(" layer="); pw.print(mSurfaceLayer);
-        pw.print(" alpha="); pw.print(mSurfaceAlpha);
-        pw.print(" rect=("); pw.print(mSurfaceX);
-        pw.print(","); pw.print(mSurfaceY); pw.print(") ");
-        pw.print(" transform=("); pw.print(mLastDsdx); pw.print(", ");
-        pw.print(mLastDtdx); pw.print(", "); pw.print(mLastDsdy);
-        pw.print(", "); pw.print(mLastDtdy); pw.println(")");
     }
 
     @Override
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 176bc283..a7d7730 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -86,6 +86,8 @@
 
 namespace android {
 
+static const bool ENABLE_POINTER_CHOREOGRAPHER = input_flags::enable_pointer_choreographer();
+
 // The exponent used to calculate the pointer speed scaling factor.
 // The scaling factor is calculated as 2 ^ (speed * exponent),
 // where the speed ranges from -7 to + 7 and is supplied by the user.
@@ -327,6 +329,8 @@
     TouchAffineTransformation getTouchAffineTransformation(JNIEnv* env, jfloatArray matrixArr);
     void notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) override;
     bool isInputMethodConnectionActive() override;
+    std::optional<DisplayViewport> getPointerViewportForAssociatedDisplay(
+            int32_t associatedDisplayId) override;
 
     /* --- InputDispatcherPolicyInterface implementation --- */
 
@@ -374,8 +378,10 @@
     virtual PointerIconStyle getCustomPointerIconId();
     virtual void onPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position);
 
-    /* --- PointerControllerPolicyInterface implementation --- */
-    std::shared_ptr<PointerControllerInterface> createPointerController() override;
+    /* --- PointerChoreographerPolicyInterface implementation --- */
+    std::shared_ptr<PointerControllerInterface> createPointerController(
+            PointerControllerInterface::ControllerType type) override;
+    void notifyPointerDisplayIdChanged(int32_t displayId, const FloatPoint& position) override;
 
 private:
     sp<InputManagerInterface> mInputManager;
@@ -492,7 +498,9 @@
         dump += StringPrintf(INDENT "Pointer Capture: %s, seq=%" PRIu32 "\n",
                              mLocked.pointerCaptureRequest.enable ? "Enabled" : "Disabled",
                              mLocked.pointerCaptureRequest.seq);
-        forEachPointerControllerLocked([&dump](PointerController& pc) { dump += pc.dump(); });
+        if (auto pc = mLocked.legacyPointerController.lock(); pc) {
+            dump += pc->dump();
+        }
     } // release lock
     dump += "\n";
 
@@ -537,6 +545,9 @@
                 [&viewports](PointerController& pc) { pc.onDisplayViewportsUpdated(viewports); });
     } // release lock
 
+    if (ENABLE_POINTER_CHOREOGRAPHER) {
+        mInputManager->getChoreographer().setDisplayViewports(viewports);
+    }
     mInputManager->getReader().requestRefreshConfiguration(
             InputReaderConfiguration::Change::DISPLAY_INFO);
 }
@@ -721,6 +732,7 @@
             continue;
         }
         apply(*pc);
+        it++;
     }
 }
 
@@ -735,9 +747,6 @@
     if (controller == nullptr) {
         ensureSpriteControllerLocked();
 
-        static const bool ENABLE_POINTER_CHOREOGRAPHER =
-                input_flags::enable_pointer_choreographer();
-
         // Disable the functionality of the legacy PointerController if PointerChoreographer is
         // enabled.
         controller = PointerController::create(this, mLooper, *mLocked.spriteController,
@@ -749,17 +758,43 @@
     return controller;
 }
 
-std::shared_ptr<PointerControllerInterface> NativeInputManager::createPointerController() {
+std::shared_ptr<PointerControllerInterface> NativeInputManager::createPointerController(
+        PointerControllerInterface::ControllerType type) {
     std::scoped_lock _l(mLock);
     ensureSpriteControllerLocked();
     std::shared_ptr<PointerController> pc =
-            PointerController::create(this, mLooper, *mLocked.spriteController, /*enabled=*/true);
+            PointerController::create(this, mLooper, *mLocked.spriteController, /*enabled=*/true,
+                                      type);
     mLocked.pointerControllers.emplace_back(pc);
     return pc;
 }
 
 void NativeInputManager::onPointerDisplayIdChanged(int32_t pointerDisplayId,
                                                    const FloatPoint& position) {
+    if (ENABLE_POINTER_CHOREOGRAPHER) {
+        return;
+    }
+    JNIEnv* env = jniEnv();
+    env->CallVoidMethod(mServiceObj, gServiceClassInfo.onPointerDisplayIdChanged, pointerDisplayId,
+                        position.x, position.y);
+    checkAndClearExceptionFromCallback(env, "onPointerDisplayIdChanged");
+}
+
+void NativeInputManager::notifyPointerDisplayIdChanged(int32_t pointerDisplayId,
+                                                       const FloatPoint& position) {
+    // Notify the Reader so that devices can be reconfigured.
+    { // acquire lock
+        std::scoped_lock _l(mLock);
+        if (mLocked.pointerDisplayId == pointerDisplayId) {
+            return;
+        }
+        mLocked.pointerDisplayId = pointerDisplayId;
+        ALOGI("%s: pointer displayId set to: %d", __func__, pointerDisplayId);
+    } // release lock
+    mInputManager->getReader().requestRefreshConfiguration(
+            InputReaderConfiguration::Change::DISPLAY_INFO);
+
+    // Notify the system.
     JNIEnv* env = jniEnv();
     env->CallVoidMethod(mServiceObj, gServiceClassInfo.onPointerDisplayIdChanged, pointerDisplayId,
                         position.x, position.y);
@@ -1118,19 +1153,23 @@
 }
 
 void NativeInputManager::setPointerDisplayId(int32_t displayId) {
-    { // acquire lock
-        std::scoped_lock _l(mLock);
+    if (ENABLE_POINTER_CHOREOGRAPHER) {
+        mInputManager->getChoreographer().setDefaultMouseDisplayId(displayId);
+    } else {
+        { // acquire lock
+            std::scoped_lock _l(mLock);
 
-        if (mLocked.pointerDisplayId == displayId) {
-            return;
-        }
+            if (mLocked.pointerDisplayId == displayId) {
+                return;
+            }
 
-        ALOGI("Setting pointer display id to %d.", displayId);
-        mLocked.pointerDisplayId = displayId;
-    } // release lock
+            ALOGI("Setting pointer display id to %d.", displayId);
+            mLocked.pointerDisplayId = displayId;
+        } // release lock
 
-    mInputManager->getReader().requestRefreshConfiguration(
-            InputReaderConfiguration::Change::DISPLAY_INFO);
+        mInputManager->getReader().requestRefreshConfiguration(
+                InputReaderConfiguration::Change::DISPLAY_INFO);
+    }
 }
 
 void NativeInputManager::setPointerSpeed(int32_t speed) {
@@ -1356,6 +1395,11 @@
     return result;
 }
 
+std::optional<DisplayViewport> NativeInputManager::getPointerViewportForAssociatedDisplay(
+        int32_t associatedDisplayId) {
+    return mInputManager->getChoreographer().getViewportForPointerDevice(associatedDisplayId);
+}
+
 bool NativeInputManager::filterInputEvent(const InputEvent& inputEvent, uint32_t policyFlags) {
     ATRACE_CALL();
     JNIEnv* env = jniEnv();
@@ -1689,6 +1733,9 @@
 }
 
 FloatPoint NativeInputManager::getMouseCursorPosition() {
+    if (ENABLE_POINTER_CHOREOGRAPHER) {
+        return mInputManager->getChoreographer().getMouseCursorPosition(ADISPLAY_ID_NONE);
+    }
     std::scoped_lock _l(mLock);
     const auto pc = mLocked.legacyPointerController.lock();
     if (!pc) return {AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION};
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index d960439..395ea91 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -16,8 +16,6 @@
 
 package com.android.server.devicepolicy;
 
-import static com.android.server.devicepolicy.DevicePolicyManagerService.DEFAULT_KEEP_PROFILES_RUNNING_FLAG;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
@@ -200,7 +198,7 @@
      * Effective state of the feature flag. It is updated to the current configuration value
      * during boot and doesn't change value after than unless overridden by test code.
      */
-    boolean mEffectiveKeepProfilesRunning = DEFAULT_KEEP_PROFILES_RUNNING_FLAG;
+    boolean mEffectiveKeepProfilesRunning = false;
 
     DevicePolicyData(@UserIdInt int userId) {
         mUserId = userId;
@@ -401,7 +399,7 @@
                 out.endTag(null, TAG_BYPASS_ROLE_QUALIFICATIONS);
             }
 
-            if (policyData.mEffectiveKeepProfilesRunning != DEFAULT_KEEP_PROFILES_RUNNING_FLAG) {
+            if (policyData.mEffectiveKeepProfilesRunning) {
                 out.startTag(null, TAG_KEEP_PROFILES_RUNNING);
                 out.attributeBoolean(null, ATTR_VALUE, policyData.mEffectiveKeepProfilesRunning);
                 out.endTag(null, TAG_KEEP_PROFILES_RUNNING);
@@ -592,7 +590,7 @@
                     policy.mCurrentRoleHolder = parser.getAttributeValue(null, ATTR_VALUE);
                 } else if (TAG_KEEP_PROFILES_RUNNING.equals(tag)) {
                     policy.mEffectiveKeepProfilesRunning = parser.getAttributeBoolean(
-                            null, ATTR_VALUE, DEFAULT_KEEP_PROFILES_RUNNING_FLAG);
+                            null, ATTR_VALUE, false);
                 // Deprecated tags below
                 } else if (TAG_PROTECTED_PACKAGES.equals(tag)) {
                     if (policy.mUserControlDisabledPackages == null) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 1ff117e..93dc219 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -873,9 +873,6 @@
             "enable_permission_based_access";
     private static final boolean DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG = false;
 
-    // TODO(b/265683382) remove the flag after rollout.
-    public static final boolean DEFAULT_KEEP_PROFILES_RUNNING_FLAG = false;
-
     // TODO(b/266831522) remove the flag after rollout.
     private static final String APPLICATION_EXEMPTIONS_FLAG = "application_exemptions";
     private static final boolean DEFAULT_APPLICATION_EXEMPTIONS_FLAG = true;
@@ -2178,13 +2175,29 @@
         return packageNameAndSignature;
     }
 
-    private void suspendAppsForQuietProfiles(boolean toSuspend) {
+    private void unsuspendAppsForQuietProfiles() {
         PackageManagerInternal pmi = mInjector.getPackageManagerInternal();
         List<UserInfo> users = mUserManagerInternal.getUsers(true /* excludeDying */);
+
         for (UserInfo user : users) {
-            if (user.isManagedProfile() && user.isQuietModeEnabled()) {
-                pmi.setPackagesSuspendedForQuietMode(user.id, toSuspend);
+            if (!user.isManagedProfile() || !user.isQuietModeEnabled()) {
+                continue;
             }
+            int userId = user.id;
+            var suspendedByAdmin = getPackagesSuspendedByAdmin(userId);
+            var packagesToUnsuspend = mInjector.getPackageManager(userId)
+                    .getInstalledPackages(PackageManager.PackageInfoFlags.of(
+                            MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE))
+                    .stream()
+                    .map(packageInfo -> packageInfo.packageName)
+                    .filter(pkg -> !suspendedByAdmin.contains(pkg))
+                    .toArray(String[]::new);
+
+            Slogf.i(LOG_TAG, "Unsuspending work apps for user %d", userId);
+            // When app suspension was used for quiet mode, the apps were suspended by platform
+            // package, just like when admin suspends them. So although it wasn't admin who
+            // suspended, this method will remove the right suspension record.
+            pmi.setPackagesSuspendedByAdmin(userId, packagesToUnsuspend, false /* suspended */);
         }
     }
 
@@ -3436,9 +3449,9 @@
             }
         }
 
-        // In case flag value has changed, we apply it during boot to avoid doing it concurrently
-        // with user toggling quiet mode.
-        setKeepProfileRunningEnabledUnchecked(isKeepProfilesRunningFlagEnabled());
+        // Check whether work apps were paused via suspension and unsuspend if necessary.
+        // TODO: move it into PolicyVersionUpgrader so that it is executed only once.
+        unsuspendWorkAppsIfNecessary();
     }
 
     // TODO(b/230841522) Make it static.
@@ -11039,9 +11052,6 @@
                             (size == 1 ? "" : "s"));
                 }
                 pw.println();
-                pw.println("Keep profiles running: "
-                        + getUserData(UserHandle.USER_SYSTEM).mEffectiveKeepProfilesRunning);
-                pw.println();
 
                 mPolicyCache.dump(pw);
                 pw.println();
@@ -15539,11 +15549,6 @@
         }
 
         @Override
-        public Set<String> getPackagesSuspendedByAdmin(@UserIdInt int userId) {
-            return DevicePolicyManagerService.this.getPackagesSuspendedByAdmin(userId);
-        }
-
-        @Override
         public void notifyUnsafeOperationStateChanged(DevicePolicySafetyChecker checker, int reason,
                 boolean isSafe) {
             // TODO(b/178494483): use EventLog instead
@@ -15571,11 +15576,6 @@
             }
         }
 
-        @Override
-        public boolean isKeepProfilesRunningEnabled() {
-            return getUserDataUnchecked(UserHandle.USER_SYSTEM).mEffectiveKeepProfilesRunning;
-        }
-
         private @Mode int findInteractAcrossProfilesResetMode(String packageName) {
             return getDefaultCrossProfilePackages().contains(packageName)
                     ? AppOpsManager.MODE_ALLOWED
@@ -23028,32 +23028,22 @@
                 DEFAULT_VALUE_PERMISSION_BASED_ACCESS_FLAG);
     }
 
-    private static boolean isKeepProfilesRunningFlagEnabled() {
-        return DEFAULT_KEEP_PROFILES_RUNNING_FLAG;
-    }
-
     private boolean isUnicornFlagEnabled() {
         return false;
     }
 
-    private void setKeepProfileRunningEnabledUnchecked(boolean keepProfileRunning) {
+    private void unsuspendWorkAppsIfNecessary() {
         synchronized (getLockObject()) {
             DevicePolicyData policyData = getUserDataUnchecked(UserHandle.USER_SYSTEM);
-            if (policyData.mEffectiveKeepProfilesRunning == keepProfileRunning) {
+            if (!policyData.mEffectiveKeepProfilesRunning) {
                 return;
             }
-            policyData.mEffectiveKeepProfilesRunning = keepProfileRunning;
+            policyData.mEffectiveKeepProfilesRunning = false;
             saveSettingsLocked(UserHandle.USER_SYSTEM);
         }
-        suspendAppsForQuietProfiles(keepProfileRunning);
-    }
 
-    @Override
-    public void setOverrideKeepProfilesRunning(boolean enabled) {
-        Preconditions.checkCallAuthorization(
-                hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
-        setKeepProfileRunningEnabledUnchecked(enabled);
-        Slog.i(LOG_TAG, "Keep profiles running overridden to: " + enabled);
+        Slog.w(LOG_TAG, "Work apps may have been paused via suspension previously.");
+        unsuspendAppsForQuietProfiles();
     }
 
     public void setMtePolicy(int flags, String callerPackageName) {
diff --git a/services/midi/Android.bp b/services/midi/Android.bp
index a385fe3..2ea28a31 100644
--- a/services/midi/Android.bp
+++ b/services/midi/Android.bp
@@ -20,6 +20,5 @@
     srcs: [":services.midi-sources"],
     libs: [
         "services.core",
-        "aconfig_midi_flags_java_lib",
     ],
 }
diff --git a/services/midi/OWNERS b/services/midi/OWNERS
index f4d51f9..683cae1 100644
--- a/services/midi/OWNERS
+++ b/services/midi/OWNERS
@@ -1 +1,3 @@
 philburk@google.com
+robertwu@google.com
+elaurent@google.com #{LAST_RESORT_SUGGESTION}
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 2f47cc7..39aaab2 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -16,7 +16,7 @@
 
 package com.android.server.midi;
 
-import static com.android.media.midi.flags.Flags.virtualUmp;
+import static android.media.midi.Flags.virtualUmp;
 
 import android.Manifest;
 import android.annotation.NonNull;
diff --git a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
index 93530cf..acaec21 100644
--- a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt
@@ -16,7 +16,6 @@
 
 package com.android.server.permission.access
 
-import android.app.admin.DevicePolicyManagerInternal
 import android.content.Context
 import android.content.pm.PackageManager
 import android.content.pm.PackageManagerInternal
@@ -75,7 +74,7 @@
 
         val userIds = MutableIntSet(userManagerService.userIdsIncludingPreCreated)
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
+        val knownPackages = packageManagerInternal.knownPackages
         val isLeanback = systemConfig.isLeanback
         val configPermissions = systemConfig.permissions
         val privilegedPermissionAllowlistPackages =
@@ -152,7 +151,7 @@
         isSystemUpdated: Boolean
     ) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
+        val knownPackages = packageManagerInternal.knownPackages
         mutateState {
             with(policy) {
                 onStorageVolumeMounted(
@@ -169,7 +168,7 @@
 
     internal fun onPackageAdded(packageName: String) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
+        val knownPackages = packageManagerInternal.knownPackages
         mutateState {
             with(policy) {
                 onPackageAdded(
@@ -184,7 +183,7 @@
 
     internal fun onPackageRemoved(packageName: String, appId: Int) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
+        val knownPackages = packageManagerInternal.knownPackages
         mutateState {
             with(policy) {
                 onPackageRemoved(
@@ -200,7 +199,7 @@
 
     internal fun onPackageInstalled(packageName: String, userId: Int) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
+        val knownPackages = packageManagerInternal.knownPackages
         mutateState {
             with(policy) {
                 onPackageInstalled(
@@ -216,7 +215,7 @@
 
     internal fun onPackageUninstalled(packageName: String, appId: Int, userId: Int) {
         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
+        val knownPackages = packageManagerInternal.knownPackages
         mutateState {
             with(policy) {
                 onPackageUninstalled(
@@ -232,69 +231,50 @@
     }
 
     internal fun onSystemReady() {
-        val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
-        val knownPackages = packageManagerInternal.getKnownPackages(packageStates)
-        mutateState {
-            with(policy) {
-                onSystemReady(packageStates, disabledSystemPackageStates, knownPackages)
-            }
-        }
+        mutateState { with(policy) { onSystemReady() } }
     }
 
     private val PackageManagerLocal.allPackageStates:
         Pair<Map<String, PackageState>, Map<String, PackageState>>
         get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates }
 
-    private fun PackageManagerInternal.getKnownPackages(
-        packageStates: Map<String, PackageState>
-    ): IntMap<Array<String>> =
-        MutableIntMap<Array<String>>().apply {
-            this[KnownPackages.PACKAGE_INSTALLER] =
-                getKnownPackageNames(KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM)
-            this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] =
-                getKnownPackageNames(
-                    KnownPackages.PACKAGE_PERMISSION_CONTROLLER,
-                    UserHandle.USER_SYSTEM
+    private val PackageManagerInternal.knownPackages: IntMap<Array<String>>
+        get() =
+            MutableIntMap<Array<String>>().apply {
+                this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM
                 )
-            this[KnownPackages.PACKAGE_VERIFIER] =
-                getKnownPackageNames(KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM)
-            this[KnownPackages.PACKAGE_SETUP_WIZARD] =
-                getKnownPackageNames(KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)
-            this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] =
-                getKnownPackageNames(
-                    KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER,
-                    UserHandle.USER_SYSTEM
+                this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM
                 )
-            this[KnownPackages.PACKAGE_CONFIGURATOR] =
-                getKnownPackageNames(KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM)
-            this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] =
-                getKnownPackageNames(
-                    KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER,
-                    UserHandle.USER_SYSTEM
+                this[KnownPackages.PACKAGE_VERIFIER] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM
                 )
-            this[KnownPackages.PACKAGE_APP_PREDICTOR] =
-                getKnownPackageNames(KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM)
-            this[KnownPackages.PACKAGE_COMPANION] =
-                getKnownPackageNames(KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM)
-            this[KnownPackages.PACKAGE_RETAIL_DEMO] =
-                getKnownPackageNames(KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM)
-                    .filter { isProfileOwner(it, packageStates) }
-                    .toTypedArray()
-            this[KnownPackages.PACKAGE_RECENTS] =
-                getKnownPackageNames(KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM)
-        }
-
-    private fun isProfileOwner(
-        packageName: String,
-        packageStates: Map<String, PackageState>
-    ): Boolean {
-        val appId = packageStates[packageName]?.appId ?: return false
-        val devicePolicyManagerInternal =
-            LocalServices.getService(DevicePolicyManagerInternal::class.java) ?: return false
-        // TODO(b/169395065): Figure out if this flow makes sense in Device Owner mode.
-        return devicePolicyManagerInternal.isActiveProfileOwner(appId) ||
-            devicePolicyManagerInternal.isActiveDeviceOwner(appId)
-    }
+                this[KnownPackages.PACKAGE_SETUP_WIZARD] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM
+                )
+                this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM
+                )
+                this[KnownPackages.PACKAGE_CONFIGURATOR] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM
+                )
+                this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM
+                )
+                this[KnownPackages.PACKAGE_APP_PREDICTOR] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM
+                )
+                this[KnownPackages.PACKAGE_COMPANION] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM
+                )
+                this[KnownPackages.PACKAGE_RETAIL_DEMO] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM
+                )
+                this[KnownPackages.PACKAGE_RECENTS] = getKnownPackageNames(
+                    KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM
+                )
+            }
 
     @OptIn(ExperimentalContracts::class)
     internal inline fun <T> getState(action: GetStateScope.() -> T): T {
diff --git a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
index 754f77ec..29fe95c 100644
--- a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt
@@ -262,17 +262,8 @@
         forEachSchemePolicy { with(it) { onPackageUninstalled(packageName, appId, userId) } }
     }
 
-    fun MutateStateScope.onSystemReady(
-        packageStates: Map<String, PackageState>,
-        disabledSystemPackageStates: Map<String, PackageState>,
-        knownPackages: IntMap<Array<String>>
-    ) {
-        newState.mutateExternalState().apply {
-            setPackageStates(packageStates)
-            setDisabledSystemPackageStates(disabledSystemPackageStates)
-            setKnownPackages(knownPackages)
-            setSystemReady(true)
-        }
+    fun MutateStateScope.onSystemReady() {
+        newState.mutateExternalState().setSystemReady(true)
         forEachSchemePolicy { with(it) { onSystemReady() } }
     }
 
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 08ba753..010604f 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -1448,15 +1448,6 @@
             // Special permissions for the system companion device manager.
             return true
         }
-        if (
-            permission.isRetailDemo &&
-                packageName in knownPackages[KnownPackages.PACKAGE_RETAIL_DEMO]!!
-        ) {
-            // Special permission granted only to the OEM specified retail demo app.
-            // Note that the original code was passing app ID as UID, so this behavior is kept
-            // unchanged.
-            return true
-        }
         if (permission.isRecents && packageName in knownPackages[KnownPackages.PACKAGE_RECENTS]!!) {
             // Special permission for the recents app.
             return true
@@ -1511,27 +1502,6 @@
     }
 
     override fun MutateStateScope.onSystemReady() {
-        // HACK: PACKAGE_USAGE_STATS is the only permission with the retailDemo protection flag,
-        // and we have to wait until DevicePolicyManagerService is started to know whether the
-        // retail demo package is a profile owner so that it can have the permission.
-        // Since there's no simple callback for profile owner change, and we are deprecating and
-        // removing the retailDemo protection flag in favor of a proper role soon, we can just
-        // re-evaluate the permission here, which is also how the old implementation has been
-        // working.
-        // TODO: Partially revert ag/22690114 once we can remove support for the retailDemo
-        //  protection flag.
-        val externalState = newState.externalState
-        for (packageName in externalState.knownPackages[KnownPackages.PACKAGE_RETAIL_DEMO]!!) {
-            val appId = externalState.packageStates[packageName]?.appId ?: continue
-            newState.userStates.forEachIndexed { _, userId, _ ->
-                evaluatePermissionState(
-                    appId,
-                    userId,
-                    Manifest.permission.PACKAGE_USAGE_STATS,
-                    null
-                )
-            }
-        }
         if (!privilegedPermissionAllowlistViolations.isEmpty()) {
             throw IllegalStateException(
                 "Signature|privileged permissions not in privileged" +
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 163d248..c7b1abf 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -28,6 +28,8 @@
 import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY;
 import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.server.display.DisplayManagerService.ENABLE_ON_CONNECT;
 import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -90,12 +92,14 @@
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionManager;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.view.ContentRecordingSession;
 import android.view.Display;
@@ -113,6 +117,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
+import com.android.modules.utils.testing.ExtendedMockitoRule;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
@@ -130,6 +135,7 @@
 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -141,6 +147,8 @@
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
 
 import java.time.Duration;
 import java.util.ArrayList;
@@ -322,6 +330,12 @@
     @Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
     @Mock DisplayManagerFlags mMockFlags;
 
+    @Rule
+    public final ExtendedMockitoRule mExtendedMockitoRule =
+            new ExtendedMockitoRule.Builder(this)
+                    .setStrictness(Strictness.LENIENT)
+                    .spyStatic(SystemProperties.class)
+                    .build();
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -2406,6 +2420,39 @@
     }
 
     @Test
+    public void testConnectExternalDisplay_withDisplayManagementAndSysprop_shouldEnableDisplay() {
+        Assume.assumeTrue(Build.IS_ENG || Build.IS_USERDEBUG);
+        when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
+        doAnswer((Answer<Boolean>) invocationOnMock -> true)
+                .when(() -> SystemProperties.getBoolean(ENABLE_ON_CONNECT, false));
+        manageDisplaysPermission(/* granted= */ true);
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        DisplayManagerInternal localService = displayManager.new LocalService();
+        DisplayManagerService.BinderService bs = displayManager.new BinderService();
+        LogicalDisplayMapper logicalDisplayMapper = displayManager.getLogicalDisplayMapper();
+        FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
+        bs.registerCallbackWithEventMask(callback, STANDARD_AND_CONNECTION_DISPLAY_EVENTS);
+        localService.registerDisplayGroupListener(callback);
+        callback.expectsEvent(EVENT_DISPLAY_ADDED);
+
+        // Create default display device
+        createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL);
+        callback.waitForExpectedEvent();
+        callback.clear();
+
+        callback.expectsEvent(EVENT_DISPLAY_CONNECTED);
+        FakeDisplayDevice displayDevice =
+                createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL);
+        callback.waitForExpectedEvent();
+
+        LogicalDisplay display =
+                logicalDisplayMapper.getDisplayLocked(displayDevice, /* includeDisabled= */ false);
+        assertThat(display.isEnabledLocked()).isTrue();
+        assertThat(callback.receivedEvents()).containsExactly(DISPLAY_GROUP_EVENT_ADDED,
+                EVENT_DISPLAY_CONNECTED, EVENT_DISPLAY_ADDED).inOrder();
+    }
+
+    @Test
     public void testConnectInternalDisplay_withDisplayManagement_shouldConnectAndAddDisplay() {
         when(mMockFlags.isConnectedDisplayManagementEnabled()).thenReturn(true);
         manageDisplaysPermission(/* granted= */ true);
diff --git a/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java
index cc97b8f..76a1c3c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java
@@ -154,10 +154,11 @@
         intent.putExtra(Intent.EXTRA_REASON, "Self destruct");
         intent.putExtra(Intent.EXTRA_FORCE_FACTORY_RESET, true);
         intent.putExtra(Intent.EXTRA_WIPE_ESIMS, true);
+        intent.putExtra("keep_memtag_mode", true);
         mReceiver.onReceive(mContext, intent);
 
         verifyRebootWipeUserData(/* shutdown= */ true, /* reason= */ "Self destruct",
-                /* force= */ true, /* wipeEuicc= */ true);
+                /* force= */ true, /* wipeEuicc= */ true, /* keepMemtagMode= */ true);
         verifyWipeExternalData();
     }
 
@@ -211,7 +212,7 @@
             mRebootWipeUserDataLatch.countDown();
             return null;
         }).when(() -> RecoverySystem
-                .rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(), anyBoolean()));
+                .rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(), anyBoolean(), anyBoolean()));
     }
 
     private void expectWipeExternalData() {
@@ -244,11 +245,16 @@
 
     private void verifyRebootWipeUserData(boolean shutdown, String reason, boolean force,
             boolean wipeEuicc) throws Exception {
+        verifyRebootWipeUserData(shutdown, reason, force, wipeEuicc, /* keepMemtagMode= */ false);
+    }
+
+    private void verifyRebootWipeUserData(boolean shutdown, String reason, boolean force,
+            boolean wipeEuicc, boolean keepMemtagMode) throws Exception {
         boolean called = mRebootWipeUserDataLatch.await(5, TimeUnit.SECONDS);
         assertWithMessage("rebootWipeUserData not called in 5s").that(called).isTrue();
 
         verify(()-> RecoverySystem.rebootWipeUserData(same(mContext), eq(shutdown), eq(reason),
-                eq(force), eq(wipeEuicc)));
+                eq(force), eq(wipeEuicc), eq(keepMemtagMode)));
     }
 
     private void verifyNoRebootWipeUserData() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 3ee8050..032d026 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -86,6 +86,9 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
 import android.provider.DeviceConfig;
 import android.util.IntArray;
 import android.util.Log;
@@ -96,6 +99,7 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.sdksandbox.flags.Flags;
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService.StickyBroadcast;
 import com.android.server.am.ProcessList.IsolatedUidRange;
@@ -145,8 +149,11 @@
 
     private static final String TEST_EXTRA_KEY1 = "com.android.server.am.TEST_EXTRA_KEY1";
     private static final String TEST_EXTRA_VALUE1 = "com.android.server.am.TEST_EXTRA_VALUE1";
+    private static final String PROPERTY_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS =
+            "apply_sdk_sandbox_audit_restrictions";
     private static final String PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS =
             "apply_sdk_sandbox_next_restrictions";
+    private static final String APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS = ":isSdkSandboxAudit";
     private static final String APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS = ":isSdkSandboxNext";
     private static final int TEST_UID = 11111;
     private static final int USER_ID = 666;
@@ -183,6 +190,9 @@
     public final ApplicationExitInfoTest.ServiceThreadRule
             mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
 
+    @Rule
+    public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
     private Context mContext = getInstrumentation().getTargetContext();
 
     @Mock private AppOpsService mAppOpsService;
@@ -338,6 +348,7 @@
             mockitoSession.finishMocking();
         }
     }
+
     @SuppressWarnings("GuardedBy")
     @SmallTest
     @Test
@@ -367,6 +378,77 @@
         }
     }
 
+    @SuppressWarnings("GuardedBy")
+    @SmallTest
+    @Test
+    @RequiresFlagsEnabled(Flags.FLAG_SELINUX_SDK_SANDBOX_AUDIT)
+    public void applySdkSandboxAuditRestrictions() throws Exception {
+        MockitoSession mockitoSession =
+                ExtendedMockito.mockitoSession().spyStatic(Process.class).startMocking();
+        try {
+            sProcessListSettingsListener.onPropertiesChanged(
+                    new DeviceConfig.Properties(
+                            DeviceConfig.NAMESPACE_ADSERVICES,
+                            Map.of(PROPERTY_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS, "true")));
+            assertThat(sProcessListSettingsListener.applySdkSandboxRestrictionsAudit()).isTrue();
+            ExtendedMockito.doReturn(true).when(() -> Process.isSdkSandboxUid(anyInt()));
+            ApplicationInfo info = new ApplicationInfo();
+            info.packageName = "com.android.sdksandbox";
+            info.seInfo = "default:targetSdkVersion=34:complete";
+            final ProcessRecord appRec =
+                    new ProcessRecord(
+                            mAms,
+                            info,
+                            TAG,
+                            Process.FIRST_SDK_SANDBOX_UID,
+                            /* sdkSandboxClientPackageName= */ "com.example.client",
+                            /* definingUid= */ 0,
+                            /* definingProcessName= */ "");
+            assertThat(mAms.mProcessList.updateSeInfo(appRec))
+                    .contains(APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS);
+        } finally {
+            mockitoSession.finishMocking();
+        }
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @SmallTest
+    @Test
+    public void applySdkSandboxNextAndAuditRestrictions() throws Exception {
+        MockitoSession mockitoSession =
+                ExtendedMockito.mockitoSession().spyStatic(Process.class).startMocking();
+        try {
+            sProcessListSettingsListener.onPropertiesChanged(
+                    new DeviceConfig.Properties(
+                            DeviceConfig.NAMESPACE_ADSERVICES,
+                            Map.of(PROPERTY_APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS, "true")));
+            sProcessListSettingsListener.onPropertiesChanged(
+                    new DeviceConfig.Properties(
+                            DeviceConfig.NAMESPACE_ADSERVICES,
+                            Map.of(PROPERTY_APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS, "true")));
+            assertThat(sProcessListSettingsListener.applySdkSandboxRestrictionsNext()).isTrue();
+            assertThat(sProcessListSettingsListener.applySdkSandboxRestrictionsAudit()).isTrue();
+            ExtendedMockito.doReturn(true).when(() -> Process.isSdkSandboxUid(anyInt()));
+            ApplicationInfo info = new ApplicationInfo();
+            info.packageName = "com.android.sdksandbox";
+            info.seInfo = "default:targetSdkVersion=34:complete";
+            final ProcessRecord appRec =
+                    new ProcessRecord(
+                            mAms,
+                            info,
+                            TAG,
+                            Process.FIRST_SDK_SANDBOX_UID,
+                            /* sdkSandboxClientPackageName= */ "com.example.client",
+                            /* definingUid= */ 0,
+                            /* definingProcessName= */ "");
+            assertThat(mAms.mProcessList.updateSeInfo(appRec))
+                    .contains(APPLY_SDK_SANDBOX_NEXT_RESTRICTIONS);
+            assertThat(mAms.mProcessList.updateSeInfo(appRec))
+                    .doesNotContain(APPLY_SDK_SANDBOX_AUDIT_RESTRICTIONS);
+        } finally {
+            mockitoSession.finishMocking();
+        }
+    }
 
     private UidRecord addUidRecord(int uid) {
         final UidRecord uidRec = new UidRecord(uid, mAms);
diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
index 4ffa0fb..5f9a17c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
@@ -88,7 +88,7 @@
             Log.d(TAG, "Mocking " + inv);
             return null;
         }).when(() -> RecoverySystem.rebootWipeUserData(any(), anyBoolean(), any(),
-                anyBoolean(), anyBoolean()));
+                anyBoolean(), anyBoolean(), anyBoolean()));
     }
 
     @After
@@ -270,17 +270,20 @@
 
     private void verifyRebootWipeUserDataMinimumArgsCalled() {
         verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ false,
-                /* reason= */ null, /* force= */ false, /* wipeEuicc= */ false));
+                /* reason= */ null, /* force= */ false, /* wipeEuicc= */ false,
+                /* keepMemtagMode= */ false));
     }
 
     private void verifyRebootWipeUserDataMinimumArgsButForceCalled() {
         verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ false,
-                /* reason= */ null, /* force= */ true, /* wipeEuicc= */ false));
+                /* reason= */ null, /* force= */ true, /* wipeEuicc= */ false,
+                /* keepMemtagMode= */ false));
     }
 
     private void verifyRebootWipeUserDataAllArgsCalled() {
         verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ true,
-                /* reason= */ REASON, /* force= */ true, /* wipeEuicc= */ true));
+                /* reason= */ REASON, /* force= */ true, /* wipeEuicc= */ true,
+                /* keepMemtagMode= */ false));
     }
 
     private void verifyWipeAdoptableStorageNotCalled() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index dd23d9f..e5291d3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -577,8 +577,14 @@
         JobStatus jobUIDT = createJobStatus("testGetMaxJobExecutionTimeMs",
                 createJobInfo(10)
                         .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+        JobStatus jobEj = createJobStatus("testGetMaxJobExecutionTimeMs",
+                createJobInfo(2).setExpedited(true));
+        JobStatus jobReg = createJobStatus("testGetMaxJobExecutionTimeMs",
+                createJobInfo(3));
         spyOn(jobUIDT);
         when(jobUIDT.shouldTreatAsUserInitiatedJob()).thenReturn(true);
+        spyOn(jobEj);
+        when(jobEj.shouldTreatAsExpeditedJob()).thenReturn(true);
 
         QuotaController quotaController = mService.getQuotaController();
         spyOn(quotaController);
@@ -595,6 +601,11 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUIDT));
+
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
+                mService.getMaxJobExecutionTimeMs(jobEj));
+        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+                mService.getMaxJobExecutionTimeMs(jobReg));
     }
 
     @Test
@@ -636,7 +647,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -649,7 +660,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -664,7 +675,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -677,7 +688,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -692,7 +703,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -705,7 +716,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -720,7 +731,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -765,7 +776,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -778,7 +789,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -792,7 +803,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -807,7 +818,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -820,7 +831,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
@@ -834,7 +845,7 @@
         grantRunUserInitiatedJobsPermission(false);
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUij));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
+        assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMaxJobExecutionTimeMs(jobEj));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobReg));
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 809a0e8..64e86f9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -983,9 +983,8 @@
         final JobStatus blue = createJobStatus(createJob()
                 .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY), UID_BLUE);
-        // Unmetered preference is disabled for now.
         assertFalse(red.getPreferUnmetered());
-        assertFalse(blue.getPreferUnmetered());
+        assertTrue(blue.getPreferUnmetered());
 
         controller.maybeStartTrackingJobLocked(red, null);
         controller.maybeStartTrackingJobLocked(blue, null);
@@ -1039,7 +1038,7 @@
             generalCallback.onLost(meteredNet);
 
             assertTrue(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
-            assertTrue(red.getHasAccessToUnmetered());
+            assertFalse(red.getHasAccessToUnmetered());
 
             assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
             assertTrue(blue.getHasAccessToUnmetered());
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
index 7ae6a2d..bb9dcf1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -189,10 +189,7 @@
     }
 
     private static JobInfo.Builder createJob(int id) {
-        return new JobInfo.Builder(id, new ComponentName("foo", "bar"))
-                .setPrefersBatteryNotLow(true)
-                .setPrefersCharging(true)
-                .setPrefersDeviceIdle(true);
+        return new JobInfo.Builder(id, new ComponentName("foo", "bar"));
     }
 
     private JobStatus createJobStatus(String testTag, JobInfo.Builder job) {
@@ -536,15 +533,12 @@
             jb = createJob(i);
             if (i > 0) {
                 jb.setRequiresDeviceIdle(true);
-                jb.setPrefersDeviceIdle(false);
             }
             if (i > 1) {
                 jb.setRequiresBatteryNotLow(true);
-                jb.setPrefersBatteryNotLow(false);
             }
             if (i > 2) {
                 jb.setRequiresCharging(true);
-                jb.setPrefersCharging(false);
             }
             jobs[i] = createJobStatus("", jb);
             flexTracker.add(jobs[i]);
@@ -553,55 +547,53 @@
         synchronized (mFlexibilityController.mLock) {
             ArrayList<ArraySet<JobStatus>> trackedJobs = flexTracker.getArrayList();
             assertEquals(1, trackedJobs.get(0).size());
-            assertEquals(1, trackedJobs.get(1).size());
+            assertEquals(0, trackedJobs.get(1).size());
+            assertEquals(0, trackedJobs.get(2).size());
+            assertEquals(3, trackedJobs.get(3).size());
+            assertEquals(0, trackedJobs.get(4).size());
+
+            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
+            assertEquals(1, trackedJobs.get(0).size());
+            assertEquals(0, trackedJobs.get(1).size());
             assertEquals(1, trackedJobs.get(2).size());
-            assertEquals(1, trackedJobs.get(3).size());
+            assertEquals(2, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
             flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
             assertEquals(1, trackedJobs.get(0).size());
             assertEquals(1, trackedJobs.get(1).size());
-            assertEquals(2, trackedJobs.get(2).size());
-            assertEquals(0, trackedJobs.get(3).size());
-            assertEquals(0, trackedJobs.get(4).size());
-
-            flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
-            assertEquals(1, trackedJobs.get(0).size());
-            assertEquals(2, trackedJobs.get(1).size());
-            assertEquals(1, trackedJobs.get(2).size());
-            assertEquals(0, trackedJobs.get(3).size());
+            assertEquals(0, trackedJobs.get(2).size());
+            assertEquals(2, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
             flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
             assertEquals(2, trackedJobs.get(0).size());
-            assertEquals(1, trackedJobs.get(1).size());
-            assertEquals(1, trackedJobs.get(2).size());
-            assertEquals(0, trackedJobs.get(3).size());
+            assertEquals(0, trackedJobs.get(1).size());
+            assertEquals(0, trackedJobs.get(2).size());
+            assertEquals(2, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
             flexTracker.remove(jobs[1]);
             assertEquals(2, trackedJobs.get(0).size());
-            assertEquals(1, trackedJobs.get(1).size());
+            assertEquals(0, trackedJobs.get(1).size());
             assertEquals(0, trackedJobs.get(2).size());
-            assertEquals(0, trackedJobs.get(3).size());
+            assertEquals(1, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
             flexTracker.resetJobNumDroppedConstraints(jobs[0], FROZEN_TIME);
             assertEquals(1, trackedJobs.get(0).size());
+            assertEquals(0, trackedJobs.get(1).size());
+            assertEquals(0, trackedJobs.get(2).size());
+            assertEquals(2, trackedJobs.get(3).size());
+            assertEquals(0, trackedJobs.get(4).size());
+
+            flexTracker.adjustJobsRequiredConstraints(jobs[0], -2, FROZEN_TIME);
+            assertEquals(1, trackedJobs.get(0).size());
             assertEquals(1, trackedJobs.get(1).size());
             assertEquals(0, trackedJobs.get(2).size());
             assertEquals(1, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
 
-            flexTracker.adjustJobsRequiredConstraints(jobs[0], -2, FROZEN_TIME);
-            assertEquals(1, trackedJobs.get(0).size());
-            assertEquals(2, trackedJobs.get(1).size());
-            assertEquals(0, trackedJobs.get(2).size());
-            assertEquals(0, trackedJobs.get(3).size());
-            assertEquals(0, trackedJobs.get(4).size());
-
-            // Over halfway through the flex window. The job that prefers all flex constraints
-            // should have its first flex constraint dropped.
             final long nowElapsed = ((DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS / 2)
                     + HOUR_IN_MILLIS);
             JobSchedulerService.sElapsedRealtimeClock =
@@ -609,9 +601,9 @@
 
             flexTracker.resetJobNumDroppedConstraints(jobs[0], nowElapsed);
             assertEquals(1, trackedJobs.get(0).size());
-            assertEquals(1, trackedJobs.get(1).size());
+            assertEquals(0, trackedJobs.get(1).size());
             assertEquals(1, trackedJobs.get(2).size());
-            assertEquals(0, trackedJobs.get(3).size());
+            assertEquals(1, trackedJobs.get(3).size());
             assertEquals(0, trackedJobs.get(4).size());
         }
     }
@@ -626,13 +618,8 @@
 
     @Test
     public void testExceptions_UserInitiated() {
-        JobInfo.Builder jb = createJob(0)
-                .setUserInitiated(true)
-                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
-                // Attempt to add flex constraints to the job. For now, we will ignore them.
-                .setPrefersBatteryNotLow(true)
-                .setPrefersCharging(true)
-                .setPrefersDeviceIdle(false);
+        JobInfo.Builder jb = createJob(0);
+        jb.setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
         JobStatus js = createJobStatus("testExceptions_UserInitiated", jb);
         assertFalse(js.hasFlexibilityConstraint());
     }
@@ -648,10 +635,10 @@
 
     @Test
     public void testExceptions_NoFlexibleConstraints() {
-        JobInfo.Builder jb = createJob(0)
-                .setPrefersBatteryNotLow(false)
-                .setPrefersCharging(false)
-                .setPrefersDeviceIdle(false);
+        JobInfo.Builder jb = createJob(0);
+        jb.setRequiresDeviceIdle(true);
+        jb.setRequiresCharging(true);
+        jb.setRequiresBatteryNotLow(true);
         JobStatus js = createJobStatus("testExceptions_NoFlexibleConstraints", jb);
         assertFalse(js.hasFlexibilityConstraint());
     }
@@ -710,50 +697,15 @@
         JobStatus js = createJobStatus("testTopAppBypass", jb);
         synchronized (mFlexibilityController.mLock) {
             js.setHasAccessToUnmetered(false);
-            assertEquals(0, mFlexibilityController.getNumSatisfiedFlexibleConstraintsLocked(js));
+            assertEquals(0, mFlexibilityController.getNumSatisfiedRequiredConstraintsLocked(js));
             js.setHasAccessToUnmetered(true);
-            assertEquals(1, mFlexibilityController.getNumSatisfiedFlexibleConstraintsLocked(js));
+            assertEquals(1, mFlexibilityController.getNumSatisfiedRequiredConstraintsLocked(js));
             js.setHasAccessToUnmetered(false);
-            assertEquals(0, mFlexibilityController.getNumSatisfiedFlexibleConstraintsLocked(js));
+            assertEquals(0, mFlexibilityController.getNumSatisfiedRequiredConstraintsLocked(js));
         }
     }
 
     @Test
-    public void testGetNumSatisfiedFlexibleConstraints() {
-        long nowElapsed = FROZEN_TIME;
-        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, true, nowElapsed);
-        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_CHARGING, true, nowElapsed);
-        mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, true, nowElapsed);
-        JobInfo.Builder jb = createJob(0)
-                .setPrefersBatteryNotLow(false)
-                .setPrefersCharging(false)
-                .setPrefersDeviceIdle(false);
-        JobStatus js = createJobStatus("testGetNumSatisfiedFlexibleConstraints", jb);
-        assertEquals(0, mFlexibilityController.getNumSatisfiedFlexibleConstraintsLocked(js));
-
-        jb = createJob(0)
-                .setPrefersBatteryNotLow(true)
-                .setPrefersCharging(false)
-                .setPrefersDeviceIdle(false);
-        js = createJobStatus("testGetNumSatisfiedFlexibleConstraints", jb);
-        assertEquals(1, mFlexibilityController.getNumSatisfiedFlexibleConstraintsLocked(js));
-
-        jb = createJob(0)
-                .setPrefersBatteryNotLow(true)
-                .setPrefersCharging(false)
-                .setPrefersDeviceIdle(true);
-        js = createJobStatus("testGetNumSatisfiedFlexibleConstraints", jb);
-        assertEquals(2, mFlexibilityController.getNumSatisfiedFlexibleConstraintsLocked(js));
-
-        jb = createJob(0)
-                .setPrefersBatteryNotLow(true)
-                .setPrefersCharging(true)
-                .setPrefersDeviceIdle(true);
-        js = createJobStatus("testGetNumSatisfiedFlexibleConstraints", jb);
-        assertEquals(3, mFlexibilityController.getNumSatisfiedFlexibleConstraintsLocked(js));
-    }
-
-    @Test
     public void testSetConstraintSatisfied_Constraints() {
         mFlexibilityController.setConstraintSatisfied(CONSTRAINT_IDLE, false, FROZEN_TIME);
         assertFalse(mFlexibilityController.isConstraintSatisfied(CONSTRAINT_IDLE));
@@ -784,11 +736,8 @@
             jb = createJob(i);
             constraints = constraintCombinations[i];
             jb.setRequiresDeviceIdle((constraints & CONSTRAINT_IDLE) != 0);
-            jb.setPrefersDeviceIdle((constraints & CONSTRAINT_IDLE) == 0);
             jb.setRequiresBatteryNotLow((constraints & CONSTRAINT_BATTERY_NOT_LOW) != 0);
-            jb.setPrefersBatteryNotLow((constraints & CONSTRAINT_BATTERY_NOT_LOW) == 0);
             jb.setRequiresCharging((constraints & CONSTRAINT_CHARGING) != 0);
-            jb.setPrefersCharging((constraints & CONSTRAINT_CHARGING) == 0);
             synchronized (mFlexibilityController.mLock) {
                 mFlexibilityController.maybeStartTrackingJobLocked(
                         createJobStatus(String.valueOf(i), jb), null);
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 1de7e37..92aa982 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -1240,9 +1240,7 @@
     @Test
     public void testReadinessStatusWithConstraint_FlexibilityConstraint() {
         final JobStatus job = createJobStatus(
-                new JobInfo.Builder(101, new ComponentName("foo", "bar"))
-                        .setPrefersCharging(true)
-                        .build());
+                new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
         job.setConstraintSatisfied(CONSTRAINT_FLEXIBLE, sElapsedRealtimeClock.millis(), false);
         markImplicitConstraintsSatisfied(job, true);
         assertTrue(job.readinessStatusWithConstraint(CONSTRAINT_FLEXIBLE, true));
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/idle/DeviceIdlenessTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/idle/DeviceIdlenessTrackerTest.java
new file mode 100644
index 0000000..09935f2
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/idle/DeviceIdlenessTrackerTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.job.controllers.idle;
+
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+import static com.android.server.job.controllers.idle.DeviceIdlenessTracker.KEY_INACTIVITY_IDLE_THRESHOLD_MS;
+import static com.android.server.job.controllers.idle.DeviceIdlenessTracker.KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.app.AlarmManager;
+import android.app.UiModeManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.AppSchedulingModuleThread;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.time.Clock;
+import java.time.Duration;
+import java.time.ZoneOffset;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceIdlenessTrackerTest {
+    private DeviceIdlenessTracker mDeviceIdlenessTracker;
+    private JobSchedulerService.Constants mConstants = new JobSchedulerService.Constants();
+    private BroadcastReceiver mBroadcastReceiver;
+    private DeviceConfig.Properties.Builder mDeviceConfigPropertiesBuilder =
+            new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER);;
+
+    private MockitoSession mMockingSession;
+    @Mock
+    private AlarmManager mAlarmManager;
+    @Mock
+    private Context mContext;
+    @Mock
+    private JobSchedulerService mJobSchedulerService;
+    @Mock
+    private PowerManager mPowerManager;
+    @Mock
+    private Resources mResources;
+
+    @Before
+    public void setUp() {
+        mMockingSession = mockitoSession()
+                .initMocks(this)
+                .strictness(Strictness.LENIENT)
+                .spyStatic(DeviceConfig.class)
+                .mockStatic(LocalServices.class)
+                .startMocking();
+
+        // Called in StateController constructor.
+        when(mJobSchedulerService.getTestableContext()).thenReturn(mContext);
+        when(mJobSchedulerService.getLock()).thenReturn(mJobSchedulerService);
+        when(mJobSchedulerService.getConstants()).thenReturn(mConstants);
+        // Called in DeviceIdlenessTracker.startTracking.
+        when(mContext.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
+        when(mContext.getSystemService(UiModeManager.class)).thenReturn(mock(UiModeManager.class));
+        when(mContext.getResources()).thenReturn(mResources);
+        doReturn((int) (31 * MINUTE_IN_MILLIS)).when(mResources).getInteger(
+                com.android.internal.R.integer.config_jobSchedulerInactivityIdleThreshold);
+        doReturn((int) (17 * MINUTE_IN_MILLIS)).when(mResources).getInteger(
+                com.android.internal.R.integer
+                        .config_jobSchedulerInactivityIdleThresholdOnStablePower);
+        doReturn(mPowerManager).when(() -> LocalServices.getService(PowerManager.class));
+
+        // Freeze the clocks at 24 hours after this moment in time. Several tests create sessions
+        // in the past, and QuotaController sometimes floors values at 0, so if the test time
+        // causes sessions with negative timestamps, they will fail.
+        JobSchedulerService.sSystemClock =
+                getAdvancedClock(Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC),
+                        24 * HOUR_IN_MILLIS);
+        JobSchedulerService.sUptimeMillisClock = getAdvancedClock(
+                Clock.fixed(SystemClock.uptimeClock().instant(), ZoneOffset.UTC),
+                24 * HOUR_IN_MILLIS);
+        JobSchedulerService.sElapsedRealtimeClock = getAdvancedClock(
+                Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC),
+                24 * HOUR_IN_MILLIS);
+
+        // Initialize real objects.
+        // Capture the listeners.
+        ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        mDeviceIdlenessTracker = new DeviceIdlenessTracker();
+        mDeviceIdlenessTracker.startTracking(mContext,
+                mJobSchedulerService, mock(IdlenessListener.class));
+
+        verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+        mBroadcastReceiver = broadcastReceiverCaptor.getValue();
+    }
+
+    @After
+    public void tearDown() {
+        if (mMockingSession != null) {
+            mMockingSession.finishMocking();
+        }
+    }
+
+    private Clock getAdvancedClock(Clock clock, long incrementMs) {
+        return Clock.offset(clock, Duration.ofMillis(incrementMs));
+    }
+
+    private void advanceElapsedClock(long incrementMs) {
+        JobSchedulerService.sElapsedRealtimeClock = getAdvancedClock(
+                JobSchedulerService.sElapsedRealtimeClock, incrementMs);
+    }
+
+    private void setBatteryState(boolean isCharging, boolean isBatteryNotLow) {
+        doReturn(isCharging).when(mJobSchedulerService).isBatteryCharging();
+        doReturn(isBatteryNotLow).when(mJobSchedulerService).isBatteryNotLow();
+        mDeviceIdlenessTracker.onBatteryStateChanged(isCharging, isBatteryNotLow);
+    }
+
+    private void setDeviceConfigLong(String key, long val) {
+        mDeviceConfigPropertiesBuilder.setLong(key, val);
+        mDeviceIdlenessTracker.processConstant(mDeviceConfigPropertiesBuilder.build(), key);
+    }
+
+    @Test
+    public void testThresholdChangeWithStablePowerChange() {
+        setDeviceConfigLong(KEY_INACTIVITY_IDLE_THRESHOLD_MS, 10 * MINUTE_IN_MILLIS);
+        setDeviceConfigLong(KEY_INACTIVITY_STABLE_POWER_IDLE_THRESHOLD_MS, 5 * MINUTE_IN_MILLIS);
+        setBatteryState(false, false);
+
+        Intent screenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
+        mBroadcastReceiver.onReceive(mContext, screenOffIntent);
+
+        final long nowElapsed = sElapsedRealtimeClock.millis();
+        long expectedUnstableAlarmElapsed = nowElapsed + 10 * MINUTE_IN_MILLIS;
+        long expectedStableAlarmElapsed = nowElapsed + 5 * MINUTE_IN_MILLIS;
+
+        InOrder inOrder = inOrder(mAlarmManager);
+        inOrder.verify(mAlarmManager)
+                .setWindow(anyInt(), eq(expectedUnstableAlarmElapsed), anyLong(), anyString(),
+                        eq(AppSchedulingModuleThread.getExecutor()), any());
+
+        // Advanced the clock a little to make sure the tracker continues to use the original time.
+        advanceElapsedClock(MINUTE_IN_MILLIS);
+
+        // Charging isn't enough for stable power.
+        setBatteryState(true, false);
+        inOrder.verify(mAlarmManager, never())
+                .setWindow(anyInt(), anyLong(), anyLong(), anyString(),
+                        eq(AppSchedulingModuleThread.getExecutor()), any());
+
+        // Now on stable power.
+        setBatteryState(true, true);
+        inOrder.verify(mAlarmManager)
+                .setWindow(anyInt(), eq(expectedStableAlarmElapsed), anyLong(), anyString(),
+                        eq(AppSchedulingModuleThread.getExecutor()), any());
+
+        // Battery-not-low isn't enough for stable power. Go back to unstable timing.
+        setBatteryState(false, true);
+        inOrder.verify(mAlarmManager)
+                .setWindow(anyInt(), eq(expectedUnstableAlarmElapsed), anyLong(), anyString(),
+                        eq(AppSchedulingModuleThread.getExecutor()), any());
+
+        // Still not on stable power.
+        setBatteryState(false, false);
+        inOrder.verify(mAlarmManager, never())
+                .setWindow(anyInt(), anyLong(), anyLong(), anyString(),
+                        eq(AppSchedulingModuleThread.getExecutor()), any());
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
index 5c8a19c..1e65c89 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.pm;
 
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.MODE_IGNORED;
 import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
 import static android.content.pm.PackageManager.DELETE_ARCHIVE;
 import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
@@ -103,6 +105,8 @@
     @Mock
     private ActivityManager mActivityManager;
     @Mock
+    private AppOpsManager mAppOpsManager;
+    @Mock
     private PackageManager mPackageManager;
     @Mock
     private PackageInstallerService mInstallerService;
@@ -160,12 +164,17 @@
         when(mPackageState.getUserStateOrDefault(eq(mUserId))).thenReturn(mUserState);
 
         when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps);
+        when(mContext.getSystemService(AppOpsManager.class)).thenReturn(
+                mAppOpsManager);
         when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
                 mLauncherActivityInfos);
 
         when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
         when(mActivityManager.getLauncherLargeIconDensity()).thenReturn(100);
 
+        when(mAppOpsManager.checkOp(
+                eq(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED),
+                anyInt(), eq(PACKAGE))).thenReturn(MODE_ALLOWED);
         doReturn(mComputer).when(mPackageManagerService).snapshotComputer();
         when(mComputer.getPackageUid(eq(CALLER_PACKAGE), eq(0L), eq(mUserId))).thenReturn(
                 Binder.getCallingUid());
@@ -305,6 +314,21 @@
     }
 
     @Test
+    public void archiveApp_appOptedOutOfArchiving() {
+        when(mAppOpsManager.checkOp(
+                eq(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED),
+                anyInt(), eq(PACKAGE))).thenReturn(MODE_IGNORED);
+
+        Exception e = assertThrows(
+                ParcelableException.class,
+                () -> mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender,
+                        UserHandle.CURRENT));
+        assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class);
+        assertThat(e.getCause()).hasMessageThat().isEqualTo(
+                TextUtils.formatSimple("The app %s is opted out of archiving.", PACKAGE));
+    }
+
+    @Test
     public void archiveApp_success() {
         mArchiveManager.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT);
         rule.mocks().getHandler().flush();
@@ -319,6 +343,39 @@
     }
 
     @Test
+    public void isAppArchivable_success() throws PackageManager.NameNotFoundException {
+        assertThat(mArchiveManager.isAppArchivable(PACKAGE, UserHandle.CURRENT)).isTrue();
+    }
+
+    @Test
+    public void isAppArchivable_installerDoesntSupportUnarchival()
+            throws PackageManager.NameNotFoundException {
+        doReturn(new ParceledListSlice<>(List.of()))
+                .when(mPackageManagerService).queryIntentReceivers(any(), any(), any(), anyLong(),
+                        eq(mUserId));
+
+        assertThat(mArchiveManager.isAppArchivable(PACKAGE, UserHandle.CURRENT)).isFalse();
+    }
+
+    @Test
+    public void isAppArchivable_noMainActivities() throws PackageManager.NameNotFoundException {
+        when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn(
+                List.of());
+
+        assertThat(mArchiveManager.isAppArchivable(PACKAGE, UserHandle.CURRENT)).isFalse();
+    }
+
+    @Test
+    public void isAppArchivable_appOptedOutOfArchiving()
+            throws PackageManager.NameNotFoundException {
+        when(mAppOpsManager.checkOp(
+                eq(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED),
+                anyInt(), eq(PACKAGE))).thenReturn(MODE_IGNORED);
+
+        assertThat(mArchiveManager.isAppArchivable(PACKAGE, UserHandle.CURRENT)).isFalse();
+    }
+
+    @Test
     public void unarchiveApp_callerPackageNameIncorrect() {
         mUserState.setArchiveState(createArchiveState()).setInstalled(false);
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
index eb00164..a6ba5d4 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageHelperTestBase.kt
@@ -87,8 +87,8 @@
                 TEST_PACKAGE_1, TEST_PACKAGE_2, DEVICE_OWNER_PACKAGE, DEVICE_ADMIN_PACKAGE,
                 DEFAULT_HOME_PACKAGE, DIALER_PACKAGE, INSTALLER_PACKAGE, UNINSTALLER_PACKAGE,
                 VERIFIER_PACKAGE, PERMISSION_CONTROLLER_PACKAGE))
-        suspendPackageHelper = SuspendPackageHelper(pms, rule.mocks().injector,
-                rule.mocks().userManagerService, broadcastHelper, protectedPackages)
+        suspendPackageHelper = SuspendPackageHelper(
+                pms, rule.mocks().injector, broadcastHelper, protectedPackages)
         defaultAppProvider = rule.mocks().defaultAppProvider
         testHandler = rule.mocks().handler
         packageSetting1 = pms.snapshotComputer().getPackageStateInternal(TEST_PACKAGE_1)!!
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index 4240373..7b381ce 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -39,7 +39,7 @@
         val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 targetPackages, true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)
         testHandler.flush()
 
         verify(pms).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
@@ -56,14 +56,14 @@
         var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 null /* packageNames */, true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)
 
         assertThat(failedNames).isNull()
 
         failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOfNulls(0), true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)
 
         assertThat(failedNames).isEmpty()
     }
@@ -73,7 +73,7 @@
         val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, TEST_PACKAGE_1, TEST_USER_ID,
-                Binder.getCallingUid(), false /* forQuietMode */, false /* quarantined */)
+                Binder.getCallingUid(), false /* quarantined */)
 
         assertThat(failedNames).asList().hasSize(1)
         assertThat(failedNames).asList().contains(TEST_PACKAGE_2)
@@ -84,7 +84,7 @@
         val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOf(DEVICE_OWNER_PACKAGE), true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)
 
         assertThat(failedNames).asList().hasSize(1)
         assertThat(failedNames).asList().contains(DEVICE_OWNER_PACKAGE)
@@ -95,7 +95,7 @@
         val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOf(NONEXISTENT_PACKAGE), true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)
 
         assertThat(failedNames).asList().hasSize(1)
         assertThat(failedNames).asList().contains(NONEXISTENT_PACKAGE)
@@ -108,7 +108,7 @@
         val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 knownPackages, true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)!!
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)!!
 
         assertThat(failedNames.size).isEqualTo(knownPackages.size)
         for (pkg in knownPackages) {
@@ -117,33 +117,19 @@
     }
 
     @Test
-    fun setPackagesSuspended_forQuietMode() {
-        val knownPackages = arrayOf(DEVICE_ADMIN_PACKAGE, DEFAULT_HOME_PACKAGE, DIALER_PACKAGE,
-                INSTALLER_PACKAGE, UNINSTALLER_PACKAGE, VERIFIER_PACKAGE,
-                PERMISSION_CONTROLLER_PACKAGE, MGMT_ROLE_HOLDER_PACKAGE)
-        val failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
-                knownPackages, true /* suspended */, null /* appExtras */,
-                null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, true /* forQuietMode */, false /* quarantined */)!!
-
-        assertThat(failedNames.size).isEqualTo(1)
-        assertThat(failedNames[0]).isEqualTo(MGMT_ROLE_HOLDER_PACKAGE)
-    }
-
-    @Test
     fun setPackagesUnsuspended() {
         val targetPackages = arrayOf(TEST_PACKAGE_1, TEST_PACKAGE_2)
         var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 targetPackages, true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)
         testHandler.flush()
         Mockito.clearInvocations(broadcastHelper)
         assertThat(failedNames).isEmpty()
         failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 targetPackages, false /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)
         testHandler.flush()
 
         verify(pms, times(2)).scheduleWritePackageRestrictions(eq(TEST_USER_ID))
@@ -191,7 +177,7 @@
         var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOf(TEST_PACKAGE_1), true /* suspended */, appExtras, null /* launcherExtras */,
                 null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
-                false /* forQuietMode */, false /* quarantined */)
+                false /* quarantined */)
         testHandler.flush()
         assertThat(failedNames).isEmpty()
 
@@ -209,7 +195,7 @@
         var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 targetPackages, true /* suspended */, appExtras, null /* launcherExtras */,
                 null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
-                false /* forQuietMode */, false /* quarantined */)
+                false /* quarantined */)
         testHandler.flush()
         Mockito.clearInvocations(broadcastHelper)
         assertThat(failedNames).isEmpty()
@@ -250,7 +236,7 @@
         var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, launcherExtras,
                 null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
-                false /* forQuietMode */, false /* quarantined */)
+                false /* quarantined */)
         testHandler.flush()
         assertThat(failedNames).isEmpty()
 
@@ -265,7 +251,7 @@
         var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOf(TEST_PACKAGE_1), true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, null /* dialogInfo */, DEVICE_OWNER_PACKAGE,
-                TEST_USER_ID, deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                TEST_USER_ID, deviceOwnerUid, false /* quarantined */)
         testHandler.flush()
         assertThat(failedNames).isEmpty()
 
@@ -280,7 +266,7 @@
         var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOf(TEST_PACKAGE_2), true /* suspended */, null /* appExtras */, launcherExtras,
                 null /* dialogInfo */, DEVICE_OWNER_PACKAGE, TEST_USER_ID, deviceOwnerUid,
-                false /* forQuietMode */, false /* quarantined */)
+                false /* quarantined */)
         testHandler.flush()
         assertThat(failedNames).isEmpty()
 
@@ -295,7 +281,7 @@
         var failedNames = suspendPackageHelper.setPackagesSuspended(pms.snapshotComputer(),
                 arrayOf(TEST_PACKAGE_1), true /* suspended */, null /* appExtras */,
                 null /* launcherExtras */, dialogInfo, DEVICE_OWNER_PACKAGE, TEST_USER_ID,
-                deviceOwnerUid, false /* forQuietMode */, false /* quarantined */)
+                deviceOwnerUid, false /* quarantined */)
         testHandler.flush()
         assertThat(failedNames).isEmpty()
 
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index f88afe7..a78f2dc 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -41,6 +41,8 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
+import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.Flags;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricService;
 import android.hardware.biometrics.IBiometricServiceReceiver;
@@ -53,6 +55,7 @@
 import android.os.Binder;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -84,6 +87,8 @@
     @Rule
     public MockitoRule mockitorule = MockitoJUnit.rule();
 
+    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     @Mock
     private Context mContext;
     @Mock
@@ -418,6 +423,37 @@
                 eq(callback));
     }
 
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetLastAuthenticationTime_flaggedOff_throwsUnsupportedOperationException()
+            throws Exception {
+        mSetFlagsRule.disableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
+        setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
+
+        mAuthService = new AuthService(mContext, mInjector);
+        mAuthService.onStart();
+
+        mAuthService.mImpl.getLastAuthenticationTime(0,
+                BiometricManager.Authenticators.BIOMETRIC_STRONG);
+    }
+
+    @Test
+    public void testGetLastAuthenticationTime_flaggedOn_callsBiometricService()
+            throws Exception {
+        mSetFlagsRule.enableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
+        setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
+
+        mAuthService = new AuthService(mContext, mInjector);
+        mAuthService.onStart();
+
+        final int userId = 0;
+        final int authenticators = BiometricManager.Authenticators.BIOMETRIC_STRONG;
+
+        mAuthService.mImpl.getLastAuthenticationTime(userId, authenticators);
+
+        waitForIdle();
+        verify(mBiometricService).getLastAuthenticationTime(eq(userId), eq(authenticators));
+    }
+
     private static void setInternalAndTestBiometricPermissions(
             Context context, boolean hasPermission) {
         for (String p : List.of(TEST_BIOMETRIC, MANAGE_BIOMETRIC, USE_BIOMETRIC_INTERNAL)) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
index 0230d77..408442b 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/BiometricServiceTest.java
@@ -62,6 +62,7 @@
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.Flags;
 import android.hardware.biometrics.IBiometricAuthenticator;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.IBiometricSensorReceiver;
@@ -71,12 +72,17 @@
 import android.hardware.biometrics.PromptInfo;
 import android.hardware.display.DisplayManagerGlobal;
 import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.keymaster.HardwareAuthenticatorType;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.UserManager;
 import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.security.GateKeeper;
 import android.security.KeyStore;
+import android.security.authorization.IKeystoreAuthorization;
+import android.service.gatekeeper.IGateKeeperService;
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.WindowManager;
@@ -92,6 +98,7 @@
 import com.android.server.biometrics.sensors.LockoutTracker;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.AdditionalMatchers;
 import org.mockito.ArgumentCaptor;
@@ -105,6 +112,9 @@
 @SmallTest
 public class BiometricServiceTest {
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     private static final String TEST_PACKAGE_NAME = "test_package";
     private static final long TEST_REQUEST_ID = 44;
 
@@ -162,10 +172,16 @@
     @Mock
     private BiometricCameraManager mBiometricCameraManager;
 
+    @Mock
+    private IKeystoreAuthorization mKeystoreAuthService;
+
+    @Mock
+    private IGateKeeperService mGateKeeperService;
+
     BiometricContextProvider mBiometricContextProvider;
 
     @Before
-    public void setUp() {
+    public void setUp() throws RemoteException {
         MockitoAnnotations.initMocks(this);
 
         resetReceivers();
@@ -215,6 +231,9 @@
                 mStatusBarService, null /* handler */,
                 mAuthSessionCoordinator);
         when(mInjector.getBiometricContext(any())).thenReturn(mBiometricContextProvider);
+        when(mInjector.getKeystoreAuthorizationService()).thenReturn(mKeystoreAuthService);
+        when(mInjector.getGateKeeperService()).thenReturn(mGateKeeperService);
+        when(mGateKeeperService.getSecureUserId(anyInt())).thenReturn(42L);
 
         final String[] config = {
                 "0:2:15",  // ID0:Fingerprint:Strong
@@ -1751,6 +1770,44 @@
         verifyNoMoreInteractions(callback);
     }
 
+    @Test(expected = UnsupportedOperationException.class)
+    public void testGetLastAuthenticationTime_flagOff_throwsUnsupportedOperationException()
+            throws RemoteException {
+        mSetFlagsRule.disableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
+
+        mBiometricService = new BiometricService(mContext, mInjector);
+        mBiometricService.mImpl.getLastAuthenticationTime(0, Authenticators.BIOMETRIC_STRONG);
+    }
+
+    @Test
+    public void testGetLastAuthenticationTime_flagOn_callsKeystoreAuthorization()
+            throws RemoteException {
+        mSetFlagsRule.enableFlags(Flags.FLAG_LAST_AUTHENTICATION_TIME);
+
+        final int[] hardwareAuthenticators = new int[] {
+                HardwareAuthenticatorType.PASSWORD,
+                HardwareAuthenticatorType.FINGERPRINT
+        };
+
+        final int userId = 0;
+        final long secureUserId = mGateKeeperService.getSecureUserId(userId);
+
+        assertNotEquals(GateKeeper.INVALID_SECURE_USER_ID, secureUserId);
+
+        final long expectedResult = 31337L;
+
+        when(mKeystoreAuthService.getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators)))
+                .thenReturn(expectedResult);
+
+        mBiometricService = new BiometricService(mContext, mInjector);
+
+        final long result = mBiometricService.mImpl.getLastAuthenticationTime(userId,
+                Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL);
+
+        assertEquals(expectedResult, result);
+        verify(mKeystoreAuthService).getLastAuthTime(eq(secureUserId), eq(hardwareAuthenticators));
+    }
+
     // Helper methods
 
     private int invokeCanAuthenticate(BiometricService service, int authenticators)
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 461d637..2598a6b 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -347,6 +347,8 @@
         final DisplayInfo displayInfo = new DisplayInfo();
         displayInfo.uniqueId = UNIQUE_ID;
         doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt());
+        doReturn(Display.INVALID_DISPLAY).when(mDisplayManagerInternalMock)
+                .getDisplayIdToMirror(anyInt());
         LocalServices.removeServiceForTest(DisplayManagerInternal.class);
         LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
 
@@ -1627,6 +1629,7 @@
 
     @Test
     public void openNonBlockedAppOnMirrorDisplay_flagDisabled_launchesActivity() {
+        mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR);
         when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt()))
                 .thenReturn(Display.DEFAULT_DISPLAY);
         addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceRule.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceRule.java
index af633cc..dbd6c88 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceRule.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceRule.java
@@ -37,6 +37,7 @@
 import android.os.Binder;
 import android.testing.TestableContext;
 import android.util.ArraySet;
+import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.WindowManager;
 
@@ -137,6 +138,8 @@
         final DisplayInfo displayInfo = new DisplayInfo();
         displayInfo.uniqueId = "uniqueId";
         doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt());
+        doReturn(Display.INVALID_DISPLAY).when(mDisplayManagerInternalMock)
+                .getDisplayIdToMirror(anyInt());
         LocalServices.removeServiceForTest(DisplayManagerInternal.class);
         LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
 
diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionAllowlistManagerTest.java b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionAllowlistManagerTest.java
index dc38f2b..a28647e 100644
--- a/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionAllowlistManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/contentprotection/ContentProtectionAllowlistManagerTest.java
@@ -33,6 +33,7 @@
 import android.os.UserHandle;
 import android.os.test.TestLooper;
 import android.platform.test.flag.junit.SetFlagsRule;
+import android.service.contentcapture.IContentProtectionAllowlistCallback;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -48,6 +49,8 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
+import java.util.List;
+
 /**
  * Test for {@link ContentProtectionAllowlistManager}.
  *
@@ -58,7 +61,9 @@
 @SmallTest
 public class ContentProtectionAllowlistManagerTest {
 
-    private static final String PACKAGE_NAME = "com.test.package.name";
+    private static final String FIRST_PACKAGE_NAME = "com.test.first.package.name";
+
+    private static final String SECOND_PACKAGE_NAME = "com.test.second.package.name";
 
     private static final long TIMEOUT_MS = 111_111_111L;
 
@@ -74,12 +79,18 @@
 
     @Mock private RemoteContentProtectionService mMockRemoteContentProtectionService;
 
+    @Mock private IContentProtectionAllowlistCallback mMockAllowlistCallback;
+
     private final TestLooper mTestLooper = new TestLooper();
 
     private Handler mHandler;
 
     private ContentProtectionAllowlistManager mContentProtectionAllowlistManager;
 
+    private boolean mUseMockPackageMonitor = true;
+
+    private boolean mUseMockAllowlistCallback = true;
+
     @Before
     public void setup() {
         mHandler = new Handler(mTestLooper.getLooper());
@@ -91,6 +102,8 @@
         assertThat(mHandler.hasMessagesOrCallbacks()).isFalse();
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verifyZeroInteractions(mMockPackageMonitor);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -103,6 +116,8 @@
         assertThat(mHandler.hasMessagesOrCallbacks()).isTrue();
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verifyZeroInteractions(mMockPackageMonitor);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -117,6 +132,8 @@
         verify(mMockContentCaptureManagerService).createRemoteContentProtectionService();
         verify(mMockPackageMonitor).register(any(), eq(UserHandle.ALL), eq(mHandler));
         verify(mMockPackageMonitor, never()).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -132,6 +149,8 @@
         verify(mMockContentCaptureManagerService).createRemoteContentProtectionService();
         verify(mMockPackageMonitor).register(any(), eq(UserHandle.ALL), eq(mHandler));
         verify(mMockPackageMonitor, never()).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -144,6 +163,8 @@
         assertThat(mHandler.hasMessagesOrCallbacks()).isTrue();
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verifyZeroInteractions(mMockPackageMonitor);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -158,6 +179,8 @@
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verify(mMockPackageMonitor).register(any(), eq(UserHandle.ALL), eq(mHandler));
         verify(mMockPackageMonitor, never()).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -173,6 +196,8 @@
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verify(mMockPackageMonitor).register(any(), eq(UserHandle.ALL), eq(mHandler));
         verify(mMockPackageMonitor, never()).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -186,6 +211,8 @@
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verify(mMockPackageMonitor, never()).register(any(), any(), any());
         verify(mMockPackageMonitor).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -201,6 +228,8 @@
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verify(mMockPackageMonitor, never()).register(any(), any(), any());
         verify(mMockPackageMonitor).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -216,6 +245,8 @@
         verify(mMockContentCaptureManagerService).createRemoteContentProtectionService();
         verify(mMockPackageMonitor).register(any(), eq(UserHandle.ALL), eq(mHandler));
         verify(mMockPackageMonitor).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -229,6 +260,8 @@
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verify(mMockPackageMonitor, never()).register(any(), any(), any());
         verify(mMockPackageMonitor).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -244,6 +277,8 @@
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verify(mMockPackageMonitor, never()).register(any(), any(), any());
         verify(mMockPackageMonitor).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -259,6 +294,8 @@
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verify(mMockPackageMonitor).register(any(), eq(UserHandle.ALL), eq(mHandler));
         verify(mMockPackageMonitor).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -274,6 +311,8 @@
         assertThat(mHandler.hasMessagesOrCallbacks()).isFalse();
         verify(mMockPackageMonitor).register(any(), eq(UserHandle.ALL), eq(mHandler));
         verify(mMockPackageMonitor).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
@@ -290,60 +329,130 @@
         assertThat(mHandler.hasMessagesOrCallbacks()).isFalse();
         verify(mMockPackageMonitor, times(2)).register(any(), eq(UserHandle.ALL), eq(mHandler));
         verify(mMockPackageMonitor).unregister();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
-    public void isAllowed() {
-        boolean actual = mContentProtectionAllowlistManager.isAllowed(PACKAGE_NAME);
+    public void isAllowed_default() {
+        boolean actual = mContentProtectionAllowlistManager.isAllowed(FIRST_PACKAGE_NAME);
 
         assertThat(actual).isFalse();
         verifyZeroInteractions(mMockContentCaptureManagerService);
         verifyZeroInteractions(mMockPackageMonitor);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
-    public void handleUpdate_updateDisabled() {
+    public void isAllowed_false() throws Exception {
+        mUseMockAllowlistCallback = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
+        manager.mAllowlistCallback.setAllowlist(List.of(FIRST_PACKAGE_NAME));
+        mTestLooper.dispatchNext();
+
+        boolean actual = manager.isAllowed(SECOND_PACKAGE_NAME);
+
+        assertThat(actual).isFalse();
+        verifyZeroInteractions(mMockContentCaptureManagerService);
+        verifyZeroInteractions(mMockPackageMonitor);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+    }
+
+    @Test
+    public void isAllowed_true() throws Exception {
+        mUseMockAllowlistCallback = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
+        manager.mAllowlistCallback.setAllowlist(List.of(FIRST_PACKAGE_NAME));
+        mTestLooper.dispatchNext();
+
+        boolean actual = manager.isAllowed(FIRST_PACKAGE_NAME);
+
+        assertThat(actual).isTrue();
+        verifyZeroInteractions(mMockContentCaptureManagerService);
+        verifyZeroInteractions(mMockPackageMonitor);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+    }
+
+    @Test
+    public void handlePackagesChanged_updateDisabled() {
         mSetFlagsRule.disableFlags(FLAG_BLOCKLIST_UPDATE_ENABLED);
-        ContentProtectionAllowlistManager manager =
-                new ContentProtectionAllowlistManager(
-                        mMockContentCaptureManagerService, mHandler, TIMEOUT_MS);
+        mUseMockPackageMonitor = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
 
         manager.mPackageMonitor.onSomePackagesChanged();
 
         verifyZeroInteractions(mMockContentCaptureManagerService);
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
-    public void handleUpdate_updateEnabled() {
+    public void handlePackagesChanged_updateEnabled_noService() {
         mSetFlagsRule.enableFlags(FLAG_BLOCKLIST_UPDATE_ENABLED);
-        ContentProtectionAllowlistManager manager =
-                new ContentProtectionAllowlistManager(
-                        mMockContentCaptureManagerService, mHandler, TIMEOUT_MS);
+        mUseMockPackageMonitor = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
 
         manager.mPackageMonitor.onSomePackagesChanged();
 
         verify(mMockContentCaptureManagerService).createRemoteContentProtectionService();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
-    public void handleUpdate_rateLimit_noService() {
+    public void handlePackagesChanged_updateEnabled_withService() {
         mSetFlagsRule.enableFlags(FLAG_BLOCKLIST_UPDATE_ENABLED);
-        ContentProtectionAllowlistManager manager =
-                new ContentProtectionAllowlistManager(
-                        mMockContentCaptureManagerService, mHandler, TIMEOUT_MS);
+        mUseMockPackageMonitor = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
+        when(mMockContentCaptureManagerService.createRemoteContentProtectionService())
+                .thenReturn(mMockRemoteContentProtectionService);
+
+        manager.mPackageMonitor.onSomePackagesChanged();
+
+        verify(mMockRemoteContentProtectionService)
+                .onUpdateAllowlistRequest(mMockAllowlistCallback);
+        verifyZeroInteractions(mMockAllowlistCallback);
+    }
+
+    @Test
+    public void handlePackagesChanged_updateEnabled_withServiceException() {
+        mSetFlagsRule.enableFlags(FLAG_BLOCKLIST_UPDATE_ENABLED);
+        mUseMockPackageMonitor = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
+        when(mMockContentCaptureManagerService.createRemoteContentProtectionService())
+                .thenReturn(mMockRemoteContentProtectionService);
+        doThrow(new RuntimeException("TEST EXCEPTION"))
+                .when(mMockRemoteContentProtectionService)
+                .onUpdateAllowlistRequest(mMockAllowlistCallback);
+
+        manager.mPackageMonitor.onSomePackagesChanged();
+
+        // Does not rethrow
+        verify(mMockRemoteContentProtectionService)
+                .onUpdateAllowlistRequest(mMockAllowlistCallback);
+        verifyZeroInteractions(mMockAllowlistCallback);
+    }
+
+    @Test
+    public void handlePackagesChanged_rateLimit_noService() {
+        mSetFlagsRule.enableFlags(FLAG_BLOCKLIST_UPDATE_ENABLED);
+        mUseMockPackageMonitor = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
 
         manager.mPackageMonitor.onSomePackagesChanged();
         manager.mPackageMonitor.onSomePackagesChanged();
 
         verify(mMockContentCaptureManagerService, times(2)).createRemoteContentProtectionService();
+        verifyZeroInteractions(mMockRemoteContentProtectionService);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
-    public void handleUpdate_rateLimit_beforeTimeout() {
+    public void handlePackagesChanged_rateLimit_beforeTimeout() {
         mSetFlagsRule.enableFlags(FLAG_BLOCKLIST_UPDATE_ENABLED);
-        ContentProtectionAllowlistManager manager =
-                new ContentProtectionAllowlistManager(
-                        mMockContentCaptureManagerService, mHandler, TIMEOUT_MS);
+        mUseMockPackageMonitor = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
         when(mMockContentCaptureManagerService.createRemoteContentProtectionService())
                 .thenReturn(mMockRemoteContentProtectionService);
 
@@ -351,14 +460,17 @@
         manager.mPackageMonitor.onSomePackagesChanged();
 
         verify(mMockContentCaptureManagerService).createRemoteContentProtectionService();
+        verify(mMockRemoteContentProtectionService)
+                .onUpdateAllowlistRequest(mMockAllowlistCallback);
+        verifyZeroInteractions(mMockAllowlistCallback);
     }
 
     @Test
-    public void handleUpdate_rateLimit_afterTimeout() {
+    public void handlePackagesChanged_rateLimit_afterTimeout() {
         mSetFlagsRule.enableFlags(FLAG_BLOCKLIST_UPDATE_ENABLED);
+        mUseMockPackageMonitor = false;
         ContentProtectionAllowlistManager manager =
-                new ContentProtectionAllowlistManager(
-                        mMockContentCaptureManagerService, mHandler, /* timeoutMs= */ 0L);
+                new TestContentProtectionAllowlistManager(/* timeoutMs= */ 0L);
         when(mMockContentCaptureManagerService.createRemoteContentProtectionService())
                 .thenReturn(mMockRemoteContentProtectionService);
 
@@ -366,17 +478,50 @@
         manager.mPackageMonitor.onSomePackagesChanged();
 
         verify(mMockContentCaptureManagerService, times(2)).createRemoteContentProtectionService();
+        verify(mMockRemoteContentProtectionService, times(2))
+                .onUpdateAllowlistRequest(mMockAllowlistCallback);
+        verifyZeroInteractions(mMockAllowlistCallback);
+    }
+
+    @Test
+    public void handlePackagesChanged_rateLimit_afterUpdate() throws Exception {
+        mSetFlagsRule.enableFlags(FLAG_BLOCKLIST_UPDATE_ENABLED);
+        mUseMockPackageMonitor = false;
+        mUseMockAllowlistCallback = false;
+        ContentProtectionAllowlistManager manager = new TestContentProtectionAllowlistManager();
+        when(mMockContentCaptureManagerService.createRemoteContentProtectionService())
+                .thenReturn(mMockRemoteContentProtectionService);
+
+        manager.mPackageMonitor.onSomePackagesChanged();
+        manager.mAllowlistCallback.setAllowlist(List.of());
+        mTestLooper.dispatchNext();
+        manager.mPackageMonitor.onSomePackagesChanged();
+
+        verify(mMockContentCaptureManagerService, times(2)).createRemoteContentProtectionService();
+        verify(mMockRemoteContentProtectionService, times(2))
+                .onUpdateAllowlistRequest(manager.mAllowlistCallback);
     }
 
     private class TestContentProtectionAllowlistManager extends ContentProtectionAllowlistManager {
 
         TestContentProtectionAllowlistManager() {
-            super(mMockContentCaptureManagerService, mHandler, TIMEOUT_MS);
+            this(TIMEOUT_MS);
+        }
+
+        TestContentProtectionAllowlistManager(long timeoutMs) {
+            super(mMockContentCaptureManagerService, mHandler, timeoutMs);
+        }
+
+        @Override
+        protected IContentProtectionAllowlistCallback createAllowlistCallback() {
+            return mUseMockAllowlistCallback
+                    ? mMockAllowlistCallback
+                    : super.createAllowlistCallback();
         }
 
         @Override
         protected PackageMonitor createPackageMonitor() {
-            return mMockPackageMonitor;
+            return mUseMockPackageMonitor ? mMockPackageMonitor : super.createPackageMonitor();
         }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 4bb7d63..2db46e6 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -784,66 +784,6 @@
     }
 
     @Test
-    public void testPersistedPreferredBatteryNotLowConstraint() throws Exception {
-        JobInfo.Builder b = new Builder(8, mComponent)
-                .setPrefersBatteryNotLow(true)
-                .setPersisted(true);
-        JobStatus taskStatus =
-                JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null, null);
-
-        mTaskStoreUnderTest.add(taskStatus);
-        waitForPendingIo();
-
-        final JobSet jobStatusSet = new JobSet();
-        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true);
-        assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
-        JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
-        assertEquals("Battery-not-low constraint not persisted correctly.",
-                taskStatus.getJob().isPreferBatteryNotLow(),
-                loaded.getJob().isPreferBatteryNotLow());
-    }
-
-    @Test
-    public void testPersistedPreferredChargingConstraint() throws Exception {
-        JobInfo.Builder b = new Builder(8, mComponent)
-                .setPrefersCharging(true)
-                .setPersisted(true);
-        JobStatus taskStatus =
-                JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null, null);
-
-        mTaskStoreUnderTest.add(taskStatus);
-        waitForPendingIo();
-
-        final JobSet jobStatusSet = new JobSet();
-        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true);
-        assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
-        JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
-        assertEquals("Charging constraint not persisted correctly.",
-                taskStatus.getJob().isPreferCharging(),
-                loaded.getJob().isPreferCharging());
-    }
-
-    @Test
-    public void testPersistedPreferredDeviceIdleConstraint() throws Exception {
-        JobInfo.Builder b = new Builder(8, mComponent)
-                .setPrefersDeviceIdle(true)
-                .setPersisted(true);
-        JobStatus taskStatus =
-                JobStatus.createFromJobInfo(b.build(), SOME_UID, null, -1, null, null);
-
-        mTaskStoreUnderTest.add(taskStatus);
-        waitForPendingIo();
-
-        final JobSet jobStatusSet = new JobSet();
-        mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet, true);
-        assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
-        JobStatus loaded = jobStatusSet.getAllJobs().iterator().next();
-        assertEquals("Idle constraint not persisted correctly.",
-                taskStatus.getJob().isPreferDeviceIdle(),
-                loaded.getJob().isPreferDeviceIdle());
-    }
-
-    @Test
     public void testJobWorkItems() throws Exception {
         JobWorkItem item1 = new JobWorkItem.Builder().build();
         item1.bumpDeliveryCount();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
index 93adddb..6e5baee 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityOptionsTest.java
@@ -275,7 +275,7 @@
                 case "android.activity.launchTypeBubble": // KEY_LAUNCHED_FROM_BUBBLE
                 case "android.activity.splashScreenStyle": // KEY_SPLASH_SCREEN_STYLE
                 case "android.activity.launchIntoPipParams": // KEY_LAUNCH_INTO_PIP_PARAMS
-                case "android.activity.dismissKeyguard": // KEY_DISMISS_KEYGUARD
+                case "android.activity.dismissKeyguardIfInsecure": // KEY_DISMISS_KEYGUARD_IF_INSECURE
                 case "android.activity.pendingIntentCreatorBackgroundActivityStartMode":
                     // KEY_PENDING_INTENT_CREATOR_BACKGROUND_ACTIVITY_START_MODE
                 case "android.activity.launchCookie": // KEY_LAUNCH_COOKIE
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
index 568471d..526201f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartInterceptorTest.java
@@ -247,39 +247,9 @@
     }
 
     @Test
-    public void testInterceptQuietProfile_keepProfilesRunningEnabled() {
-        // GIVEN that the user the activity is starting as is currently in quiet mode and
-        // profiles are kept running when in quiet mode.
+    public void testInterceptQuietProfile() {
+        // GIVEN that the user the activity is starting as is currently in quiet mode
         when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
-        when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
-
-        // THEN calling intercept returns false because package also has to be suspended.
-        assertFalse(
-                mInterceptor.intercept(null, null, mAInfo, null, null,  null, 0, 0, null, null));
-    }
-
-    @Test
-    public void testInterceptQuietProfile_keepProfilesRunningDisabled() {
-        // GIVEN that the user the activity is starting as is currently in quiet mode and
-        // profiles are stopped when in quiet mode (pre-U behavior, no profile app suspension).
-        when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
-        when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
-
-        // THEN calling intercept returns true
-        assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null,  null, 0, 0, null, null));
-
-        // THEN the returned intent is the quiet mode intent
-        assertTrue(UnlaunchableAppActivity.createInQuietModeDialogIntent(TEST_USER_ID)
-                .filterEquals(mInterceptor.mIntent));
-    }
-
-    @Test
-    public void testInterceptQuietProfileWhenPackageSuspended_keepProfilesRunningEnabled() {
-        // GIVEN that the user the activity is starting as is currently in quiet mode,
-        // the package is suspended and profiles are kept running while in quiet mode.
-        suspendPackage("com.test.suspending.package");
-        when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
-        when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(true);
 
         // THEN calling intercept returns true
         assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
@@ -290,12 +260,10 @@
     }
 
     @Test
-    public void testInterceptQuietProfileWhenPackageSuspended_keepProfilesRunningDisabled() {
-        // GIVEN that the user the activity is starting as is currently in quiet mode,
-        // the package is suspended and profiles are stopped while in quiet mode.
+    public void testInterceptQuietProfileWhenPackageSuspended() {
         suspendPackage("com.test.suspending.package");
+        // GIVEN that the user the activity is starting as is currently in quiet mode
         when(mUserManager.isQuietModeEnabled(eq(UserHandle.of(TEST_USER_ID)))).thenReturn(true);
-        when(mDevicePolicyManager.isKeepProfilesRunningEnabled()).thenReturn(false);
 
         // THEN calling intercept returns true
         assertTrue(mInterceptor.intercept(null, null, mAInfo, null, null, null, 0, 0, null, null));
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index ba31944..7b2cd63 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -66,8 +66,6 @@
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
 import android.view.SurfaceControl;
-import android.view.View;
-import android.view.WindowManager;
 import android.window.DisplayAreaInfo;
 import android.window.IDisplayAreaOrganizer;
 
@@ -451,17 +449,11 @@
     @Test
     public void testGetOrientation() {
         final DisplayArea.Tokens area = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "test");
-        final WindowToken token = createWindowToken(TYPE_APPLICATION_OVERLAY);
-        spyOn(token);
-        doReturn(mock(DisplayContent.class)).when(token).getDisplayContent();
-        doNothing().when(token).setParent(any());
-        final WindowState win = createWindowState(token);
-        spyOn(win);
-        doNothing().when(win).setParent(any());
+        mDisplayContent.addChild(area, POSITION_TOP);
+        final WindowState win = createWindow(null, TYPE_APPLICATION_OVERLAY, "overlay");
         win.mAttrs.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
-        token.addChild(win, 0);
-        area.addChild(token);
-
+        win.mToken.reparent(area, POSITION_TOP);
+        spyOn(win);
         doReturn(true).when(win).isVisible();
 
         assertEquals("Visible window can request orientation",
@@ -753,13 +745,6 @@
         }
     }
 
-    private WindowState createWindowState(WindowToken token) {
-        return new WindowState(mWm, getTestSession(), new TestIWindow(), token,
-                null /* parentWindow */, 0 /* appOp */, new WindowManager.LayoutParams(),
-                View.VISIBLE, 0 /* ownerId */, 0 /* showUserId */,
-                false /* ownerCanAddInternalSystemWindow */);
-    }
-
     private WindowToken createWindowToken(int type) {
         return new WindowToken.Builder(mWm, new Binder(), type).build();
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index 4c25a4b..3b4b220 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1444,7 +1444,7 @@
         });
         assertSecurityException(expectCallable,
                 () -> mAtm.startActivityFromRecents(0, new Bundle()));
-        assertSecurityException(expectCallable, () -> mAtm.getTaskSnapshot(0, true, false));
+        assertSecurityException(expectCallable, () -> mAtm.getTaskSnapshot(0, true));
         assertSecurityException(expectCallable, () -> mAtm.registerTaskStackListener(null));
         assertSecurityException(expectCallable,
                 () -> mAtm.unregisterTaskStackListener(null));
diff --git a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
index 9f43a17..55a7089 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java
@@ -145,7 +145,7 @@
             verifySecureExceptionThrown(activityOptions, taskSupervisor);
 
             activityOptions = ActivityOptions.makeBasic();
-            activityOptions.setDismissKeyguard();
+            activityOptions.setDismissKeyguardIfInsecure();
             verifySecureExceptionThrown(activityOptions, taskSupervisor);
 
             activityOptions = ActivityOptions.makeBasic();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 435a835..0639deb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -73,6 +73,7 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -570,12 +571,15 @@
                 .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build();
         final Task task = rootTask.getBottomMostTask();
         final ActivityRecord root = task.getTopNonFinishingActivity();
+        final PackageManager pm = mContext.getPackageManager();
+        spyOn(pm);
         spyOn(mWm.mLetterboxConfiguration);
         spyOn(root);
         spyOn(root.mLetterboxUiController);
 
         doReturn(true).when(root.mLetterboxUiController)
                 .shouldEnableUserAspectRatioSettings();
+        doReturn(new Intent()).when(pm).getLaunchIntentForPackage(anyString());
         doReturn(false).when(root).inSizeCompatMode();
         doReturn(task).when(root).getOrganizedTask();
 
@@ -593,6 +597,10 @@
         doReturn(true).when(root).inSizeCompatMode();
         assertFalse(task.getTaskInfo().topActivityEligibleForUserAspectRatioButton);
         doReturn(false).when(root).inSizeCompatMode();
+
+        // When app doesn't have any launchable activities the button is not enabled
+        doReturn(null).when(pm).getLaunchIntentForPackage(anyString());
+        assertFalse(task.getTaskInfo().topActivityEligibleForUserAspectRatioButton);
     }
 
     /**
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index e413663..f64ab22 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -57,6 +57,7 @@
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents;
 import android.app.usage.UsageEvents.Event;
+import android.app.usage.UsageEventsQuery;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManager.StandbyBuckets;
@@ -113,6 +114,8 @@
 import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
 import com.android.server.utils.AlarmQueue;
 
+import libcore.util.EmptyArray;
+
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
@@ -1478,6 +1481,14 @@
      * Called by the Binder stub.
      */
     UsageEvents queryEvents(int userId, long beginTime, long endTime, int flags) {
+        return queryEventsWithTypes(userId, beginTime, endTime, flags, EmptyArray.INT);
+    }
+
+    /**
+     * Called by the Binder stub.
+     */
+    UsageEvents queryEventsWithTypes(int userId, long beginTime, long endTime, int flags,
+            int[] eventTypeFilter) {
         synchronized (mLock) {
             if (!mUserUnlockedStates.contains(userId)) {
                 Slog.w(TAG, "Failed to query events for locked user " + userId);
@@ -1488,7 +1499,7 @@
             if (service == null) {
                 return null; // user was stopped or removed
             }
-            return service.queryEvents(beginTime, endTime, flags);
+            return service.queryEvents(beginTime, endTime, flags, eventTypeFilter);
         }
     }
 
@@ -2123,7 +2134,7 @@
 
     private final class BinderService extends IUsageStatsManager.Stub {
 
-        private boolean hasPermission(String callingPackage) {
+        private boolean hasQueryPermission(String callingPackage) {
             final int callingUid = Binder.getCallingUid();
             if (callingUid == Process.SYSTEM_UID) {
                 return true;
@@ -2203,10 +2214,37 @@
             return uid == Process.SYSTEM_UID;
         }
 
+        private UsageEvents queryEventsHelper(int userId, long beginTime, long endTime,
+                String callingPackage, int[] eventTypeFilter) {
+            final int callingUid = Binder.getCallingUid();
+            final int callingPid = Binder.getCallingPid();
+            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
+                    callingUid, userId);
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
+                        userId, callingPackage, callingPid, callingUid);
+                final boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
+                final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents(
+                        callingPid, callingUid);
+                int flags = UsageEvents.SHOW_ALL_EVENT_DATA;
+                if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS;
+                if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS;
+                if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS;
+                if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS;
+
+                return UsageStatsService.this.queryEventsWithTypes(userId, beginTime, endTime,
+                        flags, eventTypeFilter);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
         @Override
         public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime,
                 long endTime, String callingPackage, int userId) {
-            if (!hasPermission(callingPackage)) {
+            if (!hasQueryPermission(callingPackage)) {
                 return null;
             }
 
@@ -2234,7 +2272,7 @@
         @Override
         public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType,
                 long beginTime, long endTime, String callingPackage) throws RemoteException {
-            if (!hasPermission(callingPackage)) {
+            if (!hasQueryPermission(callingPackage)) {
                 return null;
             }
 
@@ -2256,7 +2294,7 @@
         @Override
         public ParceledListSlice<EventStats> queryEventStats(int bucketType,
                 long beginTime, long endTime, String callingPackage) throws RemoteException {
-            if (!hasPermission(callingPackage)) {
+            if (!hasQueryPermission(callingPackage)) {
                 return null;
             }
 
@@ -2277,32 +2315,25 @@
 
         @Override
         public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) {
-            if (!hasPermission(callingPackage)) {
+            if (!hasQueryPermission(callingPackage)) {
                 return null;
             }
 
-            final int userId = UserHandle.getCallingUserId();
-            final int callingUid = Binder.getCallingUid();
-            final int callingPid = Binder.getCallingPid();
-            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
-                    callingUid, userId);
+            return queryEventsHelper(UserHandle.getCallingUserId(), beginTime, endTime,
+                    callingPackage, /* eventTypeFilter= */ EmptyArray.INT);
+        }
 
-            final long token = Binder.clearCallingIdentity();
-            try {
-                final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
-                        userId, callingPackage, callingPid, callingUid);
-                final boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
-                final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents(
-                        callingPid, callingUid);
-                int flags = UsageEvents.SHOW_ALL_EVENT_DATA;
-                if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS;
-                if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS;
-                if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS;
-                if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS;
-                return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags);
-            } finally {
-                Binder.restoreCallingIdentity(token);
+        @Override
+        public UsageEvents queryEventsWithFilter(@NonNull UsageEventsQuery query,
+                @NonNull String callingPackage) {
+            Objects.requireNonNull(query);
+            Objects.requireNonNull(callingPackage);
+
+            if (!hasQueryPermission(callingPackage)) {
+                return null;
             }
+            return queryEventsHelper(UserHandle.getCallingUserId(), query.getBeginTimeMillis(),
+                    query.getEndTimeMillis(), callingPackage, query.getEventTypeFilter());
         }
 
         @Override
@@ -2312,7 +2343,7 @@
             final int callingUserId = UserHandle.getUserId(callingUid);
 
             checkCallerIsSameApp(callingPackage);
-            final boolean includeTaskRoot = hasPermission(callingPackage);
+            final boolean includeTaskRoot = hasQueryPermission(callingPackage);
 
             final long token = Binder.clearCallingIdentity();
             try {
@@ -2326,7 +2357,7 @@
         @Override
         public UsageEvents queryEventsForUser(long beginTime, long endTime, int userId,
                 String callingPackage) {
-            if (!hasPermission(callingPackage)) {
+            if (!hasQueryPermission(callingPackage)) {
                 return null;
             }
 
@@ -2337,33 +2368,14 @@
                         "No permission to query usage stats for this user");
             }
 
-            final int callingUid = Binder.getCallingUid();
-            final int callingPid = Binder.getCallingPid();
-            final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
-                    callingUid, callingUserId);
-
-            final long token = Binder.clearCallingIdentity();
-            try {
-                final boolean hideShortcutInvocationEvents = shouldHideShortcutInvocationEvents(
-                        userId, callingPackage, callingPid, callingUid);
-                final boolean obfuscateNotificationEvents = shouldObfuscateNotificationEvents(
-                        callingPid, callingUid);
-                boolean hideLocusIdEvents = shouldHideLocusIdEvents(callingPid, callingUid);
-                int flags = UsageEvents.SHOW_ALL_EVENT_DATA;
-                if (obfuscateInstantApps) flags |= UsageEvents.OBFUSCATE_INSTANT_APPS;
-                if (hideShortcutInvocationEvents) flags |= UsageEvents.HIDE_SHORTCUT_EVENTS;
-                if (hideLocusIdEvents) flags |= UsageEvents.HIDE_LOCUS_EVENTS;
-                if (obfuscateNotificationEvents) flags |= UsageEvents.OBFUSCATE_NOTIFICATION_EVENTS;
-                return UsageStatsService.this.queryEvents(userId, beginTime, endTime, flags);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
+            return queryEventsHelper(userId, beginTime, endTime, callingPackage,
+                    /* eventTypeFilter= */ EmptyArray.INT);
         }
 
         @Override
         public UsageEvents queryEventsForPackageForUser(long beginTime, long endTime,
                 int userId, String pkg, String callingPackage) {
-            if (!hasPermission(callingPackage)) {
+            if (!hasQueryPermission(callingPackage)) {
                 return null;
             }
             if (userId != UserHandle.getCallingUserId()) {
@@ -2404,7 +2416,7 @@
                 if (actualCallingUid != callingUid) {
                     return false;
                 }
-            } else if (!hasPermission(callingPackage)) {
+            } else if (!hasQueryPermission(callingPackage)) {
                 return false;
             }
             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(
@@ -2454,7 +2466,7 @@
             final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
             // If the calling app is asking about itself, continue, else check for permission.
             final boolean sameApp = packageUid == callingUid;
-            if (!sameApp && !hasPermission(callingPackage)) {
+            if (!sameApp && !hasQueryPermission(callingPackage)) {
                 throw new SecurityException("Don't have permission to query app standby bucket");
             }
 
@@ -2502,7 +2514,7 @@
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
-            if (!hasPermission(callingPackageName)) {
+            if (!hasQueryPermission(callingPackageName)) {
                 throw new SecurityException(
                         "Don't have permission to query app standby bucket");
             }
@@ -2556,7 +2568,7 @@
             final int packageUid = mPackageManagerInternal.getPackageUid(packageName, 0, userId);
             // If the calling app is asking about itself, continue, else check for permission.
             if (packageUid != callingUid) {
-                if (!hasPermission(callingPackage)) {
+                if (!hasQueryPermission(callingPackage)) {
                     throw new SecurityException(
                             "Don't have permission to query min app standby bucket");
                 }
@@ -2900,7 +2912,7 @@
             if (!hasPermissions(android.Manifest.permission.INTERACT_ACROSS_USERS)) {
                 throw new SecurityException("Caller doesn't have INTERACT_ACROSS_USERS permission");
             }
-            if (!hasPermission(callingPackage)) {
+            if (!hasQueryPermission(callingPackage)) {
                 throw new SecurityException("Don't have permission to query usage stats");
             }
             synchronized (mLock) {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index ddb2796..9b67ab6 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -70,7 +70,7 @@
  * in UsageStatsService.
  */
 class UserUsageStatsService {
-    private static final String TAG = "UsageStatsService";
+    private static final String TAG = UsageStatsService.TAG;
     private static final boolean DEBUG = UsageStatsService.DEBUG;
     private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
     private static final int sDateFormatFlags =
@@ -535,10 +535,23 @@
         return queryStats(bucketType, beginTime, endTime, sEventStatsCombiner, true);
     }
 
-    UsageEvents queryEvents(final long beginTime, final long endTime, int flags) {
+    UsageEvents queryEvents(final long beginTime, final long endTime, int flags,
+            int[] eventTypeFilter) {
         if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) {
             return null;
         }
+
+        // Ensure valid event type filter.
+        final boolean isQueryForAllEvents = ArrayUtils.isEmpty(eventTypeFilter);
+        final boolean[] queryEventFilter = new boolean[Event.MAX_EVENT_TYPE + 1];
+        if (!isQueryForAllEvents) {
+            for (int eventType : eventTypeFilter) {
+                if (eventType < Event.NONE || eventType > Event.MAX_EVENT_TYPE) {
+                    throw new IllegalArgumentException("invalid event type: " + eventType);
+                }
+                queryEventFilter[eventType] = true;
+            }
+        }
         final ArraySet<String> names = new ArraySet<>();
         List<Event> results = queryStats(INTERVAL_DAILY,
                 beginTime, endTime, new StatCombiner<Event>() {
@@ -547,6 +560,7 @@
                             List<Event> accumulatedResult) {
                         final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
                         final int size = stats.events.size();
+
                         for (int i = startIndex; i < size; i++) {
                             Event event = stats.events.get(i);
                             if (event.mTimeStamp >= endTime) {
@@ -554,6 +568,10 @@
                             }
 
                             final int eventType = event.mEventType;
+                            if (!isQueryForAllEvents && !queryEventFilter[eventType]) {
+                                continue;
+                            }
+
                             if (eventType == Event.SHORTCUT_INVOCATION
                                     && (flags & HIDE_SHORTCUT_EVENTS) == HIDE_SHORTCUT_EVENTS) {
                                 continue;
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 11cbcb1..cb7926c 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -568,6 +568,7 @@
     private final int mSkip464Xlat;
     private final boolean mAlwaysOn;
     private final @InfrastructureBitmask int mInfrastructureBitmask;
+    private final boolean mEsimBootstrapProvisioning;
 
     /**
      * Returns the default MTU (Maximum Transmission Unit) size in bytes of the IPv4 routes brought
@@ -979,6 +980,18 @@
         return mInfrastructureBitmask;
     }
 
+    /**
+     * Returns esim bootstrap provisioning flag for which the APN can be used on. For example,
+     * some APNs are only allowed to bring up network, when the device esim bootstrap provisioning
+     * is being activated.
+     *
+     * {@code true} if the APN is used for eSIM bootstrap provisioning, {@code false} otherwise.
+     * @hide
+     */
+    public boolean isEsimBootstrapProvisioning() {
+        return mEsimBootstrapProvisioning;
+    }
+
     private ApnSetting(Builder builder) {
         this.mEntryName = builder.mEntryName;
         this.mApnName = builder.mApnName;
@@ -1016,6 +1029,7 @@
         this.mSkip464Xlat = builder.mSkip464Xlat;
         this.mAlwaysOn = builder.mAlwaysOn;
         this.mInfrastructureBitmask = builder.mInfrastructureBitmask;
+        this.mEsimBootstrapProvisioning = builder.mEsimBootstrapProvisioning;
     }
 
     /**
@@ -1097,6 +1111,8 @@
                 .setAlwaysOn(cursor.getInt(cursor.getColumnIndexOrThrow(Carriers.ALWAYS_ON)) == 1)
                 .setInfrastructureBitmask(cursor.getInt(cursor.getColumnIndexOrThrow(
                         Telephony.Carriers.INFRASTRUCTURE_BITMASK)))
+                .setEsimBootstrapProvisioning(cursor.getInt(
+                        cursor.getColumnIndexOrThrow(Carriers.ESIM_BOOTSTRAP_PROVISIONING)) == 1)
                 .buildWithoutCheck();
     }
 
@@ -1137,6 +1153,7 @@
                 .setSkip464Xlat(apn.mSkip464Xlat)
                 .setAlwaysOn(apn.mAlwaysOn)
                 .setInfrastructureBitmask(apn.mInfrastructureBitmask)
+                .setEsimBootstrapProvisioning(apn.mEsimBootstrapProvisioning)
                 .buildWithoutCheck();
     }
 
@@ -1184,6 +1201,7 @@
         sb.append(", ").append(mAlwaysOn);
         sb.append(", ").append(mInfrastructureBitmask);
         sb.append(", ").append(Objects.hash(mUser, mPassword));
+        sb.append(", ").append(mEsimBootstrapProvisioning);
         return sb.toString();
     }
 
@@ -1247,7 +1265,7 @@
                 mProtocol, mRoamingProtocol, mMtuV4, mMtuV6, mCarrierEnabled, mNetworkTypeBitmask,
                 mLingeringNetworkTypeBitmask, mProfileId, mPersistent, mMaxConns, mWaitTime,
                 mMaxConnsTime, mMvnoType, mMvnoMatchData, mApnSetId, mCarrierId, mSkip464Xlat,
-                mAlwaysOn, mInfrastructureBitmask);
+                mAlwaysOn, mInfrastructureBitmask, mEsimBootstrapProvisioning);
     }
 
     @Override
@@ -1289,7 +1307,8 @@
                 && mCarrierId == other.mCarrierId
                 && mSkip464Xlat == other.mSkip464Xlat
                 && mAlwaysOn == other.mAlwaysOn
-                && mInfrastructureBitmask == other.mInfrastructureBitmask;
+                && mInfrastructureBitmask == other.mInfrastructureBitmask
+                && Objects.equals(mEsimBootstrapProvisioning, other.mEsimBootstrapProvisioning);
     }
 
     /**
@@ -1340,7 +1359,8 @@
                 && Objects.equals(mCarrierId, other.mCarrierId)
                 && Objects.equals(mSkip464Xlat, other.mSkip464Xlat)
                 && Objects.equals(mAlwaysOn, other.mAlwaysOn)
-                && Objects.equals(mInfrastructureBitmask, other.mInfrastructureBitmask);
+                && Objects.equals(mInfrastructureBitmask, other.mInfrastructureBitmask)
+                && Objects.equals(mEsimBootstrapProvisioning, other.mEsimBootstrapProvisioning);
     }
 
     /**
@@ -1378,7 +1398,9 @@
                 && Objects.equals(this.mCarrierId, other.mCarrierId)
                 && Objects.equals(this.mSkip464Xlat, other.mSkip464Xlat)
                 && Objects.equals(this.mAlwaysOn, other.mAlwaysOn)
-                && Objects.equals(this.mInfrastructureBitmask, other.mInfrastructureBitmask);
+                && Objects.equals(this.mInfrastructureBitmask, other.mInfrastructureBitmask)
+                && Objects.equals(this.mEsimBootstrapProvisioning,
+                other.mEsimBootstrapProvisioning);
     }
 
     // Equal or one is null.
@@ -1451,6 +1473,7 @@
         apnValue.put(Telephony.Carriers.SKIP_464XLAT, mSkip464Xlat);
         apnValue.put(Telephony.Carriers.ALWAYS_ON, mAlwaysOn);
         apnValue.put(Telephony.Carriers.INFRASTRUCTURE_BITMASK, mInfrastructureBitmask);
+        apnValue.put(Carriers.ESIM_BOOTSTRAP_PROVISIONING, mEsimBootstrapProvisioning);
         return apnValue;
     }
 
@@ -1724,6 +1747,7 @@
         dest.writeInt(mSkip464Xlat);
         dest.writeBoolean(mAlwaysOn);
         dest.writeInt(mInfrastructureBitmask);
+        dest.writeBoolean(mEsimBootstrapProvisioning);
     }
 
     private static ApnSetting readFromParcel(Parcel in) {
@@ -1760,6 +1784,7 @@
                 .setSkip464Xlat(in.readInt())
                 .setAlwaysOn(in.readBoolean())
                 .setInfrastructureBitmask(in.readInt())
+                .setEsimBootstrapProvisioning(in.readBoolean())
                 .buildWithoutCheck();
     }
 
@@ -1842,6 +1867,7 @@
         private int mSkip464Xlat = Carriers.SKIP_464XLAT_DEFAULT;
         private boolean mAlwaysOn;
         private int mInfrastructureBitmask = INFRASTRUCTURE_CELLULAR;
+        private boolean mEsimBootstrapProvisioning;
 
         /**
          * Default constructor for Builder.
@@ -2280,6 +2306,19 @@
         }
 
         /**
+         * Sets esim bootstrap provisioning flag
+         *
+         * @param esimBootstrapProvisioning {@code true} if the APN is used for eSIM bootstrap
+         * provisioning, {@code false} otherwise.
+         * @hide
+         */
+        @NonNull
+        public Builder setEsimBootstrapProvisioning(boolean esimBootstrapProvisioning) {
+            this.mEsimBootstrapProvisioning = esimBootstrapProvisioning;
+            return this;
+        }
+
+        /**
          * Builds {@link ApnSetting} from this builder.
          *
          * @return {@code null} if {@link #setApnName(String)} or {@link #setEntryName(String)}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index a20f26c..f56347f 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -618,4 +618,5 @@
     int RIL_UNSOL_TRIGGER_IMS_DEREGISTRATION = 1107;
     int RIL_UNSOL_CONNECTION_SETUP_FAILURE = 1108;
     int RIL_UNSOL_NOTIFY_ANBR = 1109;
+    int RIL_UNSOL_IMEI_MAPPING_CHANGED = 1110;
 }
diff --git a/tests/FlickerTests/AndroidTestTemplate.xml b/tests/FlickerTests/AndroidTestTemplate.xml
index 85709c9..ed71531 100644
--- a/tests/FlickerTests/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/AndroidTestTemplate.xml
@@ -28,7 +28,13 @@
         <option name="run-command" value="su root service call SurfaceFlinger 1029 i32 81920"/>
         <!-- b/307664397 - Ensure camera has the correct permissions and doesn't show a dialog -->
         <option name="run-command"
+                value="pm grant com.google.android.GoogleCamera android.permission.CAMERA"/>
+        <option name="run-command"
+                value="pm grant com.google.android.GoogleCamera android.permission.RECORD_AUDIO"/>
+        <option name="run-command"
                 value="pm grant com.google.android.GoogleCamera android.permission.ACCESS_FINE_LOCATION"/>
+        <option name="run-command"
+                value="pm grant com.google.android.GoogleCamera android.permission.ACCESS_COARSE_LOCATION"/>
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="test-user-token" value="%TEST_USER%"/>
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
index cb37821..59dc689 100644
--- a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -313,7 +313,8 @@
 
     @Test
     public void testBuilderAndGettersSafeModeDisabled() {
-        final VcnGatewayConnectionConfig config = newBuilderMinimal().enableSafeMode(false).build();
+        final VcnGatewayConnectionConfig config =
+                newBuilderMinimal().setSafeModeEnabled(false).build();
 
         assertFalse(config.isSafeModeEnabled());
     }
@@ -335,7 +336,8 @@
 
     @Test
     public void testPersistableBundleSafeModeDisabled() {
-        final VcnGatewayConnectionConfig config = newBuilderMinimal().enableSafeMode(false).build();
+        final VcnGatewayConnectionConfig config =
+                newBuilderMinimal().setSafeModeEnabled(false).build();
 
         assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
     }
@@ -456,7 +458,7 @@
         assertEquals(config.isSafeModeEnabled(), configEqual.isSafeModeEnabled());
 
         final VcnGatewayConnectionConfig configNotEqual =
-                newBuilderMinimal().enableSafeMode(false).build();
+                newBuilderMinimal().setSafeModeEnabled(false).build();
 
         assertEquals(config, configEqual);
         assertNotEquals(config, configNotEqual);
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index bf73198..f846164 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -661,7 +661,7 @@
             throws Exception {
         final VcnGatewayConnectionConfig config =
                 VcnGatewayConnectionConfigTest.newTestBuilderMinimal()
-                        .enableSafeMode(safeModeEnabledByCaller)
+                        .setSafeModeEnabled(safeModeEnabledByCaller)
                         .build();
         final VcnGatewayConnection.Dependencies deps =
                 mock(VcnGatewayConnection.Dependencies.class);
diff --git a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/dark_landscape_credential_view_pin_or_password_emergency_call_button.png b/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/dark_landscape_credential_view_pin_or_password_emergency_call_button.png
deleted file mode 100644
index 6bd8595..0000000
--- a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/dark_landscape_credential_view_pin_or_password_emergency_call_button.png
+++ /dev/null
Binary files differ
diff --git a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/dark_portrait_credential_view_pin_or_password_emergency_call_button.png b/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/dark_portrait_credential_view_pin_or_password_emergency_call_button.png
deleted file mode 100644
index d5d6fb6..0000000
--- a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/dark_portrait_credential_view_pin_or_password_emergency_call_button.png
+++ /dev/null
Binary files differ
diff --git a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/light_landscape_credential_view_pin_or_password_emergency_call_button.png b/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/light_landscape_credential_view_pin_or_password_emergency_call_button.png
deleted file mode 100644
index fe8dc69..0000000
--- a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/light_landscape_credential_view_pin_or_password_emergency_call_button.png
+++ /dev/null
Binary files differ
diff --git a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/light_portrait_credential_view_pin_or_password_emergency_call_button.png b/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/light_portrait_credential_view_pin_or_password_emergency_call_button.png
deleted file mode 100644
index ccd8a33..0000000
--- a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/phone/light_portrait_credential_view_pin_or_password_emergency_call_button.png
+++ /dev/null
Binary files differ
diff --git a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/dark_landscape_credential_view_pin_or_password_emergency_call_button.png b/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/dark_landscape_credential_view_pin_or_password_emergency_call_button.png
deleted file mode 100644
index de84c4a..0000000
--- a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/dark_landscape_credential_view_pin_or_password_emergency_call_button.png
+++ /dev/null
Binary files differ
diff --git a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/dark_portrait_credential_view_pin_or_password_emergency_call_button.png b/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/dark_portrait_credential_view_pin_or_password_emergency_call_button.png
deleted file mode 100644
index af9d7cf..0000000
--- a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/dark_portrait_credential_view_pin_or_password_emergency_call_button.png
+++ /dev/null
Binary files differ
diff --git a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/light_landscape_credential_view_pin_or_password_emergency_call_button.png b/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/light_landscape_credential_view_pin_or_password_emergency_call_button.png
deleted file mode 100644
index 33daab9..0000000
--- a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/light_landscape_credential_view_pin_or_password_emergency_call_button.png
+++ /dev/null
Binary files differ
diff --git a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/light_portrait_credential_view_pin_or_password_emergency_call_button.png b/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/light_portrait_credential_view_pin_or_password_emergency_call_button.png
deleted file mode 100644
index 14a799c..0000000
--- a/vendor/unbundled_google/packages/SystemUIGoogle/tests/screenshotBiometrics/assets/tablet/light_portrait_credential_view_pin_or_password_emergency_call_button.png
+++ /dev/null
Binary files differ