1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.packageinstaller.permission.model;
18 
19 import android.app.LoaderManager;
20 import android.app.LoaderManager.LoaderCallbacks;
21 import android.content.AsyncTaskLoader;
22 import android.content.Context;
23 import android.content.Loader;
24 import android.os.Bundle;
25 import android.os.Process;
26 
27 import androidx.annotation.NonNull;
28 import androidx.annotation.Nullable;
29 
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.List;
33 
34 /**
35  * Loads all permission usages for a set of apps and permission groups.
36  */
37 public final class PermissionUsages implements LoaderCallbacks<List<AppPermissionUsage>> {
38     public static final int USAGE_FLAG_LAST = 1 << 0;
39     public static final int USAGE_FLAG_HISTORICAL = 1 << 2;
40 
41     private final ArrayList<AppPermissionUsage> mUsages = new ArrayList<>();
42     private final @NonNull Context mContext;
43 
44     private static final String KEY_FILTER_UID =  "KEY_FILTER_UID";
45     private static final String KEY_FILTER_PACKAGE_NAME =  "KEY_FILTER_PACKAGE_NAME";
46     private static final String KEY_FILTER_PERMISSION_GROUP =  "KEY_FILTER_PERMISSION_GROUP";
47     private static final String KEY_FILTER_BEGIN_TIME_MILLIS =  "KEY_FILTER_BEGIN_TIME_MILLIS";
48     private static final String KEY_FILTER_END_TIME_MILLIS =  "KEY_FILTER_END_TIME_MILLIS";
49     private static final String KEY_USAGE_FLAGS =  "KEY_USAGE_FLAGS";
50     private static final String KEY_GET_UI_INFO =  "KEY_GET_UI_INFO";
51     private static final String KEY_GET_NON_PLATFORM_PERMISSIONS =
52             "KEY_GET_NON_PLATFORM_PERMISSIONS";
53 
54     private @Nullable PermissionsUsagesChangeCallback mCallback;
55 
56     public interface PermissionsUsagesChangeCallback {
onPermissionUsagesChanged()57         void onPermissionUsagesChanged();
58     }
59 
PermissionUsages(@onNull Context context)60     public PermissionUsages(@NonNull Context context) {
61         mContext = context;
62     }
63 
load(@ullable String filterPackageName, @Nullable String[] filterPermissionGroups, long filterBeginTimeMillis, long filterEndTimeMillis, int usageFlags, @NonNull LoaderManager loaderManager, boolean getUiInfo, boolean getNonPlatformPermissions, @NonNull PermissionsUsagesChangeCallback callback, boolean sync)64     public void load(@Nullable String filterPackageName,
65             @Nullable String[] filterPermissionGroups, long filterBeginTimeMillis,
66             long filterEndTimeMillis, int usageFlags, @NonNull LoaderManager loaderManager,
67             boolean getUiInfo, boolean getNonPlatformPermissions,
68             @NonNull PermissionsUsagesChangeCallback callback, boolean sync) {
69         load(Process.INVALID_UID, filterPackageName, filterPermissionGroups, filterBeginTimeMillis,
70                 filterEndTimeMillis, usageFlags, loaderManager, getUiInfo,
71                 getNonPlatformPermissions, callback, sync);
72     }
73 
load(int filterUid, @Nullable String filterPackageName, @Nullable String[] filterPermissionGroups, long filterBeginTimeMillis, long filterEndTimeMillis, int usageFlags, @NonNull LoaderManager loaderManager, boolean getUiInfo, boolean getNonPlatformPermissions, @NonNull PermissionsUsagesChangeCallback callback, boolean sync)74     public void load(int filterUid, @Nullable String filterPackageName,
75             @Nullable String[] filterPermissionGroups, long filterBeginTimeMillis,
76             long filterEndTimeMillis, int usageFlags, @NonNull LoaderManager loaderManager,
77             boolean getUiInfo, boolean getNonPlatformPermissions,
78             @NonNull PermissionsUsagesChangeCallback callback, boolean sync) {
79         mCallback = callback;
80         final Bundle args = new Bundle();
81         args.putInt(KEY_FILTER_UID, filterUid);
82         args.putString(KEY_FILTER_PACKAGE_NAME, filterPackageName);
83         args.putStringArray(KEY_FILTER_PERMISSION_GROUP, filterPermissionGroups);
84         args.putLong(KEY_FILTER_BEGIN_TIME_MILLIS, filterBeginTimeMillis);
85         args.putLong(KEY_FILTER_END_TIME_MILLIS, filterEndTimeMillis);
86         args.putInt(KEY_USAGE_FLAGS, usageFlags);
87         args.putBoolean(KEY_GET_UI_INFO, getUiInfo);
88         args.putBoolean(KEY_GET_NON_PLATFORM_PERMISSIONS, getNonPlatformPermissions);
89         if (sync) {
90             final UsageLoader loader = new UsageLoader(mContext, args);
91             final List<AppPermissionUsage> usages = loader.loadInBackground();
92             onLoadFinished(loader, usages);
93         } else {
94             loaderManager.restartLoader(1, args, this);
95         }
96     }
97 
98     @Override
onCreateLoader(int id, Bundle args)99     public Loader<List<AppPermissionUsage>> onCreateLoader(int id, Bundle args) {
100         return new UsageLoader(mContext, args);
101     }
102 
103     @Override
onLoadFinished(@onNull Loader<List<AppPermissionUsage>> loader, List<AppPermissionUsage> usages)104     public void onLoadFinished(@NonNull Loader<List<AppPermissionUsage>> loader,
105             List<AppPermissionUsage> usages) {
106         mUsages.clear();
107         mUsages.addAll(usages);
108         if (mCallback != null) {
109             mCallback.onPermissionUsagesChanged();
110         }
111     }
112 
113     @Override
onLoaderReset(@onNull Loader<List<AppPermissionUsage>> loader)114     public void onLoaderReset(@NonNull Loader<List<AppPermissionUsage>> loader) {
115         mUsages.clear();
116         mCallback.onPermissionUsagesChanged();
117     }
118 
getUsages()119     public @NonNull List<AppPermissionUsage> getUsages() {
120         return mUsages;
121     }
122 
stopLoader(@onNull LoaderManager loaderManager)123     public void stopLoader(@NonNull LoaderManager loaderManager) {
124         loaderManager.destroyLoader(1);
125     }
126 
loadLastGroupUsage( @onNull Context context, @NonNull AppPermissionGroup group)127     public static @Nullable AppPermissionUsage.GroupUsage loadLastGroupUsage(
128             @NonNull Context context, @NonNull AppPermissionGroup group) {
129         return null;
130     }
131 
132     private static final class UsageLoader extends AsyncTaskLoader<List<AppPermissionUsage>> {
133         private final int mFilterUid;
134         private @Nullable String mFilterPackageName;
135         private @Nullable String[] mFilterPermissionGroups;
136         private final long mFilterBeginTimeMillis;
137         private final long mFilterEndTimeMillis;
138         private final int mUsageFlags;
139         private final boolean mGetUiInfo;
140         private final boolean mGetNonPlatformPermissions;
141 
UsageLoader(@onNull Context context, @NonNull Bundle args)142         UsageLoader(@NonNull Context context, @NonNull Bundle args) {
143             super(context);
144             mFilterUid = args.getInt(KEY_FILTER_UID);
145             mFilterPackageName = args.getString(KEY_FILTER_PACKAGE_NAME);
146             mFilterPermissionGroups = args.getStringArray(KEY_FILTER_PERMISSION_GROUP);
147             mFilterBeginTimeMillis = args.getLong(KEY_FILTER_BEGIN_TIME_MILLIS);
148             mFilterEndTimeMillis = args.getLong(KEY_FILTER_END_TIME_MILLIS);
149             mUsageFlags = args.getInt(KEY_USAGE_FLAGS);
150             mGetUiInfo = args.getBoolean(KEY_GET_UI_INFO);
151             mGetNonPlatformPermissions = args.getBoolean(KEY_GET_NON_PLATFORM_PERMISSIONS);
152         }
153 
154         @Override
onStartLoading()155         protected void onStartLoading() {
156             forceLoad();
157         }
158 
159         @Override
loadInBackground()160         public @NonNull List<AppPermissionUsage> loadInBackground() {
161             return Collections.emptyList();
162         }
163     }
164 }
165