Loading AconfigFlags.bp +9 −2 Original line number Diff line number Diff line Loading @@ -111,7 +111,6 @@ aconfig_declarations_group { "com.android.window.flags.window-aconfig-java", "configinfra_framework_flags_java_exported_lib", "conscrypt_exported_aconfig_flags_lib", "sdk_sandbox_exported_flags_lib", "device_policy_aconfig_flags_lib", "display_flags_lib", "dropbox_flags_lib", Loading @@ -125,6 +124,7 @@ aconfig_declarations_group { "libcore_readonly_aconfig_flags_lib", "libgui_flags_java_lib", "power_flags_lib", "sdk_sandbox_exported_flags_lib", "surfaceflinger_flags_java_lib", "telecom_flags_core_java_lib", "telephony_flags_core_java_lib", Loading Loading @@ -873,9 +873,9 @@ java_aconfig_library { min_sdk_version: "30", apex_available: [ "//apex_available:platform", "com.android.extservices", "com.android.nfcservices", "com.android.permission", "com.android.extservices", ], } Loading Loading @@ -1443,6 +1443,13 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } java_aconfig_library { name: "android.app.supervision.flags-aconfig-java-host", aconfig_declarations: "android.app.supervision.flags-aconfig", host_supported: true, defaults: ["framework-minus-apex-aconfig-java-defaults"], } // SurfaceFlinger java_aconfig_library { name: "surfaceflinger_flags_java_lib", Loading core/java/android/app/supervision/SupervisionAppService.java +12 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package android.app.supervision; import android.annotation.FlaggedApi; import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.app.Service; import android.app.supervision.flags.Flags; Loading @@ -33,6 +35,16 @@ import android.os.IBinder; @SystemApi @FlaggedApi(Flags.FLAG_ENABLE_SUPERVISION_APP_SERVICE) public class SupervisionAppService extends Service { /** * Service action: Action for a service that the {@code * android.app.role.RoleManager.ROLE_SYSTEM_SUPERVISION} role holder must implement. * * @hide */ @SdkConstant(SdkConstantType.SERVICE_ACTION) public static final String ACTION_BIND_SUPERVISION_APP_SERVICE = "android.app.action.BIND_SUPERVISION_APP_SERVICE"; private final ISupervisionAppService mBinder = new ISupervisionAppService.Stub() { @Override Loading services/core/java/com/android/server/appbinding/AppBindingConstants.java +30 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,12 @@ public class AppBindingConstants { private static final String SMS_APP_BIND_FLAGS_KEY = "sms_app_bind_flags"; private static final String SUPERVISION_APP_SERVICE_ENABLED_KEY = "supervision_app_service_enabled"; private static final String SUPERVISION_APP_SERVICE_BIND_FLAGS_KEY = "supervision_app_service_bind_flags"; public final String sourceSettings; /** Loading Loading @@ -79,6 +85,12 @@ public class AppBindingConstants { */ public final int SMS_APP_BIND_FLAGS; /** Whether to actually bind to the supervision app service. (Feature flag) */ public final boolean SUPERVISION_APP_SERVICE_ENABLED; /** Extra binding flags for supervision app service. */ public final int SUPERVISION_APP_SERVICE_BIND_FLAGS; private AppBindingConstants(String settings) { sourceSettings = settings; Loading Loading @@ -113,6 +125,14 @@ public class AppBindingConstants { Context.BIND_NOT_VISIBLE | Context.BIND_FOREGROUND_SERVICE); } boolean supervisionAppServiceEnabled = parser.getBoolean(SUPERVISION_APP_SERVICE_ENABLED_KEY, true); int supervisionAppServiceBindFlags = parser.getInt( SUPERVISION_APP_SERVICE_BIND_FLAGS_KEY, Context.BIND_NOT_VISIBLE | Context.BIND_FOREGROUND_SERVICE); long serviceStableConnectionThresholdSec = parser.getLong( SERVICE_STABLE_CONNECTION_THRESHOLD_SEC_KEY, TimeUnit.MINUTES.toSeconds(2)); Loading @@ -133,6 +153,8 @@ public class AppBindingConstants { SERVICE_STABLE_CONNECTION_THRESHOLD_SEC = serviceStableConnectionThresholdSec; SMS_SERVICE_ENABLED = smsServiceEnabled; SMS_APP_BIND_FLAGS = smsAppBindFlags; SUPERVISION_APP_SERVICE_ENABLED = supervisionAppServiceEnabled; SUPERVISION_APP_SERVICE_BIND_FLAGS = supervisionAppServiceBindFlags; } /** Loading Loading @@ -173,5 +195,13 @@ public class AppBindingConstants { pw.print(prefix); pw.print(" SMS_APP_BIND_FLAGS: 0x"); pw.println(Integer.toHexString(SMS_APP_BIND_FLAGS)); pw.print(prefix); pw.print(" SUPERVISION_APP_SERVICE_ENABLED: "); pw.println(SUPERVISION_APP_SERVICE_ENABLED); pw.print(prefix); pw.print(" SUPERVISION_APP_SERVICE_BIND_FLAGS: 0x"); pw.println(Integer.toHexString(SUPERVISION_APP_SERVICE_BIND_FLAGS)); } } services/core/java/com/android/server/appbinding/AppBindingService.java +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.appbinding; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppGlobals; import android.app.supervision.flags.Flags; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; Loading Loading @@ -49,6 +50,7 @@ import com.android.server.SystemService.TargetUser; import com.android.server.am.PersistentConnection; import com.android.server.appbinding.finders.AppServiceFinder; import com.android.server.appbinding.finders.CarrierMessagingClientServiceFinder; import com.android.server.appbinding.finders.SupervisionAppServiceFinder; import java.io.FileDescriptor; import java.io.PrintWriter; Loading Loading @@ -149,6 +151,9 @@ public class AppBindingService extends Binder { mHandler = BackgroundThread.getHandler(); mApps.add(new CarrierMessagingClientServiceFinder(context, this::onAppChanged, mHandler)); if (Flags.enableSupervisionAppService()) { mApps.add(new SupervisionAppServiceFinder(context, this::onAppChanged, mHandler)); } // Initialize with the default value to make it non-null. mConstants = AppBindingConstants.initializeFromString(""); Loading services/core/java/com/android/server/appbinding/finders/SupervisionAppServiceFinder.java 0 → 100644 +130 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appbinding.finders; import android.app.role.OnRoleHoldersChangedListener; import android.app.role.RoleManager; import android.app.supervision.ISupervisionAppService; import android.app.supervision.SupervisionAppService; import android.app.supervision.flags.Flags; import android.content.Context; import android.content.pm.ServiceInfo; import android.os.Handler; import android.os.IBinder; import android.os.UserHandle; import android.text.TextUtils; import android.util.Slog; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.os.BackgroundThread; import com.android.internal.util.CollectionUtils; import com.android.server.appbinding.AppBindingConstants; import java.util.function.BiConsumer; /** Finds the @{link SupervisionAppService} implementation within the supervision app. */ public class SupervisionAppServiceFinder extends AppServiceFinder<SupervisionAppService, ISupervisionAppService> { private final RoleManager mRoleManager; public SupervisionAppServiceFinder( Context context, BiConsumer<AppServiceFinder, Integer> listener, Handler callbackHandler) { super(context, listener, callbackHandler); mRoleManager = context.getSystemService(RoleManager.class); } @Override protected boolean isEnabled(AppBindingConstants constants) { return constants.SUPERVISION_APP_SERVICE_ENABLED && Flags.enableSupervisionAppService(); } @NonNull @Override public String getAppDescription() { return "[Supervision app]"; } @Override protected Class<SupervisionAppService> getServiceClass() { return SupervisionAppService.class; } @Override public ISupervisionAppService asInterface(IBinder obj) { return ISupervisionAppService.Stub.asInterface(obj); } @Nullable @Override public String getTargetPackage(int userId) { final String ret = CollectionUtils.firstOrNull( mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SYSTEM_SUPERVISION, UserHandle.of(userId))); if (DEBUG) { Slog.d(TAG, "getTargetPackage()=" + ret); } return ret; } @NonNull @Override protected String getServiceAction() { return SupervisionAppService.ACTION_BIND_SUPERVISION_APP_SERVICE; } @NonNull @Override protected String getServicePermission() { return "android.permission.BIND_SUPERVISION_APP_SERVICE"; } @Override public void startMonitoring() { mRoleManager.addOnRoleHoldersChangedListenerAsUser( BackgroundThread.getExecutor(), mRoleHolderChangedListener, UserHandle.ALL); } @Override protected String validateService(ServiceInfo service) { final String packageName = service.packageName; final String process = service.processName; if (process == null || TextUtils.equals(packageName, process)) { return "Service must not run on the main process"; } return null; // Null means accept this service. } @Override public int getBindFlags(AppBindingConstants constants) { return constants.SUPERVISION_APP_SERVICE_BIND_FLAGS; } private final OnRoleHoldersChangedListener mRoleHolderChangedListener = (role, user) -> { if (RoleManager.ROLE_SYSTEM_SUPERVISION.equals(role)) { mListener.accept(SupervisionAppServiceFinder.this, user.getIdentifier()); } }; } Loading
AconfigFlags.bp +9 −2 Original line number Diff line number Diff line Loading @@ -111,7 +111,6 @@ aconfig_declarations_group { "com.android.window.flags.window-aconfig-java", "configinfra_framework_flags_java_exported_lib", "conscrypt_exported_aconfig_flags_lib", "sdk_sandbox_exported_flags_lib", "device_policy_aconfig_flags_lib", "display_flags_lib", "dropbox_flags_lib", Loading @@ -125,6 +124,7 @@ aconfig_declarations_group { "libcore_readonly_aconfig_flags_lib", "libgui_flags_java_lib", "power_flags_lib", "sdk_sandbox_exported_flags_lib", "surfaceflinger_flags_java_lib", "telecom_flags_core_java_lib", "telephony_flags_core_java_lib", Loading Loading @@ -873,9 +873,9 @@ java_aconfig_library { min_sdk_version: "30", apex_available: [ "//apex_available:platform", "com.android.extservices", "com.android.nfcservices", "com.android.permission", "com.android.extservices", ], } Loading Loading @@ -1443,6 +1443,13 @@ java_aconfig_library { defaults: ["framework-minus-apex-aconfig-java-defaults"], } java_aconfig_library { name: "android.app.supervision.flags-aconfig-java-host", aconfig_declarations: "android.app.supervision.flags-aconfig", host_supported: true, defaults: ["framework-minus-apex-aconfig-java-defaults"], } // SurfaceFlinger java_aconfig_library { name: "surfaceflinger_flags_java_lib", Loading
core/java/android/app/supervision/SupervisionAppService.java +12 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package android.app.supervision; import android.annotation.FlaggedApi; import android.annotation.Nullable; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.app.Service; import android.app.supervision.flags.Flags; Loading @@ -33,6 +35,16 @@ import android.os.IBinder; @SystemApi @FlaggedApi(Flags.FLAG_ENABLE_SUPERVISION_APP_SERVICE) public class SupervisionAppService extends Service { /** * Service action: Action for a service that the {@code * android.app.role.RoleManager.ROLE_SYSTEM_SUPERVISION} role holder must implement. * * @hide */ @SdkConstant(SdkConstantType.SERVICE_ACTION) public static final String ACTION_BIND_SUPERVISION_APP_SERVICE = "android.app.action.BIND_SUPERVISION_APP_SERVICE"; private final ISupervisionAppService mBinder = new ISupervisionAppService.Stub() { @Override Loading
services/core/java/com/android/server/appbinding/AppBindingConstants.java +30 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,12 @@ public class AppBindingConstants { private static final String SMS_APP_BIND_FLAGS_KEY = "sms_app_bind_flags"; private static final String SUPERVISION_APP_SERVICE_ENABLED_KEY = "supervision_app_service_enabled"; private static final String SUPERVISION_APP_SERVICE_BIND_FLAGS_KEY = "supervision_app_service_bind_flags"; public final String sourceSettings; /** Loading Loading @@ -79,6 +85,12 @@ public class AppBindingConstants { */ public final int SMS_APP_BIND_FLAGS; /** Whether to actually bind to the supervision app service. (Feature flag) */ public final boolean SUPERVISION_APP_SERVICE_ENABLED; /** Extra binding flags for supervision app service. */ public final int SUPERVISION_APP_SERVICE_BIND_FLAGS; private AppBindingConstants(String settings) { sourceSettings = settings; Loading Loading @@ -113,6 +125,14 @@ public class AppBindingConstants { Context.BIND_NOT_VISIBLE | Context.BIND_FOREGROUND_SERVICE); } boolean supervisionAppServiceEnabled = parser.getBoolean(SUPERVISION_APP_SERVICE_ENABLED_KEY, true); int supervisionAppServiceBindFlags = parser.getInt( SUPERVISION_APP_SERVICE_BIND_FLAGS_KEY, Context.BIND_NOT_VISIBLE | Context.BIND_FOREGROUND_SERVICE); long serviceStableConnectionThresholdSec = parser.getLong( SERVICE_STABLE_CONNECTION_THRESHOLD_SEC_KEY, TimeUnit.MINUTES.toSeconds(2)); Loading @@ -133,6 +153,8 @@ public class AppBindingConstants { SERVICE_STABLE_CONNECTION_THRESHOLD_SEC = serviceStableConnectionThresholdSec; SMS_SERVICE_ENABLED = smsServiceEnabled; SMS_APP_BIND_FLAGS = smsAppBindFlags; SUPERVISION_APP_SERVICE_ENABLED = supervisionAppServiceEnabled; SUPERVISION_APP_SERVICE_BIND_FLAGS = supervisionAppServiceBindFlags; } /** Loading Loading @@ -173,5 +195,13 @@ public class AppBindingConstants { pw.print(prefix); pw.print(" SMS_APP_BIND_FLAGS: 0x"); pw.println(Integer.toHexString(SMS_APP_BIND_FLAGS)); pw.print(prefix); pw.print(" SUPERVISION_APP_SERVICE_ENABLED: "); pw.println(SUPERVISION_APP_SERVICE_ENABLED); pw.print(prefix); pw.print(" SUPERVISION_APP_SERVICE_BIND_FLAGS: 0x"); pw.println(Integer.toHexString(SUPERVISION_APP_SERVICE_BIND_FLAGS)); } }
services/core/java/com/android/server/appbinding/AppBindingService.java +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.appbinding; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppGlobals; import android.app.supervision.flags.Flags; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; Loading Loading @@ -49,6 +50,7 @@ import com.android.server.SystemService.TargetUser; import com.android.server.am.PersistentConnection; import com.android.server.appbinding.finders.AppServiceFinder; import com.android.server.appbinding.finders.CarrierMessagingClientServiceFinder; import com.android.server.appbinding.finders.SupervisionAppServiceFinder; import java.io.FileDescriptor; import java.io.PrintWriter; Loading Loading @@ -149,6 +151,9 @@ public class AppBindingService extends Binder { mHandler = BackgroundThread.getHandler(); mApps.add(new CarrierMessagingClientServiceFinder(context, this::onAppChanged, mHandler)); if (Flags.enableSupervisionAppService()) { mApps.add(new SupervisionAppServiceFinder(context, this::onAppChanged, mHandler)); } // Initialize with the default value to make it non-null. mConstants = AppBindingConstants.initializeFromString(""); Loading
services/core/java/com/android/server/appbinding/finders/SupervisionAppServiceFinder.java 0 → 100644 +130 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appbinding.finders; import android.app.role.OnRoleHoldersChangedListener; import android.app.role.RoleManager; import android.app.supervision.ISupervisionAppService; import android.app.supervision.SupervisionAppService; import android.app.supervision.flags.Flags; import android.content.Context; import android.content.pm.ServiceInfo; import android.os.Handler; import android.os.IBinder; import android.os.UserHandle; import android.text.TextUtils; import android.util.Slog; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.os.BackgroundThread; import com.android.internal.util.CollectionUtils; import com.android.server.appbinding.AppBindingConstants; import java.util.function.BiConsumer; /** Finds the @{link SupervisionAppService} implementation within the supervision app. */ public class SupervisionAppServiceFinder extends AppServiceFinder<SupervisionAppService, ISupervisionAppService> { private final RoleManager mRoleManager; public SupervisionAppServiceFinder( Context context, BiConsumer<AppServiceFinder, Integer> listener, Handler callbackHandler) { super(context, listener, callbackHandler); mRoleManager = context.getSystemService(RoleManager.class); } @Override protected boolean isEnabled(AppBindingConstants constants) { return constants.SUPERVISION_APP_SERVICE_ENABLED && Flags.enableSupervisionAppService(); } @NonNull @Override public String getAppDescription() { return "[Supervision app]"; } @Override protected Class<SupervisionAppService> getServiceClass() { return SupervisionAppService.class; } @Override public ISupervisionAppService asInterface(IBinder obj) { return ISupervisionAppService.Stub.asInterface(obj); } @Nullable @Override public String getTargetPackage(int userId) { final String ret = CollectionUtils.firstOrNull( mRoleManager.getRoleHoldersAsUser( RoleManager.ROLE_SYSTEM_SUPERVISION, UserHandle.of(userId))); if (DEBUG) { Slog.d(TAG, "getTargetPackage()=" + ret); } return ret; } @NonNull @Override protected String getServiceAction() { return SupervisionAppService.ACTION_BIND_SUPERVISION_APP_SERVICE; } @NonNull @Override protected String getServicePermission() { return "android.permission.BIND_SUPERVISION_APP_SERVICE"; } @Override public void startMonitoring() { mRoleManager.addOnRoleHoldersChangedListenerAsUser( BackgroundThread.getExecutor(), mRoleHolderChangedListener, UserHandle.ALL); } @Override protected String validateService(ServiceInfo service) { final String packageName = service.packageName; final String process = service.processName; if (process == null || TextUtils.equals(packageName, process)) { return "Service must not run on the main process"; } return null; // Null means accept this service. } @Override public int getBindFlags(AppBindingConstants constants) { return constants.SUPERVISION_APP_SERVICE_BIND_FLAGS; } private final OnRoleHoldersChangedListener mRoleHolderChangedListener = (role, user) -> { if (RoleManager.ROLE_SYSTEM_SUPERVISION.equals(role)) { mListener.accept(SupervisionAppServiceFinder.this, user.getIdentifier()); } }; }