17f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau/*
27f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * Copyright (C) 2015 The Android Open Source Project
37f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau *
47f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * Licensed under the Apache License, Version 2.0 (the "License");
57f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * you may not use this file except in compliance with the License.
67f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * You may obtain a copy of the License at
77f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau *
87f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau *      http://www.apache.org/licenses/LICENSE-2.0
97f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau *
107f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * Unless required by applicable law or agreed to in writing, software
117f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * distributed under the License is distributed on an "AS IS" BASIS,
127f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * See the License for the specific language governing permissions and
147f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * limitations under the License.
157f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau */
167f70ba18e6760c2539704c16cf3865bf49953d50Billy Laupackage com.android.settings.applications;
177f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
187f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.app.AppGlobals;
197f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.app.AppOpsManager;
207f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.app.AppOpsManager.PackageOps;
217f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.Context;
227f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.pm.PackageInfo;
237f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.pm.PackageManager;
247f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.os.RemoteException;
257f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.os.UserHandle;
267f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.os.UserManager;
27cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Lingimport android.support.annotation.VisibleForTesting;
287f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.util.ArrayMap;
297f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.util.Log;
307f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.util.SparseArray;
317f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
327f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport com.android.settingslib.applications.ApplicationsState;
337f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport com.android.settingslib.applications.ApplicationsState.AppEntry;
347f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
353d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lauimport java.util.Arrays;
367f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport java.util.Collection;
373d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lauimport java.util.HashSet;
387f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport java.util.List;
393d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lauimport java.util.Set;
407f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
417f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau/*
427f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * Connects app ops info to the ApplicationsState. Makes use of AppOpsManager to
437f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * determine further permission level.
447f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau */
457f70ba18e6760c2539704c16cf3865bf49953d50Billy Laupublic abstract class AppStateAppOpsBridge extends AppStateBaseBridge {
467f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
477f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private static final String TAG = "AppStateAppOpsBridge";
487f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
49cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling    private final IPackageManagerWrapper mIPackageManager;
507f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private final UserManager mUserManager;
517f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private final List<UserHandle> mProfiles;
527f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private final AppOpsManager mAppOpsManager;
537f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private final Context mContext;
547f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private final int[] mAppOpsOpCodes;
557f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private final String[] mPermissions;
567f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
577f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    public AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
583d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau            int appOpsOpCode, String[] permissions) {
59cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling        this(context, appState, callback, appOpsOpCode, permissions,
60cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling            new IPackageManagerWrapperImpl(AppGlobals.getPackageManager()));
61cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling    }
62cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling
63cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling    @VisibleForTesting(otherwise = VisibleForTesting.NONE)
64cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling    AppStateAppOpsBridge(Context context, ApplicationsState appState, Callback callback,
65cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling            int appOpsOpCode, String[] permissions, IPackageManagerWrapper packageManager) {
667f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        super(appState, callback);
677f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        mContext = context;
68cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling        mIPackageManager = packageManager;
697f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        mUserManager = UserManager.get(context);
707f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        mProfiles = mUserManager.getUserProfiles();
717f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
727f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        mAppOpsOpCodes = new int[] {appOpsOpCode};
733d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau        mPermissions = permissions;
747f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
757f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
767f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private boolean isThisUserAProfileOfCurrentUser(final int userId) {
777f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        final int profilesMax = mProfiles.size();
787f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        for (int i = 0; i < profilesMax; i++) {
797f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            if (mProfiles.get(i).getIdentifier() == userId) {
807f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                return true;
817f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
827f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
837f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        return false;
847f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
857f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
867f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    protected abstract void updateExtraInfo(AppEntry app, String pkg, int uid);
877f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
883d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau    private boolean doesAnyPermissionMatch(String permissionToMatch, String[] permissions) {
893d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau        for (String permission : permissions) {
903d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau            if (permissionToMatch.equals(permission)) {
913d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau                return true;
923d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau            }
933d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau        }
943d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau        return false;
953d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau    }
963d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau
977f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    public PermissionState getPermissionInfo(String pkg, int uid) {
987f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        PermissionState permissionState = new PermissionState(pkg, new UserHandle(UserHandle
997f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                .getUserId(uid)));
1007f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        try {
1017f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            permissionState.packageInfo = mIPackageManager.getPackageInfo(pkg,
102cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                    PackageManager.GET_PERMISSIONS | PackageManager.MATCH_ANY_USER,
103bde1a7cfb13736ad52ba838e0b21117b7da6dafbJason Monk                    permissionState.userHandle.getIdentifier());
104cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling            if (permissionState.packageInfo != null) {
105cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                // Check static permission state (whatever that is declared in package manifest)
106cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                String[] requestedPermissions = permissionState.packageInfo.requestedPermissions;
107cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                int[] permissionFlags = permissionState.packageInfo.requestedPermissionsFlags;
108cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                if (requestedPermissions != null) {
109cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                    for (int i = 0; i < requestedPermissions.length; i++) {
110cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                        if (doesAnyPermissionMatch(requestedPermissions[i], mPermissions)) {
111cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                            permissionState.permissionDeclared = true;
112cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                            if ((permissionFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED)
113cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                                    != 0) {
114cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                                permissionState.staticPermissionGranted = true;
115cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                                break;
116cc28cb372da331e75330d4544d5ae90b7cf34f65Doris Ling                            }
117fee785645b57c519a31ed403e60e8f76dcc8abbbBilly Lau                        }
1187f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    }
1197f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                }
1207f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
1217f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            // Check app op state.
1227f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            List<PackageOps> ops = mAppOpsManager.getOpsForPackage(uid, pkg, mAppOpsOpCodes);
1237f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            if (ops != null && ops.size() > 0 && ops.get(0).getOps().size() > 0) {
1247f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                permissionState.appOpMode = ops.get(0).getOps().get(0).getMode();
1257f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
1267f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        } catch (RemoteException e) {
1277f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            Log.w(TAG, "PackageManager is dead. Can't get package info " + pkg, e);
1287f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
1297f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        return permissionState;
1307f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
1317f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
1327f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    @Override
1337f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    protected void loadAllExtraInfo() {
1347f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        SparseArray<ArrayMap<String, PermissionState>> entries = getEntries();
1357f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
1367f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        // Load state info.
1377f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        loadPermissionsStates(entries);
1387f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        loadAppOpsStates(entries);
1397f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
1407f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        // Map states to application info.
1417f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        List<AppEntry> apps = mAppSession.getAllApps();
1427f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        final int N = apps.size();
1437f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        for (int i = 0; i < N; i++) {
1447f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            AppEntry app = apps.get(i);
1457f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            int userId = UserHandle.getUserId(app.info.uid);
1467f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            ArrayMap<String, PermissionState> userMap = entries.get(userId);
1477f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            app.extraInfo = userMap != null ? userMap.get(app.info.packageName) : null;
1487f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
1497f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
1507f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
1517f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    /*
1527f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     * Gets a sparse array that describes every user on the device and all the associated packages
1537f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     * of each user, together with the packages available for that user.
1547f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     */
1557f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private SparseArray<ArrayMap<String, PermissionState>> getEntries() {
1567f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        try {
1573d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau            Set<String> packagesSet = new HashSet<>();
1583d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau            for (String permission : mPermissions) {
1593d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau                String[] pkgs = mIPackageManager.getAppOpPermissionPackages(permission);
1603d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau                if (pkgs != null) {
1613d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau                    packagesSet.addAll(Arrays.asList(pkgs));
1623d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau                }
1633d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau            }
1647f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
1653d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau            if (packagesSet.isEmpty()) {
1667f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                // No packages are requesting permission as specified by mPermissions.
1677f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                return null;
1687f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
1697f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
1707f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            // Create a sparse array that maps profileIds to an ArrayMap that maps package names to
1717f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            // an associated PermissionState object
1727f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            SparseArray<ArrayMap<String, PermissionState>> entries = new SparseArray<>();
1737f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            for (final UserHandle profile : mProfiles) {
1747f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                final ArrayMap<String, PermissionState> entriesForProfile = new ArrayMap<>();
1757f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                final int profileId = profile.getIdentifier();
1767f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                entries.put(profileId, entriesForProfile);
1773d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau                for (final String packageName : packagesSet) {
1787f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    final boolean isAvailable = mIPackageManager.isPackageAvailable(packageName,
1797f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                            profileId);
1807f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    if (!shouldIgnorePackage(packageName) && isAvailable) {
1817f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                        final PermissionState newEntry = new PermissionState(packageName, profile);
1827f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                        entriesForProfile.put(packageName, newEntry);
1837f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    }
1847f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                }
1857f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
1867f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
1877f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            return entries;
1887f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        } catch (RemoteException e) {
1897f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            Log.w(TAG, "PackageManager is dead. Can't get list of packages requesting "
1907f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    + mPermissions[0], e);
1917f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            return null;
1927f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
1937f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
1947f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
1957f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    /*
196fee785645b57c519a31ed403e60e8f76dcc8abbbBilly Lau     * This method will set the packageInfo and staticPermissionGranted field of the associated
1977f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     * PermissionState, which describes a particular package.
1987f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     */
1997f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private void loadPermissionsStates(SparseArray<ArrayMap<String, PermissionState>> entries) {
2007f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau         // Load the packages that have been granted the permission specified in mPermission.
2017f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        try {
2027f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            for (final UserHandle profile : mProfiles) {
2037f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                final int profileId = profile.getIdentifier();
2047f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                final ArrayMap<String, PermissionState> entriesForProfile = entries.get(profileId);
2057f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                if (entriesForProfile == null) {
2067f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    continue;
2077f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                }
2087f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                @SuppressWarnings("unchecked")
2097f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                final List<PackageInfo> packageInfos = mIPackageManager
2107f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                        .getPackagesHoldingPermissions(mPermissions, 0, profileId).getList();
2117f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                final int packageInfoCount = packageInfos != null ? packageInfos.size() : 0;
2127f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                for (int i = 0; i < packageInfoCount; i++) {
2137f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    final PackageInfo packageInfo = packageInfos.get(i);
2147f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    final PermissionState pe = entriesForProfile.get(packageInfo.packageName);
2157f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    if (pe != null) {
2167f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                        pe.packageInfo = packageInfo;
217fee785645b57c519a31ed403e60e8f76dcc8abbbBilly Lau                        pe.staticPermissionGranted = true;
2187f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                    }
2197f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                }
2207f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
2217f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        } catch (RemoteException e) {
2227f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            Log.w(TAG, "PackageManager is dead. Can't get list of packages granted "
2233d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau                    + mPermissions, e);
2247f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            return;
2257f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
2267f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
2277f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
2287f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    /*
2297f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     * This method will set the appOpMode field of the associated PermissionState, which describes
2307f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     * a particular package.
2317f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     */
2327f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private void loadAppOpsStates(SparseArray<ArrayMap<String, PermissionState>> entries) {
2337f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        // Find out which packages have been granted permission from AppOps.
2347f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        final List<AppOpsManager.PackageOps> packageOps = mAppOpsManager.getPackagesForOps(
2357f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                mAppOpsOpCodes);
2367f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        final int packageOpsCount = packageOps != null ? packageOps.size() : 0;
2377f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        for (int i = 0; i < packageOpsCount; i++) {
2387f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            final AppOpsManager.PackageOps packageOp = packageOps.get(i);
2397f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            final int userId = UserHandle.getUserId(packageOp.getUid());
2407f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            if (!isThisUserAProfileOfCurrentUser(userId)) {
2417f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                // This AppOp does not belong to any of this user's profiles.
2427f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                continue;
2437f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
2447f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
2457f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            final ArrayMap<String, PermissionState> entriesForProfile = entries.get(userId);
2467f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            if (entriesForProfile == null) {
2477f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                continue;
2487f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
2497f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            final PermissionState pe = entriesForProfile.get(packageOp.getPackageName());
2507f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            if (pe == null) {
2517f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                Log.w(TAG, "AppOp permission exists for package " + packageOp.getPackageName()
2527f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                        + " of user " + userId + " but package doesn't exist or did not request "
2533d9c7fc9982ddd513bc1bebdce76a12eecb61c88Billy Lau                        + mPermissions + " access");
2547f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                continue;
2557f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
2567f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
2577f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            if (packageOp.getOps().size() < 1) {
2587f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                Log.w(TAG, "No AppOps permission exists for package " + packageOp.getPackageName());
2597f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                continue;
2607f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
2617f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            pe.appOpMode = packageOp.getOps().get(0).getMode();
2627f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
2637f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
2647f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
2657f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    /*
2667f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     * Check for packages that should be ignored for further processing
2677f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau     */
2687f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    private boolean shouldIgnorePackage(String packageName) {
2697f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        return packageName.equals("android") || packageName.equals(mContext.getPackageName());
2707f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
2717f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
2727f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    public int getNumPackagesDeclaredPermission() {
2737f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        SparseArray<ArrayMap<String, PermissionState>> entries = getEntries();
2747f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        if (entries == null) {
2757f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            return 0;
2767f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
2777f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        final ArrayMap<String, PermissionState> entriesForProfile = entries.get(mUserManager
2787f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                .getUserHandle());
2797f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        if (entriesForProfile == null) {
2807f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            return 0;
2817f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
2827f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        return entriesForProfile.size();
2837f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
2847f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
2857f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    public int getNumPackagesAllowedByAppOps() {
2867f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        SparseArray<ArrayMap<String, PermissionState>> entries = getEntries();
2877f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        if (entries == null) {
2887f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            return 0;
2897f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
2907f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        loadPermissionsStates(entries);
2917f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        loadAppOpsStates(entries);
2927f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        final ArrayMap<String, PermissionState> entriesForProfile = entries.get(mUserManager
2937f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                .getUserHandle());
2947f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        if (entriesForProfile == null) {
2957f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            return 0;
2967f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
2977f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        Collection<PermissionState> permStates = entriesForProfile.values();
2987f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        int result = 0;
2997f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        for (PermissionState permState : permStates) {
3007f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            if (permState.isPermissible()) {
3017f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau                result++;
3027f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
3037f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
3047f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        return result;
3057f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
3067f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
3077f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    public static class PermissionState {
3087f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        public final String packageName;
3097f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        public final UserHandle userHandle;
3107f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        public PackageInfo packageInfo;
311fee785645b57c519a31ed403e60e8f76dcc8abbbBilly Lau        public boolean staticPermissionGranted;
3127f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        public boolean permissionDeclared;
3137f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        public int appOpMode;
3147f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
3157f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        public PermissionState(String packageName, UserHandle userHandle) {
3167f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            this.packageName = packageName;
3177f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            this.appOpMode = AppOpsManager.MODE_DEFAULT;
3187f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            this.userHandle = userHandle;
3197f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
3207f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau
3217f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        public boolean isPermissible() {
3227f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            // defining the default behavior as permissible as long as the package requested this
3237f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            // permission (this means pre-M gets approval during install time; M apps gets approval
3247f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            // during runtime.
3257f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            if (appOpMode == AppOpsManager.MODE_DEFAULT) {
326fee785645b57c519a31ed403e60e8f76dcc8abbbBilly Lau                return staticPermissionGranted;
3277f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            }
3287f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau            return appOpMode == AppOpsManager.MODE_ALLOWED;
3297f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau        }
3307f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau    }
3317f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau}
332