• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.settings.applications;
18 
19 import android.Manifest;
20 import android.app.admin.DevicePolicyManager;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.ActivityInfo;
25 import android.content.pm.ComponentInfo;
26 import android.content.pm.IPackageManager;
27 import android.content.pm.PackageManager;
28 import android.content.pm.ResolveInfo;
29 import android.content.pm.ServiceInfo;
30 import android.content.pm.UserInfo;
31 import android.location.LocationManager;
32 import android.os.RemoteException;
33 import android.os.UserManager;
34 import android.service.euicc.EuiccService;
35 import android.telecom.DefaultDialerManager;
36 import android.text.TextUtils;
37 import android.util.ArraySet;
38 import android.util.Log;
39 
40 import androidx.annotation.VisibleForTesting;
41 
42 import com.android.internal.telephony.SmsApplication;
43 import com.android.settings.R;
44 
45 import java.util.ArrayList;
46 import java.util.List;
47 import java.util.Set;
48 
49 public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
50     private static final String TAG = "AppFeatureProviderImpl";
51 
52     protected final Context mContext;
53     private final PackageManager mPm;
54     private final IPackageManager mPms;
55     private final DevicePolicyManager mDpm;
56     private final UserManager mUm;
57     /** Flags to use when querying PackageManager for Euicc component implementations. */
58     private static final int EUICC_QUERY_FLAGS =
59             PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEBUG_TRIAGED_MISSING
60                 | PackageManager.GET_RESOLVED_FILTER;
61 
ApplicationFeatureProviderImpl(Context context, PackageManager pm, IPackageManager pms, DevicePolicyManager dpm)62     public ApplicationFeatureProviderImpl(Context context, PackageManager pm,
63             IPackageManager pms, DevicePolicyManager dpm) {
64         mContext = context.getApplicationContext();
65         mPm = pm;
66         mPms = pms;
67         mDpm = dpm;
68         mUm = UserManager.get(mContext);
69     }
70 
71     @Override
calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback)72     public void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback) {
73         final CurrentUserAndManagedProfilePolicyInstalledAppCounter counter =
74                 new CurrentUserAndManagedProfilePolicyInstalledAppCounter(mContext, mPm, callback);
75         if (async) {
76             counter.execute();
77         } else {
78             counter.executeInForeground();
79         }
80     }
81 
82     @Override
listPolicyInstalledApps(ListOfAppsCallback callback)83     public void listPolicyInstalledApps(ListOfAppsCallback callback) {
84         final CurrentUserPolicyInstalledAppLister lister =
85                 new CurrentUserPolicyInstalledAppLister(mPm, mUm, callback);
86         lister.execute();
87     }
88 
89     @Override
calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions, boolean async, NumberOfAppsCallback callback)90     public void calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions,
91             boolean async, NumberOfAppsCallback callback) {
92         final CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter counter =
93                 new CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(mContext,
94                         permissions, mPm, mPms, mDpm, callback);
95         if (async) {
96             counter.execute();
97         } else {
98             counter.executeInForeground();
99         }
100     }
101 
102     @Override
listAppsWithAdminGrantedPermissions(String[] permissions, ListOfAppsCallback callback)103     public void listAppsWithAdminGrantedPermissions(String[] permissions,
104             ListOfAppsCallback callback) {
105         final CurrentUserAppWithAdminGrantedPermissionsLister lister =
106                 new CurrentUserAppWithAdminGrantedPermissionsLister(permissions, mPm, mPms, mDpm,
107                         mUm, callback);
108         lister.execute();
109     }
110 
111     @Override
findPersistentPreferredActivities(int userId, Intent[] intents)112     public List<UserAppInfo> findPersistentPreferredActivities(int userId, Intent[] intents) {
113         final List<UserAppInfo> preferredActivities = new ArrayList<>();
114         final Set<UserAppInfo> uniqueApps = new ArraySet<>();
115         final UserInfo userInfo = mUm.getUserInfo(userId);
116         for (final Intent intent : intents) {
117             try {
118                 final ResolveInfo resolveInfo =
119                         mPms.findPersistentPreferredActivity(intent, userId);
120                 if (resolveInfo != null) {
121                     ComponentInfo componentInfo = null;
122                     if (resolveInfo.activityInfo != null) {
123                         componentInfo = resolveInfo.activityInfo;
124                     } else if (resolveInfo.serviceInfo != null) {
125                         componentInfo = resolveInfo.serviceInfo;
126                     } else if (resolveInfo.providerInfo != null) {
127                         componentInfo = resolveInfo.providerInfo;
128                     }
129                     if (componentInfo != null) {
130                         UserAppInfo info = new UserAppInfo(userInfo, componentInfo.applicationInfo);
131                         if (uniqueApps.add(info)) {
132                             preferredActivities.add(info);
133                         }
134                     }
135                 }
136             } catch (RemoteException exception) {
137             }
138         }
139         return preferredActivities;
140     }
141 
142     @Override
getKeepEnabledPackages()143     public Set<String> getKeepEnabledPackages() {
144         // Find current default phone/sms app. We should keep them enabled.
145         final Set<String> keepEnabledPackages = new ArraySet<>();
146         final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext);
147         if (!TextUtils.isEmpty(defaultDialer)) {
148             keepEnabledPackages.add(defaultDialer);
149         }
150         final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(
151                 mContext, true /* updateIfNeeded */);
152         if (defaultSms != null) {
153             keepEnabledPackages.add(defaultSms.getPackageName());
154         }
155 
156         // Keep Euicc Service enabled.
157         final ComponentInfo euicc = findEuiccService(mPm);
158         if (euicc != null) {
159             keepEnabledPackages.add(euicc.packageName);
160         }
161 
162         keepEnabledPackages.addAll(getEnabledPackageWhitelist());
163 
164         final LocationManager locationManager =
165                 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
166         final String locationHistoryPackage = locationManager.getExtraLocationControllerPackage();
167         if (locationHistoryPackage != null) {
168             keepEnabledPackages.add(locationHistoryPackage);
169         }
170         return keepEnabledPackages;
171     }
172 
getEnabledPackageWhitelist()173     private Set<String> getEnabledPackageWhitelist() {
174         final Set<String> keepEnabledPackages = new ArraySet<>();
175 
176         // Keep Settings intelligence enabled, otherwise search feature will be disabled.
177         keepEnabledPackages.add(
178                 mContext.getString(R.string.config_settingsintelligence_package_name));
179 
180         // Keep Package Installer enabled.
181         keepEnabledPackages.add(mContext.getString(R.string.config_package_installer_package_name));
182 
183         return keepEnabledPackages;
184     }
185 
186     private static class CurrentUserAndManagedProfilePolicyInstalledAppCounter
187             extends InstalledAppCounter {
188         private NumberOfAppsCallback mCallback;
189 
CurrentUserAndManagedProfilePolicyInstalledAppCounter(Context context, PackageManager packageManager, NumberOfAppsCallback callback)190         CurrentUserAndManagedProfilePolicyInstalledAppCounter(Context context,
191                 PackageManager packageManager, NumberOfAppsCallback callback) {
192             super(context, PackageManager.INSTALL_REASON_POLICY, packageManager);
193             mCallback = callback;
194         }
195 
196         @Override
onCountComplete(int num)197         protected void onCountComplete(int num) {
198             mCallback.onNumberOfAppsResult(num);
199         }
200     }
201 
202     private static class CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter
203             extends AppWithAdminGrantedPermissionsCounter {
204         private NumberOfAppsCallback mCallback;
205 
CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context, String[] permissions, PackageManager packageManager, IPackageManager packageManagerService, DevicePolicyManager devicePolicyManager, NumberOfAppsCallback callback)206         CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context,
207                 String[] permissions, PackageManager packageManager,
208                 IPackageManager packageManagerService,
209                 DevicePolicyManager devicePolicyManager, NumberOfAppsCallback callback) {
210             super(context, permissions, packageManager, packageManagerService, devicePolicyManager);
211             mCallback = callback;
212         }
213 
214         @Override
onCountComplete(int num)215         protected void onCountComplete(int num) {
216             mCallback.onNumberOfAppsResult(num);
217         }
218     }
219 
220     private static class CurrentUserPolicyInstalledAppLister extends InstalledAppLister {
221         private ListOfAppsCallback mCallback;
222 
CurrentUserPolicyInstalledAppLister(PackageManager packageManager, UserManager userManager, ListOfAppsCallback callback)223         CurrentUserPolicyInstalledAppLister(PackageManager packageManager,
224                 UserManager userManager, ListOfAppsCallback callback) {
225             super(packageManager, userManager);
226             mCallback = callback;
227         }
228 
229         @Override
onAppListBuilt(List<UserAppInfo> list)230         protected void onAppListBuilt(List<UserAppInfo> list) {
231             mCallback.onListOfAppsResult(list);
232         }
233     }
234 
235     private static class CurrentUserAppWithAdminGrantedPermissionsLister extends
236             AppWithAdminGrantedPermissionsLister {
237         private ListOfAppsCallback mCallback;
238 
CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions, PackageManager packageManager, IPackageManager packageManagerService, DevicePolicyManager devicePolicyManager, UserManager userManager, ListOfAppsCallback callback)239         CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions,
240                 PackageManager packageManager, IPackageManager packageManagerService,
241                 DevicePolicyManager devicePolicyManager, UserManager userManager,
242                 ListOfAppsCallback callback) {
243             super(permissions, packageManager, packageManagerService, devicePolicyManager,
244                     userManager);
245             mCallback = callback;
246         }
247 
248         @Override
onAppListBuilt(List<UserAppInfo> list)249         protected void onAppListBuilt(List<UserAppInfo> list) {
250             mCallback.onListOfAppsResult(list);
251         }
252     }
253 
254     /**
255      * Return the component info of the EuiccService to bind to, or null if none were found.
256      */
257     @VisibleForTesting
findEuiccService(PackageManager packageManager)258     ComponentInfo findEuiccService(PackageManager packageManager) {
259         final Intent intent = new Intent(EuiccService.EUICC_SERVICE_INTERFACE);
260         final List<ResolveInfo> resolveInfoList =
261                 packageManager.queryIntentServices(intent, EUICC_QUERY_FLAGS);
262         final ComponentInfo bestComponent = findEuiccService(packageManager, resolveInfoList);
263         if (bestComponent == null) {
264             Log.w(TAG, "No valid EuiccService implementation found");
265         }
266         return bestComponent;
267     }
268 
findEuiccService( PackageManager packageManager, List<ResolveInfo> resolveInfoList)269     private ComponentInfo findEuiccService(
270             PackageManager packageManager, List<ResolveInfo> resolveInfoList) {
271         int bestPriority = Integer.MIN_VALUE;
272         ComponentInfo bestComponent = null;
273         if (resolveInfoList != null) {
274             for (ResolveInfo resolveInfo : resolveInfoList) {
275                 if (!isValidEuiccComponent(packageManager, resolveInfo)) {
276                     continue;
277                 }
278 
279                 if (resolveInfo.filter.getPriority() > bestPriority) {
280                     bestPriority = resolveInfo.filter.getPriority();
281                     bestComponent = getComponentInfo(resolveInfo);
282                 }
283             }
284         }
285 
286         return bestComponent;
287     }
288 
isValidEuiccComponent( PackageManager packageManager, ResolveInfo resolveInfo)289     private boolean isValidEuiccComponent(
290             PackageManager packageManager, ResolveInfo resolveInfo) {
291         final ComponentInfo componentInfo = getComponentInfo(resolveInfo);
292         final String packageName = componentInfo.packageName;
293 
294         // Verify that the app is privileged (via granting of a privileged permission).
295         if (packageManager.checkPermission(
296                 Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS, packageName)
297                 != PackageManager.PERMISSION_GRANTED) {
298             Log.e(TAG, "Package " + packageName
299                     + " does not declare WRITE_EMBEDDED_SUBSCRIPTIONS");
300             return false;
301         }
302 
303         // Verify that only the system can access the component.
304         final String permission;
305         if (componentInfo instanceof ServiceInfo) {
306             permission = ((ServiceInfo) componentInfo).permission;
307         } else if (componentInfo instanceof ActivityInfo) {
308             permission = ((ActivityInfo) componentInfo).permission;
309         } else {
310             throw new IllegalArgumentException("Can only verify services/activities");
311         }
312         if (!TextUtils.equals(permission, Manifest.permission.BIND_EUICC_SERVICE)) {
313             Log.e(TAG, "Package " + packageName
314                     + " does not require the BIND_EUICC_SERVICE permission");
315             return false;
316         }
317 
318         // Verify that the component declares a priority.
319         if (resolveInfo.filter == null || resolveInfo.filter.getPriority() == 0) {
320             Log.e(TAG, "Package " + packageName + " does not specify a priority");
321             return false;
322         }
323         return true;
324     }
325 
getComponentInfo(ResolveInfo resolveInfo)326     private ComponentInfo getComponentInfo(ResolveInfo resolveInfo) {
327         if (resolveInfo.activityInfo != null) {
328             return resolveInfo.activityInfo;
329         }
330         if (resolveInfo.serviceInfo != null) {
331             return resolveInfo.serviceInfo;
332         }
333         if (resolveInfo.providerInfo != null) {
334             return resolveInfo.providerInfo;
335         }
336         throw new IllegalStateException("Missing ComponentInfo!");
337     }
338 }
339