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.user.UserCreationResult; 30 import android.car.user.UserRemovalResult; 31 import android.car.user.UserStartResult; 32 import android.car.user.UserStopResult; 33 import android.os.IBinder; 34 import android.os.RemoteException; 35 import android.os.UserHandle; 36 import android.sysprop.CarProperties; 37 import android.util.EventLog; 38 39 import com.android.car.internal.common.EventLogTags; 40 import com.android.car.internal.common.UserHelperLite; 41 import com.android.internal.annotations.VisibleForTesting; 42 import com.android.internal.infra.AndroidFuture; 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 private static final String TAG = CarDevicePolicyManager.class.getSimpleName(); 69 private final ICarDevicePolicyService mService; 70 71 private static final String PREFIX_USER_TYPE = "USER_TYPE_"; 72 73 /** 74 * Type used to indicate the user is a regular user. 75 */ 76 public static final int USER_TYPE_REGULAR = 0; 77 78 /** 79 * Type used to indicate the user is an admin user. 80 */ 81 public static final int USER_TYPE_ADMIN = 1; 82 83 /** 84 * Type used to indicate the user is a guest user. 85 */ 86 public static final int USER_TYPE_GUEST = 2; 87 88 /** @hide - Used on test cases only */ 89 public static final int FIRST_USER_TYPE = USER_TYPE_REGULAR; 90 /** @hide - Used on test cases only */ 91 public static final int LAST_USER_TYPE = USER_TYPE_GUEST; 92 93 private static final int DEVICE_POLICY_MANAGER_TIMEOUT_MS = CarProperties 94 .device_policy_manager_timeout().orElse(60_000); 95 96 /** @hide */ 97 @IntDef(prefix = PREFIX_USER_TYPE, value = { 98 USER_TYPE_REGULAR, 99 USER_TYPE_ADMIN, 100 USER_TYPE_GUEST 101 }) 102 @Retention(RetentionPolicy.SOURCE) 103 public @interface UserType { 104 } 105 106 /** 107 * @hide 108 */ CarDevicePolicyManager(@onNull Car car, @NonNull IBinder service)109 public CarDevicePolicyManager(@NonNull Car car, @NonNull IBinder service) { 110 this(car, ICarDevicePolicyService.Stub.asInterface(service)); 111 } 112 113 /** 114 * @hide 115 */ 116 @VisibleForTesting CarDevicePolicyManager(@onNull Car car, @NonNull ICarDevicePolicyService service)117 public CarDevicePolicyManager(@NonNull Car car, @NonNull ICarDevicePolicyService service) { 118 super(car); 119 mService = service; 120 } 121 122 /** 123 * Removes the given user. 124 * 125 * <p><b>Note: </b>if the caller user is not an admin, it can only remove itself 126 * (otherwise it will fail with {@link RemoveUserResult#STATUS_FAILURE_INVALID_ARGUMENTS}). 127 * 128 * @param user identification of the user to be removed. 129 * 130 * @return whether the user was successfully removed. 131 * 132 * @hide 133 */ 134 @SystemApi 135 @TestApi 136 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 137 android.Manifest.permission.CREATE_USERS}) 138 @NonNull removeUser(@onNull UserHandle user)139 public RemoveUserResult removeUser(@NonNull UserHandle user) { 140 Objects.requireNonNull(user, "user cannot be null"); 141 142 int userId = user.getIdentifier(); 143 int uid = myUid(); 144 EventLog.writeEvent(EventLogTags.CAR_DP_MGR_REMOVE_USER_REQ, uid, userId); 145 int status = RemoveUserResult.STATUS_FAILURE_GENERIC; 146 try { 147 AndroidFuture<UserRemovalResult> future = new AndroidFuture<UserRemovalResult>(); 148 mService.removeUser(userId, future); 149 UserRemovalResult result = future.get(DEVICE_POLICY_MANAGER_TIMEOUT_MS, 150 TimeUnit.MILLISECONDS); 151 status = result.getStatus(); 152 return new RemoveUserResult(status); 153 } catch (InterruptedException e) { 154 Thread.currentThread().interrupt(); 155 return new RemoveUserResult(status); 156 } catch (ExecutionException | TimeoutException e) { 157 return new RemoveUserResult(status); 158 } catch (RemoteException e) { 159 return handleRemoteExceptionFromCarService(e, new RemoveUserResult(status)); 160 } finally { 161 EventLog.writeEvent(EventLogTags.CAR_DP_MGR_REMOVE_USER_RESP, uid, status); 162 } 163 } 164 165 /** 166 * Creates a user with the given characteristics. 167 * 168 * <p><b>Note: </b>if the caller user is not an admin, it can only create non-admin users 169 * (otherwise it will fail with {@link CreateUserResult#STATUS_FAILURE_INVALID_ARGUMENTS}). 170 * 171 * @param name user name. 172 * @param type either {@link #USER_TYPE_REGULAR}, {@link #USER_TYPE_ADMIN}, 173 * or {@link #USER_TYPE_GUEST}. 174 * 175 * @return whether the user was successfully removed. 176 * 177 * @hide 178 */ 179 @SystemApi 180 @TestApi 181 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 182 android.Manifest.permission.CREATE_USERS}) 183 @NonNull createUser(@ullable String name, @UserType int type)184 public CreateUserResult createUser(@Nullable String name, @UserType int type) { 185 int uid = myUid(); 186 EventLog.writeEvent(EventLogTags.CAR_DP_MGR_CREATE_USER_REQ, uid, 187 UserHelperLite.safeName(name), type); 188 int status = CreateUserResult.STATUS_FAILURE_GENERIC; 189 try { 190 AndroidFuture<UserCreationResult> future = new AndroidFuture<UserCreationResult>(); 191 mService.createUser(name, type, future); 192 UserCreationResult result = future.get(DEVICE_POLICY_MANAGER_TIMEOUT_MS, 193 TimeUnit.MILLISECONDS); 194 status = result.getStatus(); 195 return new CreateUserResult(result); 196 } catch (InterruptedException e) { 197 Thread.currentThread().interrupt(); 198 return CreateUserResult.forGenericError(); 199 } catch (ExecutionException | TimeoutException e) { 200 return CreateUserResult.forGenericError(); 201 } catch (RemoteException e) { 202 return handleRemoteExceptionFromCarService(e, CreateUserResult.forGenericError()); 203 } finally { 204 EventLog.writeEvent(EventLogTags.CAR_DP_MGR_CREATE_USER_RESP, uid, status); 205 } 206 } 207 208 /** 209 * Starts a user in the background. 210 * 211 * @param user identification of the user to be started. 212 * 213 * @return whether the user was successfully started. 214 * 215 * @hide 216 */ 217 @TestApi 218 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 219 android.Manifest.permission.CREATE_USERS}) 220 @NonNull startUserInBackground(@onNull UserHandle user)221 public StartUserInBackgroundResult startUserInBackground(@NonNull UserHandle user) { 222 Objects.requireNonNull(user, "user cannot be null"); 223 224 int userId = user.getIdentifier(); 225 int uid = myUid(); 226 EventLog.writeEvent(EventLogTags.CAR_DP_MGR_START_USER_IN_BACKGROUND_REQ, uid, userId); 227 int status = StartUserInBackgroundResult.STATUS_FAILURE_GENERIC; 228 try { 229 AndroidFuture<UserStartResult> future = new AndroidFuture<>(); 230 mService.startUserInBackground(userId, future); 231 UserStartResult result = future.get(DEVICE_POLICY_MANAGER_TIMEOUT_MS, 232 TimeUnit.MILLISECONDS); 233 status = result.getStatus(); 234 return new StartUserInBackgroundResult(status); 235 } catch (InterruptedException e) { 236 Thread.currentThread().interrupt(); 237 return new StartUserInBackgroundResult(status); 238 } catch (ExecutionException | TimeoutException e) { 239 return new StartUserInBackgroundResult(status); 240 } catch (RemoteException e) { 241 return handleRemoteExceptionFromCarService(e, new StartUserInBackgroundResult(status)); 242 } finally { 243 EventLog.writeEvent(EventLogTags.CAR_DP_MGR_START_USER_IN_BACKGROUND_RESP, uid, status); 244 } 245 } 246 247 /** 248 * Stops the given user. 249 * 250 * @param user identification of the user to stop. 251 * 252 * @return whether the user was successfully stopped. 253 * 254 * @hide 255 */ 256 @TestApi 257 @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, 258 android.Manifest.permission.CREATE_USERS}) 259 @NonNull stopUser(@onNull UserHandle user)260 public StopUserResult stopUser(@NonNull UserHandle user) { 261 Objects.requireNonNull(user, "user cannot be null"); 262 263 int userId = user.getIdentifier(); 264 int uid = myUid(); 265 EventLog.writeEvent(EventLogTags.CAR_DP_MGR_STOP_USER_REQ, uid, userId); 266 int status = StopUserResult.STATUS_FAILURE_GENERIC; 267 try { 268 AndroidFuture<UserStopResult> future = new AndroidFuture<>(); 269 mService.stopUser(userId, future); 270 UserStopResult result = 271 future.get(DEVICE_POLICY_MANAGER_TIMEOUT_MS, TimeUnit.MILLISECONDS); 272 status = result.getStatus(); 273 return new StopUserResult(status); 274 } catch (InterruptedException e) { 275 Thread.currentThread().interrupt(); 276 return new StopUserResult(status); 277 } catch (ExecutionException | TimeoutException e) { 278 return new StopUserResult(status); 279 } catch (RemoteException e) { 280 return handleRemoteExceptionFromCarService(e, new StopUserResult(status)); 281 } finally { 282 EventLog.writeEvent(EventLogTags.CAR_DP_MGR_STOP_USER_RESP, uid, status); 283 } 284 } 285 286 /** @hide */ 287 @Override onCarDisconnected()288 public void onCarDisconnected() { 289 // nothing to do 290 } 291 } 292