1 /* 2 * Copyright (C) 2022 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 com.android.server.devicelock; 18 19 import static android.app.AppOpsManager.OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION; 20 import static android.app.role.RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP; 21 import static android.content.IntentFilter.SYSTEM_HIGH_PRIORITY; 22 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; 23 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; 24 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; 25 import static android.content.pm.PackageManager.DONT_KILL_APP; 26 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 27 import static android.devicelock.DeviceId.DEVICE_ID_TYPE_IMEI; 28 import static android.devicelock.DeviceId.DEVICE_ID_TYPE_MEID; 29 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; 30 31 import android.Manifest; 32 import android.Manifest.permission; 33 import android.annotation.NonNull; 34 import android.annotation.Nullable; 35 import android.app.AppOpsManager; 36 import android.app.role.RoleManager; 37 import android.content.BroadcastReceiver; 38 import android.content.ComponentName; 39 import android.content.ContentResolver; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.content.IntentFilter; 43 import android.content.ServiceConnection; 44 import android.content.pm.PackageManager; 45 import android.content.pm.PackageManager.NameNotFoundException; 46 import android.content.pm.ServiceInfo; 47 import android.database.ContentObserver; 48 import android.devicelock.DeviceId.DeviceIdType; 49 import android.devicelock.DeviceLockManager; 50 import android.devicelock.IDeviceLockService; 51 import android.devicelock.IGetDeviceIdCallback; 52 import android.devicelock.IGetKioskAppsCallback; 53 import android.devicelock.IIsDeviceLockedCallback; 54 import android.devicelock.ILockUnlockDeviceCallback; 55 import android.devicelock.ParcelableException; 56 import android.net.NetworkPolicyManager; 57 import android.net.Uri; 58 import android.os.Binder; 59 import android.os.Bundle; 60 import android.os.Environment; 61 import android.os.IBinder; 62 import android.os.OutcomeReceiver; 63 import android.os.PowerExemptionManager; 64 import android.os.RemoteCallback; 65 import android.os.RemoteException; 66 import android.os.UserHandle; 67 import android.os.UserManager; 68 import android.provider.Settings; 69 import android.telephony.TelephonyManager; 70 import android.text.TextUtils; 71 import android.util.ArrayMap; 72 import android.util.Slog; 73 74 import com.android.internal.annotations.GuardedBy; 75 import com.android.internal.annotations.VisibleForTesting; 76 77 import java.io.File; 78 import java.lang.reflect.InvocationTargetException; 79 import java.util.ArrayList; 80 import java.util.List; 81 import java.util.concurrent.ExecutorService; 82 import java.util.concurrent.Executors; 83 84 /** 85 * Implementation of {@link android.devicelock.IDeviceLockService} binder service. 86 */ 87 final class DeviceLockServiceImpl extends IDeviceLockService.Stub { 88 private static final String TAG = "DeviceLockServiceImpl"; 89 90 // Keep this in sync with NetworkPolicyManager#POLICY_NONE. 91 private static final int POLICY_NONE = 0x0; 92 //Keep this in sync with NetworkPolicyManager#POLICY_ALLOW_METERED_BACKGROUND. 93 private static final int POLICY_ALLOW_METERED_BACKGROUND = 0x4; 94 private static final String ACTION_DEVICE_LOCK_KEEPALIVE = 95 "com.android.devicelock.action.KEEPALIVE"; 96 97 // Workaround for timeout while adding the kiosk app as role holder for financing. 98 private static final int MAX_ADD_ROLE_HOLDER_TRIES = 4; 99 100 private final Context mContext; 101 private final ExecutorService mExecutorService; 102 103 private final RoleManager mRoleManager; 104 private final TelephonyManager mTelephonyManager; 105 private final AppOpsManager mAppOpsManager; 106 private final UserManager mUserManager; 107 108 // Map user id -> DeviceLockControllerConnector 109 @GuardedBy("this") 110 private final ArrayMap<Integer, DeviceLockControllerConnector> mDeviceLockControllerConnectors; 111 112 private final DeviceLockControllerConnectorStub mDeviceLockControllerConnectorStub = 113 new DeviceLockControllerConnectorStub(); 114 115 private final DeviceLockControllerPackageUtils mPackageUtils; 116 117 private final ServiceInfo mServiceInfo; 118 119 // Map user id -> ServiceConnection for kiosk keepalive. 120 private final ArrayMap<Integer, KeepaliveServiceConnection> mKioskKeepaliveServiceConnections; 121 122 // Map user id -> ServiceConnection for controller keepalive. 123 private final ArrayMap<Integer, KeepaliveServiceConnection> 124 mControllerKeepaliveServiceConnections; 125 126 private final DeviceLockPersistentStore mPersistentStore; 127 128 // The following string constants should be a SystemApi on AppOpsManager. 129 @VisibleForTesting 130 static final String OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION = 131 "android:system_exempt_from_activity_bg_start_restriction"; 132 @VisibleForTesting 133 static final String OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS = 134 "android:system_exempt_from_dismissible_notifications"; 135 @VisibleForTesting 136 static final String OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS = 137 "android:system_exempt_from_power_restrictions"; 138 139 // Stopgap: this receiver should be replaced by an API on DeviceLockManager. 140 private final class DeviceLockClearReceiver extends BroadcastReceiver { 141 static final String ACTION_CLEAR = "com.android.devicelock.intent.action.CLEAR"; 142 static final int CLEAR_SUCCEEDED = 0; 143 static final int CLEAR_FAILED = 1; 144 145 @Override onReceive(Context context, Intent intent)146 public void onReceive(Context context, Intent intent) { 147 Slog.i(TAG, "Received request to clear device"); 148 149 // This receiver should be the only one. 150 // The result will still be sent to the 'resultReceiver' of 'sendOrderedBroadcast'. 151 abortBroadcast(); 152 153 final UserHandle userHandle = getSendingUser(); 154 155 final PendingResult pendingResult = goAsync(); 156 157 getDeviceLockControllerConnector(userHandle).clearDeviceRestrictions( 158 new OutcomeReceiver<>() { 159 160 private void setResult(int resultCode) { 161 pendingResult.setResultCode(resultCode); 162 163 pendingResult.finish(); 164 } 165 166 @Override 167 public void onResult(Void ignored) { 168 Slog.i(TAG, "Device cleared "); 169 170 setResult(DeviceLockClearReceiver.CLEAR_SUCCEEDED); 171 } 172 173 @Override 174 public void onError(Exception ex) { 175 Slog.e(TAG, "Exception clearing device: ", ex); 176 177 setResult(DeviceLockClearReceiver.CLEAR_FAILED); 178 } 179 }); 180 } 181 } 182 183 // Last supported device id type 184 private static final @DeviceIdType int LAST_DEVICE_ID_TYPE = DEVICE_ID_TYPE_MEID; 185 186 @VisibleForTesting 187 static final String MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER = 188 "com.android.devicelockcontroller.permission." 189 + "MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER"; 190 191 @NonNull getDeviceLockControllerConnector(UserHandle userHandle)192 private DeviceLockControllerConnector getDeviceLockControllerConnector(UserHandle userHandle) { 193 synchronized (this) { 194 final int userId = userHandle.getIdentifier(); 195 DeviceLockControllerConnector deviceLockControllerConnector = 196 mDeviceLockControllerConnectors.get(userId); 197 if (deviceLockControllerConnector == null) { 198 if (isDlcPackageEnabledForUser(userHandle)) { 199 final ComponentName componentName = new ComponentName(mServiceInfo.packageName, 200 mServiceInfo.name); 201 deviceLockControllerConnector = new DeviceLockControllerConnectorImpl(mContext, 202 componentName, userHandle); 203 } else { 204 deviceLockControllerConnector = mDeviceLockControllerConnectorStub; 205 } 206 mDeviceLockControllerConnectors.put(userId, deviceLockControllerConnector); 207 } 208 return deviceLockControllerConnector; 209 } 210 } 211 212 @NonNull getDeviceLockControllerConnector()213 private DeviceLockControllerConnector getDeviceLockControllerConnector() { 214 final UserHandle userHandle = Binder.getCallingUserHandle(); 215 return getDeviceLockControllerConnector(userHandle); 216 } 217 DeviceLockServiceImpl(@onNull Context context)218 DeviceLockServiceImpl(@NonNull Context context) { 219 this(context, context.getSystemService(TelephonyManager.class), 220 Executors.newCachedThreadPool(), 221 Environment.getDataDirectory()); 222 } 223 224 @VisibleForTesting DeviceLockServiceImpl(@onNull Context context, TelephonyManager telephonyManager, ExecutorService executorService, File dataDirectory)225 DeviceLockServiceImpl(@NonNull Context context, TelephonyManager telephonyManager, 226 ExecutorService executorService, File dataDirectory) { 227 mContext = context; 228 mTelephonyManager = telephonyManager; 229 mExecutorService = executorService; 230 231 mRoleManager = context.getSystemService(RoleManager.class); 232 mAppOpsManager = context.getSystemService(AppOpsManager.class); 233 mUserManager = context.getSystemService(UserManager.class); 234 235 mDeviceLockControllerConnectors = new ArrayMap<>(); 236 237 mKioskKeepaliveServiceConnections = new ArrayMap<>(); 238 mControllerKeepaliveServiceConnections = new ArrayMap<>(); 239 240 mPackageUtils = new DeviceLockControllerPackageUtils(context); 241 242 mPersistentStore = new DeviceLockPersistentStore(executorService, dataDirectory); 243 244 final StringBuilder errorMessage = new StringBuilder(); 245 mServiceInfo = mPackageUtils.findService(errorMessage); 246 247 if (mServiceInfo == null) { 248 throw new RuntimeException(errorMessage.toString()); 249 } 250 251 enableDlcIfNeeded(UserHandle.SYSTEM); 252 253 final IntentFilter intentFilter = new IntentFilter(DeviceLockClearReceiver.ACTION_CLEAR); 254 // Run before any eventual app receiver (there should be none). 255 intentFilter.setPriority(SYSTEM_HIGH_PRIORITY); 256 context.registerReceiverForAllUsers(new DeviceLockClearReceiver(), intentFilter, 257 Manifest.permission.MANAGE_DEVICE_LOCK_STATE, null /* scheduler */, 258 Context.RECEIVER_EXPORTED); 259 } 260 261 /** 262 * Enable DLC for user if it should be enabled. 263 * <p> 264 * Note that this is separate from {@link #disableDlcIfNeeded} because we always want to enable 265 * if the device is not finalized but we generally do not want to disable immediately if 266 * the device is finalized in case we still need to do some clean up. See 267 * {@link #disableDlcIfNeeded}. 268 * 269 * @param userHandle user to enable for 270 */ enableDlcIfNeeded(@onNull UserHandle userHandle)271 private void enableDlcIfNeeded(@NonNull UserHandle userHandle) { 272 mPersistentStore.readFinalizedState( 273 isFinalized -> { 274 if (!isFinalized || !canDlcBeDisabledForFinalizedUser(userHandle)) { 275 setDeviceLockControllerPackageEnabledState(userHandle, true); 276 } 277 }, 278 mContext.getMainExecutor()); 279 } 280 281 /** 282 * Disable DLC for user if it should be disabled. 283 * <p> 284 * We only want to do this for newly created users or previously provisioned users that have 285 * run their clean-up logic and told us to disable them with {@link #setDeviceFinalized}. 286 * Otherwise, we risk disabling before all the roles, permissions, etc. have been removed. 287 * 288 * @param userHandle user to disable for 289 */ disableDlcIfNeeded(@onNull UserHandle userHandle)290 private void disableDlcIfNeeded(@NonNull UserHandle userHandle) { 291 mPersistentStore.readFinalizedState( 292 isFinalized -> { 293 if (isFinalized && canDlcBeDisabledForFinalizedUser(userHandle)) { 294 setDeviceLockControllerPackageEnabledState(userHandle, false); 295 } 296 }, 297 mContext.getMainExecutor()); 298 } 299 300 /** 301 * Whether the DLC on a given user can be disabled safely at this point assuming the user 302 * has been finalized (i.e. the DLC has done its clean-up logic on finalization). 303 * 304 * @param userHandle user handle to check 305 * @return true if it can be disabled, false otherwise 306 */ canDlcBeDisabledForFinalizedUser(UserHandle userHandle)307 private boolean canDlcBeDisabledForFinalizedUser(UserHandle userHandle) { 308 if (!userHandle.isSystem()) { 309 return true; 310 } 311 // If the user is system, we can only disable it if all other users have finished 312 // finalizing since the system user DLC process hosts services that DLC processes in other 313 // users need to complete finalization (e.g. global parameters). 314 boolean allNonSystemUsersFinalized = true; 315 final long identity = Binder.clearCallingIdentity(); 316 List<UserHandle> users = mUserManager.getUserHandles(/* excludeDying= */ true); 317 for (int i = 0; i < users.size(); i++) { 318 UserHandle user = users.get(i); 319 if (user.isSystem()) { 320 continue; 321 } 322 if (isDlcPackageEnabledForUser(user)) { 323 Slog.d(TAG, "Cannot disable DLC for system user. User " + user + " " 324 + "is not finalized."); 325 allNonSystemUsersFinalized = false; 326 break; 327 } 328 } 329 Binder.restoreCallingIdentity(identity); 330 return allNonSystemUsersFinalized; 331 } 332 isDlcPackageEnabledForUser(UserHandle userHandle)333 private boolean isDlcPackageEnabledForUser(UserHandle userHandle) { 334 final String controllerPackageName = mServiceInfo.packageName; 335 Context controllerContext; 336 try { 337 controllerContext = mContext.createPackageContextAsUser(controllerPackageName, 338 0 /* flags */, userHandle); 339 } catch (NameNotFoundException e) { 340 Slog.e(TAG, "Cannot create package context for: " + userHandle, e); 341 return false; 342 } 343 final PackageManager controllerPackageManager = controllerContext.getPackageManager(); 344 final int enabledState = 345 controllerPackageManager.getApplicationEnabledSetting(controllerPackageName); 346 return (enabledState != COMPONENT_ENABLED_STATE_DISABLED 347 && enabledState != COMPONENT_ENABLED_STATE_DISABLED_USER); 348 } 349 setDeviceLockControllerPackageEnabledState(UserHandle userHandle, boolean enabled)350 private void setDeviceLockControllerPackageEnabledState(UserHandle userHandle, 351 boolean enabled) { 352 final String controllerPackageName = mServiceInfo.packageName; 353 354 Context controllerContext; 355 try { 356 controllerContext = mContext.createPackageContextAsUser(controllerPackageName, 357 0 /* flags */, userHandle); 358 } catch (NameNotFoundException e) { 359 Slog.e(TAG, "Cannot create package context for: " + userHandle, e); 360 361 return; 362 } 363 364 final PackageManager controllerPackageManager = controllerContext.getPackageManager(); 365 366 final int enableState = 367 enabled ? COMPONENT_ENABLED_STATE_DEFAULT : COMPONENT_ENABLED_STATE_DISABLED; 368 // We cannot check if user control is disabled since 369 // DevicePolicyManager.getUserControlDisabledPackages() acts on the calling user. 370 // Additionally, we would have to catch SecurityException anyways to avoid TOCTOU bugs 371 // since checking and setting is not atomic. 372 try { 373 controllerPackageManager.setApplicationEnabledSetting(controllerPackageName, 374 enableState, enabled ? DONT_KILL_APP : 0); 375 } catch (SecurityException ex) { 376 // This exception is thrown when Device Lock Controller has already enabled 377 // package protection for itself. This is an expected behaviour. 378 // Note: the exception description thrown by 379 // PackageManager.setApplicationEnabledSetting() is somehow misleading because it says 380 // that a protected package cannot be disabled (but we're actually trying to enable it). 381 } 382 synchronized (this) { 383 // Refresh connector 384 mDeviceLockControllerConnectors.put(userHandle.getIdentifier(), null); 385 getDeviceLockControllerConnector(userHandle); 386 } 387 } 388 onUserAdded(@onNull UserHandle userHandle)389 void onUserAdded(@NonNull UserHandle userHandle) { 390 // New users do not have any provisioning to clean up and can be disabled immediately 391 disableDlcIfNeeded(userHandle); 392 } 393 onUserSwitching(@onNull UserHandle userHandle)394 void onUserSwitching(@NonNull UserHandle userHandle) { 395 enableDlcIfNeeded(userHandle); 396 getDeviceLockControllerConnector(userHandle).onUserSwitching(new OutcomeReceiver<>() { 397 @Override 398 public void onResult(Void ignored) { 399 Slog.i(TAG, "User switching reported for: " + userHandle); 400 } 401 402 @Override 403 public void onError(Exception ex) { 404 Slog.e(TAG, "Exception reporting user switching for: " + userHandle, ex); 405 } 406 }); 407 } 408 onUserUnlocked(@onNull Context userContext, @NonNull UserHandle userHandle)409 void onUserUnlocked(@NonNull Context userContext, @NonNull UserHandle userHandle) { 410 enableDlcIfNeeded(userHandle); 411 mExecutorService.execute(() -> { 412 getDeviceLockControllerConnector(userHandle).onUserUnlocked(new OutcomeReceiver<>() { 413 @Override 414 public void onResult(Void ignored) { 415 Slog.i(TAG, "User unlocked reported for: " + userHandle); 416 } 417 418 @Override 419 public void onError(Exception ex) { 420 Slog.e(TAG, "Exception reporting user unlocked for: " + userHandle, ex); 421 } 422 }); 423 // TODO(b/312521897): Add unit tests for this flow 424 registerUserSetupCompleteListener(userContext, userHandle); 425 }); 426 } 427 registerUserSetupCompleteListener(Context userContext, UserHandle userHandle)428 private void registerUserSetupCompleteListener(Context userContext, UserHandle userHandle) { 429 final ContentResolver contentResolver = userContext.getContentResolver(); 430 Uri setupCompleteUri = Settings.Secure.getUriFor(USER_SETUP_COMPLETE); 431 contentResolver.registerContentObserver(setupCompleteUri, 432 false /* notifyForDescendants */, new ContentObserver(null /* handler */) { 433 @Override 434 public void onChange(boolean selfChange, @Nullable Uri uri) { 435 if (setupCompleteUri.equals(uri) 436 && Settings.Secure.getInt( 437 contentResolver, USER_SETUP_COMPLETE, 0) != 0) { 438 onUserSetupCompleted(userHandle); 439 } 440 } 441 }); 442 } 443 onUserSetupCompleted(UserHandle userHandle)444 void onUserSetupCompleted(UserHandle userHandle) { 445 getDeviceLockControllerConnector(userHandle).onUserSetupCompleted(new OutcomeReceiver<>() { 446 @Override 447 public void onResult(Void ignored) { 448 Slog.i(TAG, "User set up complete reported for: " + userHandle); 449 } 450 451 @Override 452 public void onError(Exception ex) { 453 Slog.e(TAG, "Exception reporting user setup complete for: " + userHandle, ex); 454 } 455 }); 456 } 457 checkCallerPermission()458 private boolean checkCallerPermission() { 459 return mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_DEVICE_LOCK_STATE) 460 == PERMISSION_GRANTED; 461 } 462 reportDeviceLockedUnlocked(@onNull ILockUnlockDeviceCallback callback, @Nullable Exception exception)463 private void reportDeviceLockedUnlocked(@NonNull ILockUnlockDeviceCallback callback, 464 @Nullable Exception exception) { 465 try { 466 if (exception == null) { 467 callback.onDeviceLockedUnlocked(); 468 } else { 469 callback.onError(getParcelableException(exception)); 470 } 471 } catch (RemoteException e) { 472 Slog.e(TAG, "Unable to send result to the callback", e); 473 } 474 } 475 getLockUnlockOutcomeReceiver( @onNull ILockUnlockDeviceCallback callback, @NonNull String successMessage)476 private OutcomeReceiver<Void, Exception> getLockUnlockOutcomeReceiver( 477 @NonNull ILockUnlockDeviceCallback callback, @NonNull String successMessage) { 478 return new OutcomeReceiver<>() { 479 @Override 480 public void onResult(Void ignored) { 481 Slog.i(TAG, successMessage); 482 reportDeviceLockedUnlocked(callback, /* exception= */ null); 483 } 484 485 @Override 486 public void onError(Exception ex) { 487 Slog.e(TAG, "Exception: ", ex); 488 reportDeviceLockedUnlocked(callback, ex); 489 } 490 }; 491 } 492 493 private ParcelableException getParcelableException(Exception exception) { 494 return exception instanceof ParcelableException ? (ParcelableException) exception 495 : new ParcelableException(exception); 496 } 497 498 @Override 499 public void lockDevice(@NonNull ILockUnlockDeviceCallback callback) { 500 if (!checkCallerPermission()) { 501 try { 502 callback.onError(new ParcelableException(new SecurityException())); 503 } catch (RemoteException e) { 504 Slog.e(TAG, "lockDevice() - Unable to send error to the callback", e); 505 } 506 return; 507 } 508 509 getDeviceLockControllerConnector().lockDevice( 510 getLockUnlockOutcomeReceiver(callback, "Device locked")); 511 } 512 513 @Override 514 public void unlockDevice(@NonNull ILockUnlockDeviceCallback callback) { 515 if (!checkCallerPermission()) { 516 try { 517 callback.onError(new ParcelableException(new SecurityException())); 518 } catch (RemoteException e) { 519 Slog.e(TAG, "unlockDevice() - Unable to send error to the callback", e); 520 } 521 return; 522 } 523 524 getDeviceLockControllerConnector().unlockDevice( 525 getLockUnlockOutcomeReceiver(callback, "Device unlocked")); 526 } 527 528 @Override 529 public void isDeviceLocked(@NonNull IIsDeviceLockedCallback callback) { 530 if (!checkCallerPermission()) { 531 try { 532 callback.onError(new ParcelableException(new SecurityException())); 533 } catch (RemoteException e) { 534 Slog.e(TAG, "isDeviceLocked() - Unable to send error to the callback", e); 535 } 536 return; 537 } 538 539 getDeviceLockControllerConnector().isDeviceLocked(new OutcomeReceiver<>() { 540 @Override 541 public void onResult(Boolean isLocked) { 542 Slog.i(TAG, isLocked ? "Device is locked" : "Device is not locked"); 543 try { 544 callback.onIsDeviceLocked(isLocked); 545 } catch (RemoteException e) { 546 Slog.e(TAG, "isDeviceLocked() - Unable to send result to the " + "callback", e); 547 } 548 } 549 550 @Override 551 public void onError(Exception ex) { 552 Slog.e(TAG, "isDeviceLocked exception: ", ex); 553 try { 554 callback.onError(getParcelableException(ex)); 555 } catch (RemoteException e) { 556 Slog.e(TAG, "isDeviceLocked() - Unable to send error to the " + "callback", e); 557 } 558 } 559 }); 560 } 561 562 private boolean hasGsm() { 563 return mContext.getPackageManager().hasSystemFeature( 564 PackageManager.FEATURE_TELEPHONY_GSM); 565 } 566 567 private boolean hasCdma() { 568 return mContext.getPackageManager().hasSystemFeature( 569 PackageManager.FEATURE_TELEPHONY_CDMA); 570 } 571 572 @VisibleForTesting 573 void getDeviceId(@NonNull IGetDeviceIdCallback callback, int deviceIdTypeBitmap) { 574 try { 575 if (deviceIdTypeBitmap < 0 || deviceIdTypeBitmap >= (1 << (LAST_DEVICE_ID_TYPE + 1))) { 576 callback.onError(new ParcelableException("Invalid device type")); 577 return; 578 } 579 } catch (RemoteException e) { 580 Slog.e(TAG, "getDeviceId() - Unable to send result to the callback", e); 581 } 582 583 int activeModemCount = mTelephonyManager.getActiveModemCount(); 584 List<String> imeiList = new ArrayList<String>(); 585 List<String> meidList = new ArrayList<String>(); 586 587 if (hasGsm() && ((deviceIdTypeBitmap & (1 << DEVICE_ID_TYPE_IMEI)) != 0)) { 588 for (int i = 0; i < activeModemCount; i++) { 589 String imei = mTelephonyManager.getImei(i); 590 if (!TextUtils.isEmpty(imei)) { 591 imeiList.add(imei); 592 } 593 } 594 } 595 596 if (hasCdma() && ((deviceIdTypeBitmap & (1 << DEVICE_ID_TYPE_MEID)) != 0)) { 597 for (int i = 0; i < activeModemCount; i++) { 598 String meid = mTelephonyManager.getMeid(i); 599 if (!TextUtils.isEmpty(meid)) { 600 meidList.add(meid); 601 } 602 } 603 } 604 605 getDeviceLockControllerConnector().getDeviceId(new OutcomeReceiver<>() { 606 @Override 607 public void onResult(String deviceId) { 608 Slog.i(TAG, "Get Device ID "); 609 try { 610 if (meidList.contains(deviceId)) { 611 callback.onDeviceIdReceived(DEVICE_ID_TYPE_MEID, deviceId); 612 return; 613 } 614 if (imeiList.contains(deviceId)) { 615 callback.onDeviceIdReceived(DEVICE_ID_TYPE_IMEI, deviceId); 616 return; 617 } 618 // When a device ID is returned from DLC App, but none of the IDs got from 619 // TelephonyManager matches that device ID. 620 // 621 // TODO(b/270392813): Send the device ID back to the callback with 622 // UNSPECIFIED device ID type. 623 callback.onError(new ParcelableException("Unable to get device id")); 624 } catch (RemoteException e) { 625 Slog.e(TAG, "getDeviceId() - Unable to send result to the callback", e); 626 } 627 } 628 629 @Override 630 public void onError(Exception ex) { 631 Slog.e(TAG, "Exception: ", ex); 632 try { 633 callback.onError(getParcelableException(ex)); 634 } catch (RemoteException e) { 635 Slog.e(TAG, 636 "getDeviceId() - " + "Unable to send error to" + " the " + "callback", 637 e); 638 } 639 } 640 }); 641 } 642 643 @Override 644 public void getDeviceId(@NonNull IGetDeviceIdCallback callback) { 645 if (!checkCallerPermission()) { 646 try { 647 callback.onError(new ParcelableException(new SecurityException())); 648 } catch (RemoteException e) { 649 Slog.e(TAG, "getDeviceId() - Unable to send error to the callback", e); 650 } 651 return; 652 } 653 654 final StringBuilder errorBuilder = new StringBuilder(); 655 656 final long identity = Binder.clearCallingIdentity(); 657 final int deviceIdTypeBitmap = mPackageUtils.getDeviceIdTypeBitmap(errorBuilder); 658 Binder.restoreCallingIdentity(identity); 659 660 if (deviceIdTypeBitmap < 0) { 661 Slog.e(TAG, "getDeviceId: " + errorBuilder); 662 } 663 664 getDeviceId(callback, deviceIdTypeBitmap); 665 } 666 667 @Override 668 public void getKioskApps(@NonNull IGetKioskAppsCallback callback) { 669 // Caller is not necessarily a kiosk app, and no particular permission enforcing is needed. 670 671 final ArrayMap kioskApps = new ArrayMap<Integer, String>(); 672 673 final UserHandle userHandle = Binder.getCallingUserHandle(); 674 final long identity = Binder.clearCallingIdentity(); 675 try { 676 List<String> roleHolders = mRoleManager.getRoleHoldersAsUser( 677 RoleManager.ROLE_FINANCED_DEVICE_KIOSK, userHandle); 678 679 if (!roleHolders.isEmpty()) { 680 kioskApps.put(DeviceLockManager.DEVICE_LOCK_ROLE_FINANCING, roleHolders.get(0)); 681 } 682 683 callback.onKioskAppsReceived(kioskApps); 684 } catch (RemoteException e) { 685 Slog.e(TAG, "getKioskApps() - Unable to send result to the callback", e); 686 } finally { 687 Binder.restoreCallingIdentity(identity); 688 } 689 } 690 691 // For calls from Controller to System Service. 692 693 private void reportErrorToCaller(@NonNull RemoteCallback remoteCallback) { 694 final Bundle result = new Bundle(); 695 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, false); 696 remoteCallback.sendResult(result); 697 } 698 699 private boolean checkDeviceLockControllerPermission(@NonNull RemoteCallback remoteCallback) { 700 if (mContext.checkCallingOrSelfPermission(MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER) 701 != PERMISSION_GRANTED) { 702 reportErrorToCaller(remoteCallback); 703 return false; 704 } 705 706 return true; 707 } 708 709 private void reportResult(boolean accepted, long identity, 710 @NonNull RemoteCallback remoteCallback) { 711 Binder.restoreCallingIdentity(identity); 712 713 final Bundle result = new Bundle(); 714 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, accepted); 715 remoteCallback.sendResult(result); 716 } 717 718 private void addFinancedDeviceKioskRoleInternal(@NonNull String packageName, 719 @NonNull RemoteCallback remoteCallback, @NonNull UserHandle userHandle, long identity, 720 int remainingTries) { 721 mRoleManager.addRoleHolderAsUser(RoleManager.ROLE_FINANCED_DEVICE_KIOSK, packageName, 722 MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, mContext.getMainExecutor(), 723 accepted -> { 724 if (accepted || remainingTries == 1) { 725 reportResult(accepted, identity, remoteCallback); 726 } else { 727 final int retryNumber = MAX_ADD_ROLE_HOLDER_TRIES - remainingTries + 1; 728 Slog.w(TAG, "Retrying adding financed device role to kiosk app (retry " 729 + retryNumber + ")"); 730 addFinancedDeviceKioskRoleInternal(packageName, remoteCallback, userHandle, 731 identity, remainingTries - 1); 732 } 733 }); 734 } 735 736 @Override 737 public void addFinancedDeviceKioskRole(@NonNull String packageName, 738 @NonNull RemoteCallback remoteCallback) { 739 if (!checkDeviceLockControllerPermission(remoteCallback)) { 740 return; 741 } 742 743 final UserHandle userHandle = Binder.getCallingUserHandle(); 744 final long identity = Binder.clearCallingIdentity(); 745 746 addFinancedDeviceKioskRoleInternal(packageName, remoteCallback, userHandle, identity, 747 MAX_ADD_ROLE_HOLDER_TRIES); 748 749 Binder.restoreCallingIdentity(identity); 750 } 751 752 @Override 753 public void removeFinancedDeviceKioskRole(@NonNull String packageName, 754 @NonNull RemoteCallback remoteCallback) { 755 if (!checkDeviceLockControllerPermission(remoteCallback)) { 756 return; 757 } 758 759 final UserHandle userHandle = Binder.getCallingUserHandle(); 760 final long identity = Binder.clearCallingIdentity(); 761 762 // Clear the FLAG_PERMISSION_GRANTED_BY_ROLE flag from POST_NOTIFICATIONS for the kiosk app 763 // before removing the ROLE_FINANCED_DEVICE_KIOSK role, to prevent the app from being 764 // killed. 765 final PackageManager packageManager = mContext.getPackageManager(); 766 packageManager.updatePermissionFlags(permission.POST_NOTIFICATIONS, packageName, 767 PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE, /* flagValues= */ 0, userHandle); 768 769 mRoleManager.removeRoleHolderAsUser(RoleManager.ROLE_FINANCED_DEVICE_KIOSK, packageName, 770 MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, mContext.getMainExecutor(), 771 accepted -> reportResult(accepted, identity, remoteCallback)); 772 773 Binder.restoreCallingIdentity(identity); 774 } 775 776 /** 777 * @param uid The uid whose AppOps mode needs to change. 778 * @param packageName The name of the package whose AppOp mode needs to change. 779 * @param appOps A list of appOps to change 780 * @param allowed If true, the mode would be set to {@link AppOpsManager#MODE_ALLOWED}; 781 * false, 782 * the mode would be set to {@link AppOpsManager#MODE_DEFAULT}. 783 * @return a boolean value indicates whether the app ops modes have been changed to the 784 * requested value. 785 */ 786 private boolean setAppOpsModes(int uid, String packageName, String[] appOps, boolean allowed) { 787 final int mode = allowed ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_DEFAULT; 788 789 long identity = Binder.clearCallingIdentity(); 790 for (String appOp : appOps) { 791 mAppOpsManager.setMode(appOp, uid, packageName, mode); 792 } 793 Binder.restoreCallingIdentity(identity); 794 return true; 795 } 796 797 /** 798 * Set the exemption state for activity background start restriction for the calling uid. 799 * Caller must hold the {@link MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER} permission. 800 * 801 * @param exempt if true, the calling uid will be set to exempt from activity background start 802 * restriction; false, the exemption state will be set to default. 803 */ 804 @Override 805 public void setCallerExemptFromActivityBgStartRestrictionState(boolean exempt, 806 @NonNull RemoteCallback remoteCallback) { 807 if (!checkDeviceLockControllerPermission(remoteCallback)) { 808 return; 809 } 810 Bundle result = new Bundle(); 811 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, 812 setAppOpsModes(Binder.getCallingUid(), mServiceInfo.packageName, 813 new String[]{OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION}, 814 exempt)); 815 remoteCallback.sendResult(result); 816 } 817 818 /** 819 * Set whether the caller is allowed to send undismissible notifications. 820 * 821 * @param allowed true if the caller can send undismissible notifications, false otherwise 822 */ 823 @Override 824 public void setCallerAllowedToSendUndismissibleNotifications(boolean allowed, 825 @NonNull RemoteCallback remoteCallback) { 826 if (!checkDeviceLockControllerPermission(remoteCallback)) { 827 return; 828 } 829 Bundle result = new Bundle(); 830 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, 831 setAppOpsModes(Binder.getCallingUid(), mServiceInfo.packageName, 832 new String[]{OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS}, allowed)); 833 remoteCallback.sendResult(result); 834 } 835 836 /** 837 * @param uid The uid whose network policy needs to change. 838 * @param allow whether to allow background data usage in metered data mode. 839 * @return a boolean value indicates whether the policy change is a success. 840 */ 841 private boolean setNetworkPolicyForUid(int uid, boolean allow) { 842 boolean result; 843 long caller = Binder.clearCallingIdentity(); 844 try { 845 // TODO(b/319266027): Figure out a long term solution instead of using reflection here. 846 NetworkPolicyManager networkPolicyManager = mContext.getSystemService( 847 NetworkPolicyManager.class); 848 NetworkPolicyManager.class.getDeclaredMethod("setUidPolicy", Integer.TYPE, 849 Integer.TYPE).invoke(networkPolicyManager, uid, 850 allow ? POLICY_ALLOW_METERED_BACKGROUND : POLICY_NONE); 851 result = true; 852 } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { 853 Slog.e(TAG, "Failed to exempt data usage for given uid: " + uid, e); 854 result = false; 855 } 856 Binder.restoreCallingIdentity(caller); 857 return result; 858 } 859 860 private boolean setPowerExemptionForPackage(String packageName, boolean allow) { 861 boolean result; 862 long caller = Binder.clearCallingIdentity(); 863 try { 864 // TODO(b/321539640): Figure out a long term solution instead of using reflection here. 865 PowerExemptionManager powerExemptionManager = mContext.getSystemService( 866 PowerExemptionManager.class); 867 String methodName = allow ? "addToPermanentAllowList" : "removeFromPermanentAllowList"; 868 PowerExemptionManager.class.getDeclaredMethod(methodName, String.class).invoke( 869 powerExemptionManager, packageName); 870 result = true; 871 } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) { 872 Slog.e(TAG, "Failed to exempt power usage for given package: " + packageName, e); 873 result = false; 874 } 875 Binder.restoreCallingIdentity(caller); 876 return result; 877 } 878 879 /** 880 * Set the exemption state for app restrictions(e.g. hibernation, battery and data usage 881 * restriction) for the given uid 882 * Caller must hold the {@link MANAGE_DEVICE_LOCK_SERVICE_FROM_CONTROLLER} permission. 883 * 884 * @param exempt if true, the given uid will be set to exempt from hibernation, battery and data 885 * usage restriction; false, the exemption state will be set to default. 886 */ 887 @Override 888 public void setUidExemptFromRestrictionsState(int uid, boolean exempt, 889 @NonNull RemoteCallback remoteCallback) { 890 if (!checkDeviceLockControllerPermission(remoteCallback)) { 891 return; 892 } 893 boolean setAppOpsResult = false; 894 boolean setPowerExemptionResult = false; 895 896 String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid); 897 if (packageNames == null || packageNames.length < 1) { 898 Slog.e(TAG, "Can not find package name for given uid: " + uid); 899 } else { 900 setAppOpsResult = setAppOpsModes(uid, packageNames[0], 901 new String[]{OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION, 902 OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS}, exempt); 903 setPowerExemptionResult = setPowerExemptionForPackage(packageNames[0], exempt); 904 } 905 boolean setNetworkPolicyResult = setNetworkPolicyForUid(uid, exempt); 906 Bundle result = new Bundle(); 907 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, 908 setAppOpsResult && setPowerExemptionResult && setNetworkPolicyResult); 909 remoteCallback.sendResult(result); 910 } 911 912 private class KeepaliveServiceConnection implements ServiceConnection { 913 final boolean mIsKiosk; 914 final String mPackageName; 915 final UserHandle mUserHandle; 916 917 final Intent mService; 918 919 KeepaliveServiceConnection(boolean isKiosk, String packageName, UserHandle userHandle) { 920 super(); 921 mIsKiosk = isKiosk; 922 mPackageName = packageName; 923 mUserHandle = userHandle; 924 mService = new Intent(ACTION_DEVICE_LOCK_KEEPALIVE).setPackage(packageName); 925 } 926 927 private boolean bind() { 928 return mContext.bindServiceAsUser(mService, this, Context.BIND_AUTO_CREATE, 929 mUserHandle); 930 } 931 932 private boolean rebind() { 933 mContext.unbindService(this); 934 boolean bound = bind(); 935 936 if (bound) { 937 getDeviceLockControllerConnector(mUserHandle).onAppCrashed(mIsKiosk, 938 new OutcomeReceiver<>() { 939 @Override 940 public void onResult(Void result) { 941 Slog.i(TAG, 942 "Notified controller about " + mPackageName + " crash"); 943 } 944 945 @Override 946 public void onError(Exception ex) { 947 Slog.e(TAG, "On " + mPackageName + " crashed error: ", ex); 948 } 949 }); 950 } 951 952 return bound; 953 } 954 955 @Override 956 public void onServiceConnected(ComponentName name, IBinder service) { 957 Slog.i(TAG, mPackageName + " keepalive successful for user " + mUserHandle); 958 } 959 960 @Override 961 public void onServiceDisconnected(ComponentName name) { 962 if (rebind()) { 963 Slog.i(TAG, 964 "onServiceDisconnected rebind successful for " + mPackageName + " user " 965 + mUserHandle); 966 } else { 967 Slog.e(TAG, "onServiceDisconnected rebind failed for " + mPackageName + " user " 968 + mUserHandle); 969 } 970 } 971 972 @Override 973 public void onBindingDied(ComponentName name) { 974 ServiceConnection.super.onBindingDied(name); 975 if (rebind()) { 976 Slog.i(TAG, "onBindingDied rebind successful for " + mPackageName + " user " 977 + mUserHandle); 978 } else { 979 Slog.e(TAG, 980 "onBindingDied rebind failed for " + mPackageName + " user " 981 + mUserHandle); 982 } 983 } 984 } 985 986 @Override 987 public void enableKioskKeepalive(String packageName, @NonNull RemoteCallback remoteCallback) { 988 enableKeepalive(true /* forKiosk */, packageName, remoteCallback); 989 } 990 991 @Override 992 public void disableKioskKeepalive(@NonNull RemoteCallback remoteCallback) { 993 disableKeepalive(true /* forKiosk */, remoteCallback); 994 } 995 996 @Override 997 public void enableControllerKeepalive(@NonNull RemoteCallback remoteCallback) { 998 enableKeepalive(false /* forKiosk */, mServiceInfo.packageName, remoteCallback); 999 } 1000 1001 @Override 1002 public void disableControllerKeepalive(@NonNull RemoteCallback remoteCallback) { 1003 disableKeepalive(false /* forKiosk */, remoteCallback); 1004 } 1005 1006 private void enableKeepalive(boolean forKiosk, String packageName, 1007 @NonNull RemoteCallback remoteCallback) { 1008 final UserHandle controllerUserHandle = Binder.getCallingUserHandle(); 1009 final int controllerUserId = controllerUserHandle.getIdentifier(); 1010 boolean keepaliveEnabled = false; 1011 final ArrayMap<Integer, KeepaliveServiceConnection> keepaliveServiceConnections = 1012 forKiosk ? mKioskKeepaliveServiceConnections 1013 : mControllerKeepaliveServiceConnections; 1014 1015 synchronized (this) { 1016 if (keepaliveServiceConnections.get(controllerUserId) == null) { 1017 final KeepaliveServiceConnection serviceConnection = 1018 new KeepaliveServiceConnection( 1019 forKiosk, packageName, controllerUserHandle); 1020 final long identity = Binder.clearCallingIdentity(); 1021 if (serviceConnection.bind()) { 1022 keepaliveServiceConnections.put(controllerUserId, serviceConnection); 1023 keepaliveEnabled = true; 1024 } else { 1025 Slog.w(TAG, "enableKeepalive: failed to bind to keepalive service " 1026 + " for package: " + packageName + " user:" + controllerUserHandle); 1027 mContext.unbindService(serviceConnection); 1028 } 1029 Binder.restoreCallingIdentity(identity); 1030 } else { 1031 // Consider success if we already have an entry for this user id. 1032 keepaliveEnabled = true; 1033 } 1034 } 1035 1036 final Bundle result = new Bundle(); 1037 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, keepaliveEnabled); 1038 remoteCallback.sendResult(result); 1039 } 1040 1041 private void disableKeepalive(boolean isKiosk, @NonNull RemoteCallback remoteCallback) { 1042 final UserHandle controllerUserHandle = Binder.getCallingUserHandle(); 1043 final int controllerUserId = controllerUserHandle.getIdentifier(); 1044 final KeepaliveServiceConnection serviceConnection; 1045 final ArrayMap<Integer, KeepaliveServiceConnection> keepaliveServiceConnections = 1046 isKiosk ? mKioskKeepaliveServiceConnections 1047 : mControllerKeepaliveServiceConnections; 1048 1049 synchronized (this) { 1050 serviceConnection = keepaliveServiceConnections.remove(controllerUserId); 1051 } 1052 1053 if (serviceConnection != null) { 1054 final long identity = Binder.clearCallingIdentity(); 1055 mContext.unbindService(serviceConnection); 1056 Binder.restoreCallingIdentity(identity); 1057 } else { 1058 final String target = isKiosk ? "kiosk" : "controller"; 1059 Slog.e(TAG, 1060 "disableKeepalive: Service connection to " + target 1061 + " not found for user: " 1062 + controllerUserHandle); 1063 } 1064 1065 final Bundle result = new Bundle(); 1066 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, serviceConnection != null); 1067 remoteCallback.sendResult(result); 1068 } 1069 1070 @Override 1071 public void setDeviceFinalized(boolean finalized, @NonNull RemoteCallback remoteCallback) { 1072 mPersistentStore.scheduleWrite(finalized); 1073 UserHandle user = getCallingUserHandle(); 1074 if (canDlcBeDisabledForFinalizedUser(user)) { 1075 setDeviceLockControllerPackageEnabledState(user, false); 1076 Slog.d(TAG, "Device finalized for user " + user + ". Disabling DLC."); 1077 } 1078 1079 final Bundle result = new Bundle(); 1080 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, true); 1081 remoteCallback.sendResult(result); 1082 } 1083 1084 @Override 1085 public void setPostNotificationsSystemFixed(boolean systemFixed, 1086 @NonNull RemoteCallback remoteCallback) { 1087 final UserHandle userHandle = Binder.getCallingUserHandle(); 1088 final PackageManager packageManager = mContext.getPackageManager(); 1089 final int permissionFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; 1090 final int newFlagValues = systemFixed ? permissionFlags : 0; 1091 final long identity = Binder.clearCallingIdentity(); 1092 // Make sure permission hasn't been revoked. 1093 packageManager.grantRuntimePermission(mServiceInfo.packageName, 1094 permission.POST_NOTIFICATIONS, userHandle); 1095 packageManager.updatePermissionFlags(permission.POST_NOTIFICATIONS, 1096 mServiceInfo.packageName, permissionFlags, newFlagValues, 1097 userHandle); 1098 Binder.restoreCallingIdentity(identity); 1099 1100 final Bundle result = new Bundle(); 1101 result.putBoolean(KEY_REMOTE_CALLBACK_RESULT, true); 1102 remoteCallback.sendResult(result); 1103 } 1104 } 1105