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