1 /* 2 * Copyright (C) 2019 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.accessibility; 18 19 import android.Manifest; 20 import android.accessibilityservice.AccessibilityServiceInfo; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.app.AppOpsManager; 24 import android.appwidget.AppWidgetManagerInternal; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.pm.ServiceInfo; 30 import android.content.pm.UserInfo; 31 import android.os.Binder; 32 import android.os.IBinder; 33 import android.os.Process; 34 import android.os.UserHandle; 35 import android.os.UserManager; 36 import android.util.ArraySet; 37 import android.util.Slog; 38 import android.view.accessibility.AccessibilityEvent; 39 40 import com.android.internal.util.ArrayUtils; 41 import com.android.server.LocalServices; 42 import com.android.server.wm.ActivityTaskManagerInternal; 43 44 import libcore.util.EmptyArray; 45 46 /** 47 * This class provides APIs of accessibility security policies for accessibility manager 48 * to grant accessibility capabilities or events access right to accessibility service. 49 */ 50 public class AccessibilitySecurityPolicy { 51 private static final int OWN_PROCESS_ID = android.os.Process.myPid(); 52 private static final String LOG_TAG = "AccessibilitySecurityPolicy"; 53 54 private final Context mContext; 55 private final PackageManager mPackageManager; 56 private final UserManager mUserManager; 57 private final AppOpsManager mAppOpsManager; 58 59 private AppWidgetManagerInternal mAppWidgetService; 60 61 private static final int KEEP_SOURCE_EVENT_TYPES = AccessibilityEvent.TYPE_VIEW_CLICKED 62 | AccessibilityEvent.TYPE_VIEW_FOCUSED 63 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER 64 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT 65 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED 66 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED 67 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED 68 | AccessibilityEvent.TYPE_WINDOWS_CHANGED 69 | AccessibilityEvent.TYPE_VIEW_SELECTED 70 | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED 71 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED 72 | AccessibilityEvent.TYPE_VIEW_SCROLLED 73 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED 74 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED 75 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY; 76 77 /** 78 * Methods that should find their way into separate modules, but are still in AMS 79 * TODO (b/111889696): Refactoring UserState to AccessibilityUserManager. 80 */ 81 public interface AccessibilityUserManager { 82 /** 83 * Returns current userId maintained in accessibility manager service 84 */ getCurrentUserIdLocked()85 int getCurrentUserIdLocked(); 86 // TODO: Should include resolveProfileParentLocked, but that was already in SecurityPolicy 87 } 88 89 private final AccessibilityUserManager mAccessibilityUserManager; 90 private AccessibilityWindowManager mAccessibilityWindowManager; 91 private final ActivityTaskManagerInternal mAtmInternal; 92 93 /** 94 * Constructor for AccessibilityManagerService. 95 */ AccessibilitySecurityPolicy(@onNull Context context, @NonNull AccessibilityUserManager a11yUserManager)96 public AccessibilitySecurityPolicy(@NonNull Context context, 97 @NonNull AccessibilityUserManager a11yUserManager) { 98 mContext = context; 99 mAccessibilityUserManager = a11yUserManager; 100 mPackageManager = mContext.getPackageManager(); 101 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 102 mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 103 mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); 104 } 105 106 /** 107 * Setup AccessibilityWindowManager. This isn't part of the constructor because the 108 * window manager and security policy both call each other. 109 */ setAccessibilityWindowManager(@onNull AccessibilityWindowManager awm)110 public void setAccessibilityWindowManager(@NonNull AccessibilityWindowManager awm) { 111 mAccessibilityWindowManager = awm; 112 } 113 114 /** 115 * Setup AppWidgetManger during boot phase. 116 */ setAppWidgetManager(@onNull AppWidgetManagerInternal appWidgetManager)117 public void setAppWidgetManager(@NonNull AppWidgetManagerInternal appWidgetManager) { 118 mAppWidgetService = appWidgetManager; 119 } 120 121 /** 122 * Check if an accessibility event can be dispatched. Events should be dispatched only if they 123 * are dispatched from items that services can see. 124 * 125 * @param userId The userId to check 126 * @param event The event to check 127 * @return {@code true} if the event can be dispatched 128 */ canDispatchAccessibilityEventLocked(int userId, @NonNull AccessibilityEvent event)129 public boolean canDispatchAccessibilityEventLocked(int userId, 130 @NonNull AccessibilityEvent event) { 131 final int eventType = event.getEventType(); 132 switch (eventType) { 133 // All events that are for changes in a global window 134 // state should *always* be dispatched. 135 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: 136 case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: 137 case AccessibilityEvent.TYPE_ANNOUNCEMENT: 138 // All events generated by the user touching the 139 // screen should *always* be dispatched. 140 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: 141 case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: 142 case AccessibilityEvent.TYPE_GESTURE_DETECTION_START: 143 case AccessibilityEvent.TYPE_GESTURE_DETECTION_END: 144 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START: 145 case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END: 146 case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: 147 case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: 148 // Also always dispatch the event that assist is reading context. 149 case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT: 150 // Also windows changing should always be dispatched. 151 case AccessibilityEvent.TYPE_WINDOWS_CHANGED: { 152 return true; 153 } 154 // All events for changes in window content should be 155 // dispatched *only* if this window is one of the windows 156 // the accessibility layer reports which are windows 157 // that a sighted user can touch. 158 default: { 159 return isRetrievalAllowingWindowLocked(userId, event.getWindowId()); 160 } 161 } 162 } 163 164 /** 165 * Find a valid package name for an app to expose to accessibility 166 * 167 * @param packageName The package name the app wants to expose 168 * @param appId The app's id 169 * @param userId The app's user id 170 * @param pid The app's process pid that requested this 171 * @return A package name that is valid to report 172 */ 173 @Nullable resolveValidReportedPackageLocked( @ullable CharSequence packageName, int appId, int userId, int pid)174 public String resolveValidReportedPackageLocked( 175 @Nullable CharSequence packageName, int appId, int userId, int pid) { 176 // Okay to pass no package 177 if (packageName == null) { 178 return null; 179 } 180 // The system gets to pass any package 181 if (appId == Process.SYSTEM_UID) { 182 return packageName.toString(); 183 } 184 // Passing a package in your UID is fine 185 final String packageNameStr = packageName.toString(); 186 final int resolvedUid = UserHandle.getUid(userId, appId); 187 if (isValidPackageForUid(packageNameStr, resolvedUid)) { 188 return packageName.toString(); 189 } 190 // Appwidget hosts get to pass packages for widgets they host 191 if (mAppWidgetService != null && ArrayUtils.contains(mAppWidgetService 192 .getHostedWidgetPackages(resolvedUid), packageNameStr)) { 193 return packageName.toString(); 194 } 195 // If app has the targeted permission to act as another package 196 if (mContext.checkPermission(Manifest.permission.ACT_AS_PACKAGE_FOR_ACCESSIBILITY, 197 pid, resolvedUid) == PackageManager.PERMISSION_GRANTED) { 198 return packageName.toString(); 199 } 200 // Otherwise, set the package to the first one in the UID 201 final String[] packageNames = mPackageManager.getPackagesForUid(resolvedUid); 202 if (ArrayUtils.isEmpty(packageNames)) { 203 return null; 204 } 205 // Okay, the caller reported a package it does not have access to. 206 // Instead of crashing the caller for better backwards compatibility 207 // we report the first package in the UID. Since most of the time apps 208 // don't use shared user id, this will yield correct results and for 209 // the edge case of using a shared user id we may report the wrong 210 // package but this is fine since first, this is a cheating app and 211 // second there is no way to get the correct package anyway. 212 return packageNames[0]; 213 } 214 215 /** 216 * Get the packages that are valid for a uid. In some situations, like app widgets, there 217 * could be several valid packages 218 * 219 * @param targetPackage A package that is known to be valid for this id 220 * @param targetUid The whose packages should be checked 221 * @return An array of all valid package names. An empty array means any package is OK 222 */ 223 @NonNull computeValidReportedPackages( @onNull String targetPackage, int targetUid)224 public String[] computeValidReportedPackages( 225 @NonNull String targetPackage, int targetUid) { 226 if (UserHandle.getAppId(targetUid) == Process.SYSTEM_UID) { 227 // Empty array means any package is Okay 228 return EmptyArray.STRING; 229 } 230 // IMPORTANT: The target package is already vetted to be in the target UID 231 String[] uidPackages = new String[]{targetPackage}; 232 // Appwidget hosts get to pass packages for widgets they host 233 if (mAppWidgetService != null) { 234 final ArraySet<String> widgetPackages = mAppWidgetService 235 .getHostedWidgetPackages(targetUid); 236 if (widgetPackages != null && !widgetPackages.isEmpty()) { 237 final String[] validPackages = new String[uidPackages.length 238 + widgetPackages.size()]; 239 System.arraycopy(uidPackages, 0, validPackages, 0, uidPackages.length); 240 final int widgetPackageCount = widgetPackages.size(); 241 for (int i = 0; i < widgetPackageCount; i++) { 242 validPackages[uidPackages.length + i] = widgetPackages.valueAt(i); 243 } 244 return validPackages; 245 } 246 } 247 return uidPackages; 248 } 249 250 /** 251 * Reset the event source for events that should not carry one 252 * 253 * @param event The event potentially to modify 254 */ updateEventSourceLocked(@onNull AccessibilityEvent event)255 public void updateEventSourceLocked(@NonNull AccessibilityEvent event) { 256 if ((event.getEventType() & KEEP_SOURCE_EVENT_TYPES) == 0) { 257 event.setSource(null); 258 } 259 } 260 261 /** 262 * Check if a service can have access to a window 263 * 264 * @param userId The id of the user running the service 265 * @param service The service requesting access 266 * @param windowId The window it wants access to 267 * 268 * @return Whether ot not the service may retrieve info from the window 269 */ canGetAccessibilityNodeInfoLocked(int userId, @NonNull AbstractAccessibilityServiceConnection service, int windowId)270 public boolean canGetAccessibilityNodeInfoLocked(int userId, 271 @NonNull AbstractAccessibilityServiceConnection service, int windowId) { 272 return canRetrieveWindowContentLocked(service) 273 && isRetrievalAllowingWindowLocked(userId, windowId); 274 } 275 276 /** 277 * Check if a service can have access the list of windows 278 * 279 * @param service The service requesting access 280 * 281 * @return Whether ot not the service may retrieve the window list 282 */ canRetrieveWindowsLocked( @onNull AbstractAccessibilityServiceConnection service)283 public boolean canRetrieveWindowsLocked( 284 @NonNull AbstractAccessibilityServiceConnection service) { 285 return canRetrieveWindowContentLocked(service) && service.mRetrieveInteractiveWindows; 286 } 287 288 /** 289 * Check if a service can have access the content of windows on the screen 290 * 291 * @param service The service requesting access 292 * 293 * @return Whether ot not the service may retrieve the content 294 */ canRetrieveWindowContentLocked( @onNull AbstractAccessibilityServiceConnection service)295 public boolean canRetrieveWindowContentLocked( 296 @NonNull AbstractAccessibilityServiceConnection service) { 297 return (service.getCapabilities() 298 & AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0; 299 } 300 301 /** 302 * Check if a service can control magnification 303 * 304 * @param service The service requesting access 305 * 306 * @return Whether ot not the service may control magnification 307 */ canControlMagnification( @onNull AbstractAccessibilityServiceConnection service)308 public boolean canControlMagnification( 309 @NonNull AbstractAccessibilityServiceConnection service) { 310 return (service.getCapabilities() 311 & AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0; 312 } 313 314 /** 315 * Check if a service can perform gestures 316 * 317 * @param service The service requesting access 318 * 319 * @return Whether ot not the service may perform gestures 320 */ canPerformGestures(@onNull AccessibilityServiceConnection service)321 public boolean canPerformGestures(@NonNull AccessibilityServiceConnection service) { 322 return (service.getCapabilities() 323 & AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0; 324 } 325 326 /** 327 * Check if a service can capture gestures from the fingerprint sensor 328 * 329 * @param service The service requesting access 330 * 331 * @return Whether ot not the service may capture gestures from the fingerprint sensor 332 */ canCaptureFingerprintGestures(@onNull AccessibilityServiceConnection service)333 public boolean canCaptureFingerprintGestures(@NonNull AccessibilityServiceConnection service) { 334 return (service.getCapabilities() 335 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES) != 0; 336 } 337 338 /** 339 * Checks if a service can take screenshot. 340 * 341 * @param service The service requesting access 342 * 343 * @return Whether ot not the service may take screenshot 344 */ canTakeScreenshotLocked( @onNull AbstractAccessibilityServiceConnection service)345 public boolean canTakeScreenshotLocked( 346 @NonNull AbstractAccessibilityServiceConnection service) { 347 return (service.getCapabilities() 348 & AccessibilityServiceInfo.CAPABILITY_CAN_TAKE_SCREENSHOT) != 0; 349 } 350 351 /** 352 * Returns the parent userId of the profile according to the specified userId. 353 * 354 * @param userId The userId to check 355 * @return the parent userId of the profile, or self if no parent exist 356 */ resolveProfileParentLocked(int userId)357 public int resolveProfileParentLocked(int userId) { 358 if (userId != mAccessibilityUserManager.getCurrentUserIdLocked()) { 359 final long identity = Binder.clearCallingIdentity(); 360 try { 361 UserInfo parent = mUserManager.getProfileParent(userId); 362 if (parent != null) { 363 return parent.getUserHandle().getIdentifier(); 364 } 365 } finally { 366 Binder.restoreCallingIdentity(identity); 367 } 368 } 369 return userId; 370 } 371 372 /** 373 * Returns the parent userId of the profile according to the specified userId. Enforcing 374 * permissions check if specified userId is not caller's userId. 375 * 376 * @param userId The userId to check 377 * @return the parent userId of the profile, or self if no parent exist 378 * @throws SecurityException if caller cannot interact across users 379 * @throws IllegalArgumentException if specified invalid userId 380 */ resolveCallingUserIdEnforcingPermissionsLocked(int userId)381 public int resolveCallingUserIdEnforcingPermissionsLocked(int userId) { 382 final int callingUid = Binder.getCallingUid(); 383 final int currentUserId = mAccessibilityUserManager.getCurrentUserIdLocked(); 384 if (callingUid == 0 385 || callingUid == Process.SYSTEM_UID 386 || callingUid == Process.SHELL_UID) { 387 if (userId == UserHandle.USER_CURRENT 388 || userId == UserHandle.USER_CURRENT_OR_SELF) { 389 return currentUserId; 390 } 391 return resolveProfileParentLocked(userId); 392 } 393 final int callingUserId = UserHandle.getUserId(callingUid); 394 if (callingUserId == userId) { 395 return resolveProfileParentLocked(userId); 396 } 397 final int callingUserParentId = resolveProfileParentLocked(callingUserId); 398 if (callingUserParentId == currentUserId && (userId == UserHandle.USER_CURRENT 399 || userId == UserHandle.USER_CURRENT_OR_SELF)) { 400 return currentUserId; 401 } 402 if (!hasPermission(Manifest.permission.INTERACT_ACROSS_USERS) 403 && !hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL)) { 404 throw new SecurityException("Call from user " + callingUserId + " as user " 405 + userId + " without permission INTERACT_ACROSS_USERS or " 406 + "INTERACT_ACROSS_USERS_FULL not allowed."); 407 } 408 if (userId == UserHandle.USER_CURRENT 409 || userId == UserHandle.USER_CURRENT_OR_SELF) { 410 return currentUserId; 411 } 412 return resolveProfileParentLocked(userId); 413 } 414 415 /** 416 * Returns false if caller is not SYSTEM and SHELL, and tried to interact across users. 417 * 418 * @param userId The userId to interact. 419 * @return false if caller cannot interact across users. 420 */ isCallerInteractingAcrossUsers(int userId)421 public boolean isCallerInteractingAcrossUsers(int userId) { 422 final int callingUid = Binder.getCallingUid(); 423 return (Binder.getCallingPid() == android.os.Process.myPid() 424 || callingUid == Process.SHELL_UID 425 || userId == UserHandle.USER_CURRENT 426 || userId == UserHandle.USER_CURRENT_OR_SELF); 427 } 428 isValidPackageForUid(String packageName, int uid)429 private boolean isValidPackageForUid(String packageName, int uid) { 430 final long token = Binder.clearCallingIdentity(); 431 try { 432 return uid == mPackageManager.getPackageUidAsUser( 433 packageName, UserHandle.getUserId(uid)); 434 } catch (PackageManager.NameNotFoundException e) { 435 return false; 436 } finally { 437 Binder.restoreCallingIdentity(token); 438 } 439 } 440 isRetrievalAllowingWindowLocked(int userId, int windowId)441 private boolean isRetrievalAllowingWindowLocked(int userId, int windowId) { 442 // The system gets to interact with any window it wants. 443 if (Binder.getCallingUid() == Process.SYSTEM_UID) { 444 return true; 445 } 446 if (Binder.getCallingUid() == Process.SHELL_UID) { 447 if (!isShellAllowedToRetrieveWindowLocked(userId, windowId)) { 448 return false; 449 } 450 } 451 if (mAccessibilityWindowManager.resolveParentWindowIdLocked(windowId) 452 == mAccessibilityWindowManager.getActiveWindowId(userId)) { 453 return true; 454 } 455 return mAccessibilityWindowManager.findA11yWindowInfoByIdLocked(windowId) != null; 456 } 457 isShellAllowedToRetrieveWindowLocked(int userId, int windowId)458 private boolean isShellAllowedToRetrieveWindowLocked(int userId, int windowId) { 459 long token = Binder.clearCallingIdentity(); 460 try { 461 IBinder windowToken = mAccessibilityWindowManager 462 .getWindowTokenForUserAndWindowIdLocked(userId, windowId); 463 if (windowToken == null) { 464 return false; 465 } 466 int windowOwnerUserId = mAccessibilityWindowManager.getWindowOwnerUserId(windowToken); 467 if (windowOwnerUserId == UserHandle.USER_NULL) { 468 return false; 469 } 470 return !mUserManager.hasUserRestriction( 471 UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.of(windowOwnerUserId)); 472 } finally { 473 Binder.restoreCallingIdentity(token); 474 } 475 } 476 477 /** 478 * Enforcing permission check to caller. 479 * 480 * @param permission The permission to check 481 * @param function The function name to check 482 */ enforceCallingPermission(@onNull String permission, @Nullable String function)483 public void enforceCallingPermission(@NonNull String permission, @Nullable String function) { 484 if (OWN_PROCESS_ID == Binder.getCallingPid()) { 485 return; 486 } 487 if (!hasPermission(permission)) { 488 throw new SecurityException("You do not have " + permission 489 + " required to call " + function + " from pid=" 490 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 491 } 492 } 493 494 /** 495 * Permission check to caller. 496 * 497 * @param permission The permission to check 498 * @return true if caller has permission 499 */ hasPermission(@onNull String permission)500 public boolean hasPermission(@NonNull String permission) { 501 return mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED; 502 } 503 504 /** 505 * Checks if accessibility service could register into the system. 506 * 507 * @param serviceInfo The ServiceInfo 508 * @return True if it could register into the system 509 */ canRegisterService(@onNull ServiceInfo serviceInfo)510 public boolean canRegisterService(@NonNull ServiceInfo serviceInfo) { 511 if (!android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE.equals( 512 serviceInfo.permission)) { 513 Slog.w(LOG_TAG, "Skipping accessibility service " + new ComponentName( 514 serviceInfo.packageName, serviceInfo.name).flattenToShortString() 515 + ": it does not require the permission " 516 + android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE); 517 return false; 518 } 519 520 int servicePackageUid = serviceInfo.applicationInfo.uid; 521 if (mAppOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE, 522 servicePackageUid, serviceInfo.packageName) != AppOpsManager.MODE_ALLOWED) { 523 Slog.w(LOG_TAG, "Skipping accessibility service " + new ComponentName( 524 serviceInfo.packageName, serviceInfo.name).flattenToShortString() 525 + ": disallowed by AppOps"); 526 return false; 527 } 528 529 return true; 530 } 531 532 /** 533 * Checks if accessibility service could execute accessibility operations. 534 * 535 * @param service The accessibility service connection 536 * @return True if it could execute accessibility operations 537 */ checkAccessibilityAccess(AbstractAccessibilityServiceConnection service)538 public boolean checkAccessibilityAccess(AbstractAccessibilityServiceConnection service) { 539 final String packageName = service.getComponentName().getPackageName(); 540 final ResolveInfo resolveInfo = service.getServiceInfo().getResolveInfo(); 541 542 if (resolveInfo == null) { 543 // For InteractionBridge and UiAutomation 544 return true; 545 } 546 547 final int uid = resolveInfo.serviceInfo.applicationInfo.uid; 548 final long identityToken = Binder.clearCallingIdentity(); 549 try { 550 // For the caller is system, just block the data to a11y services. 551 if (OWN_PROCESS_ID == Binder.getCallingPid()) { 552 return mAppOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_ACCESS_ACCESSIBILITY, 553 uid, packageName) == AppOpsManager.MODE_ALLOWED; 554 } 555 556 return mAppOpsManager.noteOp(AppOpsManager.OPSTR_ACCESS_ACCESSIBILITY, 557 uid, packageName) == AppOpsManager.MODE_ALLOWED; 558 } finally { 559 Binder.restoreCallingIdentity(identityToken); 560 } 561 } 562 563 /** 564 * Enforcing permission check to IPC caller or grant it if it's not through IPC. 565 * 566 * @param permission The permission to check 567 */ enforceCallingOrSelfPermission(@onNull String permission)568 public void enforceCallingOrSelfPermission(@NonNull String permission) { 569 if (mContext.checkCallingOrSelfPermission(permission) 570 != PackageManager.PERMISSION_GRANTED) { 571 throw new SecurityException("Caller does not hold permission " 572 + permission); 573 } 574 } 575 576 /** 577 * Enforcing permission check to IPC caller or grant it if it's recents. 578 * 579 * @param permission The permission to check 580 */ enforceCallerIsRecentsOrHasPermission(@onNull String permission, String func)581 public void enforceCallerIsRecentsOrHasPermission(@NonNull String permission, String func) { 582 mAtmInternal.enforceCallerIsRecentsOrHasPermission(permission, func); 583 } 584 } 585