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