• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.admin;
18 
19 import static android.os.Process.myUid;
20 
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresPermission;
25 import android.annotation.SystemApi;
26 import android.annotation.TestApi;
27 import android.car.Car;
28 import android.car.CarManagerBase;
29 import android.car.annotation.AddedInOrBefore;
30 import android.car.builtin.util.EventLogHelper;
31 import android.car.user.UserCreationResult;
32 import android.car.user.UserRemovalResult;
33 import android.car.user.UserStartResult;
34 import android.car.user.UserStopResult;
35 import android.car.util.concurrent.AndroidFuture;
36 import android.os.IBinder;
37 import android.os.RemoteException;
38 import android.os.UserHandle;
39 
40 import com.android.car.internal.common.UserHelperLite;
41 import com.android.car.internal.os.CarSystemProperties;
42 import com.android.internal.annotations.VisibleForTesting;
43 
44 import java.lang.annotation.Retention;
45 import java.lang.annotation.RetentionPolicy;
46 import java.util.Objects;
47 import java.util.concurrent.ExecutionException;
48 import java.util.concurrent.TimeUnit;
49 import java.util.concurrent.TimeoutException;
50 
51 /**
52  * Public interface for managing policies enforced on a device.
53  *
54  * <p>This is a sub-set of {@link android.app.admin.DevicePolicyManager}, but with the following
55  * differences:
56  *
57  * <ol>
58  *   <li>Its methods take in consideration driver-safety restrictions.
59  *   <li>Callers doesn't need to be a {@code DPC}, but rather have the proper permissions.
60  * </ol>
61  *
62  * @hide
63  */
64 @SystemApi
65 @TestApi
66 public final class CarDevicePolicyManager extends CarManagerBase {
67 
68     /**
69      * @hide
70      */
71     @VisibleForTesting
72     @AddedInOrBefore(majorVersion = 33)
73     public static final String TAG = CarDevicePolicyManager.class.getSimpleName();
74 
75     private final ICarDevicePolicyService mService;
76 
77     private static final String PREFIX_USER_TYPE = "USER_TYPE_";
78 
79     /**
80      * Type used to indicate the user is a regular user.
81      */
82     @AddedInOrBefore(majorVersion = 33)
83     public static final int USER_TYPE_REGULAR = 0;
84 
85     /**
86      * Type used to indicate the user is an admin user.
87      */
88     @AddedInOrBefore(majorVersion = 33)
89     public static final int USER_TYPE_ADMIN = 1;
90 
91     /**
92      * Type used to indicate the user is a guest user.
93      */
94     @AddedInOrBefore(majorVersion = 33)
95     public static final int USER_TYPE_GUEST = 2;
96 
97     /** @hide - Used on test cases only */
98     @AddedInOrBefore(majorVersion = 33)
99     public static final int FIRST_USER_TYPE = USER_TYPE_REGULAR;
100     /** @hide - Used on test cases only */
101     @AddedInOrBefore(majorVersion = 33)
102     public static final int LAST_USER_TYPE = USER_TYPE_GUEST;
103 
104     private static final int DEVICE_POLICY_MANAGER_TIMEOUT_MS =
105             CarSystemProperties.getDevicePolicyManagerTimeout().orElse(60_000);
106 
107     /** @hide */
108     @IntDef(prefix = PREFIX_USER_TYPE, value = {
109             USER_TYPE_REGULAR,
110             USER_TYPE_ADMIN,
111             USER_TYPE_GUEST
112     })
113     @Retention(RetentionPolicy.SOURCE)
114     public @interface UserType {
115     }
116 
117     /**
118      * @hide
119      */
CarDevicePolicyManager(@onNull Car car, @NonNull IBinder service)120     public CarDevicePolicyManager(@NonNull Car car, @NonNull IBinder service) {
121         this(car, ICarDevicePolicyService.Stub.asInterface(service));
122     }
123 
124     /**
125      * @hide
126      */
127     @VisibleForTesting
CarDevicePolicyManager(@onNull Car car, @NonNull ICarDevicePolicyService service)128     public CarDevicePolicyManager(@NonNull Car car, @NonNull ICarDevicePolicyService service) {
129         super(car);
130         mService = service;
131     }
132 
133     /**
134      * Removes the given user.
135      *
136      * <p><b>Note: </b>if the caller user is not an admin, it can only remove itself
137      * (otherwise it will fail with {@link RemoveUserResult#STATUS_FAILURE_INVALID_ARGUMENTS}).
138      *
139      * @param user identification of the user to be removed.
140      *
141      * @return whether the user was successfully removed.
142      *
143      * @hide
144      */
145     @SystemApi
146     @TestApi
147     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
148             android.Manifest.permission.CREATE_USERS})
149     @NonNull
150     @AddedInOrBefore(majorVersion = 33)
removeUser(@onNull UserHandle user)151     public RemoveUserResult removeUser(@NonNull UserHandle user) {
152         Objects.requireNonNull(user, "user cannot be null");
153 
154         int userId = user.getIdentifier();
155         int uid = myUid();
156         EventLogHelper.writeCarDevicePolicyManagerRemoveUserReq(uid, userId);
157         int status = RemoveUserResult.STATUS_FAILURE_GENERIC;
158         try {
159             AndroidFuture<UserRemovalResult> future = new AndroidFuture<UserRemovalResult>();
160             mService.removeUser(userId, future);
161             UserRemovalResult result = future.get(DEVICE_POLICY_MANAGER_TIMEOUT_MS,
162                     TimeUnit.MILLISECONDS);
163             status = result.getStatus();
164             return new RemoveUserResult(status);
165         } catch (InterruptedException e) {
166             Thread.currentThread().interrupt();
167             return new RemoveUserResult(status);
168         } catch (ExecutionException | TimeoutException e) {
169             return new RemoveUserResult(status);
170         } catch (RemoteException e) {
171             return handleRemoteExceptionFromCarService(e, new RemoveUserResult(status));
172         } finally {
173             EventLogHelper.writeCarDevicePolicyManagerRemoveUserResp(uid, status);
174         }
175     }
176 
177     /**
178      * Creates a user with the given characteristics.
179      *
180      * <p><b>Note: </b>if the caller user is not an admin, it can only create non-admin users
181      * (otherwise it will fail with {@link CreateUserResult#STATUS_FAILURE_INVALID_ARGUMENTS}).
182      *
183      * @param name user name.
184      * @param type either {@link #USER_TYPE_REGULAR}, {@link #USER_TYPE_ADMIN},
185      * or {@link #USER_TYPE_GUEST}.
186      *
187      * @return whether the user was successfully removed.
188      *
189      * @hide
190      */
191     @SystemApi
192     @TestApi
193     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
194             android.Manifest.permission.CREATE_USERS})
195     @NonNull
196     @AddedInOrBefore(majorVersion = 33)
createUser(@ullable String name, @UserType int type)197     public CreateUserResult createUser(@Nullable String name, @UserType int type) {
198         int uid = myUid();
199         EventLogHelper.writeCarDevicePolicyManagerCreateUserReq(uid, UserHelperLite.safeName(name),
200                 type);
201         int status = CreateUserResult.STATUS_FAILURE_GENERIC;
202         try {
203             AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>();
204             mService.createUser(name, type, future);
205             UserCreationResult result = future.get(DEVICE_POLICY_MANAGER_TIMEOUT_MS,
206                     TimeUnit.MILLISECONDS);
207             status = result.getStatus();
208             return new CreateUserResult(result);
209         } catch (InterruptedException e) {
210             Thread.currentThread().interrupt();
211             return CreateUserResult.forGenericError();
212         } catch (ExecutionException | TimeoutException e) {
213             return CreateUserResult.forGenericError();
214         } catch (RemoteException e) {
215             return handleRemoteExceptionFromCarService(e, CreateUserResult.forGenericError());
216         } finally {
217             EventLogHelper.writeCarDevicePolicyManagerCreateUserResp(uid, status);
218         }
219     }
220 
221     /**
222      * Starts a user in the background.
223      *
224      * @param user identification of the user to be started.
225      *
226      * @return whether the user was successfully started.
227      *
228      * @hide
229      */
230     @TestApi
231     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
232             android.Manifest.permission.CREATE_USERS})
233     @NonNull
234     @AddedInOrBefore(majorVersion = 33)
startUserInBackground(@onNull UserHandle user)235     public StartUserInBackgroundResult startUserInBackground(@NonNull UserHandle user) {
236         Objects.requireNonNull(user, "user cannot be null");
237 
238         int userId = user.getIdentifier();
239         int uid = myUid();
240         EventLogHelper.writeCarDevicePolicyManagerStartUserInBackgroundReq(uid, userId);
241         int status = StartUserInBackgroundResult.STATUS_FAILURE_GENERIC;
242         try {
243             AndroidFuture<UserStartResult> future = new AndroidFuture<>();
244             mService.startUserInBackground(userId, future);
245             UserStartResult result = future.get(DEVICE_POLICY_MANAGER_TIMEOUT_MS,
246                     TimeUnit.MILLISECONDS);
247             status = result.getStatus();
248             return new StartUserInBackgroundResult(status);
249         } catch (InterruptedException e) {
250             Thread.currentThread().interrupt();
251             return new StartUserInBackgroundResult(status);
252         } catch (ExecutionException | TimeoutException e) {
253             return new StartUserInBackgroundResult(status);
254         } catch (RemoteException e) {
255             return handleRemoteExceptionFromCarService(e, new StartUserInBackgroundResult(status));
256         } finally {
257             EventLogHelper.writeCarDevicePolicyManagerStartUserInBackgroundResp(uid, status);
258         }
259     }
260 
261     /**
262      * Stops the given user.
263      *
264      * @param user identification of the user to stop.
265      *
266      * @return whether the user was successfully stopped.
267      *
268      * @hide
269      */
270     @TestApi
271     @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
272             android.Manifest.permission.CREATE_USERS})
273     @NonNull
274     @AddedInOrBefore(majorVersion = 33)
stopUser(@onNull UserHandle user)275     public StopUserResult stopUser(@NonNull UserHandle user) {
276         Objects.requireNonNull(user, "user cannot be null");
277 
278         int userId = user.getIdentifier();
279         int uid = myUid();
280         EventLogHelper.writeCarDevicePolicyManagerStopUserReq(uid, userId);
281         int status = StopUserResult.STATUS_FAILURE_GENERIC;
282         try {
283             AndroidFuture<UserStopResult> future = new AndroidFuture<>();
284             mService.stopUser(userId, future);
285             UserStopResult result =
286                     future.get(DEVICE_POLICY_MANAGER_TIMEOUT_MS, TimeUnit.MILLISECONDS);
287             status = result.getStatus();
288             return new StopUserResult(status);
289         } catch (InterruptedException e) {
290             Thread.currentThread().interrupt();
291             return new StopUserResult(status);
292         } catch (ExecutionException | TimeoutException e) {
293             return new StopUserResult(status);
294         } catch (RemoteException e) {
295             return handleRemoteExceptionFromCarService(e, new StopUserResult(status));
296         } finally {
297             EventLogHelper.writeCarDevicePolicyManagerStopUserResp(uid, status);
298         }
299     }
300 
301     /** @hide */
302     @AddedInOrBefore(majorVersion = 33)
setUserDisclaimerShown(@onNull UserHandle user)303     public void setUserDisclaimerShown(@NonNull UserHandle user) {
304         Objects.requireNonNull(user, "user cannot be null");
305         try {
306             mService.setUserDisclaimerShown(user.getIdentifier());
307         } catch (RemoteException e) {
308             handleRemoteExceptionFromCarService(e, null);
309         }
310     }
311 
312     /** @hide */
313     @AddedInOrBefore(majorVersion = 33)
setUserDisclaimerAcknowledged(@onNull UserHandle user)314     public void setUserDisclaimerAcknowledged(@NonNull UserHandle user) {
315         Objects.requireNonNull(user, "user cannot be null");
316         try {
317             mService.setUserDisclaimerAcknowledged(user.getIdentifier());
318         } catch (RemoteException e) {
319             handleRemoteExceptionFromCarService(e, null);
320         }
321     }
322 
323     /** @hide */
324     @Override
325     @AddedInOrBefore(majorVersion = 33)
onCarDisconnected()326     public void onCarDisconnected() {
327         // nothing to do
328     }
329 }
330