1/*
2 * Copyright (C) 2015 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.packageinstaller.permission.utils;
18
19import android.Manifest;
20import android.content.Context;
21import android.content.Intent;
22import android.content.pm.ApplicationInfo;
23import android.content.pm.PackageManager;
24import android.content.pm.ResolveInfo;
25import android.content.res.Resources;
26import android.content.res.Resources.Theme;
27import android.graphics.drawable.Drawable;
28import android.util.ArraySet;
29import android.util.Log;
30import android.util.TypedValue;
31
32import com.android.packageinstaller.permission.model.AppPermissionGroup;
33import com.android.packageinstaller.permission.model.AppPermissions;
34import com.android.packageinstaller.permission.model.PermissionApps.PermissionApp;
35
36import java.util.List;
37
38public final class Utils {
39
40    private static final String LOG_TAG = "Utils";
41
42    public static final String OS_PKG = "android";
43
44    public static final String[] MODERN_PERMISSION_GROUPS = {
45            Manifest.permission_group.CALENDAR,
46            Manifest.permission_group.CAMERA,
47            Manifest.permission_group.CONTACTS,
48            Manifest.permission_group.LOCATION,
49            Manifest.permission_group.SENSORS,
50            Manifest.permission_group.SMS,
51            Manifest.permission_group.PHONE,
52            Manifest.permission_group.MICROPHONE,
53            Manifest.permission_group.STORAGE
54    };
55
56    private static final Intent LAUNCHER_INTENT = new Intent(Intent.ACTION_MAIN, null)
57                            .addCategory(Intent.CATEGORY_LAUNCHER);
58
59    private Utils() {
60        /* do nothing - hide constructor */
61    }
62
63    public static Drawable loadDrawable(PackageManager pm, String pkg, int resId) {
64        try {
65            return pm.getResourcesForApplication(pkg).getDrawable(resId, null);
66        } catch (Resources.NotFoundException | PackageManager.NameNotFoundException e) {
67            Log.d(LOG_TAG, "Couldn't get resource", e);
68            return null;
69        }
70    }
71
72    public static boolean isModernPermissionGroup(String name) {
73        for (String modernGroup : MODERN_PERMISSION_GROUPS) {
74            if (modernGroup.equals(name)) {
75                return true;
76            }
77        }
78        return false;
79    }
80
81    public static boolean shouldShowPermission(AppPermissionGroup group, String packageName) {
82        // We currently will not show permissions fixed by the system.
83        // which is what the system does for system components.
84        if (group.isSystemFixed() && !LocationUtils.isLocationGroupAndProvider(
85                group.getName(), packageName)) {
86            return false;
87        }
88
89        final boolean isPlatformPermission = group.getDeclaringPackage().equals(OS_PKG);
90        // Show legacy permissions only if the user chose that.
91        if (isPlatformPermission
92                && !Utils.isModernPermissionGroup(group.getName())) {
93            return false;
94        }
95        return true;
96    }
97
98    public static boolean shouldShowPermission(PermissionApp app) {
99        // We currently will not show permissions fixed by the system
100        // which is what the system does for system components.
101        if (app.isSystemFixed() && !LocationUtils.isLocationGroupAndProvider(
102                app.getPermissionGroup().getName(), app.getPackageName())) {
103            return false;
104        }
105
106        return true;
107    }
108
109    public static Drawable applyTint(Context context, Drawable icon, int attr) {
110        Theme theme = context.getTheme();
111        TypedValue typedValue = new TypedValue();
112        theme.resolveAttribute(attr, typedValue, true);
113        icon = icon.mutate();
114        icon.setTint(context.getColor(typedValue.resourceId));
115        return icon;
116    }
117
118    public static Drawable applyTint(Context context, int iconResId, int attr) {
119        return applyTint(context, context.getDrawable(iconResId), attr);
120    }
121
122    public static ArraySet<String> getLauncherPackages(Context context) {
123        ArraySet<String> launcherPkgs = new ArraySet<>();
124        for (ResolveInfo info :
125            context.getPackageManager().queryIntentActivities(LAUNCHER_INTENT, 0)) {
126            launcherPkgs.add(info.activityInfo.packageName);
127        }
128
129        return launcherPkgs;
130    }
131
132    public static List<ApplicationInfo> getAllInstalledApplications(Context context) {
133        return context.getPackageManager().getInstalledApplications(0);
134    }
135
136    public static boolean isSystem(PermissionApp app, ArraySet<String> launcherPkgs) {
137        return isSystem(app.getAppInfo(), launcherPkgs);
138    }
139
140    public static boolean isSystem(AppPermissions app, ArraySet<String> launcherPkgs) {
141        return isSystem(app.getPackageInfo().applicationInfo, launcherPkgs);
142    }
143
144    public static boolean isSystem(ApplicationInfo info, ArraySet<String> launcherPkgs) {
145        return info.isSystemApp() && (info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0
146                && !launcherPkgs.contains(info.packageName);
147    }
148
149    public static boolean areGroupPermissionsIndividuallyControlled(Context context, String group) {
150        if (!context.getResources().getBoolean(
151                com.android.internal.R.bool.config_permissionReviewRequired)) {
152            return false;
153        }
154        return Manifest.permission_group.SMS.equals(group)
155                || Manifest.permission_group.PHONE.equals(group)
156                || Manifest.permission_group.CONTACTS.equals(group);
157    }
158}
159