Merge "Support direct DOZING->PRIMARY_BOUNCER" into main
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 2922dd9..afb796b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10758,7 +10758,7 @@
     method public final double readDouble();
     method public final java.util.ArrayList<java.lang.Double> readDoubleVector();
     method public final android.os.HwBlob readEmbeddedBuffer(long, long, long, boolean);
-    method @NonNull @Nullable public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
+    method @NonNull public final android.os.HidlMemory readEmbeddedHidlMemory(long, long, long);
     method @Nullable public final android.os.NativeHandle readEmbeddedNativeHandle(long, long);
     method public final float readFloat();
     method public final java.util.ArrayList<java.lang.Float> readFloatVector();
@@ -12963,9 +12963,22 @@
     method public abstract void onGetReadOnlyFeatureFileDescriptorMap(@NonNull android.app.ondeviceintelligence.Feature, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,android.os.ParcelFileDescriptor>>);
     method public abstract void onGetVersion(@NonNull java.util.function.LongConsumer);
     method public abstract void onListFeatures(@NonNull android.os.OutcomeReceiver<java.util.List<android.app.ondeviceintelligence.Feature>,android.app.ondeviceintelligence.OnDeviceIntelligenceManager.OnDeviceIntelligenceManagerException>);
+    method public final void updateProcessingState(@NonNull android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.os.PersistableBundle,android.service.ondeviceintelligence.OnDeviceIntelligenceService.OnDeviceUpdateProcessingException>);
     field public static final String SERVICE_INTERFACE = "android.service.ondeviceintelligence.OnDeviceIntelligenceService";
   }
 
+  public static class OnDeviceIntelligenceService.OnDeviceIntelligenceServiceException extends java.lang.Exception {
+    ctor public OnDeviceIntelligenceService.OnDeviceIntelligenceServiceException(int);
+    ctor public OnDeviceIntelligenceService.OnDeviceIntelligenceServiceException(int, @NonNull String);
+    method public int getErrorCode();
+  }
+
+  public static class OnDeviceIntelligenceService.OnDeviceUpdateProcessingException extends android.service.ondeviceintelligence.OnDeviceIntelligenceService.OnDeviceIntelligenceServiceException {
+    ctor public OnDeviceIntelligenceService.OnDeviceUpdateProcessingException(int);
+    ctor public OnDeviceIntelligenceService.OnDeviceUpdateProcessingException(int, @NonNull String);
+    field public static final int PROCESSING_UPDATE_STATUS_CONNECTION_FAILED = 1; // 0x1
+  }
+
   @FlaggedApi("android.app.ondeviceintelligence.flags.enable_on_device_intelligence") public abstract class OnDeviceTrustedInferenceService extends android.app.Service {
     ctor public OnDeviceTrustedInferenceService();
     method public final void fetchFeatureFileInputStreamMap(@NonNull android.app.ondeviceintelligence.Feature, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.Map<java.lang.String,java.io.FileInputStream>>);
@@ -12973,6 +12986,7 @@
     method @NonNull public abstract void onCountTokens(@NonNull android.app.ondeviceintelligence.Feature, @NonNull android.app.ondeviceintelligence.Content, @Nullable android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<java.lang.Long,android.app.ondeviceintelligence.OnDeviceIntelligenceManager.OnDeviceIntelligenceManagerProcessingException>);
     method @NonNull public abstract void onProcessRequest(@NonNull android.app.ondeviceintelligence.Feature, @NonNull android.app.ondeviceintelligence.Content, int, @Nullable android.os.CancellationSignal, @Nullable android.app.ondeviceintelligence.ProcessingSignal, @NonNull android.os.OutcomeReceiver<android.app.ondeviceintelligence.Content,android.app.ondeviceintelligence.OnDeviceIntelligenceManager.OnDeviceIntelligenceManagerProcessingException>);
     method @NonNull public abstract void onProcessRequestStreaming(@NonNull android.app.ondeviceintelligence.Feature, @NonNull android.app.ondeviceintelligence.Content, int, @Nullable android.os.CancellationSignal, @Nullable android.app.ondeviceintelligence.ProcessingSignal, @NonNull android.app.ondeviceintelligence.StreamingResponseReceiver<android.app.ondeviceintelligence.Content,android.app.ondeviceintelligence.Content,android.app.ondeviceintelligence.OnDeviceIntelligenceManager.OnDeviceIntelligenceManagerProcessingException>);
+    method public abstract void onUpdateProcessingState(@NonNull android.os.Bundle, @NonNull android.os.OutcomeReceiver<android.os.PersistableBundle,android.service.ondeviceintelligence.OnDeviceIntelligenceService.OnDeviceUpdateProcessingException>);
     method public final java.io.FileInputStream openFileInput(@NonNull String) throws java.io.FileNotFoundException;
     method public final void openFileInputAsync(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.io.FileInputStream>) throws java.io.FileNotFoundException;
     field public static final String SERVICE_INTERFACE = "android.service.ondeviceintelligence.OnDeviceTrustedInferenceService";
diff --git a/core/java/android/companion/virtual/VirtualDeviceInternal.java b/core/java/android/companion/virtual/VirtualDeviceInternal.java
index 39f6de7..00d5343 100644
--- a/core/java/android/companion/virtual/VirtualDeviceInternal.java
+++ b/core/java/android/companion/virtual/VirtualDeviceInternal.java
@@ -16,6 +16,9 @@
 
 package android.companion.virtual;
 
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -352,12 +355,20 @@
             @Nullable Executor executor,
             @Nullable VirtualAudioDevice.AudioConfigurationChangeCallback callback) {
         if (mVirtualAudioDevice == null) {
-            Context context = mContext;
-            if (Flags.deviceAwareRecordAudioPermission()) {
-                context = mContext.createDeviceContext(getDeviceId());
+            try {
+                Context context = mContext;
+                if (Flags.deviceAwareRecordAudioPermission()) {
+                    // When using a default policy for audio device-aware RECORD_AUDIO permission
+                    // should not take effect, thus register policies with the default context.
+                    if (mVirtualDevice.getDevicePolicy(POLICY_TYPE_AUDIO) == DEVICE_POLICY_CUSTOM) {
+                        context = mContext.createDeviceContext(getDeviceId());
+                    }
+                }
+                mVirtualAudioDevice = new VirtualAudioDevice(context, mVirtualDevice, display,
+                        executor, callback, () -> mVirtualAudioDevice = null);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
             }
-            mVirtualAudioDevice = new VirtualAudioDevice(context, mVirtualDevice, display,
-                    executor, callback, () -> mVirtualAudioDevice = null);
         }
         return mVirtualAudioDevice;
     }
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 3e9f260..8a3a3ad 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -112,6 +112,12 @@
     /**
      * Indicates that this user is disabled.
      *
+     * <p> This is currently used to indicate that a Managed Profile, when created via
+     * DevicePolicyManager, has not yet been provisioned; once the DPC provisions it, a DPM call
+     * will manually set it to enabled.
+     *
+     * <p>Users that are slated for deletion are also generally set to disabled.
+     *
      * <p>Note: If an ephemeral user is disabled, it shouldn't be later re-enabled. Ephemeral users
      * are disabled as their removal is in progress to indicate that they shouldn't be re-entered.
      */
@@ -398,6 +404,7 @@
         return UserManager.isUserTypePrivateProfile(userType);
     }
 
+    /** See {@link #FLAG_DISABLED}*/
     @UnsupportedAppUsage
     public boolean isEnabled() {
         return (flags & FLAG_DISABLED) != FLAG_DISABLED;
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 05a1abea..b417534 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -240,7 +240,7 @@
             new Dimensions(POWER_COMPONENT_ANY, PROCESS_STATE_ANY);
 
     /**
-     * Identifies power attribution dimensions that are captured by an data element of
+     * Identifies power attribution dimensions that are captured by a data element of
      * a BatteryConsumer. These Keys are used to access those values and to set them using
      * Builders.  See for example {@link #getConsumedPower(Key)}.
      *
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index e090942..c611cb9 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1587,7 +1587,7 @@
                 outNumOfInterest[0] = numOfInterest;
             }
 
-            // The estimated time is the average time we spend in each level, multipled
+            // The estimated time is the average time we spend in each level, multiplied
             // by 100 -- the total number of battery levels
             return (total / numOfInterest) * 100;
         }
@@ -2019,7 +2019,7 @@
         public static final int EVENT_TOP = 0x0003;
         // Event is about active sync operations.
         public static final int EVENT_SYNC = 0x0004;
-        // Events for all additional wake locks aquired/release within a wake block.
+        // Events for all additional wake locks acquired/release within a wake block.
         // These are not generated by default.
         public static final int EVENT_WAKE_LOCK = 0x0005;
         // Event is about an application executing a scheduled job.
@@ -3419,7 +3419,7 @@
      * incoming service calls from apps.  The result is returned as an array of longs,
      * organized as a sequence like this:
      * <pre>
-     *     cluster1-speeed1, cluster1-speed2, ..., cluster2-speed1, cluster2-speed2, ...
+     *     cluster1-speed1, cluster1-speed2, ..., cluster2-speed1, cluster2-speed2, ...
      * </pre>
      *
      * @see com.android.internal.os.CpuScalingPolicies#getPolicies
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 3149de4..beb9a93 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -120,7 +120,6 @@
     private ClassLoader mClassLoader;
     private String mLibrarySearchPaths;
     private String mLibraryPermittedPaths;
-    private GameManager mGameManager;
 
     private int mAngleOptInIndex = -1;
     private boolean mShouldUseAngle = false;
@@ -134,8 +133,6 @@
         final ApplicationInfo appInfoWithMetaData =
                 getAppInfoWithMetadata(context, pm, packageName);
 
-        mGameManager = context.getSystemService(GameManager.class);
-
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setupGpuLayers");
         setupGpuLayers(context, coreSettings, pm, packageName, appInfoWithMetaData);
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
@@ -161,9 +158,11 @@
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
 
         Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "notifyGraphicsEnvironmentSetup");
-        if (mGameManager != null
-                && appInfoWithMetaData.category == ApplicationInfo.CATEGORY_GAME) {
-            mGameManager.notifyGraphicsEnvironmentSetup();
+        if (appInfoWithMetaData.category == ApplicationInfo.CATEGORY_GAME) {
+            final GameManager gameManager = context.getSystemService(GameManager.class);
+            if (gameManager != null) {
+                gameManager.notifyGraphicsEnvironmentSetup();
+            }
         }
         Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
     }
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 9fd37d4..fb500a9 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -618,7 +618,7 @@
      */
     @FastNative
     @NonNull
-    public native final @Nullable
+    public native final
     HidlMemory readEmbeddedHidlMemory(long fieldHandle, long parentHandle, long offset);
 
     /**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index ccb534e..9757a10 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -4708,6 +4708,9 @@
      * Sets the user as enabled, if such an user exists.
      *
      * <p>Note that the default is true, it's only that managed profiles might not be enabled.
+     * (Managed profiles created by DevicePolicyManager will start out disabled, and DPM will later
+     * toggle them to enabled once they are provisioned. This is the primary purpose of the
+     * {@link UserInfo#FLAG_DISABLED} flag.)
      * Also ephemeral users can be disabled to indicate that their removal is in progress and they
      * shouldn't be re-entered. Therefore ephemeral users should not be re-enabled once disabled.
      *
@@ -5259,7 +5262,7 @@
 
     /**
      * Returns list of the profiles of userId including userId itself.
-     * Note that this returns only enabled.
+     * Note that this returns only {@link UserInfo#isEnabled() enabled} profiles.
      * <p>Note that this includes all profile types (not including Restricted profiles).
      *
      * <p>Requires {@link android.Manifest.permission#MANAGE_USERS} or
diff --git a/core/java/android/os/health/HealthStatsWriter.java b/core/java/android/os/health/HealthStatsWriter.java
index d4d10b0..4118775 100644
--- a/core/java/android/os/health/HealthStatsWriter.java
+++ b/core/java/android/os/health/HealthStatsWriter.java
@@ -58,7 +58,7 @@
      * Construct a HealthStatsWriter object with the given constants.
      *
      * The "getDataType()" of the resulting HealthStats object will be the
-     * short name of the java class that the Constants object was initalized
+     * short name of the java class that the Constants object was initialized
      * with.
      */
     public HealthStatsWriter(HealthKeys.Constants constants) {
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index 88096ab..ada708b 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -52,7 +52,7 @@
  *
  * After the installation is completed, the device will be running in the new system on next the
  * reboot. Then, when the user reboots the device again, it will leave {@code DynamicSystem} and go
- * back to the original system. While running in {@code DynamicSystem}, persitent storage for
+ * back to the original system. While running in {@code DynamicSystem}, persistent storage for
  * factory reset protection (FRP) remains unchanged. Since the user is running the new system with
  * a temporarily created data partition, their original user data are kept unchanged.</p>
  *
diff --git a/core/java/android/os/image/DynamicSystemManager.java b/core/java/android/os/image/DynamicSystemManager.java
index 536795b..8ce87e9 100644
--- a/core/java/android/os/image/DynamicSystemManager.java
+++ b/core/java/android/os/image/DynamicSystemManager.java
@@ -172,7 +172,7 @@
         }
     }
     /**
-     * Finish a previously started installation. Installations without a cooresponding
+     * Finish a previously started installation. Installations without a corresponding
      * finishInstallation() will be cleaned up during device boot.
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 5a09541..d45a17f 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1395,7 +1395,7 @@
                 // Package name can be null if the activity thread is running but the app
                 // hasn't bound yet. In this case we fall back to the first package in the
                 // current UID. This works for runtime permissions as permission state is
-                // per UID and permission realted app ops are updated for all UID packages.
+                // per UID and permission related app ops are updated for all UID packages.
                 String[] packageNames = ActivityThread.getPackageManager().getPackagesForUid(
                         android.os.Process.myUid());
                 if (packageNames == null || packageNames.length <= 0) {
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index e1f112a..4cf2fd4 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -62,7 +62,7 @@
  * <li>To get access to standard directories (like the {@link Environment#DIRECTORY_PICTURES}), they
  * can use the {@link #createAccessIntent(String)}. This is the recommend way, since it provides a
  * simpler API and narrows the access to the given directory (and its descendants).
- * <li>To get access to any directory (and its descendants), they can use the Storage Acess
+ * <li>To get access to any directory (and its descendants), they can use the Storage Access
  * Framework APIs (such as {@link Intent#ACTION_OPEN_DOCUMENT} and
  * {@link Intent#ACTION_OPEN_DOCUMENT_TREE}, although these APIs do not guarantee the user will
  * select this specific volume.
diff --git a/core/java/android/service/ondeviceintelligence/IOnDeviceIntelligenceService.aidl b/core/java/android/service/ondeviceintelligence/IOnDeviceIntelligenceService.aidl
index bbb4bc6..e44c69c 100644
--- a/core/java/android/service/ondeviceintelligence/IOnDeviceIntelligenceService.aidl
+++ b/core/java/android/service/ondeviceintelligence/IOnDeviceIntelligenceService.aidl
@@ -26,6 +26,7 @@
 import android.app.ondeviceintelligence.IListFeaturesCallback;
 import android.app.ondeviceintelligence.IFeatureDetailsCallback;
 import com.android.internal.infra.AndroidFuture;
+import android.service.ondeviceintelligence.IRemoteProcessingService;
 
 
 /**
@@ -41,4 +42,5 @@
     void getReadOnlyFileDescriptor(in String fileName, in AndroidFuture<ParcelFileDescriptor> future);
     void getReadOnlyFeatureFileDescriptorMap(in Feature feature, in RemoteCallback remoteCallback);
     void requestFeatureDownload(in Feature feature, in ICancellationSignal cancellationSignal, in IDownloadCallback downloadCallback);
+    void registerRemoteServices(in IRemoteProcessingService remoteProcessingService);
 }
\ No newline at end of file
diff --git a/core/java/android/service/ondeviceintelligence/IOnDeviceTrustedInferenceService.aidl b/core/java/android/service/ondeviceintelligence/IOnDeviceTrustedInferenceService.aidl
index 08eb927..e3fda04 100644
--- a/core/java/android/service/ondeviceintelligence/IOnDeviceTrustedInferenceService.aidl
+++ b/core/java/android/service/ondeviceintelligence/IOnDeviceTrustedInferenceService.aidl
@@ -23,8 +23,10 @@
 import android.app.ondeviceintelligence.Content;
 import android.app.ondeviceintelligence.Feature;
 import android.os.ICancellationSignal;
+import android.os.PersistableBundle;
+import android.os.Bundle;
 import android.service.ondeviceintelligence.IRemoteStorageService;
-
+import android.service.ondeviceintelligence.IProcessingUpdateStatusCallback;
 
 /**
  * Interface for a concrete implementation to provide on device trusted inference.
@@ -41,4 +43,6 @@
     void processRequestStreaming(in Feature feature, in Content request, in int requestType,
                                 in ICancellationSignal cancellationSignal, in IProcessingSignal processingSignal,
                                 in IStreamingResponseCallback callback);
+    void updateProcessingState(in Bundle processingState,
+                                     in IProcessingUpdateStatusCallback callback);
 }
\ No newline at end of file
diff --git a/core/java/android/service/ondeviceintelligence/IProcessingUpdateStatusCallback.aidl b/core/java/android/service/ondeviceintelligence/IProcessingUpdateStatusCallback.aidl
new file mode 100644
index 0000000..7ead869
--- /dev/null
+++ b/core/java/android/service/ondeviceintelligence/IProcessingUpdateStatusCallback.aidl
@@ -0,0 +1,14 @@
+package android.service.ondeviceintelligence;
+
+import android.os.PersistableBundle;
+
+/**
+  * Interface for receiving status from a updateProcessingState call from on-device intelligence
+  * service.
+  *
+  * @hide
+  */
+interface IProcessingUpdateStatusCallback {
+    void onSuccess(in PersistableBundle statusParams) = 1;
+    void onFailure(int errorCode, in String errorMessage) = 2;
+}
diff --git a/core/java/android/service/ondeviceintelligence/IRemoteProcessingService.aidl b/core/java/android/service/ondeviceintelligence/IRemoteProcessingService.aidl
new file mode 100644
index 0000000..32a8a6a
--- /dev/null
+++ b/core/java/android/service/ondeviceintelligence/IRemoteProcessingService.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.ondeviceintelligence;
+
+import android.os.Bundle;
+import android.service.ondeviceintelligence.IProcessingUpdateStatusCallback;
+
+
+/**
+ * Interface for a concrete implementation to provide methods to update state of a remote service.
+ *
+ * @hide
+ */
+oneway interface IRemoteProcessingService {
+    void updateProcessingState(in Bundle processingState,
+                                 in IProcessingUpdateStatusCallback callback);
+}
diff --git a/core/java/android/service/ondeviceintelligence/OnDeviceIntelligenceService.java b/core/java/android/service/ondeviceintelligence/OnDeviceIntelligenceService.java
index 0cba1d3..46ba25d 100644
--- a/core/java/android/service/ondeviceintelligence/OnDeviceIntelligenceService.java
+++ b/core/java/android/service/ondeviceintelligence/OnDeviceIntelligenceService.java
@@ -18,6 +18,7 @@
 
 import static android.app.ondeviceintelligence.flags.Flags.FLAG_ENABLE_ON_DEVICE_INTELLIGENCE;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -47,11 +48,18 @@
 
 import com.android.internal.infra.AndroidFuture;
 
+import androidx.annotation.IntDef;
+
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 import java.util.function.LongConsumer;
 
@@ -64,6 +72,10 @@
  * {@code config_defaultOnDeviceIntelligenceService}. If this config has no value, a stub is
  * returned.
  *
+ * <p> Similar to {@link OnDeviceIntelligenceManager} class, the contracts in this service are
+ * defined to be open-ended in general, to allow interoperability. Therefore, it is recommended
+ * that implementations of this system-service expose this API to the clients via a library which
+ * has more defined contract.</p>
  * <pre>
  * {@literal
  * <service android:name=".SampleOnDeviceIntelligenceService"
@@ -78,6 +90,8 @@
 public abstract class OnDeviceIntelligenceService extends Service {
     private static final String TAG = OnDeviceIntelligenceService.class.getSimpleName();
 
+    private volatile IRemoteProcessingService mRemoteProcessingService;
+
     /**
      * The {@link Intent} that must be declared as handled by the service. To be supported, the
      * service must also require the
@@ -88,6 +102,7 @@
     public static final String SERVICE_INTERFACE =
             "android.service.ondeviceintelligence.OnDeviceIntelligenceService";
 
+
     /**
      * @hide
      */
@@ -167,12 +182,58 @@
                                 remoteCallback.sendResult(bundle);
                             });
                 }
+
+                @Override
+                public void registerRemoteServices(
+                        IRemoteProcessingService remoteProcessingService) {
+                    mRemoteProcessingService = remoteProcessingService;
+                }
             };
         }
         Slog.w(TAG, "Incorrect service interface, returning null.");
         return null;
     }
 
+    /**
+     * Invoked by the {@link OnDeviceIntelligenceService} inorder to send updates to the inference
+     * service if there is a state change to be performed.
+     *
+     * @param processingState  the updated state to be applied.
+     * @param callbackExecutor executor to the run status callback on.
+     * @param statusReceiver   receiver to get status of the update state operation.
+     */
+    public final void updateProcessingState(@NonNull Bundle processingState,
+            @NonNull @CallbackExecutor Executor callbackExecutor,
+            @NonNull OutcomeReceiver<PersistableBundle, OnDeviceUpdateProcessingException> statusReceiver) {
+        Objects.requireNonNull(callbackExecutor);
+        if (mRemoteProcessingService == null) {
+            throw new IllegalStateException("Remote processing service is unavailable.");
+        }
+        try {
+            mRemoteProcessingService.updateProcessingState(processingState,
+                    new IProcessingUpdateStatusCallback.Stub() {
+                        @Override
+                        public void onSuccess(PersistableBundle result) {
+                            Binder.withCleanCallingIdentity(() -> {
+                                callbackExecutor.execute(
+                                        () -> statusReceiver.onResult(result));
+                            });
+                        }
+
+                        @Override
+                        public void onFailure(int errorCode, String errorMessage) {
+                            Binder.withCleanCallingIdentity(() -> callbackExecutor.execute(
+                                    () -> statusReceiver.onError(
+                                            new OnDeviceUpdateProcessingException(
+                                                    errorCode, errorMessage))));
+                        }
+                    });
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Error in updateProcessingState: " + e);
+            throw new RuntimeException(e);
+        }
+    }
+
     private OutcomeReceiver<Feature,
             OnDeviceIntelligenceManager.OnDeviceIntelligenceManagerException> wrapFeatureCallback(
             IFeatureCallback featureCallback) {
@@ -197,7 +258,6 @@
                 }
             }
         };
-
     }
 
     private OutcomeReceiver<List<Feature>,
@@ -380,4 +440,60 @@
      * @param versionConsumer consumer to populate the version.
      */
     public abstract void onGetVersion(@NonNull LongConsumer versionConsumer);
+
+
+    /**
+     * Exception type to be populated when calls to {@link #updateProcessingState} fail.
+     */
+    public static class OnDeviceUpdateProcessingException extends
+            OnDeviceIntelligenceServiceException {
+        /**
+         * The connection to remote service failed and the processing state could not be updated.
+         */
+        public static final int PROCESSING_UPDATE_STATUS_CONNECTION_FAILED = 1;
+
+
+        /**
+         * @hide
+         */
+        @IntDef(value = {
+                PROCESSING_UPDATE_STATUS_CONNECTION_FAILED
+        }, open = true)
+        @Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.PARAMETER,
+                ElementType.FIELD})
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface ErrorCode {
+        }
+
+        public OnDeviceUpdateProcessingException(@ErrorCode int errorCode) {
+            super(errorCode);
+        }
+
+        public OnDeviceUpdateProcessingException(@ErrorCode int errorCode,
+                @NonNull String errorMessage) {
+            super(errorCode, errorMessage);
+        }
+    }
+
+    /**
+     * Exception type to be used for surfacing errors to service implementation.
+     */
+    public abstract static class OnDeviceIntelligenceServiceException extends Exception {
+        private final int mErrorCode;
+
+        public OnDeviceIntelligenceServiceException(int errorCode) {
+            this.mErrorCode = errorCode;
+        }
+
+        public OnDeviceIntelligenceServiceException(int errorCode,
+                @NonNull String errorMessage) {
+            super(errorMessage);
+            this.mErrorCode = errorCode;
+        }
+
+        public int getErrorCode() {
+            return mErrorCode;
+        }
+
+    }
 }
diff --git a/core/java/android/service/ondeviceintelligence/OnDeviceTrustedInferenceService.java b/core/java/android/service/ondeviceintelligence/OnDeviceTrustedInferenceService.java
index 96982e3..8600197 100644
--- a/core/java/android/service/ondeviceintelligence/OnDeviceTrustedInferenceService.java
+++ b/core/java/android/service/ondeviceintelligence/OnDeviceTrustedInferenceService.java
@@ -36,13 +36,16 @@
 import android.app.ondeviceintelligence.StreamingResponseReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.IBinder;
 import android.os.ICancellationSignal;
 import android.os.OutcomeReceiver;
 import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
+import android.service.ondeviceintelligence.OnDeviceIntelligenceService.OnDeviceUpdateProcessingException;
 import android.util.Log;
 import android.util.Slog;
 
@@ -65,6 +68,11 @@
  * non-streaming fashion. Also, provides a way to register a storage service that will be used to
  * read-only access files from the {@link OnDeviceIntelligenceService} counterpart. </p>
  *
+ * <p> Similar to {@link OnDeviceIntelligenceManager} class, the contracts in this service are
+ * defined to be open-ended in general, to allow interoperability. Therefore, it is recommended
+ * that implementations of this system-service expose this API to the clients via a library which
+ * has more defined contract.</p>
+ *
  * <pre>
  * {@literal
  * <service android:name=".SampleTrustedInferenceService"
@@ -152,6 +160,17 @@
                             wrapResponseCallback(callback)
                     );
                 }
+
+                @Override
+                public void updateProcessingState(Bundle processingState,
+                        IProcessingUpdateStatusCallback callback) {
+                    Objects.requireNonNull(processingState);
+                    Objects.requireNonNull(callback);
+
+                    OnDeviceTrustedInferenceService.this.onUpdateProcessingState(processingState,
+                            wrapOutcomeReceiver(callback)
+                    );
+                }
             };
         }
         Slog.w(TAG, "Incorrect service interface, returning null.");
@@ -233,6 +252,21 @@
             @NonNull OutcomeReceiver<Content,
                     OnDeviceIntelligenceManager.OnDeviceIntelligenceManagerProcessingException> callback);
 
+
+    /**
+     * Invoked when processing environment needs to be updated or refreshed with fresh
+     * configuration, files or state.
+     *
+     * @param processingState contains updated state and params that are to be applied to the
+     *                        processing environmment,
+     * @param callback        callback to populate the update status and if there are params
+     *                        associated with the status.
+     */
+    public abstract void onUpdateProcessingState(@NonNull Bundle processingState,
+            @NonNull OutcomeReceiver<PersistableBundle,
+                    OnDeviceUpdateProcessingException> callback);
+
+
     /**
      * Overrides {@link Context#openFileInput} to read files with the given file names under the
      * internal app storage of the {@link OnDeviceIntelligenceService}, i.e., only files stored in
@@ -407,4 +441,31 @@
             }
         };
     }
+
+    @NonNull
+    private static OutcomeReceiver<PersistableBundle, OnDeviceUpdateProcessingException> wrapOutcomeReceiver(
+            IProcessingUpdateStatusCallback callback) {
+        return new OutcomeReceiver<>() {
+            @Override
+            public void onResult(@NonNull PersistableBundle result) {
+                try {
+                    callback.onSuccess(result);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Error sending result: " + e);
+
+                }
+            }
+
+            @Override
+            public void onError(
+                    @androidx.annotation.NonNull OnDeviceUpdateProcessingException error) {
+                try {
+                    callback.onFailure(error.getErrorCode(), error.getMessage());
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Error sending exception details: " + e);
+                }
+            }
+        };
+    }
+
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 708751a..a7cb169 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1210,6 +1210,9 @@
             mSensitiveContentProtectionService =
                     ISensitiveContentProtectionManager.Stub.asInterface(
                         ServiceManager.getService(Context.SENSITIVE_CONTENT_PROTECTION_SERVICE));
+            if (mSensitiveContentProtectionService == null) {
+                Log.e(TAG, "SensitiveContentProtectionService shouldn't be null");
+            }
         } else {
             mSensitiveContentProtectionService = null;
         }
@@ -4179,6 +4182,9 @@
      */
     void notifySensitiveContentAppProtection(boolean showSensitiveContent) {
         try {
+            if (mSensitiveContentProtectionService == null) {
+                return;
+            }
             // The window would be blocked during screen share if it shows sensitive content.
             mSensitiveContentProtectionService.setSensitiveContentProtection(
                     getWindowToken(), mContext.getPackageName(), showSensitiveContent);
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 5e3e1b0..660e4c0 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -334,4 +334,17 @@
     <bool name="config_enable_cellular_on_boot_default">true</bool>
     <java-symbol type="bool" name="config_enable_cellular_on_boot_default" />
 
+    <!-- The network capabilities that would be forced marked as cellular transport regardless it's
+         on cellular or satellite-->
+    <string-array name="config_force_cellular_transport_capabilities">
+        <!-- Added the following three capabilities for now. For the long term solution, the client
+             requests satellite network should really include TRANSPORT_SATELLITE in the network
+             request. With the following workaround, the clients can continue request network with
+             the following capabilities with TRANSPORT_CELLULAR. The network with one of the
+             following capabilities would also be marked as cellular. -->
+        <item>ims</item>
+        <item>eims</item>
+        <item>xcap</item>
+    </string-array>
+    <java-symbol type="array" name="config_force_cellular_transport_capabilities" />
 </resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OWNERS
index 7237d2b..37ccd15 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/OWNERS
@@ -1,2 +1,4 @@
 # WM shell sub-modules splitscreen owner
 chenghsiuchang@google.com
+jeremysim@google.com
+peanutbutter@google.com
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OWNERS b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OWNERS
index 7237d2b..37ccd15 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OWNERS
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OWNERS
@@ -1,2 +1,4 @@
 # WM shell sub-modules splitscreen owner
 chenghsiuchang@google.com
+jeremysim@google.com
+peanutbutter@google.com
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt
index 83490b8..892eabf 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ktx/CredentialKtx.kt
@@ -30,6 +30,7 @@
 import android.text.TextUtils
 import android.util.Log
 import androidx.activity.result.IntentSenderRequest
+import androidx.credentials.PasswordCredential
 import androidx.credentials.PublicKeyCredential
 import androidx.credentials.provider.Action
 import androidx.credentials.provider.AuthenticationAction
@@ -125,6 +126,7 @@
                     pendingIntent = credentialEntry.pendingIntent,
                     fillInIntent = it.frameworkExtrasIntent,
                     credentialType = CredentialType.PASSWORD,
+                    rawCredentialType = PasswordCredential.TYPE_PASSWORD_CREDENTIAL,
                     credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
                     userName = credentialEntry.username.toString(),
                     displayName = credentialEntry.displayName?.toString(),
@@ -136,6 +138,7 @@
                     entryGroupId = credentialEntry.entryGroupId.toString(),
                     isDefaultIconPreferredAsSingleProvider =
                             credentialEntry.isDefaultIconPreferredAsSingleProvider,
+                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                 )
                 )
             }
@@ -149,6 +152,7 @@
                     pendingIntent = credentialEntry.pendingIntent,
                     fillInIntent = it.frameworkExtrasIntent,
                     credentialType = CredentialType.PASSKEY,
+                    rawCredentialType = PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL,
                     credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(),
                     userName = credentialEntry.username.toString(),
                     displayName = credentialEntry.displayName?.toString(),
@@ -162,6 +166,7 @@
                     entryGroupId = credentialEntry.entryGroupId.toString(),
                     isDefaultIconPreferredAsSingleProvider =
                             credentialEntry.isDefaultIconPreferredAsSingleProvider,
+                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                 )
                 )
             }
@@ -175,6 +180,7 @@
                     pendingIntent = credentialEntry.pendingIntent,
                     fillInIntent = it.frameworkExtrasIntent,
                     credentialType = CredentialType.UNKNOWN,
+                    rawCredentialType = credentialEntry.type,
                     credentialTypeDisplayName =
                     credentialEntry.typeDisplayName?.toString().orEmpty(),
                     userName = credentialEntry.title.toString(),
@@ -187,6 +193,7 @@
                     entryGroupId = credentialEntry.entryGroupId.toString(),
                     isDefaultIconPreferredAsSingleProvider =
                             credentialEntry.isDefaultIconPreferredAsSingleProvider,
+                    affiliatedDomain = credentialEntry.affiliatedDomain?.toString(),
                 )
                 )
             }
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/model/get/CredentialEntryInfo.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/model/get/CredentialEntryInfo.kt
index 9f36096..a657e97 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/model/get/CredentialEntryInfo.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/model/get/CredentialEntryInfo.kt
@@ -31,6 +31,11 @@
     fillInIntent: Intent?,
     /** Type of this credential used for sorting. Not localized so must not be directly displayed. */
     val credentialType: CredentialType,
+    /**
+     * String type value of this credential used for sorting. Not localized so must not be directly
+     * displayed.
+     */
+    val rawCredentialType: String,
     /** Localized type value of this credential used for display purpose. */
     val credentialTypeDisplayName: String,
     val providerDisplayName: String,
@@ -43,6 +48,7 @@
     val entryGroupId: String, // Used for deduplication, and displayed as the grouping title
                               // "For <value-of-entryGroupId>" on the more-option screen.
     val isDefaultIconPreferredAsSingleProvider: Boolean,
+    val affiliatedDomain: String?,
 ) : EntryInfo(
     providerId,
     entryKey,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index ccf401d..6a1998a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -20,6 +20,7 @@
 import android.content.Context
 import android.content.pm.PackageInfo
 import android.content.pm.PackageManager
+import android.credentials.GetCredentialRequest
 import android.credentials.selection.CreateCredentialProviderData
 import android.credentials.selection.DisabledProviderData
 import android.credentials.selection.Entry
@@ -44,6 +45,9 @@
 import androidx.credentials.CreateCustomCredentialRequest
 import androidx.credentials.CreatePasswordRequest
 import androidx.credentials.CreatePublicKeyCredentialRequest
+import androidx.credentials.PasswordCredential
+import androidx.credentials.PriorityHints
+import androidx.credentials.PublicKeyCredential
 import androidx.credentials.provider.CreateEntry
 import androidx.credentials.provider.RemoteEntry
 import org.json.JSONObject
@@ -162,6 +166,25 @@
 /** Utility functions for converting CredentialManager data structures to or from UI formats. */
 class GetFlowUtils {
     companion object {
+        fun extractTypePriorityMap(request: GetCredentialRequest): Map<String, Int> {
+            val typePriorityMap = mutableMapOf<String, Int>()
+            request.credentialOptions.forEach {option ->
+                // TODO(b/280085288) - use jetpack conversion method when exposed, rather than
+                // parsing from the raw Bundle
+                val priority = option.candidateQueryData.getInt(
+                        "androidx.credentials.BUNDLE_KEY_TYPE_PRIORITY_VALUE",
+                        when (option.type) {
+                            PasswordCredential.TYPE_PASSWORD_CREDENTIAL ->
+                                PriorityHints.PRIORITY_PASSWORD_OR_SIMILAR
+                            PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL -> 100
+                            else -> PriorityHints.PRIORITY_DEFAULT
+                        }
+                )
+                typePriorityMap[option.type] = priority
+            }
+            return typePriorityMap
+        }
+
         // Returns the list (potentially empty) of enabled provider.
         fun toProviderList(
             providerDataList: List<GetCredentialProviderData>,
@@ -193,6 +216,9 @@
                         null
                     }
                 }
+
+            val typePriorityMap = extractTypePriorityMap(getCredentialRequest)
+
             return com.android.credentialmanager.getflow.RequestDisplayInfo(
                 appName = originName?.ifEmpty { null }
                     ?: getAppLabel(context.packageManager, requestInfo.packageName)
@@ -203,6 +229,7 @@
                     // exposed.
                     "androidx.credentials.BUNDLE_KEY_PREFER_IDENTITY_DOC_UI"),
                 preferTopBrandingContent = preferTopBrandingContent,
+                typePriorityMap = typePriorityMap,
             )
         }
     }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
index 293e111..4e1f4ee 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt
@@ -33,7 +33,6 @@
 import android.os.Bundle
 import android.os.CancellationSignal
 import android.os.OutcomeReceiver
-import android.provider.Settings
 import android.service.autofill.AutofillService
 import android.service.autofill.Dataset
 import android.service.autofill.Field
@@ -140,7 +139,7 @@
             override fun onResult(result: GetCandidateCredentialsResponse) {
                 Log.i(TAG, "getCandidateCredentials onResult")
                 val fillResponse = convertToFillResponse(result, request,
-                    responseClientState)
+                    responseClientState, GetFlowUtils.extractTypePriorityMap(getCredRequest))
                 if (fillResponse != null) {
                     callback.onSuccess(fillResponse)
                 } else {
@@ -197,7 +196,8 @@
     private fun convertToFillResponse(
             getCredResponse: GetCandidateCredentialsResponse,
             filLRequest: FillRequest,
-            responseClientState: Bundle
+            responseClientState: Bundle,
+            typePriorityMap: Map<String, Int>,
     ): FillResponse? {
         val candidateProviders = getCredResponse.candidateProviderDataList
         if (candidateProviders.isEmpty()) {
@@ -213,7 +213,7 @@
         autofillIdToProvidersMap.forEach { (autofillId, providers) ->
             validFillResponse = processProvidersForAutofillId(
                     filLRequest, autofillId, providers, entryIconMap, fillResponseBuilder,
-                    getCredResponse.intent)
+                    getCredResponse.intent, typePriorityMap)
                     .or(validFillResponse)
         }
         if (!validFillResponse) {
@@ -229,7 +229,8 @@
             providerDataList: ArrayList<GetCredentialProviderData>,
             entryIconMap: Map<String, Icon>,
             fillResponseBuilder: FillResponse.Builder,
-            bottomSheetIntent: Intent
+            bottomSheetIntent: Intent,
+            typePriorityMap: Map<String, Int>,
     ): Boolean {
         val providerList = GetFlowUtils.toProviderList(
             providerDataList,
@@ -237,7 +238,8 @@
         if (providerList.isEmpty()) {
             return false
         }
-        val providerDisplayInfo: ProviderDisplayInfo = toProviderDisplayInfo(providerList)
+        val providerDisplayInfo: ProviderDisplayInfo =
+                toProviderDisplayInfo(providerList, typePriorityMap)
         var totalEntryCount = providerDisplayInfo.sortedUserNameToCredentialEntryList.size
         val inlineSuggestionsRequest = filLRequest.inlineSuggestionsRequest
         val inlinePresentationSpecs = inlineSuggestionsRequest?.inlinePresentationSpecs
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
index 8ff17e0..56bd066 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -78,6 +78,8 @@
     isLockedAuthEntry: Boolean = false,
     enforceOneLine: Boolean = false,
     onTextLayout: (TextLayoutResult) -> Unit = {},
+    /** Get flow only, if present, where be drawn as a line above the headline. */
+    affiliatedDomainText: String? = null,
 ) {
     val iconPadding = Modifier.wrapContentSize().padding(
         // Horizontal padding should be 16dp, but the suggestion chip itself
@@ -102,6 +104,13 @@
             ) {
                 // Apply weight so that the trailing icon can always show.
                 Column(modifier = Modifier.wrapContentHeight().fillMaxWidth().weight(1f)) {
+                    if (!affiliatedDomainText.isNullOrBlank()) {
+                        BodySmallText(
+                            text = affiliatedDomainText,
+                            enforceOneLine = enforceOneLine,
+                            onTextLayout = onTextLayout,
+                        )
+                    }
                     SmallTitleText(
                         text = entryHeadlineText,
                         enforceOneLine = enforceOneLine,
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 1fef522..748c798 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -376,6 +376,7 @@
 }
 
 internal const val MAX_ENTRY_FOR_PRIMARY_PAGE = 4
+
 /** Draws the primary credential selection page, used starting from android V. */
 @Composable
 fun PrimarySelectionCardVImpl(
@@ -805,6 +806,7 @@
         },
         enforceOneLine = enforceOneLine,
         onTextLayout = onTextLayout,
+        affiliatedDomainText = credentialEntryInfo.affiliatedDomain,
     )
 }
 
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
index e7f11a1..ef40188 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -18,9 +18,9 @@
 
 import android.credentials.flags.Flags.selectorUiImprovementsEnabled
 import android.graphics.drawable.Drawable
+import androidx.credentials.PriorityHints
 import com.android.credentialmanager.model.get.ProviderInfo
 import com.android.credentialmanager.model.EntryInfo
-import com.android.credentialmanager.model.CredentialType
 import com.android.credentialmanager.model.get.AuthenticationEntryInfo
 import com.android.credentialmanager.model.get.CredentialEntryInfo
 import com.android.credentialmanager.model.get.RemoteEntryInfo
@@ -30,7 +30,8 @@
     val isRequestForAllOptions: Boolean,
     val providerInfoList: List<ProviderInfo>,
     val requestDisplayInfo: RequestDisplayInfo,
-    val providerDisplayInfo: ProviderDisplayInfo = toProviderDisplayInfo(providerInfoList),
+    val providerDisplayInfo: ProviderDisplayInfo =
+            toProviderDisplayInfo(providerInfoList, requestDisplayInfo.typePriorityMap),
     val currentScreenState: GetScreenState = toGetScreenState(
             providerDisplayInfo, isRequestForAllOptions),
     val activeEntry: EntryInfo? = toActiveEntry(providerDisplayInfo),
@@ -79,6 +80,8 @@
     val preferIdentityDocUi: Boolean,
     // A top level branding icon + display name preferred by the app.
     val preferTopBrandingContent: TopBrandingContent?,
+    // Map of credential type -> priority.
+    val typePriorityMap: Map<String, Int>,
 )
 
 data class TopBrandingContent(
@@ -119,7 +122,8 @@
  * @hide
  */
 fun toProviderDisplayInfo(
-    providerInfoList: List<ProviderInfo>
+    providerInfoList: List<ProviderInfo>,
+    typePriorityMap: Map<String, Int>,
 ): ProviderDisplayInfo {
     val userNameToCredentialEntryMap = mutableMapOf<String, MutableList<CredentialEntryInfo>>()
     val authenticationEntryList = mutableListOf<AuthenticationEntryInfo>()
@@ -147,7 +151,7 @@
     }
 
     // Compose sortedUserNameToCredentialEntryList
-    val comparator = CredentialEntryInfoComparatorByTypeThenTimestamp()
+    val comparator = CredentialEntryInfoComparatorByTypeThenTimestamp(typePriorityMap)
     // Sort per username
     userNameToCredentialEntryMap.values.forEach {
         it.sortWith(comparator)
@@ -203,13 +207,21 @@
     else GetScreenState.PRIMARY_SELECTION
 }
 
-internal class CredentialEntryInfoComparatorByTypeThenTimestamp : Comparator<CredentialEntryInfo> {
+internal class CredentialEntryInfoComparatorByTypeThenTimestamp(
+        val typePriorityMap: Map<String, Int>,
+) : Comparator<CredentialEntryInfo> {
     override fun compare(p0: CredentialEntryInfo, p1: CredentialEntryInfo): Int {
         // First prefer passkey type for its security benefits
-        if (p0.credentialType != p1.credentialType) {
-            if (CredentialType.PASSKEY == p0.credentialType) {
+        if (p0.rawCredentialType != p1.rawCredentialType) {
+            val p0Priority = typePriorityMap.getOrDefault(
+                    p0.rawCredentialType, PriorityHints.PRIORITY_DEFAULT
+            )
+            val p1Priority = typePriorityMap.getOrDefault(
+                    p1.rawCredentialType, PriorityHints.PRIORITY_DEFAULT
+            )
+            if (p0Priority < p1Priority) {
                 return -1
-            } else if (CredentialType.PASSKEY == p1.credentialType) {
+            } else if (p1Priority < p0Priority) {
                 return 1
             }
         }
diff --git a/packages/CredentialManager/tests/robotests/screenshot/src/com/android/credentialmanager/GetCredScreenshotTest.kt b/packages/CredentialManager/tests/robotests/screenshot/src/com/android/credentialmanager/GetCredScreenshotTest.kt
index 94217d0..28d83ee 100644
--- a/packages/CredentialManager/tests/robotests/screenshot/src/com/android/credentialmanager/GetCredScreenshotTest.kt
+++ b/packages/CredentialManager/tests/robotests/screenshot/src/com/android/credentialmanager/GetCredScreenshotTest.kt
@@ -53,6 +53,7 @@
                 preferImmediatelyAvailableCredentials = false,
                 preferIdentityDocUi = false,
                 preferTopBrandingContent = null,
+                typePriorityMap = emptyMap(),
         )
     }
 
@@ -68,7 +69,7 @@
     fun singleCredentialScreen_M3BottomSheetDisabled() {
         setFlagsRule.disableFlags(Flags.FLAG_SELECTOR_UI_IMPROVEMENTS_ENABLED)
         val providerInfoList = buildProviderInfoList()
-        val providerDisplayInfo = toProviderDisplayInfo(providerInfoList)
+        val providerDisplayInfo = toProviderDisplayInfo(providerInfoList, emptyMap())
         val activeEntry = toActiveEntry(providerDisplayInfo)
         screenshotRule.screenshotTest("singleCredentialScreen") {
             ModalBottomSheet(
@@ -96,7 +97,7 @@
     fun singleCredentialScreen_M3BottomSheetEnabled() {
         setFlagsRule.enableFlags(Flags.FLAG_SELECTOR_UI_IMPROVEMENTS_ENABLED)
         val providerInfoList = buildProviderInfoList()
-        val providerDisplayInfo = toProviderDisplayInfo(providerInfoList)
+        val providerDisplayInfo = toProviderDisplayInfo(providerInfoList, emptyMap())
         val activeEntry = toActiveEntry(providerDisplayInfo)
         screenshotRule.screenshotTest(
                 "singleCredentialScreen_newM3BottomSheet",
@@ -149,6 +150,8 @@
                                 isAutoSelectable = false,
                                 entryGroupId = "username",
                                 isDefaultIconPreferredAsSingleProvider = false,
+                                rawCredentialType = "unknown-type",
+                                affiliatedDomain = null,
                         )
                 ),
                 authenticationEntryList = emptyList(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
index a4741a5..ef4e530 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java
@@ -482,11 +482,30 @@
                         context.getString(R.string.keyboard_shortcut_group_system),
                         new ArrayList<>());
         List<ShortcutKeyGroupMultiMappingInfo> infoList = Arrays.asList(
-                /* Access notification shade: Meta + N */
+                /* Access list of all apps and search (i.e. Search/Launcher): Meta */
                 new ShortcutKeyGroupMultiMappingInfo(
-                        context.getString(R.string.group_system_access_notification_shade),
+                        context.getString(R.string.group_system_access_all_apps_search),
                         Arrays.asList(
-                                Pair.create(KeyEvent.KEYCODE_N, KeyEvent.META_META_ON))),
+                                Pair.create(KeyEvent.KEYCODE_UNKNOWN, KeyEvent.META_META_ON))),
+                /* Access home screen: Meta + H, Meta + Enter */
+                new ShortcutKeyGroupMultiMappingInfo(
+                        context.getString(R.string.group_system_access_home_screen),
+                        Arrays.asList(
+                                Pair.create(KeyEvent.KEYCODE_H, KeyEvent.META_META_ON),
+                                Pair.create(KeyEvent.KEYCODE_ENTER, KeyEvent.META_META_ON))),
+                /* Overview of open apps: Meta + Tab */
+                new ShortcutKeyGroupMultiMappingInfo(
+                        context.getString(R.string.group_system_overview_open_apps),
+                        Arrays.asList(
+                                Pair.create(KeyEvent.KEYCODE_TAB, KeyEvent.META_META_ON))),
+                /* Back: go back to previous state (back button) */
+                /* Meta + Escape, Meta + backspace, Meta + left arrow */
+                new ShortcutKeyGroupMultiMappingInfo(
+                        context.getString(R.string.group_system_go_back),
+                        Arrays.asList(
+                                Pair.create(KeyEvent.KEYCODE_ESCAPE, KeyEvent.META_META_ON),
+                                Pair.create(KeyEvent.KEYCODE_DEL, KeyEvent.META_META_ON),
+                                Pair.create(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_META_ON))),
                 /* Take a full screenshot: Meta + Ctrl + S */
                 new ShortcutKeyGroupMultiMappingInfo(
                         context.getString(R.string.group_system_full_screenshot),
@@ -499,25 +518,6 @@
                         context.getString(R.string.group_system_access_system_app_shortcuts),
                         Arrays.asList(
                                 Pair.create(KeyEvent.KEYCODE_SLASH, KeyEvent.META_META_ON))),
-                /* Back: go back to previous state (back button) */
-                /* Meta + Escape, Meta + Grave, Meta + backspace, Meta + left arrow */
-                new ShortcutKeyGroupMultiMappingInfo(
-                        context.getString(R.string.group_system_go_back),
-                        Arrays.asList(
-                                Pair.create(KeyEvent.KEYCODE_ESCAPE, KeyEvent.META_META_ON),
-                                Pair.create(KeyEvent.KEYCODE_DEL, KeyEvent.META_META_ON),
-                                Pair.create(KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.META_META_ON))),
-                /* Access home screen: Meta + H, Meta + Enter */
-                new ShortcutKeyGroupMultiMappingInfo(
-                        context.getString(R.string.group_system_access_home_screen),
-                        Arrays.asList(
-                                Pair.create(KeyEvent.KEYCODE_H, KeyEvent.META_META_ON),
-                                Pair.create(KeyEvent.KEYCODE_ENTER, KeyEvent.META_META_ON))),
-                /* Overview of open apps: Meta + Tab */
-                new ShortcutKeyGroupMultiMappingInfo(
-                        context.getString(R.string.group_system_overview_open_apps),
-                        Arrays.asList(
-                                Pair.create(KeyEvent.KEYCODE_TAB, KeyEvent.META_META_ON))),
                 /* Cycle through recent apps (forward): Alt + Tab */
                 new ShortcutKeyGroupMultiMappingInfo(
                         context.getString(R.string.group_system_cycle_forward),
@@ -530,26 +530,16 @@
                                 Pair.create(
                                         KeyEvent.KEYCODE_TAB,
                                         KeyEvent.META_SHIFT_ON | KeyEvent.META_ALT_ON))),
-                /* Access list of all apps and search (i.e. Search/Launcher): Meta */
-                new ShortcutKeyGroupMultiMappingInfo(
-                        context.getString(R.string.group_system_access_all_apps_search),
-                        Arrays.asList(
-                                Pair.create(KeyEvent.KEYCODE_UNKNOWN, KeyEvent.META_META_ON))),
                 /* Hide and (re)show taskbar: Meta + T */
                 new ShortcutKeyGroupMultiMappingInfo(
                         context.getString(R.string.group_system_hide_reshow_taskbar),
                         Arrays.asList(
                                 Pair.create(KeyEvent.KEYCODE_T, KeyEvent.META_META_ON))),
-                /* Access system settings: Meta + I */
+                /* Access notification shade: Meta + N */
                 new ShortcutKeyGroupMultiMappingInfo(
-                        context.getString(R.string.group_system_access_system_settings),
+                        context.getString(R.string.group_system_access_notification_shade),
                         Arrays.asList(
-                                Pair.create(KeyEvent.KEYCODE_I, KeyEvent.META_META_ON))),
-                /* Access Google Assistant: Meta + A */
-                new ShortcutKeyGroupMultiMappingInfo(
-                        context.getString(R.string.group_system_access_google_assistant),
-                        Arrays.asList(
-                                Pair.create(KeyEvent.KEYCODE_A, KeyEvent.META_META_ON))),
+                                Pair.create(KeyEvent.KEYCODE_N, KeyEvent.META_META_ON))),
                 /*  Lock screen: Meta + L */
                 new ShortcutKeyGroupMultiMappingInfo(
                         context.getString(R.string.group_system_lock_screen),
@@ -561,7 +551,17 @@
                         Arrays.asList(
                                 Pair.create(
                                         KeyEvent.KEYCODE_N,
-                                        KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON)))
+                                        KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON))),
+                /* Access system settings: Meta + I */
+                new ShortcutKeyGroupMultiMappingInfo(
+                        context.getString(R.string.group_system_access_system_settings),
+                        Arrays.asList(
+                                Pair.create(KeyEvent.KEYCODE_I, KeyEvent.META_META_ON))),
+                /* Access Google Assistant: Meta + A */
+                new ShortcutKeyGroupMultiMappingInfo(
+                        context.getString(R.string.group_system_access_google_assistant),
+                        Arrays.asList(
+                                Pair.create(KeyEvent.KEYCODE_A, KeyEvent.META_META_ON)))
         );
         for (ShortcutKeyGroupMultiMappingInfo info : infoList) {
             systemGroup.addItem(info.getShortcutMultiMappingInfo());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractor.kt
new file mode 100644
index 0000000..9cd46f5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractor.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
+
+/** Interactor exposing states related to the stack's context */
+@SysUISingleton
+class NotificationStackInteractor
+@Inject
+constructor(
+    keyguardInteractor: KeyguardInteractor,
+    powerInteractor: PowerInteractor,
+) {
+    val isShowingOnLockscreen: Flow<Boolean> =
+        combine(
+                // Non-notification UI elements of the notification list should not be visible
+                // on the lockscreen (incl. AOD and bouncer), except if the shade is opened on
+                // top. See b/219680200 for the footer and b/228790482, b/267060171 for the
+                // empty shade.
+                // TODO(b/323187006): There's a plan to eventually get rid of StatusBarState
+                //  entirely, so this will have to be replaced at some point.
+                keyguardInteractor.statusBarState.map { it == StatusBarState.KEYGUARD },
+                // The StatusBarState is unfortunately not updated quickly enough when the power
+                // button is pressed, so this is necessary in addition to the KEYGUARD check to
+                // cover the transition to AOD while going to sleep (b/190227875).
+                powerInteractor.isAsleep,
+            ) { (isOnKeyguard, isAsleep) ->
+                isOnKeyguard || isAsleep
+            }
+            .distinctUntilChanged()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
index 7b50256..c85a18a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt
@@ -16,9 +16,6 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.shared.model.StatusBarState
-import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.statusbar.domain.interactor.RemoteInputInteractor
 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
@@ -26,6 +23,7 @@
 import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
 import com.android.systemui.statusbar.notification.footer.ui.viewmodel.FooterViewModel
 import com.android.systemui.statusbar.notification.shelf.ui.viewmodel.NotificationShelfViewModel
+import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackInteractor
 import com.android.systemui.statusbar.policy.domain.interactor.UserSetupInteractor
 import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
 import com.android.systemui.util.kotlin.combine
@@ -51,8 +49,7 @@
     val footer: Optional<FooterViewModel>,
     val logger: Optional<NotificationLoggerViewModel>,
     activeNotificationsInteractor: ActiveNotificationsInteractor,
-    keyguardInteractor: KeyguardInteractor,
-    powerInteractor: PowerInteractor,
+    notificationStackInteractor: NotificationStackInteractor,
     remoteInputInteractor: RemoteInputInteractor,
     seenNotificationsInteractor: SeenNotificationsInteractor,
     shadeInteractor: ShadeInteractor,
@@ -71,7 +68,7 @@
         } else {
             combine(
                     activeNotificationsInteractor.areAnyNotificationsPresent,
-                    isShowingOnLockscreen,
+                    notificationStackInteractor.isShowingOnLockscreen,
                 ) { hasNotifications, isShowingOnLockscreen ->
                     hasNotifications || !isShowingOnLockscreen
                 }
@@ -86,7 +83,7 @@
             combine(
                     activeNotificationsInteractor.areAnyNotificationsPresent,
                     shadeInteractor.isQsFullscreen,
-                    isShowingOnLockscreen,
+                    notificationStackInteractor.isShowingOnLockscreen,
                 ) { hasNotifications, isQsFullScreen, isShowingOnLockscreen ->
                     when {
                         hasNotifications -> false
@@ -109,7 +106,7 @@
             combine(
                     activeNotificationsInteractor.areAnyNotificationsPresent,
                     userSetupInteractor.isUserSetUp,
-                    isShowingOnLockscreen,
+                    notificationStackInteractor.isShowingOnLockscreen,
                     shadeInteractor.qsExpansion,
                     shadeInteractor.isQsFullscreen,
                     remoteInputInteractor.isRemoteInputActive,
@@ -177,29 +174,6 @@
         SHOW_WITH_ANIMATION(visible = true, canAnimate = true)
     }
 
-    private val isShowingOnLockscreen: Flow<Boolean> by lazy {
-        if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
-            flowOf(false)
-        } else {
-            combine(
-                    // Non-notification UI elements of the notification list should not be visible
-                    // on the lockscreen (incl. AOD and bouncer), except if the shade is opened on
-                    // top. See b/219680200 for the footer and b/228790482, b/267060171 for the
-                    // empty shade.
-                    // TODO(b/323187006): There's a plan to eventually get rid of StatusBarState
-                    //  entirely, so this will have to be replaced at some point.
-                    keyguardInteractor.statusBarState.map { it == StatusBarState.KEYGUARD },
-                    // The StatusBarState is unfortunately not updated quickly enough when the power
-                    // button is pressed, so this is necessary in addition to the KEYGUARD check to
-                    // cover the transition to AOD while going to sleep (b/190227875).
-                    powerInteractor.isAsleep,
-                ) { (isOnKeyguard, isAsleep) ->
-                    isOnKeyguard || isAsleep
-                }
-                .distinctUntilChanged()
-        }
-    }
-
     // TODO(b/308591475): This should be tracked separately by the empty shade.
     val areNotificationsHiddenInShade: Flow<Boolean> by lazy {
         if (FooterViewRefactor.isUnexpectedlyInLegacyMode()) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorTest.kt
new file mode 100644
index 0000000..1c6bda9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorTest.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar.notification.stack.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.shared.model.StatusBarState
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class NotificationStackInteractorTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+    val underTest
+        get() = kosmos.notificationStackInteractor
+
+    @Test
+    fun testIsShowingOnLockscreen_falseWhenViewingShade() =
+        kosmos.testScope.runTest {
+            val onLockscreen by collectLastValue(underTest.isShowingOnLockscreen)
+
+            // WHEN shade is open
+            kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.SHADE)
+            runCurrent()
+
+            // THEN notifications are not showing on lockscreen
+            assertThat(onLockscreen).isFalse()
+        }
+
+    @Test
+    fun testIsShowingOnLockscreen_trueWhenViewingKeyguard() =
+        kosmos.testScope.runTest {
+            val onLockscreen by collectLastValue(underTest.isShowingOnLockscreen)
+
+            // WHEN on keyguard
+            kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+            runCurrent()
+
+            // THEN notifications are showing on lockscreen
+            assertThat(onLockscreen).isTrue()
+        }
+
+    @Test
+    fun testIsShowingOnLockscreen_trueWhenStartingToSleep() =
+        kosmos.testScope.runTest {
+            val onLockscreen by collectLastValue(underTest.isShowingOnLockscreen)
+
+            // WHEN shade is open
+            kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.SHADE)
+            // AND device is starting to go to sleep
+            kosmos.fakePowerRepository.updateWakefulness(WakefulnessState.STARTING_TO_SLEEP)
+            runCurrent()
+
+            // THEN notifications are showing on lockscreen
+            assertThat(onLockscreen).isTrue()
+        }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorKosmos.kt
new file mode 100644
index 0000000..db6ba62
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackInteractorKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack.domain.interactor
+
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.power.domain.interactor.powerInteractor
+
+val Kosmos.notificationStackInteractor by Fixture {
+    NotificationStackInteractor(
+        keyguardInteractor = keyguardInteractor,
+        powerInteractor = powerInteractor,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelKosmos.kt
index 25e3eac..f1767eb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelKosmos.kt
@@ -16,16 +16,15 @@
 
 package com.android.systemui.statusbar.notification.stack.ui.viewmodel
 
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.statusbar.domain.interactor.remoteInputInteractor
 import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
 import com.android.systemui.statusbar.notification.domain.interactor.seenNotificationsInteractor
 import com.android.systemui.statusbar.notification.footer.ui.viewmodel.footerViewModel
 import com.android.systemui.statusbar.notification.shelf.ui.viewmodel.notificationShelfViewModel
+import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationStackInteractor
 import com.android.systemui.statusbar.policy.domain.interactor.userSetupInteractor
 import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
 import java.util.Optional
@@ -37,8 +36,7 @@
         Optional.of(footerViewModel),
         Optional.of(notificationListLoggerViewModel),
         activeNotificationsInteractor,
-        keyguardInteractor,
-        powerInteractor,
+        notificationStackInteractor,
         remoteInputInteractor,
         seenNotificationsInteractor,
         shadeInteractor,
diff --git a/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java b/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
index a4c4347..0abe50f 100644
--- a/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
+++ b/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
@@ -16,6 +16,8 @@
 
 package com.android.server.ondeviceintelligence;
 
+import static android.service.ondeviceintelligence.OnDeviceIntelligenceService.OnDeviceUpdateProcessingException.PROCESSING_UPDATE_STATUS_CONNECTION_FAILED;
+
 import android.Manifest;
 import android.annotation.NonNull;
 import android.app.AppGlobals;
@@ -36,6 +38,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.os.Bundle;
 import android.os.ICancellationSignal;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
@@ -43,8 +46,12 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
+import android.service.ondeviceintelligence.IOnDeviceIntelligenceService;
 import android.service.ondeviceintelligence.IOnDeviceTrustedInferenceService;
+import android.service.ondeviceintelligence.IRemoteProcessingService;
 import android.service.ondeviceintelligence.IRemoteStorageService;
+import android.service.ondeviceintelligence.IProcessingUpdateStatusCallback;
+import android.service.ondeviceintelligence.OnDeviceIntelligenceService;
 import android.text.TextUtils;
 import android.util.Slog;
 
@@ -59,10 +66,11 @@
 import java.util.Set;
 
 /**
- * This is the system service for handling calls on the {@link OnDeviceIntelligenceManager}. This
+ * This is the system service for handling calls on the
+ * {@link android.app.ondeviceintelligence.OnDeviceIntelligenceManager}. This
  * service holds connection references to the underlying remote services i.e. the isolated service
- * {@link android.service.ondeviceintelligence.OnDeviceTrustedInferenceService} and a regular
- * service counter part {@link android.service.ondeviceintelligence.OnDeviceIntelligenceService}.
+ * {@link  OnDeviceTrustedInferenceService} and a regular
+ * service counter part {@link OnDeviceIntelligenceService}.
  *
  * Note: Both the remote services run under the SYSTEM user, as we cannot have separate instance of
  * the Inference service for each user, due to possible high memory footprint.
@@ -313,10 +321,48 @@
                 mRemoteOnDeviceIntelligenceService = new RemoteOnDeviceIntelligenceService(mContext,
                         ComponentName.unflattenFromString(serviceName),
                         UserHandle.SYSTEM.getIdentifier());
+                mRemoteOnDeviceIntelligenceService.setServiceLifecycleCallbacks(
+                        new ServiceConnector.ServiceLifecycleCallbacks<>() {
+                            @Override
+                            public void onConnected(
+                                    @NonNull IOnDeviceIntelligenceService service) {
+                                try {
+                                    service.registerRemoteServices(
+                                            getRemoteProcessingService());
+                                } catch (RemoteException ex) {
+                                    Slog.w(TAG, "Failed to send connected event", ex);
+                                }
+                            }
+                        });
             }
         }
     }
 
+    @NonNull
+    private IRemoteProcessingService.Stub getRemoteProcessingService() {
+        return new IRemoteProcessingService.Stub() {
+            @Override
+            public void updateProcessingState(
+                    Bundle processingState,
+                    IProcessingUpdateStatusCallback callback) {
+                try {
+                    ensureRemoteTrustedInferenceServiceInitialized();
+                    mRemoteInferenceService.post(
+                            service -> service.updateProcessingState(
+                                    processingState, callback));
+                } catch (RemoteException unused) {
+                    try {
+                        callback.onFailure(
+                                PROCESSING_UPDATE_STATUS_CONNECTION_FAILED,
+                                "Received failure invoking the remote processing service.");
+                    } catch (RemoteException ex) {
+                        Slog.w(TAG, "Failed to send failure status.", ex);
+                    }
+                }
+            }
+        };
+    }
+
     private void ensureRemoteTrustedInferenceServiceInitialized() throws RemoteException {
         synchronized (mLock) {
             if (mRemoteInferenceService == null) {
@@ -332,6 +378,7 @@
                             public void onConnected(
                                     @NonNull IOnDeviceTrustedInferenceService service) {
                                 try {
+                                    ensureRemoteIntelligenceServiceInitialized();
                                     service.registerRemoteStorageService(
                                             getIRemoteStorageService());
                                 } catch (RemoteException ex) {
@@ -358,8 +405,7 @@
             @Override
             public void getReadOnlyFeatureFileDescriptorMap(
                     Feature feature,
-                    RemoteCallback remoteCallback)
-                    throws RemoteException {
+                    RemoteCallback remoteCallback) {
                 mRemoteOnDeviceIntelligenceService.post(
                         service -> service.getReadOnlyFeatureFileDescriptorMap(
                                 feature, remoteCallback));
diff --git a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
index c2f5b8f..901daf8 100644
--- a/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
+++ b/telephony/java/android/telephony/TelephonyFrameworkInitializer.java
@@ -19,12 +19,14 @@
 import android.annotation.NonNull;
 import android.app.SystemServiceRegistry;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.TelephonyServiceManager;
 import android.telephony.euicc.EuiccCardManager;
 import android.telephony.euicc.EuiccManager;
 import android.telephony.ims.ImsManager;
 import android.telephony.satellite.SatelliteManager;
 
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.util.Preconditions;
 
 
@@ -55,6 +57,11 @@
         sTelephonyServiceManager = Preconditions.checkNotNull(telephonyServiceManager);
     }
 
+    private static boolean hasSystemFeature(Context context, String feature) {
+        if (!Flags.minimalTelephonyManagersConditionalOnFeatures()) return true;
+        return context.getPackageManager().hasSystemFeature(feature);
+    }
+
     /**
      * Called by {@link SystemServiceRegistry}'s static initializer and registers all telephony
      * services to {@link Context}, so that {@link Context#getSystemService} can return them.
@@ -76,33 +83,39 @@
         SystemServiceRegistry.registerContextAwareService(
                 Context.CARRIER_CONFIG_SERVICE,
                 CarrierConfigManager.class,
-                context -> new CarrierConfigManager(context)
+                context -> hasSystemFeature(context, PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION)
+                        ? new CarrierConfigManager(context) : null
         );
         SystemServiceRegistry.registerContextAwareService(
                 Context.EUICC_SERVICE,
                 EuiccManager.class,
-                context -> new EuiccManager(context)
+                context -> hasSystemFeature(context, PackageManager.FEATURE_TELEPHONY_EUICC)
+                        ? new EuiccManager(context) : null
         );
         SystemServiceRegistry.registerContextAwareService(
                 Context.EUICC_CARD_SERVICE,
                 EuiccCardManager.class,
-                context -> new EuiccCardManager(context)
+                context -> hasSystemFeature(context, PackageManager.FEATURE_TELEPHONY_EUICC)
+                        ? new EuiccCardManager(context) : null
         );
         SystemServiceRegistry.registerContextAwareService(
                 Context.TELEPHONY_IMS_SERVICE,
                 ImsManager.class,
-                context -> new ImsManager(context)
+                context -> hasSystemFeature(context, PackageManager.FEATURE_TELEPHONY_IMS)
+                        ? new ImsManager(context) : null
         );
         SystemServiceRegistry.registerContextAwareService(
                 Context.SMS_SERVICE,
                 SmsManager.class,
-                context -> SmsManager.getSmsManagerForContextAndSubscriptionId(context,
-                        SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)
+                context -> hasSystemFeature(context, PackageManager.FEATURE_TELEPHONY_MESSAGING)
+                        ? SmsManager.getSmsManagerForContextAndSubscriptionId(context,
+                                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) : null
         );
         SystemServiceRegistry.registerContextAwareService(
                 Context.SATELLITE_SERVICE,
                 SatelliteManager.class,
-                context -> new SatelliteManager(context)
+                context -> hasSystemFeature(context, PackageManager.FEATURE_TELEPHONY_SATELLITE)
+                        ? new SatelliteManager(context) : null
         );
     }
 
diff --git a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt
index d47329e..57da05f 100644
--- a/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt
+++ b/tests/FlickerTests/AppLaunch/src/com/android/server/wm/flicker/launch/OpenAppFromIntentColdAfterCameraTest.kt
@@ -52,6 +52,7 @@
                 // Can't use TAPL due to Recents not showing in 3 Button Nav in full screen mode
                 device.pressHome()
                 tapl.getWorkspace()
+                wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
             }
             teardown { testApp.exit(wmHelper) }
             transitions { testApp.launchViaIntent(wmHelper) }