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.FlaggedApi; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SystemApi; 24 import android.annotation.WorkerThread; 25 import android.app.Service; 26 import android.content.Intent; 27 import android.os.Binder; 28 import android.os.Bundle; 29 import android.os.Handler; 30 import android.os.HandlerThread; 31 import android.os.IBinder; 32 import android.os.Process; 33 import android.os.RemoteCallback; 34 import android.os.UserHandle; 35 import android.permission.flags.Flags; 36 import android.util.Log; 37 38 import com.android.internal.util.Preconditions; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.Objects; 43 import java.util.concurrent.Executor; 44 45 /** 46 * Abstract base class for the role controller service. 47 * <p> 48 * Subclass should implement the business logic for role management, including enforcing role 49 * requirements and granting or revoking relevant privileges of roles. This class can only be 50 * implemented by the permission controller app which is registered in {@code PackageManager}. 51 * 52 * @deprecated The role controller service is an internal implementation detail inside role, and it 53 * may be replaced by other mechanisms in the future and no longer be called. 54 * 55 * @hide 56 */ 57 @Deprecated 58 @SystemApi 59 public abstract class RoleControllerService extends Service { 60 private static final String LOG_TAG = RoleControllerService.class.getSimpleName(); 61 62 /** 63 * The {@link Intent} that must be declared as handled by the service. 64 */ 65 public static final String SERVICE_INTERFACE = "android.app.role.RoleControllerService"; 66 67 private HandlerThread mWorkerThread; 68 private Handler mWorkerHandler; 69 70 @Override onCreate()71 public void onCreate() { 72 super.onCreate(); 73 74 mWorkerThread = new HandlerThread(RoleControllerService.class.getSimpleName()); 75 mWorkerThread.start(); 76 mWorkerHandler = new Handler(mWorkerThread.getLooper()); 77 } 78 79 @Override onDestroy()80 public void onDestroy() { 81 super.onDestroy(); 82 83 mWorkerThread.quitSafely(); 84 } 85 86 @Nullable 87 @Override onBind(@ullable Intent intent)88 public final IBinder onBind(@Nullable Intent intent) { 89 return new IRoleController.Stub() { 90 91 @Override 92 public void grantDefaultRoles(RemoteCallback callback) { 93 enforceCallerSystemUid("grantDefaultRoles"); 94 Objects.requireNonNull(callback, "callback cannot be null"); 95 96 mWorkerHandler.post(() -> RoleControllerService.this.grantDefaultRoles(callback)); 97 } 98 99 @Override 100 public void onAddRoleHolder(String roleName, String packageName, int flags, 101 RemoteCallback callback) { 102 enforceCallerSystemUid("onAddRoleHolder"); 103 Objects.requireNonNull(callback, "callback cannot be null"); 104 105 mWorkerHandler.post(() -> RoleControllerService.this.onAddRoleHolder(roleName, 106 packageName, flags, callback)); 107 } 108 109 @Override 110 public void onRemoveRoleHolder(String roleName, String packageName, int flags, 111 RemoteCallback callback) { 112 enforceCallerSystemUid("onRemoveRoleHolder"); 113 Objects.requireNonNull(callback, "callback cannot be null"); 114 115 mWorkerHandler.post(() -> RoleControllerService.this.onRemoveRoleHolder(roleName, 116 packageName, flags, callback)); 117 } 118 119 @Override 120 public void onClearRoleHolders(String roleName, int flags, RemoteCallback callback) { 121 enforceCallerSystemUid("onClearRoleHolders"); 122 Objects.requireNonNull(callback, "callback cannot be null"); 123 124 mWorkerHandler.post(() -> RoleControllerService.this.onClearRoleHolders(roleName, 125 flags, callback)); 126 } 127 128 private void enforceCallerSystemUid(@NonNull String methodName) { 129 if (Binder.getCallingUid() != Process.SYSTEM_UID) { 130 throw new SecurityException("Only the system process can call " + methodName 131 + "()"); 132 } 133 } 134 135 @Override 136 public void isApplicationQualifiedForRole(String roleName, String packageName, 137 RemoteCallback callback) { 138 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); 139 Objects.requireNonNull(callback, "callback cannot be null"); 140 141 Bundle result = new Bundle(); 142 try { 143 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 144 Preconditions.checkStringNotEmpty(packageName, 145 "packageName cannot be null or empty"); 146 boolean qualified = onIsApplicationQualifiedForRole(roleName, packageName); 147 result.putBoolean(RoleControllerManager.KEY_RESULT, qualified); 148 } catch (Exception e) { 149 result.putSerializable(RoleControllerManager.KEY_EXCEPTION, e); 150 } 151 callback.sendResult(result); 152 } 153 154 @Override 155 public void isApplicationVisibleForRole(String roleName, String packageName, 156 RemoteCallback callback) { 157 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); 158 Objects.requireNonNull(callback, "callback cannot be null"); 159 160 Bundle result = new Bundle(); 161 try { 162 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 163 Preconditions.checkStringNotEmpty(packageName, 164 "packageName cannot be null or empty"); 165 boolean visible = onIsApplicationVisibleForRole(roleName, packageName); 166 result.putBoolean(RoleControllerManager.KEY_RESULT, visible); 167 } catch (Exception e) { 168 result.putSerializable(RoleControllerManager.KEY_EXCEPTION, e); 169 } 170 callback.sendResult(result); 171 } 172 173 @Override 174 public void isRoleVisible(String roleName, RemoteCallback callback) { 175 enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); 176 Objects.requireNonNull(callback, "callback cannot be null"); 177 178 Bundle result = new Bundle(); 179 try { 180 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 181 boolean visible = onIsRoleVisible(roleName); 182 result.putBoolean(RoleControllerManager.KEY_RESULT, visible); 183 } catch (Exception e) { 184 result.putSerializable(RoleControllerManager.KEY_EXCEPTION, e); 185 } 186 callback.sendResult(result); 187 } 188 189 @Override 190 public void getLegacyFallbackDisabledRoles(RemoteCallback callback) { 191 enforceCallerSystemUid("getLegacyFallbackDisabledRoles"); 192 193 Objects.requireNonNull(callback, "callback cannot be null"); 194 195 Bundle result = new Bundle(); 196 try { 197 List<String> legacyFallbackDisabledRoles = onGetLegacyFallbackDisabledRoles(); 198 result.putStringArrayList(RoleControllerManager.KEY_RESULT, 199 new ArrayList<>(legacyFallbackDisabledRoles)); 200 } catch (Exception e) { 201 result.putSerializable(RoleControllerManager.KEY_EXCEPTION, e); 202 } 203 callback.sendResult(result); 204 } 205 }; 206 } 207 208 private void grantDefaultRoles(RemoteCallback callback) { 209 Bundle result = new Bundle(); 210 try { 211 boolean successful = onGrantDefaultRoles(); 212 result.putBoolean(RoleControllerManager.KEY_RESULT, successful); 213 } catch (Exception e) { 214 result.putSerializable(RoleControllerManager.KEY_EXCEPTION, e); 215 } 216 callback.sendResult(result); 217 } 218 219 private void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, 220 @RoleManager.ManageHoldersFlags int flags, RemoteCallback callback) { 221 Bundle result = new Bundle(); 222 try { 223 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 224 Preconditions.checkStringNotEmpty(packageName, 225 "packageName cannot be null or empty"); 226 boolean successful = onAddRoleHolder(roleName, packageName, flags); 227 result.putBoolean(RoleControllerManager.KEY_RESULT, successful); 228 } catch (Exception e) { 229 result.putSerializable(RoleControllerManager.KEY_EXCEPTION, e); 230 } 231 callback.sendResult(result); 232 } 233 234 private void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName, 235 @RoleManager.ManageHoldersFlags int flags, RemoteCallback callback) { 236 Bundle result = new Bundle(); 237 try { 238 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 239 Preconditions.checkStringNotEmpty(packageName, 240 "packageName cannot be null or empty"); 241 boolean successful = onRemoveRoleHolder(roleName, packageName, flags); 242 result.putBoolean(RoleControllerManager.KEY_RESULT, successful); 243 } catch (Exception e) { 244 result.putSerializable(RoleControllerManager.KEY_EXCEPTION, e); 245 } 246 callback.sendResult(result); 247 } 248 249 private void onClearRoleHolders(@NonNull String roleName, 250 @RoleManager.ManageHoldersFlags int flags, RemoteCallback callback) { 251 Bundle result = new Bundle(); 252 try { 253 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); 254 boolean successful = onClearRoleHolders(roleName, flags); 255 result.putBoolean(RoleControllerManager.KEY_RESULT, successful); 256 } catch (Exception e) { 257 result.putSerializable(RoleControllerManager.KEY_EXCEPTION, e); 258 } 259 callback.sendResult(result); 260 } 261 262 /** 263 * Called by system to grant default permissions and roles. 264 * <p> 265 * This is typically when creating a new user or upgrading either system or 266 * permission controller package 267 * 268 * @return whether this call was successful 269 */ 270 @WorkerThread 271 public abstract boolean onGrantDefaultRoles(); 272 273 /** 274 * Add a specific application to the holders of a role. If the role is exclusive, the previous 275 * holder will be replaced. 276 * <p> 277 * Implementation should enforce the role requirements and grant or revoke the relevant 278 * privileges of roles. 279 * 280 * @param roleName the name of the role to add the role holder for 281 * @param packageName the package name of the application to add to the role holders 282 * @param flags optional behavior flags 283 * 284 * @return whether this call was successful 285 * 286 * @see RoleManager#addRoleHolderAsUser(String, String, int, UserHandle, Executor, 287 * RemoteCallback) 288 */ 289 @WorkerThread 290 public abstract boolean onAddRoleHolder(@NonNull String roleName, @NonNull String packageName, 291 @RoleManager.ManageHoldersFlags int flags); 292 293 /** 294 * Remove a specific application from the holders of a role. 295 * 296 * @param roleName the name of the role to remove the role holder for 297 * @param packageName the package name of the application to remove from the role holders 298 * @param flags optional behavior flags 299 * 300 * @return whether this call was successful 301 * 302 * @see RoleManager#removeRoleHolderAsUser(String, String, int, UserHandle, Executor, 303 * RemoteCallback) 304 */ 305 @WorkerThread 306 public abstract boolean onRemoveRoleHolder(@NonNull String roleName, 307 @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags); 308 309 /** 310 * Remove all holders of a role. 311 * 312 * @param roleName the name of the role to remove role holders for 313 * @param flags optional behavior flags 314 * 315 * @return whether this call was successful 316 * 317 * @see RoleManager#clearRoleHoldersAsUser(String, int, UserHandle, Executor, RemoteCallback) 318 */ 319 @WorkerThread 320 public abstract boolean onClearRoleHolders(@NonNull String roleName, 321 @RoleManager.ManageHoldersFlags int flags); 322 323 /** 324 * Check whether an application is qualified for a role. 325 * 326 * @param roleName name of the role to check for 327 * @param packageName package name of the application to check for 328 * 329 * @return whether the application is qualified for the role 330 * 331 * @deprecated Implement {@link #onIsApplicationVisibleForRole(String, String)} instead. 332 */ 333 @Deprecated 334 public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName, 335 @NonNull String packageName); 336 337 /** 338 * Check whether an application is visible for a role. 339 * 340 * While an application can be qualified for a role, it can still stay hidden from user (thus 341 * not visible). If an application is visible for a role, we may show things related to the role 342 * for it, e.g. showing an entry pointing to the role settings in its application info page. 343 * 344 * @param roleName name of the role to check for 345 * @param packageName package name of the application to check for 346 * 347 * @return whether the application is visible for the role 348 */ 349 public boolean onIsApplicationVisibleForRole(@NonNull String roleName, 350 @NonNull String packageName) { 351 return onIsApplicationQualifiedForRole(roleName, packageName); 352 } 353 354 /** 355 * Check whether a role should be visible to user. 356 * 357 * @param roleName name of the role to check for 358 * 359 * @return whether the role should be visible to user 360 */ 361 public abstract boolean onIsRoleVisible(@NonNull String roleName); 362 363 /** 364 * Get the legacy fallback disabled state. 365 * 366 * @return A list of role names with disabled fallback state. 367 */ 368 @FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED) 369 @NonNull 370 public List<String> onGetLegacyFallbackDisabledRoles() { 371 Log.wtf(LOG_TAG, "onGetLegacyFallbackDisabledRoles is unsupported by this version of" 372 + " PermissionController"); 373 throw new UnsupportedOperationException(); 374 } 375 } 376