1 /* 2 * Copyright (C) 2015 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.car.content.pm; 18 19 import static android.car.Car.PERMISSION_CONTROL_APP_BLOCKING; 20 import static android.car.CarLibLog.TAG_CAR; 21 22 import android.Manifest; 23 import android.annotation.IntDef; 24 import android.annotation.NonNull; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SystemApi; 27 import android.annotation.TestApi; 28 import android.annotation.UserIdInt; 29 import android.app.PendingIntent; 30 import android.car.Car; 31 import android.car.CarManagerBase; 32 import android.car.CarVersion; 33 import android.car.annotation.AddedInOrBefore; 34 import android.car.annotation.ApiRequirements; 35 import android.content.ComponentName; 36 import android.content.pm.PackageManager.NameNotFoundException; 37 import android.os.IBinder; 38 import android.os.Looper; 39 import android.os.Process; 40 import android.os.RemoteException; 41 import android.os.ServiceSpecificException; 42 import android.util.Log; 43 44 import com.android.internal.annotations.VisibleForTesting; 45 46 import java.lang.annotation.Retention; 47 import java.lang.annotation.RetentionPolicy; 48 import java.util.Collections; 49 import java.util.List; 50 51 /** 52 * Provides car specific API related with package management. 53 */ 54 public final class CarPackageManager extends CarManagerBase { 55 56 private static final String TAG = CarPackageManager.class.getSimpleName(); 57 58 /** 59 * Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this 60 * flag is set, the call will be blocked until policy is set to system. This can take time 61 * and the flag cannot be used in main thread. 62 * 63 * @hide 64 * @deprecated see the {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)} 65 * documentation for alternative mechanism. 66 */ 67 @SystemApi 68 @Deprecated 69 @AddedInOrBefore(majorVersion = 33) 70 public static final int FLAG_SET_POLICY_WAIT_FOR_CHANGE = 0x1; 71 /** 72 * Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this 73 * flag is set, passed policy is added to existing policy set from the current package. 74 * If none of {@link #FLAG_SET_POLICY_ADD} or {@link #FLAG_SET_POLICY_REMOVE} is set, existing 75 * policy is replaced. Note that policy per each package is always replaced and will not be 76 * added. 77 * 78 * @hide 79 * @deprecated see the {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)} 80 * documentation for alternative mechanism. 81 */ 82 @SystemApi 83 @Deprecated 84 @AddedInOrBefore(majorVersion = 33) 85 public static final int FLAG_SET_POLICY_ADD = 0x2; 86 /** 87 * Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this 88 * flag is set, passed policy is removed from existing policy set from the current package. 89 * If none of {@link #FLAG_SET_POLICY_ADD} or {@link #FLAG_SET_POLICY_REMOVE} is set, existing 90 * policy is replaced. 91 * 92 * @hide 93 * @deprecated see the {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)} 94 * documentation for alternative mechanism. 95 */ 96 @SystemApi 97 @Deprecated 98 @AddedInOrBefore(majorVersion = 33) 99 public static final int FLAG_SET_POLICY_REMOVE = 0x4; 100 101 /** 102 * Name of blocked activity. 103 * 104 * @hide 105 */ 106 @AddedInOrBefore(majorVersion = 33) 107 public static final String BLOCKING_INTENT_EXTRA_BLOCKED_ACTIVITY_NAME = "blocked_activity"; 108 /** 109 * int task id of the blocked task. 110 * 111 * @hide 112 */ 113 @AddedInOrBefore(majorVersion = 33) 114 public static final String BLOCKING_INTENT_EXTRA_BLOCKED_TASK_ID = "blocked_task_id"; 115 /** 116 * Name of root activity of blocked task. 117 * 118 * @hide 119 */ 120 @AddedInOrBefore(majorVersion = 33) 121 public static final String BLOCKING_INTENT_EXTRA_ROOT_ACTIVITY_NAME = "root_activity_name"; 122 /** 123 * Boolean indicating whether the root activity is distraction-optimized (DO). 124 * Blocking screen should show a button to restart the task if {@code true}. 125 * 126 * @hide 127 */ 128 @AddedInOrBefore(majorVersion = 33) 129 public static final String BLOCKING_INTENT_EXTRA_IS_ROOT_ACTIVITY_DO = "is_root_activity_do"; 130 131 /** 132 * int display id of the blocked task. 133 * 134 * @hide 135 */ 136 @AddedInOrBefore(majorVersion = 33) 137 public static final String BLOCKING_INTENT_EXTRA_DISPLAY_ID = "display_id"; 138 139 /** 140 * Represents support of all regions for driving safety. 141 * 142 * @hide 143 */ 144 @AddedInOrBefore(majorVersion = 33) 145 public static final String DRIVING_SAFETY_REGION_ALL = "android.car.drivingsafetyregion.all"; 146 147 /** 148 * Metadata which Activity can use to specify the driving safety regions it is supporting. 149 * 150 * <p>Definition of driving safety region is car OEM specific for now and only OEM apps 151 * should use this. If there are multiple regions, it should be comma separated. Not specifying 152 * this means supporting all regions. 153 * 154 * <p>Some examples are: 155 * <meta-data android:name="android.car.drivingsafetyregions" 156 * android:value="com.android.drivingsafetyregion.1,com.android.drivingsafetyregion.2"/> 157 * 158 * @hide 159 */ 160 @AddedInOrBefore(majorVersion = 33) 161 public static final String DRIVING_SAFETY_ACTIVITY_METADATA_REGIONS = 162 "android.car.drivingsafetyregions"; 163 164 /** 165 * Internal error code for throwing {@code NameNotFoundException} from service. 166 * 167 * @hide 168 */ 169 @AddedInOrBefore(majorVersion = 33) 170 public static final int ERROR_CODE_NO_PACKAGE = -100; 171 172 /** 173 * Manifest metadata used to specify the minimum major and minor Car API version an app is 174 * targeting. 175 * 176 * <p>Format is in the form {@code major:minor} or {@code major}. 177 * 178 * <p>For example, for {@link android.os.Build.VERSION_CODES#TIRAMISU Android 13}, it would be: 179 * <code><meta-data android:name="android.car.targetCarVersion" android:value="33"/></code> 180 * 181 * <p>Or: 182 * 183 * <code><meta-data android:name="android.car.targetCarVersion" android:value="33:0"/></code> 184 * 185 * <p>And for {@link android.os.Build.VERSION_CODES#TIRAMISU Android 13} first update: 186 * 187 * <code><meta-data android:name="android.car.targetCarVersion" android:value="33:1"/></code> 188 */ 189 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_1, 190 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 191 public static final String MANIFEST_METADATA_TARGET_CAR_VERSION = 192 "android.car.targetCarVersion"; 193 194 195 /** @hide */ 196 @IntDef(flag = true, 197 value = {FLAG_SET_POLICY_WAIT_FOR_CHANGE, FLAG_SET_POLICY_ADD, FLAG_SET_POLICY_REMOVE}) 198 @Retention(RetentionPolicy.SOURCE) 199 public @interface SetPolicyFlags {} 200 201 private final ICarPackageManager mService; 202 203 /** @hide */ CarPackageManager(Car car, IBinder service)204 public CarPackageManager(Car car, IBinder service) { 205 this(car, ICarPackageManager.Stub.asInterface(service)); 206 } 207 208 /** @hide */ 209 @VisibleForTesting CarPackageManager(Car car, ICarPackageManager service)210 public CarPackageManager(Car car, ICarPackageManager service) { 211 super(car); 212 mService = service; 213 } 214 215 /** @hide */ 216 @Override 217 @AddedInOrBefore(majorVersion = 33) onCarDisconnected()218 public void onCarDisconnected() { 219 // nothing to do 220 } 221 222 /** 223 * Set Application blocking policy for system app. {@link #FLAG_SET_POLICY_ADD} or 224 * {@link #FLAG_SET_POLICY_REMOVE} flag allows adding or removing from already set policy. When 225 * none of these flags are set, it will completely replace existing policy for each package 226 * specified. 227 * When {@link #FLAG_SET_POLICY_WAIT_FOR_CHANGE} flag is set, this call will be blocked 228 * until the policy is set to system and become effective. Otherwise, the call will start 229 * changing the policy but it will be completed asynchronously and the call will return 230 * without waiting for system level policy change. 231 * 232 * @param packageName Package name of the client. If wrong package name is passed, exception 233 * will be thrown. This name is used to update the policy. 234 * @param policy 235 * @param flags 236 * @throws SecurityException if caller has no permission. 237 * @throws IllegalArgumentException For wrong or invalid arguments. 238 * @throws IllegalStateException If {@link #FLAG_SET_POLICY_WAIT_FOR_CHANGE} is set while 239 * called from main thread. 240 * @hide 241 * @deprecated It is no longer possible to change the app blocking policy at runtime. The first 242 * choice to mark an activity as safe for driving should always be to to include 243 * {@code <meta-data android:name="distractionOptimized" android:value="true"/>} in its 244 * manifest. All other activities will be blocked whenever driving restrictions are required. If 245 * an activity's manifest cannot be changed, then you can explicitly make an exception to its 246 * behavior using the build-time XML configuration. Allow or deny specific activities by 247 * changing the appropriate value ({@code R.string.activityAllowlist}, 248 * {@code R.string.activityDenylist}) within the 249 * {@code packages/services/Car/service/res/values/config.xml} overlay. 250 */ 251 @SystemApi 252 @Deprecated 253 @AddedInOrBefore(majorVersion = 33) setAppBlockingPolicy( String packageName, CarAppBlockingPolicy policy, @SetPolicyFlags int flags)254 public void setAppBlockingPolicy( 255 String packageName, CarAppBlockingPolicy policy, @SetPolicyFlags int flags) { 256 if ((flags & FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0 257 && Looper.getMainLooper().isCurrentThread()) { 258 throw new IllegalStateException( 259 "FLAG_SET_POLICY_WAIT_FOR_CHANGE cannot be used in main thread"); 260 } 261 try { 262 mService.setAppBlockingPolicy(packageName, policy, flags); 263 } catch (RemoteException e) { 264 handleRemoteExceptionFromCarService(e); 265 } 266 } 267 268 /** 269 * Restarts the requested task. If task with {@code taskId} does not exist, do nothing. 270 * 271 * <p>This requires {@code android.permission.REAL_GET_TASKS} permission. 272 * 273 * @hide 274 */ 275 @AddedInOrBefore(majorVersion = 33) restartTask(int taskId)276 public void restartTask(int taskId) { 277 try { 278 mService.restartTask(taskId); 279 } catch (RemoteException e) { 280 handleRemoteExceptionFromCarService(e); 281 } 282 } 283 284 /** 285 * Check if finishing Activity will lead into safe Activity (=allowed Activity) to be shown. 286 * This can be used by unsafe activity blocking Activity to check if finishing itself can 287 * lead into being launched again due to unsafe activity shown. Note that checking this does not 288 * guarantee that blocking will not be done as driving state can change after this call is made. 289 * 290 * @param activityName 291 * @return true if there is a safe Activity (or car is stopped) in the back of task stack 292 * so that finishing the Activity will not trigger another Activity blocking. If 293 * the given Activity is not in foreground, then it will return true as well as 294 * finishing the Activity will not make any difference. 295 * 296 * @hide 297 */ 298 @SystemApi 299 @AddedInOrBefore(majorVersion = 33) isActivityBackedBySafeActivity(ComponentName activityName)300 public boolean isActivityBackedBySafeActivity(ComponentName activityName) { 301 try { 302 return mService.isActivityBackedBySafeActivity(activityName); 303 } catch (RemoteException e) { 304 return handleRemoteExceptionFromCarService(e, false); 305 } 306 } 307 308 /** 309 * Enable/Disable Activity Blocking. This is to provide an option for toggling app blocking 310 * behavior for development purposes. 311 * @hide 312 */ 313 @TestApi 314 @AddedInOrBefore(majorVersion = 33) setEnableActivityBlocking(boolean enable)315 public void setEnableActivityBlocking(boolean enable) { 316 try { 317 mService.setEnableActivityBlocking(enable); 318 } catch (RemoteException e) { 319 handleRemoteExceptionFromCarService(e); 320 } 321 } 322 323 /** 324 * Returns whether an activity is distraction optimized, i.e, allowed in a restricted 325 * driving state. 326 * 327 * @param packageName the activity's {@link android.content.pm.ActivityInfo#packageName}. 328 * @param className the activity's {@link android.content.pm.ActivityInfo#name}. 329 * @return true if the activity is distraction optimized, false if it isn't or if the value 330 * could not be determined. 331 */ 332 @AddedInOrBefore(majorVersion = 33) isActivityDistractionOptimized(String packageName, String className)333 public boolean isActivityDistractionOptimized(String packageName, String className) { 334 try { 335 return mService.isActivityDistractionOptimized(packageName, className); 336 } catch (RemoteException e) { 337 return handleRemoteExceptionFromCarService(e, false); 338 } 339 } 340 341 /** 342 * Returns whether the given {@link PendingIntent} represents an activity that is distraction 343 * optimized, i.e, allowed in a restricted driving state. 344 * 345 * @param pendingIntent the {@link PendingIntent} to check. 346 * @return true if the pending intent represents an activity that is distraction optimized, 347 * false if it isn't or if the value could not be determined. 348 */ 349 @AddedInOrBefore(majorVersion = 33) isPendingIntentDistractionOptimized(@onNull PendingIntent pendingIntent)350 public boolean isPendingIntentDistractionOptimized(@NonNull PendingIntent pendingIntent) { 351 try { 352 return mService.isPendingIntentDistractionOptimized(pendingIntent); 353 } catch (RemoteException e) { 354 return handleRemoteExceptionFromCarService(e, false); 355 } 356 } 357 358 /** 359 * Check if given service is distraction optimized, i.e, allowed in a restricted 360 * driving state. 361 * 362 * @param packageName 363 * @param className 364 * @return 365 */ 366 @AddedInOrBefore(majorVersion = 33) isServiceDistractionOptimized(String packageName, String className)367 public boolean isServiceDistractionOptimized(String packageName, String className) { 368 try { 369 return mService.isServiceDistractionOptimized(packageName, className); 370 } catch (RemoteException e) { 371 return handleRemoteExceptionFromCarService(e, false); 372 } 373 } 374 375 /** 376 * Returns the current driving safety region of the system. It will return OEM specific regions 377 * or {@link #DRIVING_SAFETY_REGION_ALL} when all regions are supported. 378 * 379 * <p> System's driving safety region is static and does not change until system restarts. 380 * 381 * @hide 382 */ 383 @RequiresPermission(anyOf = {PERMISSION_CONTROL_APP_BLOCKING, 384 Car.PERMISSION_CAR_DRIVING_STATE}) 385 @NonNull 386 @AddedInOrBefore(majorVersion = 33) getCurrentDrivingSafetyRegion()387 public String getCurrentDrivingSafetyRegion() { 388 try { 389 return mService.getCurrentDrivingSafetyRegion(); 390 } catch (RemoteException e) { 391 return handleRemoteExceptionFromCarService(e, DRIVING_SAFETY_REGION_ALL); 392 } 393 } 394 395 /** 396 * Enables or disables bypassing of unsafe {@code Activity} blocking for a specific 397 * {@code Activity} temporarily. 398 * 399 * <p> Enabling bypassing only lasts until the user stops using the car or until a user 400 * switching happens. Apps like launcher may ask user's consent to bypass. Note that bypassing 401 * is done for the package for all android users including the current user and user 0. 402 * <p> If bypassing is disabled and if the unsafe app is in foreground with driving state, the 403 * app will be immediately blocked. 404 * 405 * @param packageName Target package name. 406 * @param activityClassName Target Activity name (in full class name). 407 * @param bypass Bypass {@code Activity} blocking when true. Do not bypass anymore when false. 408 * @param userId User Id where the package is installed. Even if the bypassing is enabled for 409 * all android users, the package should be available for the specified user id. 410 * 411 * @throws NameNotFoundException If the given package / Activity class does not exist for the 412 * user. 413 * 414 * @hide 415 */ 416 @RequiresPermission(allOf = {PERMISSION_CONTROL_APP_BLOCKING, 417 android.Manifest.permission.QUERY_ALL_PACKAGES}) 418 @AddedInOrBefore(majorVersion = 33) controlTemporaryActivityBlockingBypassingAsUser(String packageName, String activityClassName, boolean bypass, @UserIdInt int userId)419 public void controlTemporaryActivityBlockingBypassingAsUser(String packageName, 420 String activityClassName, boolean bypass, @UserIdInt int userId) 421 throws NameNotFoundException { 422 try { 423 mService.controlOneTimeActivityBlockingBypassingAsUser(packageName, activityClassName, 424 bypass, userId); 425 } catch (ServiceSpecificException e) { 426 handleServiceSpecificFromCarService(e, packageName, activityClassName, userId); 427 } catch (RemoteException e) { 428 handleRemoteExceptionFromCarService(e); 429 } 430 } 431 432 /** 433 * Returns all supported driving safety regions for the given Activity. If the Activity supports 434 * all regions, it will only include {@link #DRIVING_SAFETY_REGION_ALL}. 435 * 436 * <p> The permission specification requires {@code PERMISSION_CONTROL_APP_BLOCKING} and 437 * {@code QUERY_ALL_PACKAGES} but this API will also work if the client has 438 * {@link Car#PERMISSION_CAR_DRIVING_STATE} and {@code QUERY_ALL_PACKAGES} permissions. 439 * 440 * @param packageName Target package name. 441 * @param activityClassName Target Activity name (in full class name). 442 * @param userId Android user Id to check the package. 443 * 444 * @return Empty list if the Activity does not support driving safety (=no 445 * {@code distractionOptimized} metadata). Otherwise returns full list of all supported 446 * regions. 447 * 448 * @throws NameNotFoundException If the given package / Activity class does not exist for the 449 * user. 450 * 451 * @hide 452 */ 453 @RequiresPermission(allOf = {PERMISSION_CONTROL_APP_BLOCKING, 454 android.Manifest.permission.QUERY_ALL_PACKAGES}) 455 @NonNull 456 @AddedInOrBefore(majorVersion = 33) getSupportedDrivingSafetyRegionsForActivityAsUser(String packageName, String activityClassName, @UserIdInt int userId)457 public List<String> getSupportedDrivingSafetyRegionsForActivityAsUser(String packageName, 458 String activityClassName, @UserIdInt int userId) throws NameNotFoundException { 459 try { 460 return mService.getSupportedDrivingSafetyRegionsForActivityAsUser(packageName, 461 activityClassName, userId); 462 } catch (ServiceSpecificException e) { 463 handleServiceSpecificFromCarService(e, packageName, activityClassName, userId); 464 } catch (RemoteException e) { 465 return handleRemoteExceptionFromCarService(e, Collections.EMPTY_LIST); 466 } 467 return Collections.EMPTY_LIST; // cannot reach here but the compiler complains. 468 } 469 470 /** 471 * Gets the Car API version targeted by the given package (as defined by 472 * {@link #MANIFEST_METADATA_TARGET_CAR_VERSION}. 473 * 474 * <p>If the app manifest doesn't contain the {@link #MANIFEST_METADATA_TARGET_CAR_VERSION} 475 * metadata attribute or if the attribute format is invalid, the returned {@code CarVersion} 476 * will be using the 477 * {@link android.content.pm.ApplicationInfo#targetSdkVersion target platform version} as major 478 * and {@code 0} as minor instead. 479 * 480 * <p><b>Note: </b>to get the target {@link CarVersion} for your own app, use 481 * {@link #getTargetCarVersion()} instead. 482 * @return Car API version targeted by the given package (as described above). 483 * 484 * @throws NameNotFoundException If the given package does not exist for the user. 485 * 486 * @hide 487 */ 488 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_1, 489 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 490 @SystemApi 491 @RequiresPermission(Manifest.permission.QUERY_ALL_PACKAGES) 492 @NonNull getTargetCarVersion(@onNull String packageName)493 public CarVersion getTargetCarVersion(@NonNull String packageName) 494 throws NameNotFoundException { 495 try { 496 return mService.getTargetCarVersion(packageName); 497 } catch (ServiceSpecificException e) { 498 Log.w(TAG, "Failed to get CarVersion for " + packageName, e); 499 handleServiceSpecificFromCarService(e, packageName); 500 } catch (RemoteException e) { 501 e.rethrowFromSystemServer(); 502 } 503 return null; // cannot reach here but the compiler complains. 504 } 505 506 /** 507 * Gets the Car API version targeted by app (as defined by 508 * {@link #MANIFEST_METADATA_TARGET_CAR_VERSION}. 509 * 510 * <p>If the app manifest doesn't contain the {@link #MANIFEST_METADATA_TARGET_CAR_VERSION} 511 * metadata attribute or if the attribute format is invalid, the returned {@code CarVersion} 512 * will be using the {@link android.content.pm.ApplicationInfo#targetSdkVersion target platform 513 * version} as major and {@code 0} as minor instead. 514 * 515 * @return targeted Car API version (as defined above) 516 */ 517 @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.TIRAMISU_1, 518 minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0) 519 @NonNull getTargetCarVersion()520 public CarVersion getTargetCarVersion() { 521 String pkgName = mCar.getContext().getPackageName(); 522 try { 523 return mService.getSelfTargetCarVersion(pkgName); 524 } catch (RemoteException e) { 525 Log.w(TAG_CAR, "Car service threw exception calling getTargetCarVersion(" + pkgName 526 + ")", e); 527 e.rethrowFromSystemServer(); 528 return null; 529 } 530 } 531 handleServiceSpecificFromCarService(ServiceSpecificException e, String packageName)532 private void handleServiceSpecificFromCarService(ServiceSpecificException e, 533 String packageName) throws NameNotFoundException { 534 if (e.errorCode == ERROR_CODE_NO_PACKAGE) { 535 throw new NameNotFoundException( 536 "cannot find " + packageName + " for user " + Process.myUserHandle()); 537 } 538 // don't know what this is 539 throw new IllegalStateException(e); 540 } 541 handleServiceSpecificFromCarService(ServiceSpecificException e, String packageName, String activityClassName, @UserIdInt int userId)542 private static void handleServiceSpecificFromCarService(ServiceSpecificException e, 543 String packageName, String activityClassName, @UserIdInt int userId) 544 throws NameNotFoundException { 545 if (e.errorCode == ERROR_CODE_NO_PACKAGE) { 546 throw new NameNotFoundException( 547 "cannot find " + packageName + "/" + activityClassName + " for user id:" 548 + userId); 549 } 550 // don't know what this is 551 throw new IllegalStateException(e); 552 } 553 } 554