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