diff options
author | 2023-11-01 17:06:01 -0700 | |
---|---|---|
committer | 2023-11-17 15:48:36 -0800 | |
commit | 7473cf54743e3a3315aed29de29739a98b13a0d3 (patch) | |
tree | 4376e6b5821b0fd989d14fb78f7238924379c8ec | |
parent | 137f496ad679f6f5753732364ab0cf0e2231ce79 (diff) |
[Role Logic Move] Shim RoleControllerServiceImpl
This implements the ability to toggle between running
RoleControllerServiceImpl (and therefore the majority of the Role
Business Logic) in either System Server or PermissionController,
depending on whether the "roleControllerInSystemServer" flag is set.
New classes/interfaces:
- RoleControllerLocal: Runs logic directly in System Server
- RoleControllerRemote: Calls PermissionController to run logic
- RoleController: Interface to allow us to toggle between the above two
Also, RoleControllerServiceImpl is moved to role-controller, and given a
shim constructor, so that it can be directly invoked from RoleService.
Bug: 302563971
Test: atest CtsRoleTestCases
Change-Id: Ifc024398a7fc558d33ff66d890fa67096c1a79e4
-rw-r--r-- | PermissionController/AndroidManifest.xml | 2 | ||||
-rw-r--r-- | PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java (renamed from PermissionController/src/com/android/permissioncontroller/role/service/RoleControllerServiceImpl.java) | 86 | ||||
-rw-r--r-- | service/java/com/android/role/LocalRoleController.java | 85 | ||||
-rw-r--r-- | service/java/com/android/role/RemoteRoleController.java | 65 | ||||
-rw-r--r-- | service/java/com/android/role/RoleController.java | 51 | ||||
-rw-r--r-- | service/java/com/android/role/RoleService.java | 24 |
6 files changed, 265 insertions, 48 deletions
diff --git a/PermissionController/AndroidManifest.xml b/PermissionController/AndroidManifest.xml index 288dc6c84..0d663bc05 100644 --- a/PermissionController/AndroidManifest.xml +++ b/PermissionController/AndroidManifest.xml @@ -521,7 +521,7 @@ </intent-filter> </service> - <service android:name="com.android.permissioncontroller.role.service.RoleControllerServiceImpl" + <service android:name="com.android.role.controller.service.RoleControllerServiceImpl" android:exported="true"> <intent-filter android:priority="1"> <action android:name="android.app.role.RoleControllerService"/> diff --git a/PermissionController/src/com/android/permissioncontroller/role/service/RoleControllerServiceImpl.java b/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java index 38fe22b76..d3c099d5e 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/service/RoleControllerServiceImpl.java +++ b/PermissionController/role-controller/java/com/android/role/controller/service/RoleControllerServiceImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.permissioncontroller.role.service; +package com.android.role.controller.service; import android.app.role.RoleControllerService; import android.app.role.RoleManager; @@ -29,10 +29,10 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; -import com.android.permissioncontroller.permission.utils.CollectionUtils; -import com.android.permissioncontroller.role.utils.PackageUtils; import com.android.role.controller.model.Role; import com.android.role.controller.model.Roles; +import com.android.role.controller.util.CollectionUtils; +import com.android.role.controller.util.PackageUtils; import com.android.role.controller.util.UserUtils; import java.util.ArrayList; @@ -48,16 +48,28 @@ public class RoleControllerServiceImpl extends RoleControllerService { private static final boolean DEBUG = false; - private UserHandle mUser; + private UserHandle mUser; + private Context mContext; private RoleManager mUserRoleManager; + public RoleControllerServiceImpl() {} + + public RoleControllerServiceImpl(@NonNull UserHandle user, @NonNull Context context) { + init(user, context); + } + @Override public void onCreate() { super.onCreate(); - mUser = Process.myUserHandle(); - Context userContext = UserUtils.getUserContext(this, mUser); + init(Process.myUserHandle(), this); + } + + private void init(@NonNull UserHandle user, @NonNull Context context) { + mUser = user; + mContext = context; + Context userContext = UserUtils.getUserContext(context, user); mUserRoleManager = userContext.getSystemService(RoleManager.class); } @@ -69,7 +81,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { } // Gather the available roles for current user. - ArrayMap<String, Role> roleMap = Roles.get(this); + ArrayMap<String, Role> roleMap = Roles.get(mContext); List<Role> roles = new ArrayList<>(); List<String> roleNames = new ArrayList<>(); ArraySet<String> addedRoleNames = new ArraySet<>(); @@ -77,7 +89,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { for (int i = 0; i < roleMapSize; i++) { Role role = roleMap.valueAt(i); - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { continue; } roles.add(role); @@ -98,7 +110,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { String roleName = addedRoleNames.valueAt(i); Role role = roleMap.get(roleName); - role.onRoleAddedAsUser(mUser, this); + role.onRoleAddedAsUser(mUser, mContext); } // Go through the holders of all roles. @@ -117,7 +129,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { currentPackageNamesIndex++) { String packageName = currentPackageNames.get(currentPackageNamesIndex); - if (role.isPackageQualifiedAsUser(packageName, mUser, this)) { + if (role.isPackageQualifiedAsUser(packageName, mUser, mContext)) { // We should not override user set or fixed permissions because we are only // redoing the grant here. Otherwise, user won't be able to revoke permissions // granted by role. @@ -137,11 +149,11 @@ public class RoleControllerServiceImpl extends RoleControllerService { if (currentPackageNamesSize == 0 || isStaticRole) { List<String> packageNamesToAdd = null; if (addedRoleNames.contains(roleName) || isStaticRole) { - packageNamesToAdd = role.getDefaultHoldersAsUser(mUser, this); + packageNamesToAdd = role.getDefaultHoldersAsUser(mUser, mContext); } if (packageNamesToAdd == null || packageNamesToAdd.isEmpty()) { packageNamesToAdd = CollectionUtils.singletonOrEmpty( - role.getFallbackHolderAsUser(mUser, this)); + role.getFallbackHolderAsUser(mUser, mContext)); } int packageNamesToAddSize = packageNamesToAdd.size(); @@ -154,7 +166,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { // static roles. continue; } - if (!role.isPackageQualifiedAsUser(packageName, mUser, this)) { + if (!role.isPackageQualifiedAsUser(packageName, mUser, mContext)) { Log.e(LOG_TAG, "Default/fallback role holder package doesn't qualify for" + " the role, package: " + packageName + ", role: " + roleName); continue; @@ -199,17 +211,17 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { Log.e(LOG_TAG, "Unknown role: " + roleName); return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { Log.e(LOG_TAG, "Role is unavailable: " + roleName); return false; } - if (!role.isPackageQualifiedAsUser(packageName, mUser, this)) { + if (!role.isPackageQualifiedAsUser(packageName, mUser, mContext)) { Log.e(LOG_TAG, "Package does not qualify for the role, package: " + packageName + ", role: " + roleName); return false; @@ -244,8 +256,8 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - role.onHolderAddedAsUser(packageName, mUser, this); - role.onHolderChangedAsUser(mUser, this); + role.onHolderAddedAsUser(packageName, mUser, mContext); + role.onHolderChangedAsUser(mUser, mContext); return true; } @@ -258,12 +270,12 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { Log.e(LOG_TAG, "Unknown role: " + roleName); return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { Log.e(LOG_TAG, "Role is unavailable: " + roleName); return false; } @@ -280,7 +292,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - role.onHolderChangedAsUser(mUser, this); + role.onHolderChangedAsUser(mUser, mContext); return true; } @@ -292,12 +304,12 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { Log.e(LOG_TAG, "Unknown role: " + roleName); return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { Log.e(LOG_TAG, "Role is unavailable: " + roleName); return false; } @@ -314,7 +326,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { return false; } - role.onHolderChangedAsUser(mUser, this); + role.onHolderChangedAsUser(mUser, mContext); return true; } @@ -328,7 +340,7 @@ public class RoleControllerServiceImpl extends RoleControllerService { @WorkerThread private boolean addRoleHolderInternal(@NonNull Role role, @NonNull String packageName, boolean dontKillApp, boolean overrideUser, boolean added) { - role.grantAsUser(packageName, dontKillApp, overrideUser, mUser, this); + role.grantAsUser(packageName, dontKillApp, overrideUser, mUser, mContext); String roleName = role.getName(); if (!added) { @@ -345,13 +357,13 @@ public class RoleControllerServiceImpl extends RoleControllerService { private boolean removeRoleHolderInternal(@NonNull Role role, @NonNull String packageName, boolean dontKillApp) { ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, - mUser, this); + mUser, mContext); if (applicationInfo == null) { Log.w(LOG_TAG, "Cannot get ApplicationInfo for package: " + packageName); } if (applicationInfo != null) { - role.revokeAsUser(packageName, dontKillApp, false, mUser, this); + role.revokeAsUser(packageName, dontKillApp, false, mUser, mContext); } String roleName = role.getName(); @@ -392,12 +404,12 @@ public class RoleControllerServiceImpl extends RoleControllerService { return true; } - String fallbackPackageName = role.getFallbackHolderAsUser(mUser, this); + String fallbackPackageName = role.getFallbackHolderAsUser(mUser, mContext); if (fallbackPackageName == null) { return true; } - if (!role.isPackageQualifiedAsUser(fallbackPackageName, mUser, this)) { + if (!role.isPackageQualifiedAsUser(fallbackPackageName, mUser, mContext)) { Log.e(LOG_TAG, "Fallback role holder package doesn't qualify for the role, package: " + fallbackPackageName + ", role: " + roleName); return false; @@ -424,20 +436,20 @@ public class RoleControllerServiceImpl extends RoleControllerService { @Override public boolean onIsApplicationVisibleForRole(@NonNull String roleName, @NonNull String packageName) { - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { return false; } - if (!role.isPackageQualifiedAsUser(packageName, mUser, this)) { + if (!role.isPackageQualifiedAsUser(packageName, mUser, mContext)) { return false; } ApplicationInfo applicationInfo = PackageUtils.getApplicationInfoAsUser(packageName, - mUser, this); + mUser, mContext); if (applicationInfo == null || !role.isApplicationVisibleAsUser(applicationInfo, mUser, - this)) { + mContext)) { return false; } return true; @@ -445,15 +457,15 @@ public class RoleControllerServiceImpl extends RoleControllerService { @Override public boolean onIsRoleVisible(@NonNull String roleName) { - Role role = Roles.get(this).get(roleName); + Role role = Roles.get(mContext).get(roleName); if (role == null) { return false; } - if (!role.isAvailableAsUser(mUser, this)) { + if (!role.isAvailableAsUser(mUser, mContext)) { return false; } - return role.isVisibleAsUser(mUser, this); + return role.isVisibleAsUser(mUser, mContext); } private static boolean checkFlags(int flags, int allowedFlags) { diff --git a/service/java/com/android/role/LocalRoleController.java b/service/java/com/android/role/LocalRoleController.java new file mode 100644 index 000000000..9bac68f4d --- /dev/null +++ b/service/java/com/android/role/LocalRoleController.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2023 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.role; + +import android.app.role.RoleControllerService; +import android.app.role.RoleManager; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.RemoteCallback; +import android.os.UserHandle; + +import androidx.annotation.NonNull; + +import com.android.role.controller.service.RoleControllerServiceImpl; + +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +public class LocalRoleController implements RoleController { + + @NonNull + private final RoleControllerServiceImpl mService; + @NonNull + private final HandlerThread mWorkerThread; + @NonNull + private final Handler mWorkerHandler; + + public LocalRoleController(@NonNull UserHandle user, @NonNull Context context) { + mService = new RoleControllerServiceImpl(user, context); + mWorkerThread = new HandlerThread(RoleControllerService.class.getSimpleName()); + mWorkerThread.start(); + mWorkerHandler = new Handler(mWorkerThread.getLooper()); + } + + @Override + public void grantDefaultRoles(@NonNull Executor executor, @NonNull Consumer<Boolean> callback) { + mWorkerHandler.post(() -> { + boolean successful = mService.onGrantDefaultRoles(); + executor.execute(() -> callback.accept(successful)); + }); + } + + @Override + public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mWorkerHandler.post(() -> { + boolean successful = mService.onAddRoleHolder(roleName, packageName, flags); + callback.sendResult(successful ? Bundle.EMPTY : null); + }); + } + + @Override + public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mWorkerHandler.post(() -> { + boolean successful = mService.onRemoveRoleHolder(roleName, packageName, flags); + callback.sendResult(successful ? Bundle.EMPTY : null); + }); + } + + @Override + public void onClearRoleHolders(@NonNull String roleName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mWorkerHandler.post(() -> { + boolean successful = mService.onClearRoleHolders(roleName, flags); + callback.sendResult(successful ? Bundle.EMPTY : null); + }); + } +} diff --git a/service/java/com/android/role/RemoteRoleController.java b/service/java/com/android/role/RemoteRoleController.java new file mode 100644 index 000000000..08854e118 --- /dev/null +++ b/service/java/com/android/role/RemoteRoleController.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2023 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.role; + +import android.app.role.RoleControllerManager; +import android.app.role.RoleManager; +import android.content.Context; +import android.os.RemoteCallback; +import android.os.UserHandle; + +import androidx.annotation.NonNull; + +import com.android.permission.util.ForegroundThread; + +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +public class RemoteRoleController implements RoleController { + @NonNull + private final RoleControllerManager mRoleControllerManager; + + public RemoteRoleController(@NonNull UserHandle user, @NonNull Context context) { + Context userContext = context.createContextAsUser(user, 0); + mRoleControllerManager = + RoleControllerManager.createWithInitializedRemoteServiceComponentName( + ForegroundThread.getHandler(), userContext); + } + + @Override + public void grantDefaultRoles(@NonNull Executor executor, @NonNull Consumer<Boolean> callback) { + mRoleControllerManager.grantDefaultRoles(executor, callback); + } + + @Override + public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mRoleControllerManager.onAddRoleHolder(roleName, packageName, flags, callback); + } + + @Override + public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mRoleControllerManager.onRemoveRoleHolder(roleName, packageName, flags, callback); + } + + @Override + public void onClearRoleHolders(@NonNull String roleName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { + mRoleControllerManager.onClearRoleHolders(roleName, flags, callback); + } +} diff --git a/service/java/com/android/role/RoleController.java b/service/java/com/android/role/RoleController.java new file mode 100644 index 000000000..4a5f2a8c2 --- /dev/null +++ b/service/java/com/android/role/RoleController.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2023 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.role; + +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.app.role.RoleManager; +import android.os.RemoteCallback; + +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +public interface RoleController { + /** + * @see android.app.role.RoleControllerManager#grantDefaultRoles + */ + void grantDefaultRoles(@NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<Boolean> callback); + + /** + * @see android.app.role.RoleControllerManager#onAddRoleHolder + */ + void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback); + + /** + * @see android.app.role.RoleControllerManager#onRemoveRoleHolder + */ + void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback); + + /** + * @see android.app.role.RoleControllerManager#onClearRoleHolders + */ + void onClearRoleHolders(@NonNull String roleName, + @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback); +} diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java index 189b61f3e..9b733ab55 100644 --- a/service/java/com/android/role/RoleService.java +++ b/service/java/com/android/role/RoleService.java @@ -45,6 +45,7 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; +import android.permission.flags.Flags; import android.provider.Settings; import android.text.TextUtils; import android.util.ArraySet; @@ -130,7 +131,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback */ @GuardedBy("mLock") @NonNull - private final SparseArray<RoleControllerManager> mControllers = new SparseArray<>(); + private final SparseArray<RoleController> mControllers = new SparseArray<>(); /** * Maps user id to its list of listeners. @@ -321,14 +322,17 @@ public class RoleService extends SystemService implements RoleUserState.Callback } @NonNull - private RoleControllerManager getOrCreateController(@UserIdInt int userId) { + private RoleController getOrCreateController(@UserIdInt int userId) { synchronized (mLock) { - RoleControllerManager controller = mControllers.get(userId); + RoleController controller = mControllers.get(userId); if (controller == null) { - Context systemContext = getContext(); - Context userContext = systemContext.createContextAsUser(UserHandle.of(userId), 0); - controller = RoleControllerManager.createWithInitializedRemoteServiceComponentName( - ForegroundThread.getHandler(), userContext); + UserHandle user = UserHandle.of(userId); + Context context = getContext(); + if (SdkLevel.isAtLeastV() && Flags.roleControllerInSystemServer()) { + controller = new LocalRoleController(user, context); + } else { + controller = new RemoteRoleController(user, context); + } mControllers.put(userId, controller); } return controller; @@ -577,11 +581,11 @@ public class RoleService extends SystemService implements RoleUserState.Callback Preconditions.checkArgumentIsSupported(DEFAULT_APPLICATION_ROLES, roleName); Objects.requireNonNull(callback, "callback cannot be null"); - RoleControllerManager roleControllerManager = getOrCreateController(userId); + RoleController roleController = getOrCreateController(userId); if (packageName != null) { - roleControllerManager.onAddRoleHolder(roleName, packageName, flags, callback); + roleController.onAddRoleHolder(roleName, packageName, flags, callback); } else { - roleControllerManager.onClearRoleHolders(roleName, flags, callback); + roleController.onClearRoleHolders(roleName, flags, callback); } } |