1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.app.role; 18 19 import android.Manifest; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.annotation.WorkerThread; 24 import android.app.Service; 25 import android.content.Intent; 26 import android.os.Binder; 27 import android.os.Bundle; 28 import android.os.Handler; 29 import android.os.HandlerThread; 30 import android.os.IBinder; 31 import android.os.Process; 32 import android.os.RemoteCallback; 33 import android.os.UserHandle; 34 35 import com.android.internal.util.Preconditions; 36 import com.android.internal.util.function.pooled.PooledLambda; 37 38 import java.util.concurrent.Executor; 39 40 /** 41 * Abstract base class for the role controller service. 42 * <p> 43 * Subclass should implement the business logic for role management, including enforcing role 44 * requirements and granting or revoking relevant privileges of roles. This class can only be 45 * implemented by the permission controller app which is registered in {@code PackageManager}. 46 * 47 * @hide 48 */ 49 @SystemApi 50 public abstract class RoleControllerService extends Service { 51 52 /** 53 * The {@link Intent} that must be declared as handled by the service. 54 */ 55 public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService"; 56 57 private HandlerThread mWorkerThread; 58 private Handler mWorkerHandler; 59 60 @Override onCreate()61 public void onCreate() { 62 super.onCreate(); 63 64 mWorkerThread = new HandlerThread(RoleControllerService.class.getSimpleName()); 65 mWorkerThread.start(); 66 mWorkerHandler = new Handler(mWorkerThread.getLooper()); 67 } 68 69 @Override onDestroy()70 public void onDestroy() { 71 super.onDestroy(); 72 73 mWorkerThread.quitSafely(); 74 } 75 76 @Nullable 77 @Override onBind(@ullable Intent intent)78 public final IBinder onBind(@Nullable Intent intent) { 79 return new IRoleController.Stub() { 80 81 @Override 82 public void grantDefaultRoles(RemoteCallback callback) { 83 enforceCallerSystemUid("grantDefaultRoles"); 84 85 Preconditions.checkNotNull(callback, "callback cannot be null"); 86 87 mWorkerHandler.sendMessage(PooledLambda.obtainMessage( 88 RoleControllerService::grantDefaultRoles, RoleControllerService.this, 89 callback)); 90 } 91 92 @Override 93 public void onAddRoleHolder(String roleName, String packageName, int flags, 94 RemoteCallback callback) { 95 enforceCallerSystemUid("onAddRoleHolder"); 96 97 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 98 Preconditions.checkStringNotEmpty(packageName, 99 "packageName cannot be null or empty"); 100 Preconditions.checkNotNull(callback, "callback cannot be null"); 101 102 mWorkerHandler.sendMessage(PooledLambda.obtainMessage( 103 RoleControllerService::onAddRoleHolder, RoleControllerService.this, 104 roleName, packageName, flags, callback)); 105 } 106 107 @Override 108 public void onRemoveRoleHolder(String roleName, String packageName, int flags, 109 RemoteCallback callback) { 110 enforceCallerSystemUid("onRemoveRoleHolder"); 111 112 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 113 Preconditions.checkStringNotEmpty(packageName, 114 "packageName cannot be null or empty"); 115 Preconditions.checkNotNull(callback, "callback cannot be null"); 116 117 mWorkerHandler.sendMessage(PooledLambda.obtainMessage( 118 RoleControllerService::onRemoveRoleHolder, RoleControllerService.this, 119 roleName, packageName, flags, callback)); 120 } 121 122 @Override 123 public void onClearRoleHolders(String roleName, int flags, RemoteCallback callback) { 124 enforceCallerSystemUid("onClearRoleHolders"); 125 126 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 127 Preconditions.checkNotNull(callback, "callback cannot be null"); 128 129 mWorkerHandler.sendMessage(PooledLambda.obtainMessage( 130 RoleControllerService::onClearRoleHolders, RoleControllerService.this, 131 roleName, flags, callback)); 132 } 133 134 private void enforceCallerSystemUid(@NonNull String methodName) { 135 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 136 throw new SecurityException("Only the system process can call " + methodName 137 + "()"); 138 } 139 } 140 141 @Override 142 public void isApplicationQualifiedForRole(String roleName, String packageName, 143 RemoteCallback callback) { 144 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); 145 146 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 147 Preconditions.checkStringNotEmpty(packageName, 148 "packageName cannot be null or empty"); 149 Preconditions.checkNotNull(callback, "callback cannot be null"); 150 151 boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName); 152 callback.sendResult(qualified ? Bundle.EMPTY : null); 153 } 154 155 @Override 156 public void isRoleVisible(String roleName, RemoteCallback callback) { 157 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); 158 159 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 160 Preconditions.checkNotNull(callback, "callback cannot be null"); 161 162 boolean visible = onIsRoleVisible(roleName); 163 callback.sendResult(visible ? Bundle.EMPTY : null); 164 } 165 }; 166 } 167 168 private void grantDefaultRoles(@NonNull RemoteCallback callback) { 169 boolean successful = onGrantDefaultRoles(); 170 callback.sendResult(successful ? Bundle.EMPTY : null); 171 } 172 173 private void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, 174 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 175 boolean successful = onAddRoleHolder(roleName, packageName, flags); 176 callback.sendResult(successful ? Bundle.EMPTY : null); 177 } 178 179 private void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, 180 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 181 boolean successful = onRemoveRoleHolder(roleName, packageName, flags); 182 callback.sendResult(successful ? Bundle.EMPTY : null); 183 } 184 185 private void onClearRoleHolders(@NonNull String roleName, 186 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 187 boolean successful = onClearRoleHolders(roleName, flags); 188 callback.sendResult(successful ? Bundle.EMPTY : null); 189 } 190 191 /** 192 * Called by system to grant default permissions and roles. 193 * <p> 194 * This is typically when creating a new user or upgrading either system or 195 * permission controller package 196 * 197 * @return whether this call was successful 198 */ 199 @WorkerThread 200 public abstract boolean onGrantDefaultRoles(); 201 202 /** 203 * Add a specific application to the holders of a role. If the role is exclusive, the previous 204 * holder will be replaced. 205 * <p> 206 * Implementation should enforce the role requirements and grant or revoke the relevant 207 * privileges of roles. 208 * 209 * @param roleName the name of the role to add the role holder for 210 * @param packageName the package name of the application to add to the role holders 211 * @param flags optional behavior flags 212 * 213 * @return whether this call was successful 214 * 215 * @see RoleManager#addRoleHolderAsUser(String, String, int, UserHandle, Executor, 216 * RemoteCallback) 217 */ 218 @WorkerThread 219 public abstract boolean onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, 220 @RoleManager.ManageHoldersFlags int flags); 221 222 /** 223 * Remove a specific application from the holders of a role. 224 * 225 * @param roleName the name of the role to remove the role holder for 226 * @param packageName the package name of the application to remove from the role holders 227 * @param flags optional behavior flags 228 * 229 * @return whether this call was successful 230 * 231 * @see RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, Executor, 232 * RemoteCallback) 233 */ 234 @WorkerThread 235 public abstract boolean onRemoveRoleHolder(@NonNull String roleName, 236 @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags); 237 238 /** 239 * Remove all holders of a role. 240 * 241 * @param roleName the name of the role to remove role holders for 242 * @param flags optional behavior flags 243 * 244 * @return whether this call was successful 245 * 246 * @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor, RemoteCallback) 247 */ 248 @WorkerThread 249 public abstract boolean onClearRoleHolders(@NonNull String roleName, 250 @RoleManager.ManageHoldersFlags int flags); 251 252 /** 253 * Check whether an application is qualified for a role. 254 * 255 * @param roleName name of the role to check for 256 * @param packageName package name of the application to check for 257 * 258 * @return whether the application is qualified for the role 259 */ 260 public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName, 261 @NonNull String packageName); 262 263 /** 264 * Check whether a role should be visible to user. 265 * 266 * @param roleName name of the role to check for 267 * 268 * @return whether the role should be visible to user 269 */ 270 public abstract boolean onIsRoleVisible(@NonNull String roleName); 271 } 272