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