• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.settings.applications;
17 
18 import android.Manifest;
19 import android.app.AppGlobals;
20 import android.app.AppOpsManager;
21 import android.content.Context;
22 import android.content.pm.IPackageManager;
23 import android.content.pm.PackageManager;
24 import android.os.RemoteException;
25 import android.util.Log;
26 
27 import com.android.internal.util.ArrayUtils;
28 import com.android.settings.R;
29 import com.android.settingslib.applications.ApplicationsState;
30 import com.android.settingslib.applications.ApplicationsState.AppEntry;
31 import com.android.settingslib.applications.ApplicationsState.AppFilter;
32 
33 import java.util.List;
34 
35 /**
36  * Connects app op info to the ApplicationsState. Wraps around the generic AppStateBaseBridge
37  * class to tailor to the semantics of {@link AppOpsManager#OP_REQUEST_INSTALL_PACKAGES}
38  * Also provides app filters that can use the info.
39  */
40 public class AppStateInstallAppsBridge extends AppStateBaseBridge {
41 
42     private static final String TAG = AppStateInstallAppsBridge.class.getSimpleName();
43 
44     private final IPackageManager mIpm;
45     private final AppOpsManager mAppOpsManager;
46 
AppStateInstallAppsBridge(Context context, ApplicationsState appState, Callback callback)47     public AppStateInstallAppsBridge(Context context, ApplicationsState appState,
48             Callback callback) {
49         super(appState, callback);
50         mIpm = AppGlobals.getPackageManager();
51         mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
52     }
53 
54     @Override
updateExtraInfo(AppEntry app, String packageName, int uid)55     protected void updateExtraInfo(AppEntry app, String packageName, int uid) {
56         app.extraInfo = createInstallAppsStateFor(packageName, uid);
57     }
58 
59     @Override
loadAllExtraInfo()60     protected void loadAllExtraInfo() {
61         // TODO: consider making this a batch operation with a single binder call
62         final List<AppEntry> allApps = mAppSession.getAllApps();
63         for (int i = 0; i < allApps.size(); i++) {
64             AppEntry currentEntry = allApps.get(i);
65             updateExtraInfo(currentEntry, currentEntry.info.packageName, currentEntry.info.uid);
66         }
67     }
68 
hasRequestedAppOpPermission(String permission, String packageName)69     private boolean hasRequestedAppOpPermission(String permission, String packageName) {
70         try {
71             String[] packages = mIpm.getAppOpPermissionPackages(permission);
72             return ArrayUtils.contains(packages, packageName);
73         } catch (RemoteException exc) {
74             Log.e(TAG, "PackageManager dead. Cannot get permission info");
75             return false;
76         }
77     }
78 
hasPermission(String permission, int uid)79     private boolean hasPermission(String permission, int uid) {
80         try {
81             int result = mIpm.checkUidPermission(permission, uid);
82             return result == PackageManager.PERMISSION_GRANTED;
83         } catch (RemoteException e) {
84             Log.e(TAG, "PackageManager dead. Cannot get permission info");
85             return false;
86         }
87     }
88 
getAppOpMode(int appOpCode, int uid, String packageName)89     private int getAppOpMode(int appOpCode, int uid, String packageName) {
90         return mAppOpsManager.checkOpNoThrow(appOpCode, uid, packageName);
91     }
92 
createInstallAppsStateFor(String packageName, int uid)93     InstallAppsState createInstallAppsStateFor(String packageName, int uid) {
94         final InstallAppsState appState = new InstallAppsState();
95         appState.permissionRequested = hasRequestedAppOpPermission(
96                 Manifest.permission.REQUEST_INSTALL_PACKAGES, packageName);
97         appState.appOpMode = getAppOpMode(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES, uid,
98                 packageName);
99         return appState;
100     }
101 
102     /**
103      * Collection of information to be used as {@link AppEntry#extraInfo} objects
104      */
105     public static class InstallAppsState {
106         boolean permissionRequested;
107         int appOpMode;
108 
InstallAppsState()109         public InstallAppsState() {
110             this.appOpMode = AppOpsManager.MODE_DEFAULT;
111         }
112 
canInstallApps()113         public boolean canInstallApps() {
114             return appOpMode == AppOpsManager.MODE_ALLOWED;
115         }
116 
isPotentialAppSource()117         public boolean isPotentialAppSource() {
118             return appOpMode != AppOpsManager.MODE_DEFAULT || permissionRequested;
119         }
120 
121         @Override
toString()122         public String toString() {
123             StringBuilder sb = new StringBuilder();
124             sb.append("[permissionRequested: " + permissionRequested);
125             sb.append(", appOpMode: " + appOpMode);
126             sb.append("]");
127             return sb.toString();
128         }
129     }
130 
131     static final AppFilter FILTER_APP_SOURCES = new AppFilter() {
132 
133         @Override
134         public void init() {
135         }
136 
137         @Override
138         public boolean filterApp(AppEntry info) {
139             if (info.extraInfo == null || !(info.extraInfo instanceof InstallAppsState)) {
140                 return false;
141             }
142             InstallAppsState state = (InstallAppsState) info.extraInfo;
143             return state.isPotentialAppSource();
144         }
145     };
146 }
147