summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jay Thomas Sullivan <jaysullivan@google.com> 2023-11-01 17:06:01 -0700
committer Jay Thomas Sullivan <jaysullivan@google.com> 2023-11-17 15:48:36 -0800
commit7473cf54743e3a3315aed29de29739a98b13a0d3 (patch)
tree4376e6b5821b0fd989d14fb78f7238924379c8ec
parent137f496ad679f6f5753732364ab0cf0e2231ce79 (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.xml2
-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.java85
-rw-r--r--service/java/com/android/role/RemoteRoleController.java65
-rw-r--r--service/java/com/android/role/RoleController.java51
-rw-r--r--service/java/com/android/role/RoleService.java24
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);
}
}