diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 8d480e5bc8f4519edd5a0ae20faf45aea691f623..de07fdde6267af63bedb7379d1dfd7aa29c98770 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -16834,6 +16834,10 @@ package android.telephony.satellite {
     field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull public static final android.os.Parcelable.Creator<android.telephony.satellite.SatelliteCapabilities> CREATOR;
   }
 
+  @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public interface SatelliteCapabilitiesCallback {
+    method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSatelliteCapabilitiesChanged(@NonNull android.telephony.satellite.SatelliteCapabilities);
+  }
+
   @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public final class SatelliteDatagram implements android.os.Parcelable {
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public int describeContents();
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull public byte[] getSatelliteDatagram();
@@ -16852,6 +16856,7 @@ package android.telephony.satellite {
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void pollPendingSatelliteDatagrams(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionSatelliteService(@NonNull String, @NonNull byte[], @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForNtnSignalStrengthChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.NtnSignalStrengthCallback);
+    method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteCapabilitiesChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCapabilitiesCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteDatagram(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteDatagramCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteModemStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteStateCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteProvisionStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteProvisionStateCallback);
@@ -16872,6 +16877,7 @@ package android.telephony.satellite {
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void startSatelliteTransmissionUpdates(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull android.telephony.satellite.SatelliteTransmissionUpdateCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void stopSatelliteTransmissionUpdates(@NonNull android.telephony.satellite.SatelliteTransmissionUpdateCallback, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForNtnSignalStrengthChanged(@NonNull android.telephony.satellite.NtnSignalStrengthCallback);
+    method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteCapabilitiesChanged(@NonNull android.telephony.satellite.SatelliteCapabilitiesCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteDatagram(@NonNull android.telephony.satellite.SatelliteDatagramCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteModemStateChanged(@NonNull android.telephony.satellite.SatelliteStateCallback);
     method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteProvisionStateChanged(@NonNull android.telephony.satellite.SatelliteProvisionStateCallback);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4c70c914ff211caa49636d389a727ac106e90089..3df11f6f5691f3e27468383eccfa50a2d85be351 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -81,6 +81,9 @@ import android.app.Activity;
 import android.app.IServiceConnection;
 import android.app.KeyguardManager;
 import android.app.admin.SecurityLog.SecurityEvent;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -9117,6 +9120,19 @@ public class DevicePolicyManager {
         return false;
     }
 
+    /**
+     * For apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above, the
+     * {@link #isDeviceOwnerApp} method will use the user contained within the
+     * context.
+     * For apps targeting an SDK version <em>below</em> this, the user of the calling process will
+     * be used (Process.myUserHandle()).
+     *
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
+    public static final long IS_DEVICE_OWNER_USER_AWARE = 307233716L;
+
     /**
      * Used to determine if a particular package has been registered as a Device Owner app.
      * A device owner app is a special device admin that cannot be deactivated by the user, once
@@ -9130,8 +9146,13 @@ public class DevicePolicyManager {
      * app, if any.
      * @return whether or not the package is registered as the device owner app.
      */
+    @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
     public boolean isDeviceOwnerApp(String packageName) {
         throwIfParentInstance("isDeviceOwnerApp");
+        if (android.permission.flags.Flags.roleControllerInSystemServer()
+                && CompatChanges.isChangeEnabled(IS_DEVICE_OWNER_USER_AWARE)) {
+            return isDeviceOwnerAppOnContextUser(packageName);
+        }
         return isDeviceOwnerAppOnCallingUser(packageName);
     }
 
@@ -9192,6 +9213,24 @@ public class DevicePolicyManager {
         return packageName.equals(deviceOwner.getPackageName());
     }
 
+    private boolean isDeviceOwnerAppOnContextUser(String packageName) {
+        if (packageName == null) {
+            return false;
+        }
+        ComponentName deviceOwner = null;
+        if (mService != null) {
+            try {
+                deviceOwner = mService.getDeviceOwnerComponentOnUser(myUserId());
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+        if (deviceOwner == null) {
+            return false;
+        }
+        return packageName.equals(deviceOwner.getPackageName());
+    }
+
     private ComponentName getDeviceOwnerComponentInner(boolean callingUserOnly) {
         if (mService != null) {
             try {
@@ -9608,6 +9647,7 @@ public class DevicePolicyManager {
      * @param packageName The package name of the app to compare with the registered profile owner.
      * @return Whether or not the package is registered as the profile owner.
      */
+    @UserHandleAware
     public boolean isProfileOwnerApp(String packageName) {
         throwIfParentInstance("isProfileOwnerApp");
         if (mService != null) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 6fe40be041cc3c54ffdaa087d78b431079bd2866..575fa4cac0b8d9f3fc088ec0ae1aa6739f2ea160 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -179,6 +179,7 @@ interface IDevicePolicyManager {
 
     boolean setDeviceOwner(in ComponentName who, int userId, boolean setProfileOwnerOnCurrentUserIfNecessary);
     ComponentName getDeviceOwnerComponent(boolean callingUserOnly);
+    ComponentName getDeviceOwnerComponentOnUser(int userId);
     boolean hasDeviceOwner();
     String getDeviceOwnerName();
     void clearDeviceOwner(String packageName);
diff --git a/core/java/android/content/pm/SigningInfo.java b/core/java/android/content/pm/SigningInfo.java
index 543703e734c2c34f7d049c7a7923bbf2bc3f02f0..a40770484ca560459ab4d6a583e216a12d85e606 100644
--- a/core/java/android/content/pm/SigningInfo.java
+++ b/core/java/android/content/pm/SigningInfo.java
@@ -190,9 +190,11 @@ public final class SigningInfo implements Parcelable {
         mSigningDetails.writeToParcel(dest, parcelableFlags);
     }
 
-    /* @hide */
+    /**
+     *  @hide
+     */
     @NonNull
-    SigningDetails getSigningDetails() {
+    public SigningDetails getSigningDetails() {
         return mSigningDetails;
     }
 
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 0df7c2047bc1045e653e910b2551bf1706f09aa2..f24c3f59155ac30e6cbb728d73dc05a39a410fd1 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -1,5 +1,6 @@
 adamp@google.com
 asc@google.com
+austindelgado@google.com
 cinek@google.com
 dsandler@android.com
 dsandler@google.com
@@ -8,6 +9,7 @@ hackbod@android.com
 hackbod@google.com
 ilyamaty@google.com
 jaggies@google.com
+jbolinger@google.com
 jsharkey@android.com
 jsharkey@google.com
 juliacr@google.com
diff --git a/media/java/android/media/tv/ad/TvAdServiceInfo.aidl b/media/java/android/media/tv/ad/TvAdServiceInfo.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..a5e631fc8426e5fd59f262b3832005bcaccbcfc5
--- /dev/null
+++ b/media/java/android/media/tv/ad/TvAdServiceInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.media.tv.ad;
+
+parcelable TvAdServiceInfo;
diff --git a/media/java/android/media/tv/ad/TvAdServiceInfo.java b/media/java/android/media/tv/ad/TvAdServiceInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed04f1f9058c98a7fd12da98fae875d43352ae22
--- /dev/null
+++ b/media/java/android/media/tv/ad/TvAdServiceInfo.java
@@ -0,0 +1,194 @@
+/*
+ * 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.media.tv.ad;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import androidx.annotation.NonNull;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is used to specify meta information of a TV AD service.
+ * @hide
+ */
+public final class TvAdServiceInfo implements Parcelable {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "TvAdServiceInfo";
+
+    private static final String XML_START_TAG_NAME = "tv-ad-service";
+
+    private final ResolveInfo mService;
+    private final String mId;
+    private final List<String> mTypes = new ArrayList<>();
+
+    /**
+     * Constructs a TvAdServiceInfo object.
+     *
+     * @param context the application context
+     * @param component the component name of the TvAdService
+     */
+    public TvAdServiceInfo(@NonNull Context context, @NonNull ComponentName component) {
+        if (context == null) {
+            throw new IllegalArgumentException("context cannot be null.");
+        }
+        // TODO: use a constant
+        Intent intent = new Intent("android.media.tv.ad.TvAdService").setComponent(component);
+        ResolveInfo resolveInfo = context.getPackageManager().resolveService(
+                intent, PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+        if (resolveInfo == null) {
+            throw new IllegalArgumentException("Invalid component. Can't find the service.");
+        }
+
+        ComponentName componentName = new ComponentName(resolveInfo.serviceInfo.packageName,
+                resolveInfo.serviceInfo.name);
+        String id;
+        id = generateAdServiceId(componentName);
+        List<String> types = new ArrayList<>();
+        parseServiceMetadata(resolveInfo, context, types);
+
+        mService = resolveInfo;
+        mId = id;
+    }
+
+    private TvAdServiceInfo(ResolveInfo service, String id, List<String> types) {
+        mService = service;
+        mId = id;
+        mTypes.addAll(types);
+    }
+
+    private TvAdServiceInfo(@NonNull Parcel in) {
+        mService = ResolveInfo.CREATOR.createFromParcel(in);
+        mId = in.readString();
+        in.readStringList(mTypes);
+    }
+
+    public static final Creator<TvAdServiceInfo> CREATOR = new Creator<TvAdServiceInfo>() {
+        @Override
+        public TvAdServiceInfo createFromParcel(Parcel in) {
+            return new TvAdServiceInfo(in);
+        }
+
+        @Override
+        public TvAdServiceInfo[] newArray(int size) {
+            return new TvAdServiceInfo[size];
+        }
+    };
+
+    /**
+     * Returns a unique ID for this TV AD service. The ID is generated from the package and class
+     * name implementing the TV AD service.
+     */
+    @NonNull
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the component of the TV AD service.
+     * @hide
+     */
+    public ComponentName getComponent() {
+        return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
+    }
+
+    /**
+     * Returns the information of the service that implements this AD service.
+     */
+    @Nullable
+    public ServiceInfo getServiceInfo() {
+        return mService.serviceInfo;
+    }
+
+    /**
+     * Gets supported TV AD types.
+     */
+    @NonNull
+    public List<String> getSupportedTypes() {
+        return mTypes;
+    }
+
+    private static String generateAdServiceId(ComponentName name) {
+        return name.flattenToShortString();
+    }
+
+    private static void parseServiceMetadata(
+            ResolveInfo resolveInfo, Context context, List<String> types) {
+        ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+        PackageManager pm = context.getPackageManager();
+        // TODO: use constant for the metadata
+        try (XmlResourceParser parser =
+                     serviceInfo.loadXmlMetaData(pm, "android.media.tv.ad.service")) {
+            if (parser == null) {
+                throw new IllegalStateException(
+                        "No " + "android.media.tv.ad.service"
+                                + " meta-data found for " + serviceInfo.name);
+            }
+
+            Resources resources = pm.getResourcesForApplication(serviceInfo.applicationInfo);
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && type != XmlPullParser.START_TAG) {
+                // move to the START_TAG
+            }
+
+            String nodeName = parser.getName();
+            if (!XML_START_TAG_NAME.equals(nodeName)) {
+                throw new IllegalStateException("Meta-data does not start with "
+                        + XML_START_TAG_NAME + " tag for " + serviceInfo.name);
+            }
+
+            // TODO: parse attributes
+        } catch (IOException | XmlPullParserException e) {
+            throw new IllegalStateException(
+                    "Failed reading meta-data for " + serviceInfo.packageName, e);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalStateException("No resources found for " + serviceInfo.packageName, e);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        mService.writeToParcel(dest, flags);
+        dest.writeString(mId);
+        dest.writeStringList(mTypes);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
index 80be008dbd3a5905c09d2c6c77ad1b39fe05b7e7..e8b16db10da5ca3d1c74d5ebb0501c0b680b146c 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
@@ -65,7 +65,7 @@ interface AuthenticationRepository {
      * Note that the length of the PIN is also important to take into consideration, please see
      * [hintedPinLength].
      */
-    val isAutoConfirmEnabled: StateFlow<Boolean>
+    val isAutoConfirmFeatureEnabled: StateFlow<Boolean>
 
     /**
      * The exact length a PIN should be for us to enable PIN length hinting.
@@ -152,14 +152,14 @@ class AuthenticationRepositoryImpl
 @Inject
 constructor(
     @Application private val applicationScope: CoroutineScope,
-    private val getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
+    private val getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>,
     private val userRepository: UserRepository,
     private val lockPatternUtils: LockPatternUtils,
     broadcastDispatcher: BroadcastDispatcher,
 ) : AuthenticationRepository {
 
-    override val isAutoConfirmEnabled: StateFlow<Boolean> =
+    override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> =
         refreshingFlow(
             initialValue = false,
             getFreshValue = lockPatternUtils::isAutoPinConfirmEnabled,
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 345f15c5c6ad7668b9dd2869fe100d059896f75d..22b44d56fe9be270620cd5d23addbb91a02dadbf 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
@@ -42,6 +42,7 @@ import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
@@ -103,9 +104,29 @@ constructor(
                 initialValue = throttling.value.remainingMs > 0,
             )
 
+    /**
+     * Whether the auto confirm feature is enabled for the currently-selected user.
+     *
+     * Note that the length of the PIN is also important to take into consideration, please see
+     * [hintedPinLength].
+     *
+     * During throttling, this is always disabled (`false`).
+     */
+    val isAutoConfirmEnabled: StateFlow<Boolean> =
+        combine(repository.isAutoConfirmFeatureEnabled, isThrottled) { featureEnabled, isThrottled
+                ->
+                // Disable auto-confirm during throttling.
+                featureEnabled && !isThrottled
+            }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = false,
+            )
+
     /** The length of the hinted PIN, or `null` if pin length hint should not be shown. */
     val hintedPinLength: StateFlow<Int?> =
-        repository.isAutoConfirmEnabled
+        isAutoConfirmEnabled
             .map { isAutoConfirmEnabled ->
                 repository.getPinLength().takeIf {
                     isAutoConfirmEnabled && it == repository.hintedPinLength
@@ -119,9 +140,6 @@ constructor(
                 initialValue = null,
             )
 
-    /** Whether the auto confirm feature is enabled for the currently-selected user. */
-    val isAutoConfirmEnabled: StateFlow<Boolean> = repository.isAutoConfirmEnabled
-
     /** Whether the pattern should be visible for the currently-selected user. */
     val isPatternVisible: StateFlow<Boolean> = repository.isPatternVisible
 
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
index 6b27ce011e16c3b5c9c1beae4552b78f61288a6f..f7fee96c83c2256005c504bc88d3f50b7487afc4 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
@@ -18,13 +18,11 @@ package com.android.systemui.communal.data.repository
 
 import android.appwidget.AppWidgetHost
 import android.appwidget.AppWidgetManager
-import android.appwidget.AppWidgetProviderInfo
 import android.content.BroadcastReceiver
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
-import android.content.pm.PackageManager
 import android.os.UserManager
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
@@ -32,13 +30,10 @@ import com.android.systemui.communal.data.db.CommunalItemRank
 import com.android.systemui.communal.data.db.CommunalWidgetDao
 import com.android.systemui.communal.data.db.CommunalWidgetItem
 import com.android.systemui.communal.shared.CommunalWidgetHost
-import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo
 import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.core.Logger
 import com.android.systemui.log.dagger.CommunalLog
@@ -58,9 +53,6 @@ import kotlinx.coroutines.launch
 
 /** Encapsulates the state of widgets for communal mode. */
 interface CommunalWidgetRepository {
-    /** A flow of provider info for the stopwatch widget, or null if widget is unavailable. */
-    val stopwatchAppWidgetInfo: Flow<CommunalAppWidgetInfo?>
-
     /** A flow of information about active communal widgets stored in database. */
     val communalWidgets: Flow<List<CommunalWidgetContentModel>>
 
@@ -84,15 +76,12 @@ constructor(
     communalRepository: CommunalRepository,
     private val communalWidgetHost: CommunalWidgetHost,
     private val communalWidgetDao: CommunalWidgetDao,
-    private val packageManager: PackageManager,
     private val userManager: UserManager,
     private val userTracker: UserTracker,
     @CommunalLog logBuffer: LogBuffer,
-    featureFlags: FeatureFlagsClassic,
 ) : CommunalWidgetRepository {
     companion object {
         const val TAG = "CommunalWidgetRepository"
-        const val WIDGET_LABEL = "Stopwatch"
     }
 
     private val logger = Logger(logBuffer, TAG)
@@ -100,9 +89,6 @@ constructor(
     // Whether the [AppWidgetHost] is listening for updates.
     private var isHostListening = false
 
-    // Widgets that should be rendered in communal mode.
-    private val widgets: HashMap<Int, CommunalAppWidgetInfo> = hashMapOf()
-
     private val isUserUnlocked: Flow<Boolean> =
         callbackFlow {
                 if (!communalRepository.isCommunalEnabled) {
@@ -149,25 +135,6 @@ constructor(
             }
         }
 
-    override val stopwatchAppWidgetInfo: Flow<CommunalAppWidgetInfo?> =
-        isHostActive.map { isHostActive ->
-            if (!isHostActive || !featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)) {
-                return@map null
-            }
-
-            val providerInfo =
-                appWidgetManager.installedProviders.find {
-                    it.loadLabel(packageManager).equals(WIDGET_LABEL)
-                }
-
-            if (providerInfo == null) {
-                logger.w("Cannot find app widget: $WIDGET_LABEL")
-                return@map null
-            }
-
-            return@map addStopWatchWidget(providerInfo)
-        }
-
     override val communalWidgets: Flow<List<CommunalWidgetContentModel>> =
         isHostActive.flatMapLatest { isHostActive ->
             if (!isHostActive) {
@@ -226,21 +193,4 @@ constructor(
         appWidgetHost.stopListening()
         isHostListening = false
     }
-
-    // TODO(b/306471933): remove this prototype that shows a stopwatch in the communal blueprint
-    private fun addStopWatchWidget(providerInfo: AppWidgetProviderInfo): CommunalAppWidgetInfo {
-        val existing = widgets.values.firstOrNull { it.providerInfo == providerInfo }
-        if (existing != null) {
-            return existing
-        }
-
-        val appWidgetId = appWidgetHost.allocateAppWidgetId()
-        val widget =
-            CommunalAppWidgetInfo(
-                providerInfo,
-                appWidgetId,
-            )
-        widgets[appWidgetId] = widget
-        return widget
-    }
 }
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 eb36b19972f98d0f2f717e8a169fe1c17a9ffc6c..508f52c849836788feea2c8668ef71af48dd42cb 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
@@ -23,7 +23,6 @@ import com.android.systemui.communal.data.repository.CommunalMediaRepository
 import com.android.systemui.communal.data.repository.CommunalRepository
 import com.android.systemui.communal.data.repository.CommunalWidgetRepository
 import com.android.systemui.communal.domain.model.CommunalContentModel
-import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo
 import com.android.systemui.communal.shared.model.CommunalContentSize
 import com.android.systemui.communal.shared.model.CommunalSceneKey
 import com.android.systemui.dagger.SysUISingleton
@@ -55,9 +54,6 @@ constructor(
     val isCommunalEnabled: Boolean
         get() = communalRepository.isCommunalEnabled
 
-    /** A flow of info about the widget to be displayed, or null if widget is unavailable. */
-    val appWidgetInfo: Flow<CommunalAppWidgetInfo?> = widgetRepository.stopwatchAppWidgetInfo
-
     /**
      * Target scene as requested by the underlying [SceneTransitionLayout] or through
      * [onSceneChanged].
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalWidgetViewBinder.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalWidgetViewBinder.kt
deleted file mode 100644
index 65bf4b3e69cd9f64d63ccc8c9b9556e4f0ffd573..0000000000000000000000000000000000000000
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalWidgetViewBinder.kt
+++ /dev/null
@@ -1,70 +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.communal.ui.binder
-
-import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.systemui.res.R
-import com.android.systemui.communal.ui.adapter.CommunalWidgetViewAdapter
-import com.android.systemui.communal.ui.view.CommunalWidgetWrapper
-import com.android.systemui.communal.ui.viewmodel.CommunalWidgetViewModel
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
-import com.android.systemui.keyguard.ui.view.KeyguardRootView
-import com.android.systemui.lifecycle.repeatWhenAttached
-import kotlinx.coroutines.launch
-
-/** Binds [CommunalWidgetViewModel] to the keyguard root view. */
-object CommunalWidgetViewBinder {
-
-    @JvmStatic
-    fun bind(
-        rootView: KeyguardRootView,
-        viewModel: CommunalWidgetViewModel,
-        adapter: CommunalWidgetViewAdapter,
-        keyguardBlueprintInteractor: KeyguardBlueprintInteractor,
-    ) {
-        rootView.repeatWhenAttached {
-            repeatOnLifecycle(Lifecycle.State.STARTED) {
-                launch {
-                    adapter.adapt(viewModel.appWidgetInfo).collect {
-                        val oldView =
-                            rootView.findViewById<CommunalWidgetWrapper>(
-                                R.id.communal_widget_wrapper
-                            )
-                        var dirty = false
-
-                        if (oldView != null) {
-                            rootView.removeView(oldView)
-                            dirty = true
-                        }
-
-                        if (it != null) {
-                            rootView.addView(it)
-                            dirty = true
-                        }
-
-                        if (dirty) {
-                            keyguardBlueprintInteractor.refreshBlueprint()
-                        }
-                    }
-                }
-
-                launch { viewModel.alpha.collect { rootView.alpha = it } }
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
index 702554ab4943345a927d92bb0a7f1307ea2747b0..9198c7bd7009970b16cde1a1dac3cc5384e7aa11 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.communal.ui.view.layout.blueprints
 
 import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalHubSection
-import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalWidgetSection
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
 import com.android.systemui.keyguard.shared.model.KeyguardSection
@@ -30,13 +29,11 @@ class DefaultCommunalBlueprint
 @Inject
 constructor(
     defaultCommunalHubSection: DefaultCommunalHubSection,
-    defaultCommunalWidgetSection: DefaultCommunalWidgetSection,
 ) : KeyguardBlueprint {
     override val id: String = COMMUNAL
     override val sections: List<KeyguardSection> =
         listOf(
             defaultCommunalHubSection,
-            defaultCommunalWidgetSection,
         )
 
     companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
deleted file mode 100644
index c3e8a96701ead940e461e52bc8f7d724238a3d84..0000000000000000000000000000000000000000
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt
+++ /dev/null
@@ -1,73 +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.communal.ui.view.layout.sections
-
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.constraintlayout.widget.ConstraintSet
-import androidx.constraintlayout.widget.ConstraintSet.BOTTOM
-import androidx.constraintlayout.widget.ConstraintSet.END
-import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
-import com.android.systemui.res.R
-import com.android.systemui.communal.ui.adapter.CommunalWidgetViewAdapter
-import com.android.systemui.communal.ui.binder.CommunalWidgetViewBinder
-import com.android.systemui.communal.ui.viewmodel.CommunalWidgetViewModel
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
-import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor
-import com.android.systemui.keyguard.shared.model.KeyguardSection
-import com.android.systemui.keyguard.ui.view.KeyguardRootView
-import dagger.Lazy
-import javax.inject.Inject
-
-class DefaultCommunalWidgetSection
-@Inject
-constructor(
-    private val featureFlags: FeatureFlags,
-    private val keyguardRootView: KeyguardRootView,
-    private val communalWidgetViewModel: CommunalWidgetViewModel,
-    private val communalWidgetViewAdapter: CommunalWidgetViewAdapter,
-    private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>,
-) : KeyguardSection() {
-    private val widgetAreaViewId = R.id.communal_widget_wrapper
-
-    override fun addViews(constraintLayout: ConstraintLayout) {}
-
-    override fun bindData(constraintLayout: ConstraintLayout) {
-        if (!featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)) {
-            return
-        }
-
-        CommunalWidgetViewBinder.bind(
-            keyguardRootView,
-            communalWidgetViewModel,
-            communalWidgetViewAdapter,
-            keyguardBlueprintInteractor.get(),
-        )
-    }
-
-    override fun applyConstraints(constraintSet: ConstraintSet) {
-        constraintSet.apply {
-            constrainWidth(widgetAreaViewId, WRAP_CONTENT)
-            constrainHeight(widgetAreaViewId, WRAP_CONTENT)
-            connect(widgetAreaViewId, BOTTOM, PARENT_ID, BOTTOM)
-            connect(widgetAreaViewId, END, PARENT_ID, END)
-        }
-    }
-
-    override fun removeViews(constraintLayout: ConstraintLayout) {}
-}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalWidgetViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalWidgetViewModel.kt
deleted file mode 100644
index d7bbea64332e8c840445ba0771a19e6a327f7530..0000000000000000000000000000000000000000
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalWidgetViewModel.kt
+++ /dev/null
@@ -1,38 +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.communal.ui.viewmodel
-
-import com.android.systemui.communal.domain.interactor.CommunalInteractor
-import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel
-import javax.inject.Inject
-import kotlinx.coroutines.flow.Flow
-
-@SysUISingleton
-class CommunalWidgetViewModel
-@Inject
-constructor(
-    communalInteractor: CommunalInteractor,
-    keyguardBottomAreaViewModel: KeyguardBottomAreaViewModel,
-) {
-    /** An observable for the alpha level for the communal widget area. */
-    val alpha: Flow<Float> = keyguardBottomAreaViewModel.alpha
-
-    /** A flow of info about the widget to be displayed, or null if widget is unavailable. */
-    val appWidgetInfo: Flow<CommunalAppWidgetInfo?> = communalInteractor.appWidgetInfo
-}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index b237b87987a4da201a9511b2cf7a719587c978b4..d64a1312ac66a22f1f9b3633adaac2a06b2b4f9b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -239,8 +239,7 @@ object Flags {
 
     /** Provide new auth messages on the bouncer. */
     // TODO(b/277961132): Tracking bug.
-    @JvmField val REVAMPED_BOUNCER_MESSAGES = unreleasedFlag("revamped_bouncer_messages",
-            teamfood = true)
+    @JvmField val REVAMPED_BOUNCER_MESSAGES = unreleasedFlag("revamped_bouncer_messages")
 
     /** Keyguard Migration */
 
@@ -255,9 +254,6 @@ object Flags {
     // TODO(b/287268101): Tracking bug.
     @JvmField val TRANSIT_CLOCK = releasedFlag("lockscreen_custom_transit_clock")
 
-    // TODO(b/288276738): Tracking bug.
-    @JvmField val WIDGET_ON_KEYGUARD = unreleasedFlag("widget_on_keyguard")
-
     /** Migrate the NSSL to the a sibling to both the panel and keyguard root view. */
     // TODO(b/288074305): Tracking bug.
     @JvmField val MIGRATE_NSSL = unreleasedFlag("migrate_nssl")
@@ -776,9 +772,4 @@ object Flags {
     @JvmField
     val COMMUNAL_SERVICE_ENABLED = resourceBooleanFlag(R.bool.config_communalServiceEnabled,
         "communal_service_enabled")
-
-    // TODO(b/303131306): Tracking Bug
-    /** Whether communal hub features are enabled. */
-    @JvmField
-    val COMMUNAL_HUB = unreleasedFlag("communal_hub")
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt
index 30b87cc9e662136da1717b372182af033417fa27..f9e0b160acd694d172478cfdbb4eb530eb61cf07 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt
@@ -18,7 +18,10 @@ package com.android.systemui.qs.tiles.viewmodel
 
 import android.content.Context
 import android.service.quicksettings.Tile
+import android.view.View
+import android.widget.Switch
 import com.android.systemui.common.shared.model.Icon
+import kotlin.reflect.KClass
 
 /**
  * Represents current a state of the tile to be displayed in on the view. Consider using
@@ -111,7 +114,7 @@ data class QSTileState(
         var stateDescription: CharSequence? = null
         var sideViewIcon: SideViewIcon = SideViewIcon.None
         var enabledState: EnabledState = EnabledState.ENABLED
-        var expandedAccessibilityClassName: String? = null
+        var expandedAccessibilityClass: KClass<out View>? = Switch::class
 
         fun build(): QSTileState =
             QSTileState(
@@ -124,7 +127,7 @@ data class QSTileState(
                 stateDescription,
                 sideViewIcon,
                 enabledState,
-                expandedAccessibilityClassName,
+                expandedAccessibilityClass?.qualifiedName,
             )
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
index 6ac84bc503a2ae283ba1d0e6db028d7471f61e19..0c06808b10c9c897861b9f8feddd7ceae8d28e93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
@@ -100,12 +100,12 @@ class AuthenticationRepositoryTest : SysuiTestCase() {
         }
 
     @Test
-    fun isAutoConfirmEnabled() =
+    fun isAutoConfirmFeatureEnabled() =
         testScope.runTest {
             whenever(lockPatternUtils.isAutoPinConfirmEnabled(USER_INFOS[0].id)).thenReturn(true)
             whenever(lockPatternUtils.isAutoPinConfirmEnabled(USER_INFOS[1].id)).thenReturn(false)
 
-            val values by collectValues(underTest.isAutoConfirmEnabled)
+            val values by collectValues(underTest.isAutoConfirmFeatureEnabled)
             assertThat(values.first()).isFalse()
             assertThat(values.last()).isTrue()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index 2f5f4606c5f059c035499a932a86af823db5efcc..103f2b8ac3136de2414c6db57487e7004aee7bdc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -213,11 +213,14 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     @Test
     fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNullAndHasNoEffect() =
         testScope.runTest {
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             val isThrottled by collectLastValue(underTest.isThrottled)
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
-                setAutoConfirmEnabled(true)
+                setAutoConfirmFeatureEnabled(true)
             }
+            assertThat(isAutoConfirmEnabled).isTrue()
+
             assertThat(
                     underTest.authenticate(
                         FakeAuthenticationRepository.DEFAULT_PIN.toMutableList().apply {
@@ -233,10 +236,13 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     @Test
     fun tryAutoConfirm_withAutoConfirmWrongPinCorrectLength_returnsFalseAndDoesNotUnlockDevice() =
         testScope.runTest {
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
-                setAutoConfirmEnabled(true)
+                setAutoConfirmFeatureEnabled(true)
             }
+            assertThat(isAutoConfirmEnabled).isTrue()
+
             assertThat(
                     underTest.authenticate(
                         FakeAuthenticationRepository.DEFAULT_PIN.map { it + 1 },
@@ -251,10 +257,13 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     @Test
     fun tryAutoConfirm_withAutoConfirmLongerPin_returnsFalseAndDoesNotUnlockDevice() =
         testScope.runTest {
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
-                setAutoConfirmEnabled(true)
+                setAutoConfirmFeatureEnabled(true)
             }
+            assertThat(isAutoConfirmEnabled).isTrue()
+
             assertThat(
                     underTest.authenticate(
                         FakeAuthenticationRepository.DEFAULT_PIN + listOf(7),
@@ -269,10 +278,13 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     @Test
     fun tryAutoConfirm_withAutoConfirmCorrectPin_returnsTrueAndUnlocksDevice() =
         testScope.runTest {
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
-                setAutoConfirmEnabled(true)
+                setAutoConfirmFeatureEnabled(true)
             }
+            assertThat(isAutoConfirmEnabled).isTrue()
+
             assertThat(
                     underTest.authenticate(
                         FakeAuthenticationRepository.DEFAULT_PIN,
@@ -284,12 +296,36 @@ class AuthenticationInteractorTest : SysuiTestCase() {
             assertThat(isUnlocked).isTrue()
         }
 
+    @Test
+    fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNullAndHasNoEffects() =
+        testScope.runTest {
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
+            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
+            val hintedPinLength by collectLastValue(underTest.hintedPinLength)
+            utils.authenticationRepository.apply {
+                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAutoConfirmFeatureEnabled(true)
+                setThrottleDuration(42)
+            }
+
+            val authResult =
+                underTest.authenticate(
+                    FakeAuthenticationRepository.DEFAULT_PIN,
+                    tryAutoConfirm = true
+                )
+
+            assertThat(authResult).isEqualTo(AuthenticationResult.SKIPPED)
+            assertThat(isAutoConfirmEnabled).isFalse()
+            assertThat(isUnlocked).isFalse()
+            assertThat(hintedPinLength).isNull()
+        }
+
     @Test
     fun tryAutoConfirm_withoutAutoConfirmButCorrectPin_returnsNullAndHasNoEffects() =
         testScope.runTest {
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
-                setAutoConfirmEnabled(false)
+                setAutoConfirmFeatureEnabled(false)
             }
             assertThat(
                     underTest.authenticate(
@@ -416,7 +452,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
             val hintedPinLength by collectLastValue(underTest.hintedPinLength)
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
-                setAutoConfirmEnabled(false)
+                setAutoConfirmFeatureEnabled(false)
             }
 
             assertThat(hintedPinLength).isNull()
@@ -433,7 +469,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
                         repeat(utils.authenticationRepository.hintedPinLength - 1) { add(it + 1) }
                     }
                 )
-                setAutoConfirmEnabled(true)
+                setAutoConfirmFeatureEnabled(true)
             }
 
             assertThat(hintedPinLength).isNull()
@@ -445,7 +481,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
             val hintedPinLength by collectLastValue(underTest.hintedPinLength)
             utils.authenticationRepository.apply {
                 setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
-                setAutoConfirmEnabled(true)
+                setAutoConfirmFeatureEnabled(true)
                 overrideCredential(
                     buildList {
                         repeat(utils.authenticationRepository.hintedPinLength) { add(it + 1) }
@@ -467,7 +503,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
                         repeat(utils.authenticationRepository.hintedPinLength + 1) { add(it + 1) }
                     }
                 )
-                setAutoConfirmEnabled(true)
+                setAutoConfirmFeatureEnabled(true)
             }
 
             assertThat(hintedPinLength).isNull()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index 915661b8a77690e5f703405c577d7752b0031175..577539620ee3a3eb33c26b7b0d89dd19210a4cb5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -110,12 +110,14 @@ class BouncerInteractorTest : SysuiTestCase() {
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(underTest.message)
+            val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
 
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             runCurrent()
-            utils.authenticationRepository.setAutoConfirmEnabled(true)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
             utils.deviceEntryRepository.setUnlocked(false)
             underTest.showOrUnlockDevice()
+            assertThat(isAutoConfirmEnabled).isTrue()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
             underTest.clearMessage()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index 3ddac7e1ad1dfbc97edcb9ff187dbc7a1e1fbe0a..e07c0b87bc7959062b98a5f62e7e0a317874313a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -247,7 +247,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
     fun onAutoConfirm_whenCorrect() =
         testScope.runTest {
             val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            utils.authenticationRepository.setAutoConfirmEnabled(true)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
             lockDeviceAndOpenPinBouncer()
 
             FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -263,7 +263,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
             val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(bouncerViewModel.message)
             val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
-            utils.authenticationRepository.setAutoConfirmEnabled(true)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
             lockDeviceAndOpenPinBouncer()
 
             FakeAuthenticationRepository.DEFAULT_PIN.dropLast(1).forEach { digit ->
@@ -323,7 +323,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
         testScope.runTest {
             val backspaceButtonAppearance by collectLastValue(underTest.backspaceButtonAppearance)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            utils.authenticationRepository.setAutoConfirmEnabled(true)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
 
             assertThat(backspaceButtonAppearance).isEqualTo(ActionButtonAppearance.Hidden)
         }
@@ -333,7 +333,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
         testScope.runTest {
             val backspaceButtonAppearance by collectLastValue(underTest.backspaceButtonAppearance)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            utils.authenticationRepository.setAutoConfirmEnabled(true)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
 
             underTest.onPinButtonClicked(1)
 
@@ -355,7 +355,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
         testScope.runTest {
             val confirmButtonAppearance by collectLastValue(underTest.confirmButtonAppearance)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            utils.authenticationRepository.setAutoConfirmEnabled(true)
+            utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
 
             assertThat(confirmButtonAppearance).isEqualTo(ActionButtonAppearance.Hidden)
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
index ca8316dce10ec58824c303253af8d21021b71e15..28fae819de98fdfbaf91d88b834614aa4fb6b436 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
@@ -21,7 +21,6 @@ import android.appwidget.AppWidgetManager
 import android.appwidget.AppWidgetProviderInfo
 import android.content.BroadcastReceiver
 import android.content.ComponentName
-import android.content.pm.PackageManager
 import android.os.UserHandle
 import android.os.UserManager
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -34,8 +33,6 @@ import com.android.systemui.communal.data.db.CommunalWidgetItem
 import com.android.systemui.communal.shared.CommunalWidgetHost
 import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FeatureFlagsClassic
-import com.android.systemui.flags.Flags
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.core.FakeLogBuffer
 import com.android.systemui.res.R
@@ -72,16 +69,12 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
 
     @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher
 
-    @Mock private lateinit var packageManager: PackageManager
-
     @Mock private lateinit var userManager: UserManager
 
     @Mock private lateinit var userHandle: UserHandle
 
     @Mock private lateinit var userTracker: UserTracker
 
-    @Mock private lateinit var featureFlags: FeatureFlagsClassic
-
     @Mock private lateinit var stopwatchProviderInfo: AppWidgetProviderInfo
 
     @Mock private lateinit var providerInfoA: AppWidgetProviderInfo
@@ -113,13 +106,13 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
         communalRepository = FakeCommunalRepository()
 
         communalEnabled(true)
-        widgetOnKeyguardEnabled(true)
         setAppWidgetIds(emptyList())
 
         overrideResource(R.array.config_communalWidgetAllowlist, fakeAllowlist.toTypedArray())
 
         whenever(stopwatchProviderInfo.loadLabel(any())).thenReturn("Stopwatch")
         whenever(userTracker.userHandle).thenReturn(userHandle)
+        whenever(communalWidgetDao.getWidgets()).thenReturn(flowOf(emptyMap()))
     }
 
     @Test
@@ -213,7 +206,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
         testScope.runTest {
             communalEnabled(false)
             val repository = initCommunalWidgetRepository()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
+            collectLastValue(repository.communalWidgets)()
             verifyBroadcastReceiverNeverRegistered()
         }
 
@@ -222,7 +215,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
         testScope.runTest {
             userUnlocked(true)
             val repository = initCommunalWidgetRepository()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
+            collectLastValue(repository.communalWidgets)()
             verifyBroadcastReceiverNeverRegistered()
         }
 
@@ -231,7 +224,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
         testScope.runTest {
             userUnlocked(false)
             val repository = initCommunalWidgetRepository()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
+            collectLastValue(repository.communalWidgets)()
             verifyBroadcastReceiverRegistered()
         }
 
@@ -241,7 +234,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
             userUnlocked(false)
             val repository = initCommunalWidgetRepository()
 
-            val job = launch { repository.stopwatchAppWidgetInfo.collect() }
+            val job = launch { repository.communalWidgets.collect() }
             runCurrent()
             val receiver = broadcastReceiverUpdate()
 
@@ -251,54 +244,17 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
             verify(broadcastDispatcher).unregisterReceiver(receiver)
         }
 
-    @Test
-    fun stopwatch_whenUserUnlocks_receiveProviderInfo() =
-        testScope.runTest {
-            userUnlocked(false)
-            val repository = initCommunalWidgetRepository()
-            val lastStopwatchProviderInfo = collectLastValue(repository.stopwatchAppWidgetInfo)
-            assertThat(lastStopwatchProviderInfo()).isNull()
-
-            userUnlocked(true)
-            installedProviders(listOf(stopwatchProviderInfo))
-            broadcastReceiverUpdate()
-
-            assertThat(lastStopwatchProviderInfo()?.providerInfo).isEqualTo(stopwatchProviderInfo)
-        }
-
-    @Test
-    fun stopwatch_userUnlockedButWidgetNotInstalled_noProviderInfo() =
-        testScope.runTest {
-            userUnlocked(true)
-            installedProviders(listOf())
-
-            val repository = initCommunalWidgetRepository()
-
-            val lastStopwatchProviderInfo = collectLastValue(repository.stopwatchAppWidgetInfo)
-            assertThat(lastStopwatchProviderInfo()).isNull()
-        }
-
-    @Test
-    fun appWidgetId_providerInfoAvailable_allocateAppWidgetId() =
-        testScope.runTest {
-            userUnlocked(true)
-            installedProviders(listOf(stopwatchProviderInfo))
-            val repository = initCommunalWidgetRepository()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
-            verify(appWidgetHost).allocateAppWidgetId()
-        }
-
     @Test
     fun appWidgetHost_userUnlocked_startListening() =
         testScope.runTest {
             userUnlocked(false)
             val repository = initCommunalWidgetRepository()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
+            collectLastValue(repository.communalWidgets)()
             verify(appWidgetHost, Mockito.never()).startListening()
 
             userUnlocked(true)
             broadcastReceiverUpdate()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
+            collectLastValue(repository.communalWidgets)()
 
             verify(appWidgetHost).startListening()
         }
@@ -308,18 +264,18 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
         testScope.runTest {
             userUnlocked(false)
             val repository = initCommunalWidgetRepository()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
+            collectLastValue(repository.communalWidgets)()
 
             userUnlocked(true)
             broadcastReceiverUpdate()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
+            collectLastValue(repository.communalWidgets)()
 
             verify(appWidgetHost).startListening()
             verify(appWidgetHost, Mockito.never()).stopListening()
 
             userUnlocked(false)
             broadcastReceiverUpdate()
-            collectLastValue(repository.stopwatchAppWidgetInfo)()
+            collectLastValue(repository.communalWidgets)()
 
             verify(appWidgetHost).stopListening()
         }
@@ -334,11 +290,9 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
             communalRepository,
             communalWidgetHost,
             communalWidgetDao,
-            packageManager,
             userManager,
             userTracker,
             logBuffer,
-            featureFlags,
         )
     }
 
@@ -385,10 +339,6 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() {
         communalRepository.setIsCommunalEnabled(enabled)
     }
 
-    private fun widgetOnKeyguardEnabled(enabled: Boolean) {
-        whenever(featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)).thenReturn(enabled)
-    }
-
     private fun userUnlocked(userUnlocked: Boolean) {
         whenever(userManager.isUserUnlockingOrUnlocked(userHandle)).thenReturn(userUnlocked)
     }
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 08d54c001d11e23b973299b7716e07421a56fa78..a6c4f1929333c394331345a508eb8546feaf5df2 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
@@ -29,7 +29,6 @@ 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.domain.model.CommunalContentModel
-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.coroutines.collectLastValue
@@ -45,7 +44,6 @@ 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.Mockito.mock
 import org.mockito.MockitoAnnotations
 
@@ -53,8 +51,6 @@ import org.mockito.MockitoAnnotations
 @OptIn(ExperimentalCoroutinesApi::class)
 @RunWith(AndroidJUnit4::class)
 class CommunalInteractorTest : SysuiTestCase() {
-    @Mock private lateinit var stopwatchAppWidgetInfo: CommunalAppWidgetInfo
-
     private lateinit var testScope: TestScope
 
     private lateinit var tutorialRepository: FakeCommunalTutorialRepository
@@ -84,18 +80,6 @@ class CommunalInteractorTest : SysuiTestCase() {
         underTest = withDeps.communalInteractor
     }
 
-    @Test
-    fun appWidgetInfoFlow() =
-        testScope.runTest {
-            val lastAppWidgetInfo = collectLastValue(underTest.appWidgetInfo)
-            runCurrent()
-            assertThat(lastAppWidgetInfo()).isNull()
-
-            widgetRepository.setStopwatchAppWidgetInfo(stopwatchAppWidgetInfo)
-            runCurrent()
-            assertThat(lastAppWidgetInfo()).isEqualTo(stopwatchAppWidgetInfo)
-        }
-
     @Test
     fun communalEnabled() =
         testScope.runTest {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
index 33a666700877ecf40585b15ff0d6b5312033c89e..a49629252520a5742cc3e90ff925cd43bf2ac83f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt
@@ -7,7 +7,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalHubSection
-import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalWidgetSection
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -20,14 +19,13 @@ import org.mockito.MockitoAnnotations
 @SmallTest
 class DefaultCommunalBlueprintTest : SysuiTestCase() {
     @Mock private lateinit var hubSection: DefaultCommunalHubSection
-    @Mock private lateinit var widgetSection: DefaultCommunalWidgetSection
 
     private lateinit var blueprint: DefaultCommunalBlueprint
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        blueprint = DefaultCommunalBlueprint(hubSection, widgetSection)
+        blueprint = DefaultCommunalBlueprint(hubSection)
     }
 
     @Test
@@ -35,7 +33,6 @@ class DefaultCommunalBlueprintTest : SysuiTestCase() {
         val constraintLayout = ConstraintLayout(context, null)
         blueprint.replaceViews(null, constraintLayout)
         verify(hubSection).addViews(constraintLayout)
-        verify(widgetSection).addViews(constraintLayout)
     }
 
     @Test
@@ -43,6 +40,5 @@ class DefaultCommunalBlueprintTest : SysuiTestCase() {
         val cs = ConstraintSet()
         blueprint.applyConstraints(cs)
         verify(hubSection).applyConstraints(cs)
-        verify(widgetSection).applyConstraints(cs)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
index b5e7e2c14211e4aa2da99228279a0923dab6a50e..92c2d743c26255039112962a7cb5dbf84fcb3f65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt
@@ -130,7 +130,7 @@ class QSTileLoggerTest : SysuiTestCase() {
                     "sd=null, " +
                     "svi=None, " +
                     "enabled=ENABLED, " +
-                    "a11y=null" +
+                    "a11y=android.widget.Switch" +
                     "], " +
                     "data=test_data"
             )
@@ -154,7 +154,7 @@ class QSTileLoggerTest : SysuiTestCase() {
                     "sd=null, " +
                     "svi=None, " +
                     "enabled=ENABLED, " +
-                    "a11y=null], " +
+                    "a11y=android.widget.Switch], " +
                     "data=test_data"
             )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
index ddfe79aedce647074c182d18eb7a19dd2a719961..81c5d9c248f3194ff9c86e5bb9649eaef02b2501 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
@@ -41,8 +41,9 @@ class FakeAuthenticationRepository(
     private val currentTime: () -> Long,
 ) : AuthenticationRepository {
 
-    private val _isAutoConfirmEnabled = MutableStateFlow(false)
-    override val isAutoConfirmEnabled: StateFlow<Boolean> = _isAutoConfirmEnabled.asStateFlow()
+    private val _isAutoConfirmFeatureEnabled = MutableStateFlow(false)
+    override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> =
+        _isAutoConfirmFeatureEnabled.asStateFlow()
 
     override val hintedPinLength: Int = HINTING_PIN_LENGTH
 
@@ -98,8 +99,8 @@ class FakeAuthenticationRepository(
         _throttling.value = throttlingModel
     }
 
-    fun setAutoConfirmEnabled(isEnabled: Boolean) {
-        _isAutoConfirmEnabled.value = isEnabled
+    fun setAutoConfirmFeatureEnabled(isEnabled: Boolean) {
+        _isAutoConfirmFeatureEnabled.value = isEnabled
     }
 
     override suspend fun setThrottleDuration(durationMs: Int) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
index 8a2ff50d8a323b8bebed5106477849e263758c63..c6f12e2014b36ccd9264c89492ad1ba1552e18cc 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
@@ -1,22 +1,14 @@
 package com.android.systemui.communal.data.repository
 
-import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo
 import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 
 /** Fake implementation of [CommunalWidgetRepository] */
 class FakeCommunalWidgetRepository : CommunalWidgetRepository {
-    private val _stopwatchAppWidgetInfo = MutableStateFlow<CommunalAppWidgetInfo?>(null)
-    override val stopwatchAppWidgetInfo: Flow<CommunalAppWidgetInfo?> = _stopwatchAppWidgetInfo
-
     private val _communalWidgets = MutableStateFlow<List<CommunalWidgetContentModel>>(emptyList())
     override val communalWidgets: Flow<List<CommunalWidgetContentModel>> = _communalWidgets
 
-    fun setStopwatchAppWidgetInfo(appWidgetInfo: CommunalAppWidgetInfo) {
-        _stopwatchAppWidgetInfo.value = appWidgetInfo
-    }
-
     fun setCommunalWidgets(inventory: List<CommunalWidgetContentModel>) {
         _communalWidgets.value = inventory
     }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 052b0c2078d1c8d8050de6f4553f2410c3fc7f9d..e5f763722bf18ba9200e59b3272ad6d4e6d3cbe8 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2391,7 +2391,8 @@ public class AppOpsService extends IAppOpsService.Stub {
         long token = Binder.clearCallingIdentity();
         try {
             // Permissions are managed by UIDs, but unfortunately a package name is required in API.
-            String packageName = ArrayUtils.firstOrNull(packageManager.getPackagesForUid(uid));
+            String packageName = ArrayUtils.firstOrNull(ArrayUtils.defeatNullable(
+                    packageManager.getPackagesForUid(uid)));
             if (packageName == null) {
                 return false;
             }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 86e417b183f8cff449a2ce5b0a3e7739edbb9b25..3b5ef4cadfdf75e6663d60c2d665d221c6dd42c8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -77,13 +77,14 @@ final class InputMethodMenuController {
     void showInputMethodMenu(boolean showAuxSubtypes, int displayId) {
         if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes);
 
-        final boolean isScreenLocked = isScreenLocked();
-
-        final String lastInputMethodId = mSettings.getSelectedInputMethod();
-        int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
-        if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
-
         synchronized (ImfLock.class) {
+            final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked()
+                    && mWindowManagerInternal.isKeyguardSecure(mSettings.getCurrentUserId());
+            final String lastInputMethodId = mSettings.getSelectedInputMethod();
+            int lastInputMethodSubtypeId =
+                    mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
+            if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
+
             final List<ImeSubtypeListItem> imList = mSwitchingController
                     .getSortedInputMethodAndSubtypeListForImeMenuLocked(
                             showAuxSubtypes, isScreenLocked);
@@ -200,12 +201,8 @@ final class InputMethodMenuController {
             mService.updateSystemUiLocked();
             mService.sendOnNavButtonFlagsChangedLocked();
             mSwitchingDialog.show();
-        }
-    }
 
-    private boolean isScreenLocked() {
-        return mWindowManagerInternal.isKeyguardLocked()
-                && mWindowManagerInternal.isKeyguardSecure(mSettings.getCurrentUserId());
+        }
     }
 
     void updateKeyboardFromSettingsLocked() {
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index cba605eac8f6db6f616b331220468754939edae1..26177037e1b45fb5c407bcc7319fa622bc5edbd8 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -60,6 +60,7 @@ import static com.android.server.pm.PackageManagerService.TAG;
 import static com.android.server.pm.PackageManagerServiceUtils.compareSignatureArrays;
 import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
 import static com.android.server.pm.PackageManagerServiceUtils.isSystemOrRootOrShell;
+import static com.android.server.pm.parsing.PackageInfoUtils.getDeprecatedSignatures;
 import static com.android.server.pm.resolution.ComponentResolver.RESOLVE_PRIORITY_SORTER;
 
 import android.Manifest;
@@ -1531,6 +1532,7 @@ public class ComputerEngine implements Computer {
             pi.applicationInfo = PackageInfoUtils.generateDelegateApplicationInfo(
                     ai, flags, state, userId);
             pi.signingInfo = ps.getSigningInfo();
+            pi.signatures = getDeprecatedSignatures(pi.signingInfo.getSigningDetails(), flags);
 
             if (DEBUG_PACKAGE_INFO) {
                 Log.v(TAG, "ps.pkg is n/a for ["
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 c26cf1c9a113830b3e74d7a60c8e55bc615f9e19..38cde3e3f7d7aa21254b1e953392caed275e42f9 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -238,21 +238,7 @@ public class PackageInfoUtils {
         }
 
         final SigningDetails signingDetails = pkg.getSigningDetails();
-        // deprecated method of getting signing certificates
-        if ((flags & PackageManager.GET_SIGNATURES) != 0) {
-            if (signingDetails.hasPastSigningCertificates()) {
-                // Package has included signing certificate rotation information.  Return the oldest
-                // cert so that programmatic checks keep working even if unaware of key rotation.
-                info.signatures = new Signature[1];
-                info.signatures[0] = signingDetails.getPastSigningCertificates()[0];
-            } else if (signingDetails.hasSignatures()) {
-                // otherwise keep old behavior
-                int numberOfSigs = signingDetails.getSignatures().length;
-                info.signatures = new Signature[numberOfSigs];
-                System.arraycopy(signingDetails.getSignatures(), 0, info.signatures, 0,
-                        numberOfSigs);
-            }
-        }
+        info.signatures = getDeprecatedSignatures(signingDetails, flags);
 
         // replacement for GET_SIGNATURES
         if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
@@ -358,6 +344,30 @@ public class PackageInfoUtils {
         return info;
     }
 
+    /**
+     *  Retrieve the deprecated {@link PackageInfo.signatures} field of signing certificates
+     */
+    public static Signature[] getDeprecatedSignatures(SigningDetails signingDetails, long flags) {
+        if ((flags & PackageManager.GET_SIGNATURES) == 0) {
+            return null;
+        }
+        if (signingDetails.hasPastSigningCertificates()) {
+            // Package has included signing certificate rotation information.  Return the oldest
+            // cert so that programmatic checks keep working even if unaware of key rotation.
+            Signature[] signatures = new Signature[1];
+            signatures[0] = signingDetails.getPastSigningCertificates()[0];
+            return signatures;
+        } else if (signingDetails.hasSignatures()) {
+            // otherwise keep old behavior
+            int numberOfSigs = signingDetails.getSignatures().length;
+            Signature[] signatures = new Signature[numberOfSigs];
+            System.arraycopy(signingDetails.getSignatures(), 0, signatures, 0,
+                    numberOfSigs);
+            return signatures;
+        }
+        return null;
+    }
+
     private static void updateApplicationInfo(ApplicationInfo ai, long flags,
             PackageUserState state) {
         if ((flags & PackageManager.GET_META_DATA) == 0) {
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 1b5631f59a3eb7101736952fc8e788b2d21f2831..a2f5a383caad1e3ac22726a76309d3ea62fddf87 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -256,13 +256,24 @@ public class BackgroundActivityStartController {
             mOriginatingPendingIntent = originatingPendingIntent;
             mIntent = intent;
             mRealCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid);
+            if (originatingPendingIntent == null) {
+                // grant creator BAL privileges unless explicitly opted out
+                mBalAllowedByPiCreator =
+                        checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
+                                == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED
+                                ? BackgroundStartPrivileges.NONE
+                                : BackgroundStartPrivileges.ALLOW_BAL;
+            } else {
+                // for PendingIntents we restrict creator BAL based on target_sdk
+                mBalAllowedByPiCreator =
+                        checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
+                                == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED
+                                ? BackgroundStartPrivileges.NONE
+                                : BackgroundStartPrivileges.ALLOW_BAL;
+            }
             mBalAllowedByPiSender =
-                    PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller(checkedOptions,
-                            realCallingUid, mRealCallingPackage);
-            mBalAllowedByPiCreator =
-                    checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
-                            == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED
-                            ? BackgroundStartPrivileges.NONE : BackgroundStartPrivileges.ALLOW_BAL;
+                    PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller(
+                            checkedOptions, realCallingUid, mRealCallingPackage);
             mAppSwitchState = mService.getBalAppSwitchesState();
             mCallingUidProcState = mService.mActiveUids.getUidState(callingUid);
             mIsCallingUidPersistentSystemProcess =
@@ -306,10 +317,14 @@ public class BackgroundActivityStartController {
             return name + "[debugOnly]";
         }
 
-        private boolean isPendingIntent() {
+        private boolean hasRealCaller() {
             return mRealCallingUid != NO_PROCESS_UID;
         }
 
+        private boolean isPendingIntent() {
+            return mOriginatingPendingIntent != null;
+        }
+
         private String dump(BalVerdict resultIfPiCreatorAllowsBal) {
             Preconditions.checkState(!isPendingIntent());
             return dump(resultIfPiCreatorAllowsBal, null);
@@ -334,7 +349,9 @@ public class BackgroundActivityStartController {
             sb.append("; isCallingUidPersistentSystemProcess: ")
                     .append(mIsCallingUidPersistentSystemProcess);
             sb.append("; balAllowedByPiCreator: ").append(mBalAllowedByPiCreator);
-            if (isPendingIntent()) {
+            sb.append("; hasRealCaller: ").append(hasRealCaller());
+            sb.append("; isPendingIntent: ").append(isPendingIntent());
+            if (hasRealCaller()) {
                 sb.append("; balAllowedByPiSender: ").append(mBalAllowedByPiSender);
                 sb.append("; realCallingPackage: ")
                         .append(getDebugPackageName(mRealCallingPackage, mRealCallingUid));
@@ -351,13 +368,13 @@ public class BackgroundActivityStartController {
             sb.append("; mForcedBalByPiSender: ").append(mForcedBalByPiSender);
             sb.append("; intent: ").append(mIntent);
             sb.append("; callerApp: ").append(mCallerApp);
-            if (isPendingIntent()) {
+            if (hasRealCaller()) {
                 sb.append("; realCallerApp: ").append(mRealCallerApp);
             }
             if (mCallerApp != null) {
                 sb.append("; inVisibleTask: ").append(mCallerApp.hasActivityInVisibleTask());
             }
-            if (isPendingIntent()) {
+            if (hasRealCaller()) {
                 if (mRealCallerApp != null) {
                     sb.append("; realInVisibleTask: ")
                             .append(mRealCallerApp.hasActivityInVisibleTask());
@@ -484,7 +501,7 @@ public class BackgroundActivityStartController {
 
         BalVerdict resultForCaller = checkBackgroundActivityStartAllowedByCaller(state);
 
-        if (!state.isPendingIntent()) {
+        if (!state.hasRealCaller()) {
             if (resultForCaller.allows()) {
                 if (DEBUG_ACTIVITY_STARTS) {
                     Slog.d(TAG, "Background activity start allowed. "
diff --git a/services/core/jni/tvinput/JTvInputHal.cpp b/services/core/jni/tvinput/JTvInputHal.cpp
index 80427b346f1a4e26ae865d1276cbfa8063683b0a..505421e81d3d32d8db981b3f03593a73eed681b3 100644
--- a/services/core/jni/tvinput/JTvInputHal.cpp
+++ b/services/core/jni/tvinput/JTvInputHal.cpp
@@ -494,12 +494,21 @@ JTvInputHal::ITvInputWrapper::ITvInputWrapper(std::shared_ptr<AidlITvInput>& aid
 ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::setCallback(
         const std::shared_ptr<TvInputCallbackWrapper>& in_callback) {
     if (mIsHidl) {
-        in_callback->aidlTvInputCallback = nullptr;
-        return hidlSetCallback(in_callback == nullptr ? nullptr : in_callback->hidlTvInputCallback);
+        if (in_callback == nullptr) {
+            return hidlSetCallback(nullptr);
+        }
+        else {
+            in_callback->aidlTvInputCallback = nullptr;
+            return hidlSetCallback(in_callback->hidlTvInputCallback);
+        }
     } else {
-        in_callback->hidlTvInputCallback = nullptr;
-        return mAidlTvInput->setCallback(in_callback == nullptr ? nullptr
-                                                                : in_callback->aidlTvInputCallback);
+        if (in_callback == nullptr) {
+            return mAidlTvInput->setCallback(nullptr);
+        }
+        else {
+            in_callback->hidlTvInputCallback = nullptr;
+            return mAidlTvInput->setCallback(in_callback->aidlTvInputCallback);
+        }
     }
 }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 34d67551d49f4b954b689d4cf7f81ae028086bc5..9b62a2c416554b1f67b50142c87454fe37e313f8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -9667,6 +9667,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
         }
     }
 
+    @Override
+    public ComponentName getDeviceOwnerComponentOnUser(int userId) {
+        if (!mHasFeature) {
+            return null;
+        }
+        if (mInjector.userHandleGetCallingUserId() != userId) {
+            Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+                    || hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
+        }
+        synchronized (getLockObject()) {
+            // There is only ever one device owner on a device so if the passed userId is the same
+            // as the device owner userId we know that the componentName returned by
+            // getDeviceOwnerComponent will be the correct one.
+            if (mOwners.getDeviceOwnerUserId() == userId || userId == UserHandle.USER_ALL) {
+                return mOwners.getDeviceOwnerComponent();
+            }
+        }
+        return null;
+    }
+
     private int getDeviceOwnerUserIdUncheckedLocked() {
         return mOwners.hasDeviceOwner() ? mOwners.getDeviceOwnerUserId() : UserHandle.USER_NULL;
     }
diff --git a/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt
index 15a58593432e81ac3cc2fed9d68670dbb8d6cc50..7db09f9125de7d666b4c41bd45af92a160dd53fc 100644
--- a/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt
@@ -16,7 +16,9 @@
 
 package com.android.server.permission.access.permission
 
+import android.Manifest
 import android.permission.PermissionManager
+import android.permission.flags.Flags
 import android.util.Slog
 import com.android.modules.utils.BinaryXmlPullParser
 import com.android.modules.utils.BinaryXmlSerializer
@@ -273,7 +275,12 @@ class DevicePermissionPolicy : SchemePolicy() {
 
         /** These permissions are supported for virtual devices. */
         // TODO: b/298661870 - Use new API to get the list of device aware permissions.
-        val DEVICE_AWARE_PERMISSIONS = emptySet<String>()
+        val DEVICE_AWARE_PERMISSIONS =
+            if (Flags.deviceAwarePermissionApis()) {
+                setOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
+            } else {
+                emptySet<String>()
+            }
     }
 
     /**
diff --git a/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesCallback.aidl
new file mode 100644
index 0000000000000000000000000000000000000000..4c37a6dc383236c2231c5f8148b0cb2977f7df8a
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesCallback.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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 android.telephony.satellite;
+
+import android.telephony.satellite.SatelliteCapabilities;
+
+/**
+ * Interface for satellite capabilities change callback.
+ * @hide
+ */
+oneway interface ISatelliteCapabilitiesCallback {
+    /**
+     * Called when satellite capability has changed.
+     *
+     * @param capabilities The new satellite capability.
+     */
+    void onSatelliteCapabilitiesChanged(in SatelliteCapabilities capabilities);
+}
+
diff --git a/telephony/java/android/telephony/satellite/SatelliteCapabilitiesCallback.java b/telephony/java/android/telephony/satellite/SatelliteCapabilitiesCallback.java
new file mode 100644
index 0000000000000000000000000000000000000000..b68dd5a150ff5a9d44b0e4edcc78fa1739e98800
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/SatelliteCapabilitiesCallback.java
@@ -0,0 +1,39 @@
+/*
+ * 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.telephony.satellite;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+
+import com.android.internal.telephony.flags.Flags;
+
+/**
+ * A callback class for satellite capabilities change events.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+public interface SatelliteCapabilitiesCallback {
+    /**
+     * Called when satellite capability has changed.
+     * @param capabilities The new satellite capabilities.
+     */
+    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    void onSatelliteCapabilitiesChanged(@NonNull SatelliteCapabilities capabilities);
+}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index f18cbeafe752947e5eb008db7c8cb55b07a07821..71786b308937c8bb25887c36fad05af6f5bdab73 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -81,6 +81,9 @@ public final class SatelliteManager {
             new ConcurrentHashMap<>();
     private static final ConcurrentHashMap<NtnSignalStrengthCallback, INtnSignalStrengthCallback>
             sNtnSignalStrengthCallbackMap = new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<SatelliteCapabilitiesCallback,
+            ISatelliteCapabilitiesCallback>
+            sSatelliteCapabilitiesCallbackMap = new ConcurrentHashMap<>();
 
     private final int mSubId;
 
@@ -2018,7 +2021,7 @@ public final class SatelliteManager {
      * {@link TelephonyManager#unregisterTelephonyCallback(TelephonyCallback)}..
      * </p>
      *
-     * @param callback The callback that was passed to
+     * @param callback The callback that was passed to.
      * {@link #registerForNtnSignalStrengthChanged(Executor, NtnSignalStrengthCallback)}.
      *
      * @throws SecurityException if the caller doesn't have required permission.
@@ -2046,9 +2049,84 @@ public final class SatelliteManager {
             loge("unregisterForNtnSignalStrengthChanged() RemoteException: " + ex);
             ex.rethrowFromSystemServer();
         }
+    }
 
+    /**
+     * Registers for satellite capabilities change event from the satellite service.
+     *
+     * @param executor The executor on which the callback will be called.
+     * @param callback The callback to handle the satellite capabilities changed event.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    @SatelliteResult public int registerForSatelliteCapabilitiesChanged(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull SatelliteCapabilitiesCallback callback) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                ISatelliteCapabilitiesCallback internalCallback =
+                        new ISatelliteCapabilitiesCallback.Stub() {
+                            @Override
+                            public void onSatelliteCapabilitiesChanged(
+                                    SatelliteCapabilities capabilities) {
+                                executor.execute(() -> Binder.withCleanCallingIdentity(
+                                        () -> callback.onSatelliteCapabilitiesChanged(
+                                                capabilities)));
+                            }
+                        };
+                sSatelliteCapabilitiesCallbackMap.put(callback, internalCallback);
+                return telephony.registerForSatelliteCapabilitiesChanged(mSubId, internalCallback);
+            } else {
+                throw new IllegalStateException("Telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            loge("registerForSatelliteCapabilitiesChanged() RemoteException: " + ex);
+            ex.rethrowFromSystemServer();
+        }
+        return SATELLITE_RESULT_REQUEST_FAILED;
     }
 
+    /**
+     * Unregisters for satellite capabilities change event from the satellite service.
+     * If callback was not registered before, the request will be ignored.
+     *
+     * @param callback The callback that was passed to.
+     * {@link #registerForSatelliteCapabilitiesChanged(Executor, SatelliteCapabilitiesCallback)}.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     */
+    @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+    @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+    public void unregisterForSatelliteCapabilitiesChanged(
+            @NonNull SatelliteCapabilitiesCallback callback) {
+        Objects.requireNonNull(callback);
+        ISatelliteCapabilitiesCallback internalCallback =
+                sSatelliteCapabilitiesCallbackMap.remove(callback);
+
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                if (internalCallback != null) {
+                    telephony.unregisterForSatelliteCapabilitiesChanged(mSubId, internalCallback);
+                } else {
+                    loge("unregisterForSatelliteCapabilitiesChanged: No internal callback.");
+                }
+            } else {
+                throw new IllegalStateException("Telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            loge("unregisterForSatelliteCapabilitiesChanged() RemoteException: " + ex);
+            ex.rethrowFromSystemServer();
+        }
+    }
 
     private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
index d44ddfa1ee7f28cd5c7f79d8da15d84f7c880932..ccca5adba3676ad470648ebf770c6945de1cd5a0 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
@@ -19,6 +19,7 @@ package android.telephony.satellite.stub;
 import android.telephony.satellite.stub.NtnSignalStrength;
 import android.telephony.satellite.stub.NTRadioTechnology;
 import android.telephony.satellite.stub.PointingInfo;
+import android.telephony.satellite.stub.SatelliteCapabilities;
 import android.telephony.satellite.stub.SatelliteDatagram;
 import android.telephony.satellite.stub.SatelliteModemState;
 
@@ -62,7 +63,15 @@ oneway interface ISatelliteListener {
 
     /**
      * Called when NTN signal strength changes.
+     *
      * @param ntnSignalStrength The new NTN signal strength.
      */
     void onNtnSignalStrengthChanged(in NtnSignalStrength ntnSignalStrength);
+
+    /**
+     * Called when satellite capabilities of the satellite service have changed.
+     *
+     * @param SatelliteCapabilities The current satellite capabilities.
+     */
+    void onSatelliteCapabilitiesChanged(in SatelliteCapabilities capabilities);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c212e3575276a6556e5ab2dedc215e99c8fdcb04..15a20cb91d0490d9efcf8101103f93db79aec351 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -68,6 +68,7 @@ import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.aidl.IRcsConfigCallback;
 import android.telephony.satellite.INtnSignalStrengthCallback;
+import android.telephony.satellite.ISatelliteCapabilitiesCallback;
 import android.telephony.satellite.ISatelliteDatagramCallback;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
@@ -3123,4 +3124,27 @@ interface ITelephony {
             + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
     void unregisterForNtnSignalStrengthChanged(int subId,
             in INtnSignalStrengthCallback callback);
+
+    /**
+     * Registers for satellite capabilities change event from the satellite service.
+     *
+     * @param executor The executor on which the callback will be called.
+     * @param callback The callback to handle the satellite capabilities changed event.
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+    int registerForSatelliteCapabilitiesChanged(int subId,
+            in ISatelliteCapabilitiesCallback callback);
+
+    /**
+     * Unregisters for satellite capabilities change event from the satellite service.
+     * If callback was not registered before, the request will be ignored.
+     *
+     * @param callback The callback that was passed to.
+     * {@link #registerForSatelliteCapabilitiesChanged(Executor, SatelliteCapabilitiesCallback)}.
+     */
+    @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+            + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+    void unregisterForSatelliteCapabilitiesChanged(int subId,
+            in ISatelliteCapabilitiesCallback callback);
 }