Merge "Allow credential providers to set an "origin" for affiliated credentials" 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/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
);
}