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 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.RequiresPermission; 24 import android.annotation.SystemApi; 25 import android.annotation.TestApi; 26 import android.annotation.UserIdInt; 27 import android.app.PendingIntent; 28 import android.car.Car; 29 import android.car.CarManagerBase; 30 import android.content.ComponentName; 31 import android.content.pm.PackageManager.NameNotFoundException; 32 import android.os.IBinder; 33 import android.os.Looper; 34 import android.os.RemoteException; 35 import android.os.ServiceSpecificException; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 import java.util.Collections; 40 import java.util.List; 41 42 /** 43 * Provides car specific API related with package management. 44 */ 45 public final class CarPackageManager extends CarManagerBase { 46 private static final String TAG = "CarPackageManager"; 47 48 /** 49 * Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this 50 * flag is set, the call will be blocked until policy is set to system. This can take time 51 * and the flag cannot be used in main thread. 52 * 53 * @hide 54 * @deprecated see the {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)} 55 * documentation for alternative mechanism. 56 */ 57 @SystemApi 58 @Deprecated 59 public static final int FLAG_SET_POLICY_WAIT_FOR_CHANGE = 0x1; 60 /** 61 * Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this 62 * flag is set, passed policy is added to existing policy set from the current package. 63 * If none of {@link #FLAG_SET_POLICY_ADD} or {@link #FLAG_SET_POLICY_REMOVE} is set, existing 64 * policy is replaced. Note that policy per each package is always replaced and will not be 65 * added. 66 * 67 * @hide 68 * @deprecated see the {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)} 69 * documentation for alternative mechanism. 70 */ 71 @SystemApi 72 @Deprecated 73 public static final int FLAG_SET_POLICY_ADD = 0x2; 74 /** 75 * Flag for {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)}. When this 76 * flag is set, passed policy is removed from existing policy set from the current package. 77 * If none of {@link #FLAG_SET_POLICY_ADD} or {@link #FLAG_SET_POLICY_REMOVE} is set, existing 78 * policy is replaced. 79 * 80 * @hide 81 * @deprecated see the {@link #setAppBlockingPolicy(String, CarAppBlockingPolicy, int)} 82 * documentation for alternative mechanism. 83 */ 84 @SystemApi 85 @Deprecated 86 public static final int FLAG_SET_POLICY_REMOVE = 0x4; 87 88 /** 89 * Represents support of all regions for driving safety. 90 * 91 * @hide 92 */ 93 public static final String DRIVING_SAFETY_REGION_ALL = "android.car.drivingsafetyregion.all"; 94 95 /** 96 * Metadata which Activity can use to specify the driving safety regions it is supporting. 97 * 98 * <p>Definition of driving safety region is car OEM specific for now and only OEM apps 99 * should use this. If there are multiple regions, it should be comma separated. Not specifying 100 * this means supporting all regions. 101 * 102 * <p>Some examples are: 103 * <meta-data android:name="android.car.drivingsafetyregions" 104 * android:value="com.android.drivingsafetyregion.1,com.android.drivingsafetyregion.2"/> 105 * 106 * @hide 107 */ 108 public static final String DRIVING_SAFETY_ACTIVITY_METADATA_REGIONS = 109 "android.car.drivingsafetyregions"; 110 111 /** 112 * Internal error code for throwing {@code NameNotFoundException} from service. 113 * 114 * @hide 115 */ 116 public static final int ERROR_CODE_NO_PACKAGE = -100; 117 118 /** @hide */ 119 @IntDef(flag = true, 120 value = {FLAG_SET_POLICY_WAIT_FOR_CHANGE, FLAG_SET_POLICY_ADD, FLAG_SET_POLICY_REMOVE}) 121 @Retention(RetentionPolicy.SOURCE) 122 public @interface SetPolicyFlags {} 123 124 private final ICarPackageManager mService; 125 126 /** @hide */ CarPackageManager(Car car, IBinder service)127 public CarPackageManager(Car car, IBinder service) { 128 super(car); 129 mService = ICarPackageManager.Stub.asInterface(service); 130 } 131 132 /** @hide */ 133 @Override onCarDisconnected()134 public void onCarDisconnected() { 135 // nothing to do 136 } 137 138 /** 139 * Set Application blocking policy for system app. {@link #FLAG_SET_POLICY_ADD} or 140 * {@link #FLAG_SET_POLICY_REMOVE} flag allows adding or removing from already set policy. When 141 * none of these flags are set, it will completely replace existing policy for each package 142 * specified. 143 * When {@link #FLAG_SET_POLICY_WAIT_FOR_CHANGE} flag is set, this call will be blocked 144 * until the policy is set to system and become effective. Otherwise, the call will start 145 * changing the policy but it will be completed asynchronously and the call will return 146 * without waiting for system level policy change. 147 * 148 * @param packageName Package name of the client. If wrong package name is passed, exception 149 * will be thrown. This name is used to update the policy. 150 * @param policy 151 * @param flags 152 * @throws SecurityException if caller has no permission. 153 * @throws IllegalArgumentException For wrong or invalid arguments. 154 * @throws IllegalStateException If {@link #FLAG_SET_POLICY_WAIT_FOR_CHANGE} is set while 155 * called from main thread. 156 * @hide 157 * @deprecated It is no longer possible to change the app blocking policy at runtime. The first 158 * choice to mark an activity as safe for driving should always be to to include 159 * {@code <meta-data android:name="distractionOptimized" android:value="true"/>} in its 160 * manifest. All other activities will be blocked whenever driving restrictions are required. If 161 * an activity's manifest cannot be changed, then you can explicitly make an exception to its 162 * behavior using the build-time XML configuration. Allow or deny specific activities by 163 * changing the appropriate value ({@code R.string.activityAllowlist}, 164 * {@code R.string.activityDenylist}) within the 165 * {@code packages/services/Car/service/res/values/config.xml} overlay. 166 */ 167 @SystemApi 168 @Deprecated setAppBlockingPolicy( String packageName, CarAppBlockingPolicy policy, @SetPolicyFlags int flags)169 public void setAppBlockingPolicy( 170 String packageName, CarAppBlockingPolicy policy, @SetPolicyFlags int flags) { 171 if ((flags & FLAG_SET_POLICY_WAIT_FOR_CHANGE) != 0 172 && Looper.getMainLooper().isCurrentThread()) { 173 throw new IllegalStateException( 174 "FLAG_SET_POLICY_WAIT_FOR_CHANGE cannot be used in main thread"); 175 } 176 try { 177 mService.setAppBlockingPolicy(packageName, policy, flags); 178 } catch (RemoteException e) { 179 handleRemoteExceptionFromCarService(e); 180 } 181 } 182 183 /** 184 * Restarts the requested task. If task with {@code taskId} does not exist, do nothing. 185 * 186 * <p>This requires {@code android.permission.REAL_GET_TASKS} permission. 187 * 188 * @hide 189 */ restartTask(int taskId)190 public void restartTask(int taskId) { 191 try { 192 mService.restartTask(taskId); 193 } catch (RemoteException e) { 194 handleRemoteExceptionFromCarService(e); 195 } 196 } 197 198 /** 199 * Check if finishing Activity will lead into safe Activity (=allowed Activity) to be shown. 200 * This can be used by unsafe activity blocking Activity to check if finishing itself can 201 * lead into being launched again due to unsafe activity shown. Note that checking this does not 202 * guarantee that blocking will not be done as driving state can change after this call is made. 203 * 204 * @param activityName 205 * @return true if there is a safe Activity (or car is stopped) in the back of task stack 206 * so that finishing the Activity will not trigger another Activity blocking. If 207 * the given Activity is not in foreground, then it will return true as well as 208 * finishing the Activity will not make any difference. 209 * 210 * @hide 211 */ 212 @SystemApi isActivityBackedBySafeActivity(ComponentName activityName)213 public boolean isActivityBackedBySafeActivity(ComponentName activityName) { 214 try { 215 return mService.isActivityBackedBySafeActivity(activityName); 216 } catch (RemoteException e) { 217 return handleRemoteExceptionFromCarService(e, false); 218 } 219 } 220 221 /** 222 * Enable/Disable Activity Blocking. This is to provide an option for toggling app blocking 223 * behavior for development purposes. 224 * @hide 225 */ 226 @TestApi setEnableActivityBlocking(boolean enable)227 public void setEnableActivityBlocking(boolean enable) { 228 try { 229 mService.setEnableActivityBlocking(enable); 230 } catch (RemoteException e) { 231 handleRemoteExceptionFromCarService(e); 232 } 233 } 234 235 /** 236 * Returns whether an activity is distraction optimized, i.e, allowed in a restricted 237 * driving state. 238 * 239 * @param packageName the activity's {@link android.content.pm.ActivityInfo#packageName}. 240 * @param className the activity's {@link android.content.pm.ActivityInfo#name}. 241 * @return true if the activity is distraction optimized, false if it isn't or if the value 242 * could not be determined. 243 */ isActivityDistractionOptimized(String packageName, String className)244 public boolean isActivityDistractionOptimized(String packageName, String className) { 245 try { 246 return mService.isActivityDistractionOptimized(packageName, className); 247 } catch (RemoteException e) { 248 return handleRemoteExceptionFromCarService(e, false); 249 } 250 } 251 252 /** 253 * Returns whether the given {@link PendingIntent} represents an activity that is distraction 254 * optimized, i.e, allowed in a restricted driving state. 255 * 256 * @param pendingIntent the {@link PendingIntent} to check. 257 * @return true if the pending intent represents an activity that is distraction optimized, 258 * false if it isn't or if the value could not be determined. 259 */ isPendingIntentDistractionOptimized(@onNull PendingIntent pendingIntent)260 public boolean isPendingIntentDistractionOptimized(@NonNull PendingIntent pendingIntent) { 261 try { 262 return mService.isPendingIntentDistractionOptimized(pendingIntent); 263 } catch (RemoteException e) { 264 return handleRemoteExceptionFromCarService(e, false); 265 } 266 } 267 268 /** 269 * Check if given service is distraction optimized, i.e, allowed in a restricted 270 * driving state. 271 * 272 * @param packageName 273 * @param className 274 * @return 275 */ isServiceDistractionOptimized(String packageName, String className)276 public boolean isServiceDistractionOptimized(String packageName, String className) { 277 try { 278 return mService.isServiceDistractionOptimized(packageName, className); 279 } catch (RemoteException e) { 280 return handleRemoteExceptionFromCarService(e, false); 281 } 282 } 283 284 /** 285 * Returns the current driving safety region of the system. It will return OEM specific regions 286 * or {@link #DRIVING_SAFETY_REGION_ALL} when all regions are supported. 287 * 288 * <p> System's driving safety region is static and does not change until system restarts. 289 * 290 * @hide 291 */ 292 @RequiresPermission(anyOf = {PERMISSION_CONTROL_APP_BLOCKING, 293 Car.PERMISSION_CAR_DRIVING_STATE}) 294 @NonNull getCurrentDrivingSafetyRegion()295 public String getCurrentDrivingSafetyRegion() { 296 try { 297 return mService.getCurrentDrivingSafetyRegion(); 298 } catch (RemoteException e) { 299 return handleRemoteExceptionFromCarService(e, DRIVING_SAFETY_REGION_ALL); 300 } 301 } 302 303 /** 304 * Enables or disables bypassing of unsafe {@code Activity} blocking for a specific 305 * {@code Activity} temporarily. 306 * 307 * <p> Enabling bypassing only lasts until the user stops using the car or until a user 308 * switching happens. Apps like launcher may ask user's consent to bypass. Note that bypassing 309 * is done for the package for all android users including the current user and user 0. 310 * <p> If bypassing is disabled and if the unsafe app is in foreground with driving state, the 311 * app will be immediately blocked. 312 * 313 * @param packageName Target package name. 314 * @param activityClassName Target Activity name (in full class name). 315 * @param bypass Bypass {@code Activity} blocking when true. Do not bypass anymore when false. 316 * @param userId User Id where the package is installed. Even if the bypassing is enabled for 317 * all android users, the package should be available for the specified user id. 318 * 319 * @throws NameNotFoundException If the given package / Activity class does not exist for the 320 * user. 321 * 322 * @hide 323 */ 324 @RequiresPermission(allOf = {PERMISSION_CONTROL_APP_BLOCKING, 325 android.Manifest.permission.QUERY_ALL_PACKAGES}) controlTemporaryActivityBlockingBypassingAsUser(String packageName, String activityClassName, boolean bypass, @UserIdInt int userId)326 public void controlTemporaryActivityBlockingBypassingAsUser(String packageName, 327 String activityClassName, boolean bypass, @UserIdInt int userId) 328 throws NameNotFoundException { 329 try { 330 mService.controlOneTimeActivityBlockingBypassingAsUser(packageName, activityClassName, 331 bypass, userId); 332 } catch (ServiceSpecificException e) { 333 handleServiceSpecificFromCarService(e, packageName, activityClassName, userId); 334 } catch (RemoteException e) { 335 handleRemoteExceptionFromCarService(e); 336 } 337 } 338 339 /** 340 * Returns all supported driving safety regions for the given Activity. If the Activity supports 341 * all regions, it will only include {@link #DRIVING_SAFETY_REGION_ALL}. 342 * 343 * <p> The permission specification requires {@code PERMISSION_CONTROL_APP_BLOCKING} and 344 * {@code QUERY_ALL_PACKAGES} but this API will also work if the client has 345 * {@link Car#PERMISSION_CAR_DRIVING_STATE} and {@code QUERY_ALL_PACKAGES} permissions. 346 * 347 * @param packageName Target package name. 348 * @param activityClassName Target Activity name (in full class name). 349 * @param userId Android user Id to check the package. 350 * 351 * @return Empty list if the Activity does not support driving safety (=no 352 * {@code distractionOptimized} metadata). Otherwise returns full list of all supported 353 * regions. 354 * 355 * @throws NameNotFoundException If the given package / Activity class does not exist for the 356 * user. 357 * 358 * @hide 359 */ 360 @RequiresPermission(allOf = {PERMISSION_CONTROL_APP_BLOCKING, 361 android.Manifest.permission.QUERY_ALL_PACKAGES}) 362 @NonNull getSupportedDrivingSafetyRegionsForActivityAsUser(String packageName, String activityClassName, @UserIdInt int userId)363 public List<String> getSupportedDrivingSafetyRegionsForActivityAsUser(String packageName, 364 String activityClassName, @UserIdInt int userId) throws NameNotFoundException { 365 try { 366 return mService.getSupportedDrivingSafetyRegionsForActivityAsUser(packageName, 367 activityClassName, userId); 368 } catch (ServiceSpecificException e) { 369 handleServiceSpecificFromCarService(e, packageName, activityClassName, userId); 370 } catch (RemoteException e) { 371 return handleRemoteExceptionFromCarService(e, Collections.EMPTY_LIST); 372 } 373 return Collections.EMPTY_LIST; // cannot reach here but the compiler complains. 374 } 375 handleServiceSpecificFromCarService(ServiceSpecificException e, String packageName, String activityClassName, @UserIdInt int userId)376 private void handleServiceSpecificFromCarService(ServiceSpecificException e, 377 String packageName, String activityClassName, @UserIdInt int userId) 378 throws NameNotFoundException { 379 if (e.errorCode == ERROR_CODE_NO_PACKAGE) { 380 throw new NameNotFoundException( 381 "cannot find " + packageName + "/" + activityClassName + " for user id:" 382 + userId); 383 } 384 // don't know what this is 385 throw new IllegalStateException(e); 386 } 387 } 388