Loading core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java +5 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,11 @@ public abstract class OnDeviceSandboxedInferenceService extends Service { */ public static final String MODEL_UNLOADED_BUNDLE_KEY = "model_unloaded"; /** * @hide */ public static final String DEVICE_CONFIG_UPDATE_BUNDLE_KEY = "device_config_update"; private IRemoteStorageService mRemoteStorageService; /** Loading core/res/res/values/config.xml +2 −0 Original line number Diff line number Diff line Loading @@ -4723,6 +4723,8 @@ <!-- The broadcast intent name for notifying when the on-device model has been unloaded --> <string name="config_onDeviceIntelligenceModelUnloadedBroadcastKey" translatable="false"></string> <!-- The DeviceConfig namespace for the default system on-device sandboxed inference service. --> <string name="config_defaultOnDeviceIntelligenceDeviceConfigNamespace" translatable="false"></string> <!-- Component name that accepts ACTION_SEND intents for requesting ambient context consent for wearable sensing. --> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3947,6 +3947,7 @@ <java-symbol type="string" name="config_defaultOnDeviceSandboxedInferenceService" /> <java-symbol type="string" name="config_onDeviceIntelligenceModelLoadedBroadcastKey" /> <java-symbol type="string" name="config_onDeviceIntelligenceModelUnloadedBroadcastKey" /> <java-symbol type="string" name="config_defaultOnDeviceIntelligenceDeviceConfigNamespace" /> <java-symbol type="string" name="config_retailDemoPackage" /> <java-symbol type="string" name="config_retailDemoPackageSignature" /> Loading services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java +89 −10 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.ondeviceintelligence; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.DEVICE_CONFIG_UPDATE_BUNDLE_KEY; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.MODEL_LOADED_BUNDLE_KEY; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.MODEL_UNLOADED_BUNDLE_KEY; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.REGISTER_MODEL_UPDATE_CALLBACK_BUNDLE_KEY; Loading Loading @@ -115,9 +116,10 @@ public class OnDeviceIntelligenceManagerService extends SystemService { /** Handler message to {@link #resetTemporaryServices()} */ private static final int MSG_RESET_TEMPORARY_SERVICE = 0; /** Handler message to clean up temporary broadcast keys. */ private static final int MSG_RESET_BROADCAST_KEYS = 1; /** Handler message to clean up temporary config namespace. */ private static final int MSG_RESET_CONFIG_NAMESPACE = 2; /** Default value in absence of {@link DeviceConfig} override. */ private static final boolean DEFAULT_SERVICE_ENABLED = true; Loading @@ -129,6 +131,7 @@ public class OnDeviceIntelligenceManagerService extends SystemService { private final Executor resourceClosingExecutor = Executors.newCachedThreadPool(); private final Executor callbackExecutor = Executors.newCachedThreadPool(); private final Executor broadcastExecutor = Executors.newCachedThreadPool(); private final Executor mConfigExecutor = Executors.newCachedThreadPool(); private final Context mContext; Loading @@ -145,6 +148,12 @@ public class OnDeviceIntelligenceManagerService extends SystemService { private String[] mTemporaryBroadcastKeys; @GuardedBy("mLock") private String mBroadcastPackageName; @GuardedBy("mLock") private String mTemporaryConfigNamespace; private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener = this::sendUpdatedConfig; /** * Handler used to reset the temporary service names. Loading Loading @@ -593,12 +602,14 @@ public class OnDeviceIntelligenceManagerService extends SystemService { @NonNull IOnDeviceSandboxedInferenceService service) { try { ensureRemoteIntelligenceServiceInitialized(); service.registerRemoteStorageService( getIRemoteStorageService()); mRemoteOnDeviceIntelligenceService.run( IOnDeviceIntelligenceService::notifyInferenceServiceConnected); broadcastExecutor.execute( () -> registerModelLoadingBroadcasts(service)); service.registerRemoteStorageService( getIRemoteStorageService()); mConfigExecutor.execute( () -> registerDeviceConfigChangeListener()); } catch (RemoteException ex) { Slog.w(TAG, "Failed to send connected event", ex); } Loading Loading @@ -658,6 +669,58 @@ public class OnDeviceIntelligenceManagerService extends SystemService { } } private void registerDeviceConfigChangeListener() { Log.e(TAG, "registerDeviceConfigChangeListener"); String configNamespace = getConfigNamespace(); if (configNamespace.isEmpty()) { Slog.e(TAG, "config_defaultOnDeviceIntelligenceDeviceConfigNamespace is empty"); return; } DeviceConfig.addOnPropertiesChangedListener( configNamespace, mConfigExecutor, mOnPropertiesChangedListener); } private String getConfigNamespace() { synchronized (mLock) { if (mTemporaryConfigNamespace != null) { return mTemporaryConfigNamespace; } return mContext.getResources().getString( R.string.config_defaultOnDeviceIntelligenceDeviceConfigNamespace); } } private void sendUpdatedConfig( DeviceConfig.Properties props) { Log.e(TAG, "sendUpdatedConfig"); PersistableBundle persistableBundle = new PersistableBundle(); for (String key : props.getKeyset()) { persistableBundle.putString(key, props.getString(key, "")); } Bundle bundle = new Bundle(); bundle.putParcelable(DEVICE_CONFIG_UPDATE_BUNDLE_KEY, persistableBundle); ensureRemoteInferenceServiceInitialized(); Log.e(TAG, "sendUpdatedConfig: BUNDLE: " + bundle); mRemoteInferenceService.run(service -> service.updateProcessingState(bundle, new IProcessingUpdateStatusCallback.Stub() { @Override public void onSuccess(PersistableBundle result) { Slog.d(TAG, "Config update successful." + result); } @Override public void onFailure(int errorCode, String errorMessage) { Slog.e(TAG, "Config update failed with code [" + String.valueOf(errorCode) + "] and message = " + errorMessage); } })); } @NonNull private IRemoteStorageService.Stub getIRemoteStorageService() { return new IRemoteStorageService.Stub() { Loading Loading @@ -848,6 +911,22 @@ public class OnDeviceIntelligenceManagerService extends SystemService { } } @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) public void setTemporaryDeviceConfigNamespace(@NonNull String configNamespace, int durationMs) { Objects.requireNonNull(configNamespace); enforceShellOnly(Binder.getCallingUid(), "setTemporaryDeviceConfigNamespace"); mContext.enforceCallingPermission( Manifest.permission.USE_ON_DEVICE_INTELLIGENCE, TAG); synchronized (mLock) { mTemporaryConfigNamespace = configNamespace; if (durationMs != -1) { getTemporaryHandler().sendEmptyMessageDelayed(MSG_RESET_CONFIG_NAMESPACE, durationMs); } } } @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) public void resetTemporaryServices() { mContext.enforceCallingPermission( Loading Loading @@ -936,19 +1015,19 @@ public class OnDeviceIntelligenceManagerService extends SystemService { mTemporaryHandler = new Handler(Looper.getMainLooper(), null, true) { @Override public void handleMessage(Message msg) { if (msg.what == MSG_RESET_TEMPORARY_SERVICE) { synchronized (mLock) { if (msg.what == MSG_RESET_TEMPORARY_SERVICE) { resetTemporaryServices(); } } else if (msg.what == MSG_RESET_BROADCAST_KEYS) { synchronized (mLock) { mTemporaryBroadcastKeys = null; mBroadcastPackageName = SYSTEM_PACKAGE; } } else if (msg.what == MSG_RESET_CONFIG_NAMESPACE) { mTemporaryConfigNamespace = null; } else { Slog.wtf(TAG, "invalid handler msg: " + msg); } } } }; } Loading services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceShellCommand.java +18 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ final class OnDeviceIntelligenceShellCommand extends ShellCommand { return getConfiguredServices(); case "set-model-broadcasts": return setBroadcastKeys(); case "set-deviceconfig-namespace": return setDeviceConfigNamespace(); default: return handleDefaultCommands(cmd); } Loading @@ -70,6 +72,10 @@ final class OnDeviceIntelligenceShellCommand extends ShellCommand { + "[ReceiverPackageName] " + "[DURATION] To set the names of broadcast intent keys that are to be " + "emitted for cts tests."); pw.println( " set-deviceconfig-namespace [DeviceConfigNamespace] " + "[DURATION] To set the device config namespace " + "to use for cts tests."); } private int setTemporaryServices() { Loading Loading @@ -123,4 +129,16 @@ final class OnDeviceIntelligenceShellCommand extends ShellCommand { return 0; } private int setDeviceConfigNamespace() { final PrintWriter out = getOutPrintWriter(); final String configNamespace = getNextArg(); final int duration = Integer.parseInt(getNextArgRequired()); mService.setTemporaryDeviceConfigNamespace(configNamespace, duration); out.println("OnDeviceIntelligence DeviceConfig Namespace temporarily set to " + configNamespace + " for " + duration + "ms"); return 0; } } No newline at end of file Loading
core/java/android/service/ondeviceintelligence/OnDeviceSandboxedInferenceService.java +5 −0 Original line number Diff line number Diff line Loading @@ -120,6 +120,11 @@ public abstract class OnDeviceSandboxedInferenceService extends Service { */ public static final String MODEL_UNLOADED_BUNDLE_KEY = "model_unloaded"; /** * @hide */ public static final String DEVICE_CONFIG_UPDATE_BUNDLE_KEY = "device_config_update"; private IRemoteStorageService mRemoteStorageService; /** Loading
core/res/res/values/config.xml +2 −0 Original line number Diff line number Diff line Loading @@ -4723,6 +4723,8 @@ <!-- The broadcast intent name for notifying when the on-device model has been unloaded --> <string name="config_onDeviceIntelligenceModelUnloadedBroadcastKey" translatable="false"></string> <!-- The DeviceConfig namespace for the default system on-device sandboxed inference service. --> <string name="config_defaultOnDeviceIntelligenceDeviceConfigNamespace" translatable="false"></string> <!-- Component name that accepts ACTION_SEND intents for requesting ambient context consent for wearable sensing. --> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -3947,6 +3947,7 @@ <java-symbol type="string" name="config_defaultOnDeviceSandboxedInferenceService" /> <java-symbol type="string" name="config_onDeviceIntelligenceModelLoadedBroadcastKey" /> <java-symbol type="string" name="config_onDeviceIntelligenceModelUnloadedBroadcastKey" /> <java-symbol type="string" name="config_defaultOnDeviceIntelligenceDeviceConfigNamespace" /> <java-symbol type="string" name="config_retailDemoPackage" /> <java-symbol type="string" name="config_retailDemoPackageSignature" /> Loading
services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java +89 −10 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.ondeviceintelligence; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.DEVICE_CONFIG_UPDATE_BUNDLE_KEY; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.MODEL_LOADED_BUNDLE_KEY; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.MODEL_UNLOADED_BUNDLE_KEY; import static android.service.ondeviceintelligence.OnDeviceSandboxedInferenceService.REGISTER_MODEL_UPDATE_CALLBACK_BUNDLE_KEY; Loading Loading @@ -115,9 +116,10 @@ public class OnDeviceIntelligenceManagerService extends SystemService { /** Handler message to {@link #resetTemporaryServices()} */ private static final int MSG_RESET_TEMPORARY_SERVICE = 0; /** Handler message to clean up temporary broadcast keys. */ private static final int MSG_RESET_BROADCAST_KEYS = 1; /** Handler message to clean up temporary config namespace. */ private static final int MSG_RESET_CONFIG_NAMESPACE = 2; /** Default value in absence of {@link DeviceConfig} override. */ private static final boolean DEFAULT_SERVICE_ENABLED = true; Loading @@ -129,6 +131,7 @@ public class OnDeviceIntelligenceManagerService extends SystemService { private final Executor resourceClosingExecutor = Executors.newCachedThreadPool(); private final Executor callbackExecutor = Executors.newCachedThreadPool(); private final Executor broadcastExecutor = Executors.newCachedThreadPool(); private final Executor mConfigExecutor = Executors.newCachedThreadPool(); private final Context mContext; Loading @@ -145,6 +148,12 @@ public class OnDeviceIntelligenceManagerService extends SystemService { private String[] mTemporaryBroadcastKeys; @GuardedBy("mLock") private String mBroadcastPackageName; @GuardedBy("mLock") private String mTemporaryConfigNamespace; private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener = this::sendUpdatedConfig; /** * Handler used to reset the temporary service names. Loading Loading @@ -593,12 +602,14 @@ public class OnDeviceIntelligenceManagerService extends SystemService { @NonNull IOnDeviceSandboxedInferenceService service) { try { ensureRemoteIntelligenceServiceInitialized(); service.registerRemoteStorageService( getIRemoteStorageService()); mRemoteOnDeviceIntelligenceService.run( IOnDeviceIntelligenceService::notifyInferenceServiceConnected); broadcastExecutor.execute( () -> registerModelLoadingBroadcasts(service)); service.registerRemoteStorageService( getIRemoteStorageService()); mConfigExecutor.execute( () -> registerDeviceConfigChangeListener()); } catch (RemoteException ex) { Slog.w(TAG, "Failed to send connected event", ex); } Loading Loading @@ -658,6 +669,58 @@ public class OnDeviceIntelligenceManagerService extends SystemService { } } private void registerDeviceConfigChangeListener() { Log.e(TAG, "registerDeviceConfigChangeListener"); String configNamespace = getConfigNamespace(); if (configNamespace.isEmpty()) { Slog.e(TAG, "config_defaultOnDeviceIntelligenceDeviceConfigNamespace is empty"); return; } DeviceConfig.addOnPropertiesChangedListener( configNamespace, mConfigExecutor, mOnPropertiesChangedListener); } private String getConfigNamespace() { synchronized (mLock) { if (mTemporaryConfigNamespace != null) { return mTemporaryConfigNamespace; } return mContext.getResources().getString( R.string.config_defaultOnDeviceIntelligenceDeviceConfigNamespace); } } private void sendUpdatedConfig( DeviceConfig.Properties props) { Log.e(TAG, "sendUpdatedConfig"); PersistableBundle persistableBundle = new PersistableBundle(); for (String key : props.getKeyset()) { persistableBundle.putString(key, props.getString(key, "")); } Bundle bundle = new Bundle(); bundle.putParcelable(DEVICE_CONFIG_UPDATE_BUNDLE_KEY, persistableBundle); ensureRemoteInferenceServiceInitialized(); Log.e(TAG, "sendUpdatedConfig: BUNDLE: " + bundle); mRemoteInferenceService.run(service -> service.updateProcessingState(bundle, new IProcessingUpdateStatusCallback.Stub() { @Override public void onSuccess(PersistableBundle result) { Slog.d(TAG, "Config update successful." + result); } @Override public void onFailure(int errorCode, String errorMessage) { Slog.e(TAG, "Config update failed with code [" + String.valueOf(errorCode) + "] and message = " + errorMessage); } })); } @NonNull private IRemoteStorageService.Stub getIRemoteStorageService() { return new IRemoteStorageService.Stub() { Loading Loading @@ -848,6 +911,22 @@ public class OnDeviceIntelligenceManagerService extends SystemService { } } @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) public void setTemporaryDeviceConfigNamespace(@NonNull String configNamespace, int durationMs) { Objects.requireNonNull(configNamespace); enforceShellOnly(Binder.getCallingUid(), "setTemporaryDeviceConfigNamespace"); mContext.enforceCallingPermission( Manifest.permission.USE_ON_DEVICE_INTELLIGENCE, TAG); synchronized (mLock) { mTemporaryConfigNamespace = configNamespace; if (durationMs != -1) { getTemporaryHandler().sendEmptyMessageDelayed(MSG_RESET_CONFIG_NAMESPACE, durationMs); } } } @RequiresPermission(Manifest.permission.USE_ON_DEVICE_INTELLIGENCE) public void resetTemporaryServices() { mContext.enforceCallingPermission( Loading Loading @@ -936,19 +1015,19 @@ public class OnDeviceIntelligenceManagerService extends SystemService { mTemporaryHandler = new Handler(Looper.getMainLooper(), null, true) { @Override public void handleMessage(Message msg) { if (msg.what == MSG_RESET_TEMPORARY_SERVICE) { synchronized (mLock) { if (msg.what == MSG_RESET_TEMPORARY_SERVICE) { resetTemporaryServices(); } } else if (msg.what == MSG_RESET_BROADCAST_KEYS) { synchronized (mLock) { mTemporaryBroadcastKeys = null; mBroadcastPackageName = SYSTEM_PACKAGE; } } else if (msg.what == MSG_RESET_CONFIG_NAMESPACE) { mTemporaryConfigNamespace = null; } else { Slog.wtf(TAG, "invalid handler msg: " + msg); } } } }; } Loading
services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceShellCommand.java +18 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,8 @@ final class OnDeviceIntelligenceShellCommand extends ShellCommand { return getConfiguredServices(); case "set-model-broadcasts": return setBroadcastKeys(); case "set-deviceconfig-namespace": return setDeviceConfigNamespace(); default: return handleDefaultCommands(cmd); } Loading @@ -70,6 +72,10 @@ final class OnDeviceIntelligenceShellCommand extends ShellCommand { + "[ReceiverPackageName] " + "[DURATION] To set the names of broadcast intent keys that are to be " + "emitted for cts tests."); pw.println( " set-deviceconfig-namespace [DeviceConfigNamespace] " + "[DURATION] To set the device config namespace " + "to use for cts tests."); } private int setTemporaryServices() { Loading Loading @@ -123,4 +129,16 @@ final class OnDeviceIntelligenceShellCommand extends ShellCommand { return 0; } private int setDeviceConfigNamespace() { final PrintWriter out = getOutPrintWriter(); final String configNamespace = getNextArg(); final int duration = Integer.parseInt(getNextArgRequired()); mService.setTemporaryDeviceConfigNamespace(configNamespace, duration); out.println("OnDeviceIntelligence DeviceConfig Namespace temporarily set to " + configNamespace + " for " + duration + "ms"); return 0; } } No newline at end of file