diff options
author | 2025-03-08 16:10:00 -0800 | |
---|---|---|
committer | 2025-03-08 16:10:00 -0800 | |
commit | 2f62693aee03f7c1c6c7c6518e96f33062ba9583 (patch) | |
tree | 8b926ecdad1b8692df679665f5d239252b6dbd77 /framework-s/java | |
parent | 40f9ebe87a821bdafdeabf9964f54309259483a4 (diff) | |
parent | 31dcc618ad79bff7c733867614496c7de7059168 (diff) |
Merge 25Q1 (ab/BP1A.250305.020) to AOSP main
Bug: 385190204
Merged-In: I47038580b42eebc4d420ba35d2bb6bedc6d660e3
Change-Id: Ic922b8088ee6990eaa48309755befafe4ceab036
Diffstat (limited to 'framework-s/java')
5 files changed, 312 insertions, 3 deletions
diff --git a/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java b/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java index 74062165e..db05a0af6 100644 --- a/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java +++ b/framework-s/java/android/app/ecm/EnhancedConfirmationManager.java @@ -20,6 +20,7 @@ import static android.annotation.SdkConstant.SdkConstantType.BROADCAST_INTENT_AC import android.annotation.FlaggedApi; import android.annotation.IntDef; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SystemApi; @@ -35,15 +36,13 @@ import android.os.RemoteException; import android.permission.flags.Flags; import android.util.ArraySet; -import androidx.annotation.NonNull; - import java.lang.annotation.Retention; /** * This class provides the core API for ECM (Enhanced Confirmation Mode). ECM is a feature that * restricts access to protected **settings** (i.e., sensitive resources) by restricted **apps** * (apps from from dangerous sources, such as sideloaded packages or packages downloaded from a web - * browser). + * browser), or restricts settings globally based on device state. * * <p>Specifically, this class provides the ability to: * @@ -71,6 +70,9 @@ import java.lang.annotation.Retention; * particular app restricted is an implementation detail of ECM. However, the user is able to * clear any restricted app's restriction status (i.e, un-restrict it), after which ECM will * consider the app **not restricted**. + * <li>A setting may be globally restricted based on device state. In this case, any app may be + * automatically considered *restricted*, regardless of the app's restriction state. Users + * cannot un-restrict the app, in these cases. * </ol> * * Why is ECM needed? Consider the following (pre-ECM) scenario: @@ -313,6 +315,9 @@ public final class EnhancedConfirmationManager { * <p>This should be called from the "Restricted setting" dialog (which {@link * #createRestrictedSettingDialogIntent} directs to) upon being presented to the user. * + * <p>This restriction clearing does not apply to any settings that are restricted based on + * global device state + * * @param packageName package name of the application which should be considered acknowledged * @throws NameNotFoundException if the provided package was not found */ diff --git a/framework-s/java/android/app/role/IRoleManager.aidl b/framework-s/java/android/app/role/IRoleManager.aidl index 522967630..dc5bc8cb4 100644 --- a/framework-s/java/android/app/role/IRoleManager.aidl +++ b/framework-s/java/android/app/role/IRoleManager.aidl @@ -45,6 +45,10 @@ interface IRoleManager { void setDefaultApplicationAsUser(in String roleName, in String packageName, int flags, int userId, in RemoteCallback callback); + int getActiveUserForRoleAsUser(in String roleName, int userId); + + void setActiveUserForRoleAsUser(in String roleName, int activeUserId, int flags, int userId); + void addOnRoleHoldersChangedListenerAsUser(IOnRoleHoldersChangedListener listener, int userId); void removeOnRoleHoldersChangedListenerAsUser(IOnRoleHoldersChangedListener listener, @@ -80,4 +84,12 @@ interface IRoleManager { boolean isApplicationVisibleForRoleAsUser(in String roleName, in String packageName, int userId); + + List<String> getDefaultHoldersForTest(in String roleName); + + void setDefaultHoldersForTest(in String roleName, in List<String> packageNames); + + boolean isRoleVisibleForTest(in String roleName); + + void setRoleVisibleForTest(in String roleName, boolean visible); } diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java index 4b8c9b388..42445b4d6 100644 --- a/framework-s/java/android/app/role/RoleManager.java +++ b/framework-s/java/android/app/role/RoleManager.java @@ -40,6 +40,7 @@ import android.os.RemoteCallback; import android.os.RemoteException; import android.os.UserHandle; import android.permission.flags.Flags; +import android.permission.internal.compat.UserHandleCompat; import android.util.ArrayMap; import android.util.SparseArray; @@ -211,6 +212,16 @@ public final class RoleManager { "android.app.role.SYSTEM_CALL_STREAMING"; /** + * The name of the role used for testing cross-user roles. + * + * @hide + */ + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @SystemApi + public static final String ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY = + "android.app.role.RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY"; + + /** * @hide */ @IntDef(flag = true, value = { MANAGE_HOLDERS_FLAG_DONT_KILL_APP }) @@ -574,6 +585,87 @@ public final class RoleManager { } } + /** + * Get the {@link UserHandle} of the user who that is the active user for the specified role. + * <p> + * Only profile-group exclusive roles can be used with this method, and they will + * have one active user within a profile group. + * <p> + * <strong>Note:</strong> Using this API requires holding + * {@code android.permission.INTERACT_ACROSS_USERS_FULL} and one of + * {@code android.permission.MANAGE_ROLE_HOLDERS} or + * {@code android.permission.MANAGE_DEFAULT_APPLICATIONS}. + * + * @param roleName the name of the role to get the active user for + * + * @return a {@link UserHandle} of the active user for the specified role + * + * @see #setActiveUserForRole(String, UserHandle, int) + * + * @hide + */ + @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.MANAGE_ROLE_HOLDERS, + Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, + conditional = true) + @RequiresApi(Build.VERSION_CODES.BAKLAVA) + @SystemApi + @UserHandleAware + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @Nullable + public UserHandle getActiveUserForRole(@NonNull String roleName) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + try { + int userId = mService.getActiveUserForRoleAsUser(roleName, + mContext.getUser().getIdentifier()); + return userId == UserHandleCompat.USER_NULL ? null : UserHandle.of(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set a specific user as active user for a role. + * <p> + * Only profile-group exclusive roles can be used with this method, and they will have + * one active user within a profile group. + * <p> + * <strong>Note:</strong> Using this API requires holding + * {@code android.permission.INTERACT_ACROSS_USERS_FULL} and one of + * {@code android.permission.MANAGE_ROLE_HOLDERS} or + * {@code android.permission.MANAGE_DEFAULT_APPLICATIONS}. + * + * @param roleName the name of the role to set the active user for + * @param user the user to set as active user for specified role + * @param flags optional behavior flags + * + * @see #getActiveUserForRole(String) + * + * @hide + */ + @RequiresPermission(allOf = {Manifest.permission.INTERACT_ACROSS_USERS_FULL, + Manifest.permission.MANAGE_ROLE_HOLDERS, + Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, + conditional = true) + @RequiresApi(Build.VERSION_CODES.BAKLAVA) + @SystemApi + @UserHandleAware + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + // The user handle parameter is a value to be set by this method, while the context user of the + // operation is indeed read from the context + @SuppressLint("UserHandle") + public void setActiveUserForRole( + @NonNull String roleName, @NonNull UserHandle user, @ManageHoldersFlags int flags) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + Objects.requireNonNull(user, "user cannot be null"); + try { + mService.setActiveUserForRoleAsUser(roleName, user.getIdentifier(), flags, + mContext.getUser().getIdentifier()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + @NonNull private static RemoteCallback createRemoteCallback(@NonNull Executor executor, @NonNull Consumer<Boolean> callback) { @@ -1074,6 +1166,118 @@ public final class RoleManager { } } + /** + * Get the default holders of this role, which will be added when the role is added for the + * first time. + * <p> + * <strong>Note:</strong> Use of this API should be limited to tests. The values returned are + * not persisted. + * <p> + * Throws {@link IllegalArgumentException} if role is not a test role + * + * @param roleName the name of the role to get test default holders for + * @return the list of package names of the default holders + * + * @hide + */ + @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) + @RequiresApi(Build.VERSION_CODES.BAKLAVA) + @SystemApi + @UserHandleAware + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @NonNull + public List<String> getDefaultHoldersForTest(@NonNull String roleName) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + try { + return mService.getDefaultHoldersForTest(roleName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set the default holders of this role, which will be added when the role is added for the + * first time. + * <p> + * <strong>Note:</strong> Use of this API should be limited to tests. The values used are + * not persisted. + * <p> + * Throws {@link IllegalArgumentException} if role is not a test role + * + * @param roleName the name of the role to set test default holders for + * @param packageNames a list of package names of the default holders or {@code null} to unset + * + * @hide + */ + @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) + @RequiresApi(Build.VERSION_CODES.BAKLAVA) + @SystemApi + @UserHandleAware + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + public void setDefaultHoldersForTest( + @NonNull String roleName, @Nullable List<String> packageNames) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + try { + mService.setDefaultHoldersForTest(roleName, packageNames); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Get whether a role should be visible for testing. + * <p> + * <strong>Note:</strong> Use of this API should be limited to tests. The values returned are + * not persisted. + * <p> + * Throws {@link IllegalArgumentException} if role is not a test role + * + * @param roleName the name of the role to get test visibility for + * @return {@code true} if role is visible, {@code false} otherwise + * + * @hide + */ + @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) + @RequiresApi(Build.VERSION_CODES.BAKLAVA) + @SystemApi + @UserHandleAware + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + public boolean isRoleVisibleForTest(@NonNull String roleName) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + try { + return mService.isRoleVisibleForTest(roleName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Set whether a role should be visible for testing. + * <p> + * <strong>Note:</strong> Use of this API should be limited to tests. The values used are + * not persisted. + * <p> + * Throws {@link IllegalArgumentException} if role is not a test role + * + * @param roleName the name of the role to set test visibility for + * @param visible {@code true} to set role as visible, {@code false} otherwise + * + * @hide + */ + @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS) + @RequiresApi(Build.VERSION_CODES.BAKLAVA) + @SystemApi + @UserHandleAware + @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + public void setRoleVisibleForTest(@NonNull String roleName, boolean visible) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + try { + mService.setRoleVisibleForTest(roleName, visible); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + @NonNull private RoleControllerManager getRoleControllerManager() { synchronized (mRoleControllerManagerLock) { diff --git a/framework-s/java/android/permission/internal/compat/UserHandleCompat.java b/framework-s/java/android/permission/internal/compat/UserHandleCompat.java new file mode 100644 index 000000000..8a3ec444d --- /dev/null +++ b/framework-s/java/android/permission/internal/compat/UserHandleCompat.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 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.permission.internal.compat; + +import android.annotation.UserIdInt; +import android.os.UserHandle; + +/** + * Helper for accessing features in {@link UserHandle}. + */ +public final class UserHandleCompat { + /** + * A user ID to indicate all users on the device. + */ + public static final int USER_ALL = UserHandle.ALL.getIdentifier(); + + /** + * A user ID to indicate an undefined user of the device. + * + * @see UserHandle#USER_NULL + */ + public static final @UserIdInt int USER_NULL = -10000; + + /** + * A user ID to indicate the "system" user of the device. + */ + public static final int USER_SYSTEM = UserHandle.SYSTEM.getIdentifier(); + + private UserHandleCompat() {} + + /** + * Get the user ID of a given UID. + * + * @param uid the UID + * @return the user ID + */ + @UserIdInt + public static int getUserId(int uid) { + return UserHandle.getUserHandleForUid(uid).getIdentifier(); + } + + /** + * Get the UID from the give user ID and app ID + * + * @param userId the user ID + * @param appId the app ID + * @return the UID + */ + public static int getUid(@UserIdInt int userId, int appId) { + return UserHandle.of(userId).getUid(appId); + } +} diff --git a/framework-s/java/android/permission/internal/compat/package-info.java b/framework-s/java/android/permission/internal/compat/package-info.java new file mode 100644 index 000000000..b78aac878 --- /dev/null +++ b/framework-s/java/android/permission/internal/compat/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2021 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. + */ + +/** + * @hide + * TODO(b/146466118) remove this javadoc tag + */ +@android.annotation.Hide +package android.permission.internal.compat; |