• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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