PermissionManagerService.java revision 460f28c2f017dcef9c34a93c7bd5b18e97c6e15f
1/*
2 * Copyright (C) 2017 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
17package com.android.server.pm.permission;
18
19import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
20import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
21
22import android.Manifest;
23import android.annotation.NonNull;
24import android.annotation.Nullable;
25import android.app.AppOpsManager;
26import android.content.Context;
27import android.content.pm.PackageManager;
28import android.content.pm.PackageManagerInternal;
29import android.content.pm.PackageParser;
30import android.content.pm.PermissionGroupInfo;
31import android.content.pm.PermissionInfo;
32import android.content.pm.PackageParser.Package;
33import android.os.Binder;
34import android.os.Build;
35import android.os.Handler;
36import android.os.HandlerThread;
37import android.os.Process;
38import android.os.UserHandle;
39import android.os.UserManager;
40import android.os.UserManagerInternal;
41import android.os.storage.StorageManagerInternal;
42import android.util.ArrayMap;
43import android.util.ArraySet;
44import android.util.Log;
45import android.util.Slog;
46
47import com.android.internal.R;
48import com.android.internal.logging.MetricsLogger;
49import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
50import com.android.internal.util.ArrayUtils;
51import com.android.server.FgThread;
52import com.android.server.LocalServices;
53import com.android.server.ServiceThread;
54import com.android.server.SystemConfig;
55import com.android.server.Watchdog;
56import com.android.server.pm.PackageManagerService;
57import com.android.server.pm.PackageManagerServiceUtils;
58import com.android.server.pm.PackageSetting;
59import com.android.server.pm.ProcessLoggingHandler;
60import com.android.server.pm.SharedUserSetting;
61import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback;
62import com.android.server.pm.permission.PermissionManagerInternal.PermissionCallback;
63import com.android.server.pm.permission.PermissionsState.PermissionState;
64
65import libcore.util.EmptyArray;
66
67import java.util.ArrayList;
68import java.util.Arrays;
69import java.util.Collection;
70import java.util.Iterator;
71import java.util.List;
72import java.util.Set;
73
74/**
75 * Manages all permissions and handles permissions related tasks.
76 */
77public class PermissionManagerService {
78    private static final String TAG = "PackageManager";
79
80    /** All dangerous permission names in the same order as the events in MetricsEvent */
81    private static final List<String> ALL_DANGEROUS_PERMISSIONS = Arrays.asList(
82            Manifest.permission.READ_CALENDAR,
83            Manifest.permission.WRITE_CALENDAR,
84            Manifest.permission.CAMERA,
85            Manifest.permission.READ_CONTACTS,
86            Manifest.permission.WRITE_CONTACTS,
87            Manifest.permission.GET_ACCOUNTS,
88            Manifest.permission.ACCESS_FINE_LOCATION,
89            Manifest.permission.ACCESS_COARSE_LOCATION,
90            Manifest.permission.RECORD_AUDIO,
91            Manifest.permission.READ_PHONE_STATE,
92            Manifest.permission.CALL_PHONE,
93            Manifest.permission.READ_CALL_LOG,
94            Manifest.permission.WRITE_CALL_LOG,
95            Manifest.permission.ADD_VOICEMAIL,
96            Manifest.permission.USE_SIP,
97            Manifest.permission.PROCESS_OUTGOING_CALLS,
98            Manifest.permission.READ_CELL_BROADCASTS,
99            Manifest.permission.BODY_SENSORS,
100            Manifest.permission.SEND_SMS,
101            Manifest.permission.RECEIVE_SMS,
102            Manifest.permission.READ_SMS,
103            Manifest.permission.RECEIVE_WAP_PUSH,
104            Manifest.permission.RECEIVE_MMS,
105            Manifest.permission.READ_EXTERNAL_STORAGE,
106            Manifest.permission.WRITE_EXTERNAL_STORAGE,
107            Manifest.permission.READ_PHONE_NUMBERS,
108            Manifest.permission.ANSWER_PHONE_CALLS);
109
110    /** Cap the size of permission trees that 3rd party apps can define */
111    private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768;     // characters of text
112
113    /** Lock to protect internal data access */
114    private final Object mLock;
115
116    /** Internal connection to the package manager */
117    private final PackageManagerInternal mPackageManagerInt;
118
119    /** Internal connection to the user manager */
120    private final UserManagerInternal mUserManagerInt;
121
122    /** Default permission policy to provide proper behaviour out-of-the-box */
123    private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy;
124
125    /** Internal storage for permissions and related settings */
126    private final PermissionSettings mSettings;
127
128    private final HandlerThread mHandlerThread;
129    private final Handler mHandler;
130    private final Context mContext;
131
132    PermissionManagerService(Context context,
133            @Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
134            @NonNull Object externalLock) {
135        mContext = context;
136        mLock = externalLock;
137        mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
138        mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
139        mSettings = new PermissionSettings(context, mLock);
140
141        mHandlerThread = new ServiceThread(TAG,
142                Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
143        mHandlerThread.start();
144        mHandler = new Handler(mHandlerThread.getLooper());
145        Watchdog.getInstance().addThread(mHandler);
146
147        mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
148                context, mHandlerThread.getLooper(), defaultGrantCallback, this);
149
150        // propagate permission configuration
151        final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
152                SystemConfig.getInstance().getPermissions();
153        synchronized (mLock) {
154            for (int i=0; i<permConfig.size(); i++) {
155                final SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
156                BasePermission bp = mSettings.getPermissionLocked(perm.name);
157                if (bp == null) {
158                    bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
159                    mSettings.putPermissionLocked(perm.name, bp);
160                }
161                if (perm.gids != null) {
162                    bp.setGids(perm.gids, perm.perUser);
163                }
164            }
165        }
166
167        LocalServices.addService(
168                PermissionManagerInternal.class, new PermissionManagerInternalImpl());
169    }
170
171    /**
172     * Creates and returns an initialized, internal service for use by other components.
173     * <p>
174     * The object returned is identical to the one returned by the LocalServices class using:
175     * {@code LocalServices.getService(PermissionManagerInternal.class);}
176     * <p>
177     * NOTE: The external lock is temporary and should be removed. This needs to be a
178     * lock created by the permission manager itself.
179     */
180    public static PermissionManagerInternal create(Context context,
181            @Nullable DefaultPermissionGrantedCallback defaultGrantCallback,
182            @NonNull Object externalLock) {
183        final PermissionManagerInternal permMgrInt =
184                LocalServices.getService(PermissionManagerInternal.class);
185        if (permMgrInt != null) {
186            return permMgrInt;
187        }
188        new PermissionManagerService(context, defaultGrantCallback, externalLock);
189        return LocalServices.getService(PermissionManagerInternal.class);
190    }
191
192    @Nullable BasePermission getPermission(String permName) {
193        synchronized (mLock) {
194            return mSettings.getPermissionLocked(permName);
195        }
196    }
197
198    private int checkPermission(String permName, String pkgName, int callingUid, int userId) {
199        if (!mUserManagerInt.exists(userId)) {
200            return PackageManager.PERMISSION_DENIED;
201        }
202
203        final PackageParser.Package pkg = mPackageManagerInt.getPackage(pkgName);
204        if (pkg != null && pkg.mExtras != null) {
205            if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
206                return PackageManager.PERMISSION_DENIED;
207            }
208            final PackageSetting ps = (PackageSetting) pkg.mExtras;
209            final boolean instantApp = ps.getInstantApp(userId);
210            final PermissionsState permissionsState = ps.getPermissionsState();
211            if (permissionsState.hasPermission(permName, userId)) {
212                if (instantApp) {
213                    synchronized (mLock) {
214                        BasePermission bp = mSettings.getPermissionLocked(permName);
215                        if (bp != null && bp.isInstant()) {
216                            return PackageManager.PERMISSION_GRANTED;
217                        }
218                    }
219                } else {
220                    return PackageManager.PERMISSION_GRANTED;
221                }
222            }
223            // Special case: ACCESS_FINE_LOCATION permission includes ACCESS_COARSE_LOCATION
224            if (Manifest.permission.ACCESS_COARSE_LOCATION.equals(permName) && permissionsState
225                    .hasPermission(Manifest.permission.ACCESS_FINE_LOCATION, userId)) {
226                return PackageManager.PERMISSION_GRANTED;
227            }
228        }
229
230        return PackageManager.PERMISSION_DENIED;
231    }
232
233    private PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags,
234            int callingUid) {
235        if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
236            return null;
237        }
238        synchronized (mLock) {
239            return PackageParser.generatePermissionGroupInfo(
240                    mSettings.mPermissionGroups.get(groupName), flags);
241        }
242    }
243
244    private List<PermissionGroupInfo> getAllPermissionGroups(int flags, int callingUid) {
245        if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
246            return null;
247        }
248        synchronized (mLock) {
249            final int N = mSettings.mPermissionGroups.size();
250            final ArrayList<PermissionGroupInfo> out
251                    = new ArrayList<PermissionGroupInfo>(N);
252            for (PackageParser.PermissionGroup pg : mSettings.mPermissionGroups.values()) {
253                out.add(PackageParser.generatePermissionGroupInfo(pg, flags));
254            }
255            return out;
256        }
257    }
258
259    private PermissionInfo getPermissionInfo(String permName, String packageName, int flags,
260            int callingUid) {
261        if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
262            return null;
263        }
264        // reader
265        synchronized (mLock) {
266            final BasePermission bp = mSettings.getPermissionLocked(permName);
267            if (bp == null) {
268                return null;
269            }
270            final int adjustedProtectionLevel = adjustPermissionProtectionFlagsLocked(
271                    bp.getProtectionLevel(), packageName, callingUid);
272            return bp.generatePermissionInfo(adjustedProtectionLevel, flags);
273        }
274    }
275
276    private List<PermissionInfo> getPermissionInfoByGroup(
277            String groupName, int flags, int callingUid) {
278        if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
279            return null;
280        }
281        synchronized (mLock) {
282            if (groupName != null && !mSettings.mPermissionGroups.containsKey(groupName)) {
283                return null;
284            }
285            final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
286            for (BasePermission bp : mSettings.mPermissions.values()) {
287                final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags);
288                if (pi != null) {
289                    out.add(pi);
290                }
291            }
292            return out;
293        }
294    }
295
296    private int adjustPermissionProtectionFlagsLocked(
297            int protectionLevel, String packageName, int uid) {
298        // Signature permission flags area always reported
299        final int protectionLevelMasked = protectionLevel
300                & (PermissionInfo.PROTECTION_NORMAL
301                | PermissionInfo.PROTECTION_DANGEROUS
302                | PermissionInfo.PROTECTION_SIGNATURE);
303        if (protectionLevelMasked == PermissionInfo.PROTECTION_SIGNATURE) {
304            return protectionLevel;
305        }
306        // System sees all flags.
307        final int appId = UserHandle.getAppId(uid);
308        if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID
309                || appId == Process.SHELL_UID) {
310            return protectionLevel;
311        }
312        // Normalize package name to handle renamed packages and static libs
313        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
314        if (pkg == null) {
315            return protectionLevel;
316        }
317        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
318            return protectionLevelMasked;
319        }
320        // Apps that target O see flags for all protection levels.
321        final PackageSetting ps = (PackageSetting) pkg.mExtras;
322        if (ps == null) {
323            return protectionLevel;
324        }
325        if (ps.getAppId() != appId) {
326            return protectionLevel;
327        }
328        return protectionLevel;
329    }
330
331    private void addAllPermissions(PackageParser.Package pkg, boolean chatty) {
332        final int N = pkg.permissions.size();
333        for (int i=0; i<N; i++) {
334            PackageParser.Permission p = pkg.permissions.get(i);
335
336            // Assume by default that we did not install this permission into the system.
337            p.info.flags &= ~PermissionInfo.FLAG_INSTALLED;
338
339            synchronized (PermissionManagerService.this.mLock) {
340                // Now that permission groups have a special meaning, we ignore permission
341                // groups for legacy apps to prevent unexpected behavior. In particular,
342                // permissions for one app being granted to someone just because they happen
343                // to be in a group defined by another app (before this had no implications).
344                if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
345                    p.group = mSettings.mPermissionGroups.get(p.info.group);
346                    // Warn for a permission in an unknown group.
347                    if (PackageManagerService.DEBUG_PERMISSIONS
348                            && p.info.group != null && p.group == null) {
349                        Slog.i(TAG, "Permission " + p.info.name + " from package "
350                                + p.info.packageName + " in an unknown group " + p.info.group);
351                    }
352                }
353
354                if (p.tree) {
355                    final BasePermission bp = BasePermission.createOrUpdate(
356                            mSettings.getPermissionTreeLocked(p.info.name), p, pkg,
357                            mSettings.getAllPermissionTreesLocked(), chatty);
358                    mSettings.putPermissionTreeLocked(p.info.name, bp);
359                } else {
360                    final BasePermission bp = BasePermission.createOrUpdate(
361                            mSettings.getPermissionLocked(p.info.name),
362                            p, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
363                    mSettings.putPermissionLocked(p.info.name, bp);
364                }
365            }
366        }
367    }
368
369    private void addAllPermissionGroups(PackageParser.Package pkg, boolean chatty) {
370        final int N = pkg.permissionGroups.size();
371        StringBuilder r = null;
372        for (int i=0; i<N; i++) {
373            final PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
374            final PackageParser.PermissionGroup cur = mSettings.mPermissionGroups.get(pg.info.name);
375            final String curPackageName = (cur == null) ? null : cur.info.packageName;
376            final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName);
377            if (cur == null || isPackageUpdate) {
378                mSettings.mPermissionGroups.put(pg.info.name, pg);
379                if (chatty && PackageManagerService.DEBUG_PACKAGE_SCANNING) {
380                    if (r == null) {
381                        r = new StringBuilder(256);
382                    } else {
383                        r.append(' ');
384                    }
385                    if (isPackageUpdate) {
386                        r.append("UPD:");
387                    }
388                    r.append(pg.info.name);
389                }
390            } else {
391                Slog.w(TAG, "Permission group " + pg.info.name + " from package "
392                        + pg.info.packageName + " ignored: original from "
393                        + cur.info.packageName);
394                if (chatty && PackageManagerService.DEBUG_PACKAGE_SCANNING) {
395                    if (r == null) {
396                        r = new StringBuilder(256);
397                    } else {
398                        r.append(' ');
399                    }
400                    r.append("DUP:");
401                    r.append(pg.info.name);
402                }
403            }
404        }
405        if (r != null && PackageManagerService.DEBUG_PACKAGE_SCANNING) {
406            Log.d(TAG, "  Permission Groups: " + r);
407        }
408
409    }
410
411    private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) {
412        synchronized (mLock) {
413            int N = pkg.permissions.size();
414            StringBuilder r = null;
415            for (int i=0; i<N; i++) {
416                PackageParser.Permission p = pkg.permissions.get(i);
417                BasePermission bp = (BasePermission) mSettings.mPermissions.get(p.info.name);
418                if (bp == null) {
419                    bp = mSettings.mPermissionTrees.get(p.info.name);
420                }
421                if (bp != null && bp.isPermission(p)) {
422                    bp.setPermission(null);
423                    if (PackageManagerService.DEBUG_REMOVE && chatty) {
424                        if (r == null) {
425                            r = new StringBuilder(256);
426                        } else {
427                            r.append(' ');
428                        }
429                        r.append(p.info.name);
430                    }
431                }
432                if (p.isAppOp()) {
433                    ArraySet<String> appOpPkgs =
434                            mSettings.mAppOpPermissionPackages.get(p.info.name);
435                    if (appOpPkgs != null) {
436                        appOpPkgs.remove(pkg.packageName);
437                    }
438                }
439            }
440            if (r != null) {
441                if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
442            }
443
444            N = pkg.requestedPermissions.size();
445            r = null;
446            for (int i=0; i<N; i++) {
447                String perm = pkg.requestedPermissions.get(i);
448                if (mSettings.isPermissionAppOp(perm)) {
449                    ArraySet<String> appOpPkgs = mSettings.mAppOpPermissionPackages.get(perm);
450                    if (appOpPkgs != null) {
451                        appOpPkgs.remove(pkg.packageName);
452                        if (appOpPkgs.isEmpty()) {
453                            mSettings.mAppOpPermissionPackages.remove(perm);
454                        }
455                    }
456                }
457            }
458            if (r != null) {
459                if (PackageManagerService.DEBUG_REMOVE) Log.d(TAG, "  Permissions: " + r);
460            }
461        }
462    }
463
464    private boolean addDynamicPermission(
465            PermissionInfo info, int callingUid, PermissionCallback callback) {
466        if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
467            throw new SecurityException("Instant apps can't add permissions");
468        }
469        if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
470            throw new SecurityException("Label must be specified in permission");
471        }
472        final BasePermission tree = mSettings.enforcePermissionTree(info.name, callingUid);
473        final boolean added;
474        final boolean changed;
475        synchronized (mLock) {
476            BasePermission bp = mSettings.getPermissionLocked(info.name);
477            added = bp == null;
478            int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
479            if (added) {
480                enforcePermissionCapLocked(info, tree);
481                bp = new BasePermission(info.name, tree.getSourcePackageName(),
482                        BasePermission.TYPE_DYNAMIC);
483            } else if (bp.isDynamic()) {
484                // TODO: switch this back to SecurityException
485                Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
486                        + info.name);
487            }
488            changed = bp.addToTree(fixedLevel, info, tree);
489            if (added) {
490                mSettings.putPermissionLocked(info.name, bp);
491            }
492        }
493        if (changed && callback != null) {
494            callback.onPermissionChanged();
495        }
496        return added;
497    }
498
499    private void removeDynamicPermission(
500            String permName, int callingUid, PermissionCallback callback) {
501        if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
502            throw new SecurityException("Instant applications don't have access to this method");
503        }
504        final BasePermission tree = mSettings.enforcePermissionTree(permName, callingUid);
505        synchronized (mLock) {
506            final BasePermission bp = mSettings.getPermissionLocked(permName);
507            if (bp == null) {
508                return;
509            }
510            if (bp.isDynamic()) {
511                // TODO: switch this back to SecurityException
512                Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
513                        + permName);
514            }
515            mSettings.removePermissionLocked(permName);
516            if (callback != null) {
517                callback.onPermissionRemoved();
518            }
519        }
520    }
521
522    private void grantRuntimePermissionsGrantedToDisabledPackageLocked(
523            PackageParser.Package pkg, int callingUid, PermissionCallback callback) {
524        if (pkg.parentPackage == null) {
525            return;
526        }
527        if (pkg.requestedPermissions == null) {
528            return;
529        }
530        final PackageParser.Package disabledPkg =
531                mPackageManagerInt.getDisabledPackage(pkg.parentPackage.packageName);
532        if (disabledPkg == null || disabledPkg.mExtras == null) {
533            return;
534        }
535        final PackageSetting disabledPs = (PackageSetting) disabledPkg.mExtras;
536        if (!disabledPs.isPrivileged() || disabledPs.hasChildPackages()) {
537            return;
538        }
539        final int permCount = pkg.requestedPermissions.size();
540        for (int i = 0; i < permCount; i++) {
541            String permission = pkg.requestedPermissions.get(i);
542            BasePermission bp = mSettings.getPermissionLocked(permission);
543            if (bp == null || !(bp.isRuntime() || bp.isDevelopment())) {
544                continue;
545            }
546            for (int userId : mUserManagerInt.getUserIds()) {
547                if (disabledPs.getPermissionsState().hasRuntimePermission(permission, userId)) {
548                    grantRuntimePermission(
549                            permission, pkg.packageName, false, callingUid, userId, callback);
550                }
551            }
552        }
553    }
554
555    private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds,
556            String[] grantedPermissions, int callingUid, PermissionCallback callback) {
557        for (int userId : userIds) {
558            grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions, callingUid,
559                    callback);
560        }
561    }
562
563    private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
564            String[] grantedPermissions, int callingUid, PermissionCallback callback) {
565        PackageSetting ps = (PackageSetting) pkg.mExtras;
566        if (ps == null) {
567            return;
568        }
569
570        PermissionsState permissionsState = ps.getPermissionsState();
571
572        final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
573                | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
574
575        final boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
576                >= Build.VERSION_CODES.M;
577
578        final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.packageName, userId);
579
580        for (String permission : pkg.requestedPermissions) {
581            final BasePermission bp;
582            synchronized (mLock) {
583                bp = mSettings.getPermissionLocked(permission);
584            }
585            if (bp != null && (bp.isRuntime() || bp.isDevelopment())
586                    && (!instantApp || bp.isInstant())
587                    && (supportsRuntimePermissions || !bp.isRuntimeOnly())
588                    && (grantedPermissions == null
589                           || ArrayUtils.contains(grantedPermissions, permission))) {
590                final int flags = permissionsState.getPermissionFlags(permission, userId);
591                if (supportsRuntimePermissions) {
592                    // Installer cannot change immutable permissions.
593                    if ((flags & immutableFlags) == 0) {
594                        grantRuntimePermission(permission, pkg.packageName, false, callingUid,
595                                userId, callback);
596                    }
597                } else if (mSettings.mPermissionReviewRequired) {
598                    // In permission review mode we clear the review flag when we
599                    // are asked to install the app with all permissions granted.
600                    if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
601                        updatePermissionFlags(permission, pkg.packageName,
602                                PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
603                                userId, callback);
604                    }
605                }
606            }
607        }
608    }
609
610    private void grantRuntimePermission(String permName, String packageName, boolean overridePolicy,
611            int callingUid, final int userId, PermissionCallback callback) {
612        if (!mUserManagerInt.exists(userId)) {
613            Log.e(TAG, "No such user:" + userId);
614            return;
615        }
616
617        mContext.enforceCallingOrSelfPermission(
618                android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
619                "grantRuntimePermission");
620
621        enforceCrossUserPermission(callingUid, userId,
622                true /* requireFullPermission */, true /* checkShell */,
623                "grantRuntimePermission");
624
625        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
626        if (pkg == null || pkg.mExtras == null) {
627            throw new IllegalArgumentException("Unknown package: " + packageName);
628        }
629        final BasePermission bp;
630        synchronized(mLock) {
631            bp = mSettings.getPermissionLocked(permName);
632        }
633        if (bp == null) {
634            throw new IllegalArgumentException("Unknown permission: " + permName);
635        }
636        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
637            throw new IllegalArgumentException("Unknown package: " + packageName);
638        }
639
640        bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
641
642        // If a permission review is required for legacy apps we represent
643        // their permissions as always granted runtime ones since we need
644        // to keep the review required permission flag per user while an
645        // install permission's state is shared across all users.
646        if (mSettings.mPermissionReviewRequired
647                && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
648                && bp.isRuntime()) {
649            return;
650        }
651
652        final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
653
654        final PackageSetting ps = (PackageSetting) pkg.mExtras;
655        final PermissionsState permissionsState = ps.getPermissionsState();
656
657        final int flags = permissionsState.getPermissionFlags(permName, userId);
658        if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
659            throw new SecurityException("Cannot grant system fixed permission "
660                    + permName + " for package " + packageName);
661        }
662        if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
663            throw new SecurityException("Cannot grant policy fixed permission "
664                    + permName + " for package " + packageName);
665        }
666
667        if (bp.isDevelopment()) {
668            // Development permissions must be handled specially, since they are not
669            // normal runtime permissions.  For now they apply to all users.
670            if (permissionsState.grantInstallPermission(bp) !=
671                    PermissionsState.PERMISSION_OPERATION_FAILURE) {
672                if (callback != null) {
673                    callback.onInstallPermissionGranted();
674                }
675            }
676            return;
677        }
678
679        if (ps.getInstantApp(userId) && !bp.isInstant()) {
680            throw new SecurityException("Cannot grant non-ephemeral permission"
681                    + permName + " for package " + packageName);
682        }
683
684        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
685            Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
686            return;
687        }
688
689        final int result = permissionsState.grantRuntimePermission(bp, userId);
690        switch (result) {
691            case PermissionsState.PERMISSION_OPERATION_FAILURE: {
692                return;
693            }
694
695            case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
696                if (callback != null) {
697                    callback.onGidsChanged(UserHandle.getAppId(pkg.applicationInfo.uid), userId);
698                }
699            }
700            break;
701        }
702
703        if (bp.isRuntime()) {
704            logPermissionGranted(mContext, permName, packageName);
705        }
706
707        if (callback != null) {
708            callback.onPermissionGranted(uid, userId);
709        }
710
711        // Only need to do this if user is initialized. Otherwise it's a new user
712        // and there are no processes running as the user yet and there's no need
713        // to make an expensive call to remount processes for the changed permissions.
714        if (READ_EXTERNAL_STORAGE.equals(permName)
715                || WRITE_EXTERNAL_STORAGE.equals(permName)) {
716            final long token = Binder.clearCallingIdentity();
717            try {
718                if (mUserManagerInt.isUserInitialized(userId)) {
719                    StorageManagerInternal storageManagerInternal = LocalServices.getService(
720                            StorageManagerInternal.class);
721                    storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName);
722                }
723            } finally {
724                Binder.restoreCallingIdentity(token);
725            }
726        }
727
728    }
729
730    private void revokeRuntimePermission(String permName, String packageName,
731            boolean overridePolicy, int callingUid, int userId, PermissionCallback callback) {
732        if (!mUserManagerInt.exists(userId)) {
733            Log.e(TAG, "No such user:" + userId);
734            return;
735        }
736
737        mContext.enforceCallingOrSelfPermission(
738                android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
739                "revokeRuntimePermission");
740
741        enforceCrossUserPermission(Binder.getCallingUid(), userId,
742                true /* requireFullPermission */, true /* checkShell */,
743                "revokeRuntimePermission");
744
745        final int appId;
746
747        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
748        if (pkg == null || pkg.mExtras == null) {
749            throw new IllegalArgumentException("Unknown package: " + packageName);
750        }
751        if (mPackageManagerInt.filterAppAccess(pkg, Binder.getCallingUid(), userId)) {
752            throw new IllegalArgumentException("Unknown package: " + packageName);
753        }
754        final BasePermission bp = mSettings.getPermissionLocked(permName);
755        if (bp == null) {
756            throw new IllegalArgumentException("Unknown permission: " + permName);
757        }
758
759        bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
760
761        // If a permission review is required for legacy apps we represent
762        // their permissions as always granted runtime ones since we need
763        // to keep the review required permission flag per user while an
764        // install permission's state is shared across all users.
765        if (mSettings.mPermissionReviewRequired
766                && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
767                && bp.isRuntime()) {
768            return;
769        }
770
771        final PackageSetting ps = (PackageSetting) pkg.mExtras;
772        final PermissionsState permissionsState = ps.getPermissionsState();
773
774        final int flags = permissionsState.getPermissionFlags(permName, userId);
775        if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
776            throw new SecurityException("Cannot revoke system fixed permission "
777                    + permName + " for package " + packageName);
778        }
779        if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
780            throw new SecurityException("Cannot revoke policy fixed permission "
781                    + permName + " for package " + packageName);
782        }
783
784        if (bp.isDevelopment()) {
785            // Development permissions must be handled specially, since they are not
786            // normal runtime permissions.  For now they apply to all users.
787            if (permissionsState.revokeInstallPermission(bp) !=
788                    PermissionsState.PERMISSION_OPERATION_FAILURE) {
789                if (callback != null) {
790                    callback.onInstallPermissionRevoked();
791                }
792            }
793            return;
794        }
795
796        if (permissionsState.revokeRuntimePermission(bp, userId) ==
797                PermissionsState.PERMISSION_OPERATION_FAILURE) {
798            return;
799        }
800
801        if (bp.isRuntime()) {
802            logPermissionRevoked(mContext, permName, packageName);
803        }
804
805        if (callback != null) {
806            final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
807            callback.onPermissionRevoked(pkg.applicationInfo.uid, userId);
808        }
809    }
810
811    private int[] revokeUnusedSharedUserPermissions(SharedUserSetting suSetting, int[] allUserIds) {
812        // Collect all used permissions in the UID
813        final ArraySet<String> usedPermissions = new ArraySet<>();
814        final List<PackageParser.Package> pkgList = suSetting.getPackages();
815        if (pkgList == null || pkgList.size() == 0) {
816            return EmptyArray.INT;
817        }
818        for (PackageParser.Package pkg : pkgList) {
819            final int requestedPermCount = pkg.requestedPermissions.size();
820            for (int j = 0; j < requestedPermCount; j++) {
821                String permission = pkg.requestedPermissions.get(j);
822                BasePermission bp = mSettings.getPermissionLocked(permission);
823                if (bp != null) {
824                    usedPermissions.add(permission);
825                }
826            }
827        }
828
829        PermissionsState permissionsState = suSetting.getPermissionsState();
830        // Prune install permissions
831        List<PermissionState> installPermStates = permissionsState.getInstallPermissionStates();
832        final int installPermCount = installPermStates.size();
833        for (int i = installPermCount - 1; i >= 0;  i--) {
834            PermissionState permissionState = installPermStates.get(i);
835            if (!usedPermissions.contains(permissionState.getName())) {
836                BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
837                if (bp != null) {
838                    permissionsState.revokeInstallPermission(bp);
839                    permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
840                            PackageManager.MASK_PERMISSION_FLAGS, 0);
841                }
842            }
843        }
844
845        int[] runtimePermissionChangedUserIds = EmptyArray.INT;
846
847        // Prune runtime permissions
848        for (int userId : allUserIds) {
849            List<PermissionState> runtimePermStates = permissionsState
850                    .getRuntimePermissionStates(userId);
851            final int runtimePermCount = runtimePermStates.size();
852            for (int i = runtimePermCount - 1; i >= 0; i--) {
853                PermissionState permissionState = runtimePermStates.get(i);
854                if (!usedPermissions.contains(permissionState.getName())) {
855                    BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
856                    if (bp != null) {
857                        permissionsState.revokeRuntimePermission(bp, userId);
858                        permissionsState.updatePermissionFlags(bp, userId,
859                                PackageManager.MASK_PERMISSION_FLAGS, 0);
860                        runtimePermissionChangedUserIds = ArrayUtils.appendInt(
861                                runtimePermissionChangedUserIds, userId);
862                    }
863                }
864            }
865        }
866
867        return runtimePermissionChangedUserIds;
868    }
869
870    private String[] getAppOpPermissionPackages(String permName) {
871        if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
872            return null;
873        }
874        synchronized (mLock) {
875            final ArraySet<String> pkgs = mSettings.mAppOpPermissionPackages.get(permName);
876            if (pkgs == null) {
877                return null;
878            }
879            return pkgs.toArray(new String[pkgs.size()]);
880        }
881    }
882
883    private int getPermissionFlags(
884            String permName, String packageName, int callingUid, int userId) {
885        if (!mUserManagerInt.exists(userId)) {
886            return 0;
887        }
888
889        enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
890
891        enforceCrossUserPermission(callingUid, userId,
892                true /* requireFullPermission */, false /* checkShell */,
893                "getPermissionFlags");
894
895        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
896        if (pkg == null || pkg.mExtras == null) {
897            return 0;
898        }
899        synchronized (mLock) {
900            if (mSettings.getPermissionLocked(permName) == null) {
901                return 0;
902            }
903        }
904        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
905            return 0;
906        }
907        final PackageSetting ps = (PackageSetting) pkg.mExtras;
908        PermissionsState permissionsState = ps.getPermissionsState();
909        return permissionsState.getPermissionFlags(permName, userId);
910    }
911
912    private int updatePermissions(String packageName, PackageParser.Package pkgInfo, int flags) {
913        Set<BasePermission> needsUpdate = null;
914        synchronized (mLock) {
915            final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
916            while (it.hasNext()) {
917                final BasePermission bp = it.next();
918                if (bp.isDynamic()) {
919                    bp.updateDynamicPermission(mSettings.mPermissionTrees.values());
920                }
921                if (bp.getSourcePackageSetting() != null) {
922                    if (packageName != null && packageName.equals(bp.getSourcePackageName())
923                        && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
924                        Slog.i(TAG, "Removing old permission tree: " + bp.getName()
925                                + " from package " + bp.getSourcePackageName());
926                        flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
927                        it.remove();
928                    }
929                    continue;
930                }
931                if (needsUpdate == null) {
932                    needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
933                }
934                needsUpdate.add(bp);
935            }
936        }
937        if (needsUpdate != null) {
938            for (final BasePermission bp : needsUpdate) {
939                final PackageParser.Package pkg =
940                        mPackageManagerInt.getPackage(bp.getSourcePackageName());
941                synchronized (mLock) {
942                    if (pkg != null && pkg.mExtras != null) {
943                        final PackageSetting ps = (PackageSetting) pkg.mExtras;
944                        if (bp.getSourcePackageSetting() == null) {
945                            bp.setSourcePackageSetting(ps);
946                        }
947                        continue;
948                    }
949                    Slog.w(TAG, "Removing dangling permission: " + bp.getName()
950                            + " from package " + bp.getSourcePackageName());
951                    mSettings.removePermissionLocked(bp.getName());
952                }
953            }
954        }
955        return flags;
956    }
957
958    private int updatePermissionTrees(String packageName, PackageParser.Package pkgInfo,
959            int flags) {
960        Set<BasePermission> needsUpdate = null;
961        synchronized (mLock) {
962            final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
963            while (it.hasNext()) {
964                final BasePermission bp = it.next();
965                if (bp.getSourcePackageSetting() != null) {
966                    if (packageName != null && packageName.equals(bp.getSourcePackageName())
967                        && (pkgInfo == null || !hasPermission(pkgInfo, bp.getName()))) {
968                        Slog.i(TAG, "Removing old permission tree: " + bp.getName()
969                                + " from package " + bp.getSourcePackageName());
970                        flags |= PackageManagerService.UPDATE_PERMISSIONS_ALL;
971                        it.remove();
972                    }
973                    continue;
974                }
975                if (needsUpdate == null) {
976                    needsUpdate = new ArraySet<>(mSettings.mPermissionTrees.size());
977                }
978                needsUpdate.add(bp);
979            }
980        }
981        if (needsUpdate != null) {
982            for (final BasePermission bp : needsUpdate) {
983                final PackageParser.Package pkg =
984                        mPackageManagerInt.getPackage(bp.getSourcePackageName());
985                synchronized (mLock) {
986                    if (pkg != null && pkg.mExtras != null) {
987                        final PackageSetting ps = (PackageSetting) pkg.mExtras;
988                        if (bp.getSourcePackageSetting() == null) {
989                            bp.setSourcePackageSetting(ps);
990                        }
991                        continue;
992                    }
993                    Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
994                            + " from package " + bp.getSourcePackageName());
995                    mSettings.removePermissionLocked(bp.getName());
996                }
997            }
998        }
999        return flags;
1000    }
1001
1002    private void updatePermissionFlags(String permName, String packageName, int flagMask,
1003            int flagValues, int callingUid, int userId, PermissionCallback callback) {
1004        if (!mUserManagerInt.exists(userId)) {
1005            return;
1006        }
1007
1008        enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
1009
1010        enforceCrossUserPermission(callingUid, userId,
1011                true /* requireFullPermission */, true /* checkShell */,
1012                "updatePermissionFlags");
1013
1014        // Only the system can change these flags and nothing else.
1015        if (callingUid != Process.SYSTEM_UID) {
1016            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
1017            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
1018            flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
1019            flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
1020            flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
1021        }
1022
1023        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
1024        if (pkg == null || pkg.mExtras == null) {
1025            throw new IllegalArgumentException("Unknown package: " + packageName);
1026        }
1027        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
1028            throw new IllegalArgumentException("Unknown package: " + packageName);
1029        }
1030
1031        final BasePermission bp;
1032        synchronized (mLock) {
1033            bp = mSettings.getPermissionLocked(permName);
1034        }
1035        if (bp == null) {
1036            throw new IllegalArgumentException("Unknown permission: " + permName);
1037        }
1038
1039        final PackageSetting ps = (PackageSetting) pkg.mExtras;
1040        final PermissionsState permissionsState = ps.getPermissionsState();
1041        final boolean hadState =
1042                permissionsState.getRuntimePermissionState(permName, userId) != null;
1043        final boolean permissionUpdated =
1044                permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
1045        if (permissionUpdated && callback != null) {
1046            // Install and runtime permissions are stored in different places,
1047            // so figure out what permission changed and persist the change.
1048            if (permissionsState.getInstallPermissionState(permName) != null) {
1049                callback.onInstallPermissionUpdated();
1050            } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
1051                    || hadState) {
1052                callback.onPermissionUpdated(userId);
1053            }
1054        }
1055    }
1056
1057    private boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
1058            int userId, Collection<Package> packages, PermissionCallback callback) {
1059        if (!mUserManagerInt.exists(userId)) {
1060            return false;
1061        }
1062
1063        enforceGrantRevokeRuntimePermissionPermissions(
1064                "updatePermissionFlagsForAllApps");
1065        enforceCrossUserPermission(callingUid, userId,
1066                true /* requireFullPermission */, true /* checkShell */,
1067                "updatePermissionFlagsForAllApps");
1068
1069        // Only the system can change system fixed flags.
1070        if (callingUid != Process.SYSTEM_UID) {
1071            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
1072            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
1073        }
1074
1075        boolean changed = false;
1076        for (PackageParser.Package pkg : packages) {
1077            final PackageSetting ps = (PackageSetting) pkg.mExtras;
1078            if (ps == null) {
1079                continue;
1080            }
1081            PermissionsState permissionsState = ps.getPermissionsState();
1082            changed |= permissionsState.updatePermissionFlagsForAllPermissions(
1083                    userId, flagMask, flagValues);
1084        }
1085        return changed;
1086    }
1087
1088    private void enforceGrantRevokeRuntimePermissionPermissions(String message) {
1089        if (mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
1090                != PackageManager.PERMISSION_GRANTED
1091            && mContext.checkCallingOrSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
1092                != PackageManager.PERMISSION_GRANTED) {
1093            throw new SecurityException(message + " requires "
1094                    + Manifest.permission.GRANT_RUNTIME_PERMISSIONS + " or "
1095                    + Manifest.permission.REVOKE_RUNTIME_PERMISSIONS);
1096        }
1097    }
1098
1099    /**
1100     * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS
1101     * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller.
1102     * @param checkShell whether to prevent shell from access if there's a debugging restriction
1103     * @param message the message to log on security exception
1104     */
1105    private void enforceCrossUserPermission(int callingUid, int userId,
1106            boolean requireFullPermission, boolean checkShell, String message) {
1107        if (userId < 0) {
1108            throw new IllegalArgumentException("Invalid userId " + userId);
1109        }
1110        if (checkShell) {
1111            PackageManagerServiceUtils.enforceShellRestriction(
1112                    UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId);
1113        }
1114        if (userId == UserHandle.getUserId(callingUid)) return;
1115        if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
1116            if (requireFullPermission) {
1117                mContext.enforceCallingOrSelfPermission(
1118                        android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
1119            } else {
1120                try {
1121                    mContext.enforceCallingOrSelfPermission(
1122                            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
1123                } catch (SecurityException se) {
1124                    mContext.enforceCallingOrSelfPermission(
1125                            android.Manifest.permission.INTERACT_ACROSS_USERS, message);
1126                }
1127            }
1128        }
1129    }
1130
1131    private int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
1132        int size = 0;
1133        for (BasePermission perm : mSettings.mPermissions.values()) {
1134            size += tree.calculateFootprint(perm);
1135        }
1136        return size;
1137    }
1138
1139    private void enforcePermissionCapLocked(PermissionInfo info, BasePermission tree) {
1140        // We calculate the max size of permissions defined by this uid and throw
1141        // if that plus the size of 'info' would exceed our stated maximum.
1142        if (tree.getUid() != Process.SYSTEM_UID) {
1143            final int curTreeSize = calculateCurrentPermissionFootprintLocked(tree);
1144            if (curTreeSize + info.calculateFootprint() > MAX_PERMISSION_TREE_FOOTPRINT) {
1145                throw new SecurityException("Permission tree size cap exceeded");
1146            }
1147        }
1148    }
1149
1150    private static boolean hasPermission(PackageParser.Package pkgInfo, String permName) {
1151        for (int i=pkgInfo.permissions.size()-1; i>=0; i--) {
1152            if (pkgInfo.permissions.get(i).info.name.equals(permName)) {
1153                return true;
1154            }
1155        }
1156        return false;
1157    }
1158
1159    /**
1160     * Get the first event id for the permission.
1161     *
1162     * <p>There are four events for each permission: <ul>
1163     *     <li>Request permission: first id + 0</li>
1164     *     <li>Grant permission: first id + 1</li>
1165     *     <li>Request for permission denied: first id + 2</li>
1166     *     <li>Revoke permission: first id + 3</li>
1167     * </ul></p>
1168     *
1169     * @param name name of the permission
1170     *
1171     * @return The first event id for the permission
1172     */
1173    private static int getBaseEventId(@NonNull String name) {
1174        int eventIdIndex = ALL_DANGEROUS_PERMISSIONS.indexOf(name);
1175
1176        if (eventIdIndex == -1) {
1177            if (AppOpsManager.permissionToOpCode(name) == AppOpsManager.OP_NONE
1178                    || Build.IS_USER) {
1179                Log.i(TAG, "Unknown permission " + name);
1180
1181                return MetricsEvent.ACTION_PERMISSION_REQUEST_UNKNOWN;
1182            } else {
1183                // Most likely #ALL_DANGEROUS_PERMISSIONS needs to be updated.
1184                //
1185                // Also update
1186                // - EventLogger#ALL_DANGEROUS_PERMISSIONS
1187                // - metrics_constants.proto
1188                throw new IllegalStateException("Unknown permission " + name);
1189            }
1190        }
1191
1192        return MetricsEvent.ACTION_PERMISSION_REQUEST_READ_CALENDAR + eventIdIndex * 4;
1193    }
1194
1195    /**
1196     * Log that a permission was revoked.
1197     *
1198     * @param context Context of the caller
1199     * @param name name of the permission
1200     * @param packageName package permission if for
1201     */
1202    private static void logPermissionRevoked(@NonNull Context context, @NonNull String name,
1203            @NonNull String packageName) {
1204        MetricsLogger.action(context, getBaseEventId(name) + 3, packageName);
1205    }
1206
1207    /**
1208     * Log that a permission request was granted.
1209     *
1210     * @param context Context of the caller
1211     * @param name name of the permission
1212     * @param packageName package permission if for
1213     */
1214    private static void logPermissionGranted(@NonNull Context context, @NonNull String name,
1215            @NonNull String packageName) {
1216        MetricsLogger.action(context, getBaseEventId(name) + 1, packageName);
1217    }
1218
1219    private class PermissionManagerInternalImpl extends PermissionManagerInternal {
1220        @Override
1221        public void addAllPermissions(Package pkg, boolean chatty) {
1222            PermissionManagerService.this.addAllPermissions(pkg, chatty);
1223        }
1224        @Override
1225        public void addAllPermissionGroups(Package pkg, boolean chatty) {
1226            PermissionManagerService.this.addAllPermissionGroups(pkg, chatty);
1227        }
1228        @Override
1229        public void removeAllPermissions(Package pkg, boolean chatty) {
1230            PermissionManagerService.this.removeAllPermissions(pkg, chatty);
1231        }
1232        @Override
1233        public boolean addDynamicPermission(PermissionInfo info, boolean async, int callingUid,
1234                PermissionCallback callback) {
1235            return PermissionManagerService.this.addDynamicPermission(info, callingUid, callback);
1236        }
1237        @Override
1238        public void removeDynamicPermission(String permName, int callingUid,
1239                PermissionCallback callback) {
1240            PermissionManagerService.this.removeDynamicPermission(permName, callingUid, callback);
1241        }
1242        @Override
1243        public void grantRuntimePermission(String permName, String packageName,
1244                boolean overridePolicy, int callingUid, int userId,
1245                PermissionCallback callback) {
1246            PermissionManagerService.this.grantRuntimePermission(
1247                    permName, packageName, overridePolicy, callingUid, userId, callback);
1248        }
1249        @Override
1250        public void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds,
1251                String[] grantedPermissions, int callingUid, PermissionCallback callback) {
1252            PermissionManagerService.this.grantRequestedRuntimePermissions(
1253                    pkg, userIds, grantedPermissions, callingUid, callback);
1254        }
1255        @Override
1256        public void grantRuntimePermissionsGrantedToDisabledPackage(PackageParser.Package pkg,
1257                int callingUid, PermissionCallback callback) {
1258            PermissionManagerService.this.grantRuntimePermissionsGrantedToDisabledPackageLocked(
1259                    pkg, callingUid, callback);
1260        }
1261        @Override
1262        public void revokeRuntimePermission(String permName, String packageName,
1263                boolean overridePolicy, int callingUid, int userId,
1264                PermissionCallback callback) {
1265            PermissionManagerService.this.revokeRuntimePermission(permName, packageName,
1266                    overridePolicy, callingUid, userId, callback);
1267        }
1268        @Override
1269        public int[] revokeUnusedSharedUserPermissions(SharedUserSetting suSetting,
1270                int[] allUserIds) {
1271            return PermissionManagerService.this.revokeUnusedSharedUserPermissions(
1272                    (SharedUserSetting) suSetting, allUserIds);
1273        }
1274        @Override
1275        public String[] getAppOpPermissionPackages(String permName) {
1276            return PermissionManagerService.this.getAppOpPermissionPackages(permName);
1277        }
1278        @Override
1279        public int getPermissionFlags(String permName, String packageName, int callingUid,
1280                int userId) {
1281            return PermissionManagerService.this.getPermissionFlags(permName, packageName,
1282                    callingUid, userId);
1283        }
1284        @Override
1285        public int updatePermissions(String packageName,
1286                PackageParser.Package pkgInfo, int flags) {
1287            return PermissionManagerService.this.updatePermissions(packageName, pkgInfo, flags);
1288        }
1289        @Override
1290        public int updatePermissionTrees(String packageName,
1291                PackageParser.Package pkgInfo, int flags) {
1292            return PermissionManagerService.this.updatePermissionTrees(packageName, pkgInfo, flags);
1293        }
1294        @Override
1295        public void updatePermissionFlags(String permName, String packageName, int flagMask,
1296                int flagValues, int callingUid, int userId, PermissionCallback callback) {
1297            PermissionManagerService.this.updatePermissionFlags(
1298                    permName, packageName, flagMask, flagValues, callingUid, userId, callback);
1299        }
1300        @Override
1301        public boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
1302                int userId, Collection<Package> packages, PermissionCallback callback) {
1303            return PermissionManagerService.this.updatePermissionFlagsForAllApps(
1304                    flagMask, flagValues, callingUid, userId, packages, callback);
1305        }
1306        @Override
1307        public void enforceCrossUserPermission(int callingUid, int userId,
1308                boolean requireFullPermission, boolean checkShell, String message) {
1309            PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
1310                    requireFullPermission, checkShell, message);
1311        }
1312        @Override
1313        public void enforceGrantRevokeRuntimePermissionPermissions(String message) {
1314            PermissionManagerService.this.enforceGrantRevokeRuntimePermissionPermissions(message);
1315        }
1316        @Override
1317        public int checkPermission(String permName, String packageName, int callingUid,
1318                int userId) {
1319            return PermissionManagerService.this.checkPermission(
1320                    permName, packageName, callingUid, userId);
1321        }
1322        @Override
1323        public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags,
1324                int callingUid) {
1325            return PermissionManagerService.this.getPermissionGroupInfo(
1326                    groupName, flags, callingUid);
1327        }
1328        @Override
1329        public List<PermissionGroupInfo> getAllPermissionGroups(int flags, int callingUid) {
1330            return PermissionManagerService.this.getAllPermissionGroups(flags, callingUid);
1331        }
1332        @Override
1333        public PermissionInfo getPermissionInfo(String permName, String packageName, int flags,
1334                int callingUid) {
1335            return PermissionManagerService.this.getPermissionInfo(
1336                    permName, packageName, flags, callingUid);
1337        }
1338        @Override
1339        public List<PermissionInfo> getPermissionInfoByGroup(String group, int flags,
1340                int callingUid) {
1341            return PermissionManagerService.this.getPermissionInfoByGroup(group, flags, callingUid);
1342        }
1343        @Override
1344        public PermissionSettings getPermissionSettings() {
1345            return mSettings;
1346        }
1347        @Override
1348        public DefaultPermissionGrantPolicy getDefaultPermissionGrantPolicy() {
1349            return mDefaultPermissionGrantPolicy;
1350        }
1351        @Override
1352        public BasePermission getPermissionTEMP(String permName) {
1353            synchronized (PermissionManagerService.this.mLock) {
1354                return mSettings.getPermissionLocked(permName);
1355            }
1356        }
1357        @Override
1358        public void putPermissionTEMP(String permName, BasePermission permission) {
1359            synchronized (PermissionManagerService.this.mLock) {
1360                mSettings.putPermissionLocked(permName, (BasePermission) permission);
1361            }
1362        }
1363        @Override
1364        public Iterator<BasePermission> getPermissionIteratorTEMP() {
1365            synchronized (PermissionManagerService.this.mLock) {
1366                return mSettings.getAllPermissionsLocked().iterator();
1367            }
1368        }
1369    }
1370}
1371