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 37 import java.util.Objects; 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 * @deprecated The role controller service is an internal implementation detail inside role, and it 48 * may be replaced by other mechanisms in the future and no longer be called. 49 * 50 * @hide 51 */ 52 @Deprecated 53 @SystemApi 54 public abstract class RoleControllerService extends Service { 55 56 /** 57 * The {@link Intent} that must be declared as handled by the service. 58 */ 59 public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService"; 60 61 private HandlerThread mWorkerThread; 62 private Handler mWorkerHandler; 63 64 @Override 65 public void onCreate() { 66 super.onCreate(); 67 68 mWorkerThread = new HandlerThread(RoleControllerService.class.getSimpleName()); 69 mWorkerThread.start(); 70 mWorkerHandler = new Handler(mWorkerThread.getLooper()); 71 } 72 73 @Override 74 public void onDestroy() { 75 super.onDestroy(); 76 77 mWorkerThread.quitSafely(); 78 } 79 80 @Nullable 81 @Override 82 public final IBinder onBind(@Nullable Intent intent) { 83 return new IRoleController.Stub() { 84 85 @Override 86 public void grantDefaultRoles(RemoteCallback callback) { 87 enforceCallerSystemUid("grantDefaultRoles"); 88 89 Objects.requireNonNull(callback, "callback cannot be null"); 90 91 mWorkerHandler.post(() -> RoleControllerService.this.grantDefaultRoles(callback)); 92 } 93 94 @Override 95 public void onAddRoleHolder(String roleName, String packageName, int flags, 96 RemoteCallback callback) { 97 enforceCallerSystemUid("onAddRoleHolder"); 98 99 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 100 Preconditions.checkStringNotEmpty(packageName, 101 "packageName cannot be null or empty"); 102 Objects.requireNonNull(callback, "callback cannot be null"); 103 104 mWorkerHandler.post(() -> RoleControllerService.this.onAddRoleHolder(roleName, 105 packageName, flags, callback)); 106 } 107 108 @Override 109 public void onRemoveRoleHolder(String roleName, String packageName, int flags, 110 RemoteCallback callback) { 111 enforceCallerSystemUid("onRemoveRoleHolder"); 112 113 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 114 Preconditions.checkStringNotEmpty(packageName, 115 "packageName cannot be null or empty"); 116 Objects.requireNonNull(callback, "callback cannot be null"); 117 118 mWorkerHandler.post(() -> RoleControllerService.this.onRemoveRoleHolder(roleName, 119 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 Objects.requireNonNull(callback, "callback cannot be null"); 128 129 mWorkerHandler.post(() -> RoleControllerService.this.onClearRoleHolders(roleName, 130 flags, callback)); 131 } 132 133 private void enforceCallerSystemUid(@NonNull String methodName) { 134 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 135 throw new SecurityException("Only the system process can call " + methodName 136 + "()"); 137 } 138 } 139 140 @Override 141 public void isApplicationQualifiedForRole(String roleName, String packageName, 142 RemoteCallback callback) { 143 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); 144 145 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 146 Preconditions.checkStringNotEmpty(packageName, 147 "packageName cannot be null or empty"); 148 Objects.requireNonNull(callback, "callback cannot be null"); 149 150 boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName); 151 callback.sendResult(qualified ? Bundle.EMPTY : null); 152 } 153 154 @Override 155 public void isApplicationVisibleForRole(String roleName, String packageName, 156 RemoteCallback callback) { 157 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); 158 159 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 160 Preconditions.checkStringNotEmpty(packageName, 161 "packageName cannot be null or empty"); 162 Objects.requireNonNull(callback, "callback cannot be null"); 163 164 boolean visible = onIsApplicationVisibleForRole(roleName, packageName); 165 callback.sendResult(visible ? Bundle.EMPTY : null); 166 } 167 168 @Override 169 public void isRoleVisible(String roleName, RemoteCallback callback) { 170 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); 171 172 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 173 Objects.requireNonNull(callback, "callback cannot be null"); 174 175 boolean visible = onIsRoleVisible(roleName); 176 callback.sendResult(visible ? Bundle.EMPTY : null); 177 } 178 }; 179 } 180 181 private void grantDefaultRoles(@NonNull RemoteCallback callback) { 182 boolean successful = onGrantDefaultRoles(); 183 callback.sendResult(successful ? Bundle.EMPTY : null); 184 } 185 186 private void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, 187 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 188 boolean successful = onAddRoleHolder(roleName, packageName, flags); 189 callback.sendResult(successful ? Bundle.EMPTY : null); 190 } 191 192 private void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, 193 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 194 boolean successful = onRemoveRoleHolder(roleName, packageName, flags); 195 callback.sendResult(successful ? Bundle.EMPTY : null); 196 } 197 198 private void onClearRoleHolders(@NonNull String roleName, 199 @RoleManager.ManageHoldersFlags int flags, @NonNull RemoteCallback callback) { 200 boolean successful = onClearRoleHolders(roleName, flags); 201 callback.sendResult(successful ? Bundle.EMPTY : null); 202 } 203 204 /** 205 * Called by system to grant default permissions and roles. 206 * <p> 207 * This is typically when creating a new user or upgrading either system or 208 * permission controller package 209 * 210 * @return whether this call was successful 211 */ 212 @WorkerThread 213 public abstract boolean onGrantDefaultRoles(); 214 215 /** 216 * Add a specific application to the holders of a role. If the role is exclusive, the previous 217 * holder will be replaced. 218 * <p> 219 * Implementation should enforce the role requirements and grant or revoke the relevant 220 * privileges of roles. 221 * 222 * @param roleName the name of the role to add the role holder for 223 * @param packageName the package name of the application to add to the role holders 224 * @param flags optional behavior flags 225 * 226 * @return whether this call was successful 227 * 228 * @see RoleManager#addRoleHolderAsUser(String, String, int, UserHandle, Executor, 229 * RemoteCallback) 230 */ 231 @WorkerThread 232 public abstract boolean onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, 233 @RoleManager.ManageHoldersFlags int flags); 234 235 /** 236 * Remove a specific application from the holders of a role. 237 * 238 * @param roleName the name of the role to remove the role holder for 239 * @param packageName the package name of the application to remove from the role holders 240 * @param flags optional behavior flags 241 * 242 * @return whether this call was successful 243 * 244 * @see RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, Executor, 245 * RemoteCallback) 246 */ 247 @WorkerThread 248 public abstract boolean onRemoveRoleHolder(@NonNull String roleName, 249 @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags); 250 251 /** 252 * Remove all holders of a role. 253 * 254 * @param roleName the name of the role to remove role holders for 255 * @param flags optional behavior flags 256 * 257 * @return whether this call was successful 258 * 259 * @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor, RemoteCallback) 260 */ 261 @WorkerThread 262 public abstract boolean onClearRoleHolders(@NonNull String roleName, 263 @RoleManager.ManageHoldersFlags int flags); 264 265 /** 266 * Check whether an application is qualified for a role. 267 * 268 * @param roleName name of the role to check for 269 * @param packageName package name of the application to check for 270 * 271 * @return whether the application is qualified for the role 272 * 273 * @deprecated Implement {@link #onIsApplicationVisibleForRole(String, String)} instead. 274 */ 275 @Deprecated 276 public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName, 277 @NonNull String packageName); 278 279 /** 280 * Check whether an application is visible for a role. 281 * 282 * While an application can be qualified for a role, it can still stay hidden from user (thus 283 * not visible). If an application is visible for a role, we may show things related to the role 284 * for it, e.g. showing an entry pointing to the role settings in its application info page. 285 * 286 * @param roleName name of the role to check for 287 * @param packageName package name of the application to check for 288 * 289 * @return whether the application is visible for the role 290 */ 291 public boolean onIsApplicationVisibleForRole(@NonNull String roleName, 292 @NonNull String packageName) { 293 return onIsApplicationQualifiedForRole(roleName, packageName); 294 } 295 296 /** 297 * Check whether a role should be visible to user. 298 * 299 * @param roleName name of the role to check for 300 * 301 * @return whether the role should be visible to user 302 */ 303 public abstract boolean onIsRoleVisible(@NonNull String roleName); 304 } 305