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.app.admin.DevicePolicyManager;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.ComponentInfo;
24 import android.content.pm.IPackageManager;
25 import android.content.pm.PackageManager;
26 import android.content.pm.ResolveInfo;
27 import android.content.pm.UserInfo;
28 import android.location.LocationManager;
29 import android.os.RemoteException;
30 import android.os.UserManager;
31 import android.telecom.DefaultDialerManager;
32 import android.text.TextUtils;
33 import android.util.ArraySet;
34 
35 import com.android.internal.telephony.SmsApplication;
36 import com.android.settings.R;
37 
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Set;
41 
42 public class ApplicationFeatureProviderImpl implements ApplicationFeatureProvider {
43 
44     protected final Context mContext;
45     private final PackageManager mPm;
46     private final IPackageManager mPms;
47     private final DevicePolicyManager mDpm;
48     private final UserManager mUm;
49 
ApplicationFeatureProviderImpl(Context context, PackageManager pm, IPackageManager pms, DevicePolicyManager dpm)50     public ApplicationFeatureProviderImpl(Context context, PackageManager pm,
51             IPackageManager pms, DevicePolicyManager dpm) {
52         mContext = context.getApplicationContext();
53         mPm = pm;
54         mPms = pms;
55         mDpm = dpm;
56         mUm = UserManager.get(mContext);
57     }
58 
59     @Override
calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback)60     public void calculateNumberOfPolicyInstalledApps(boolean async, NumberOfAppsCallback callback) {
61         final CurrentUserAndManagedProfilePolicyInstalledAppCounter counter =
62                 new CurrentUserAndManagedProfilePolicyInstalledAppCounter(mContext, mPm, callback);
63         if (async) {
64             counter.execute();
65         } else {
66             counter.executeInForeground();
67         }
68     }
69 
70     @Override
listPolicyInstalledApps(ListOfAppsCallback callback)71     public void listPolicyInstalledApps(ListOfAppsCallback callback) {
72         final CurrentUserPolicyInstalledAppLister lister =
73                 new CurrentUserPolicyInstalledAppLister(mPm, mUm, callback);
74         lister.execute();
75     }
76 
77     @Override
calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions, boolean async, NumberOfAppsCallback callback)78     public void calculateNumberOfAppsWithAdminGrantedPermissions(String[] permissions,
79             boolean async, NumberOfAppsCallback callback) {
80         final CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter counter =
81                 new CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(mContext,
82                         permissions, mPm, mPms, mDpm, callback);
83         if (async) {
84             counter.execute();
85         } else {
86             counter.executeInForeground();
87         }
88     }
89 
90     @Override
listAppsWithAdminGrantedPermissions(String[] permissions, ListOfAppsCallback callback)91     public void listAppsWithAdminGrantedPermissions(String[] permissions,
92             ListOfAppsCallback callback) {
93         final CurrentUserAppWithAdminGrantedPermissionsLister lister =
94                 new CurrentUserAppWithAdminGrantedPermissionsLister(permissions, mPm, mPms, mDpm,
95                         mUm, callback);
96         lister.execute();
97     }
98 
99     @Override
findPersistentPreferredActivities(int userId, Intent[] intents)100     public List<UserAppInfo> findPersistentPreferredActivities(int userId, Intent[] intents) {
101         final List<UserAppInfo> preferredActivities = new ArrayList<>();
102         final Set<UserAppInfo> uniqueApps = new ArraySet<>();
103         final UserInfo userInfo = mUm.getUserInfo(userId);
104         for (final Intent intent : intents) {
105             try {
106                 final ResolveInfo resolveInfo =
107                         mPms.findPersistentPreferredActivity(intent, userId);
108                 if (resolveInfo != null) {
109                     ComponentInfo componentInfo = null;
110                     if (resolveInfo.activityInfo != null) {
111                         componentInfo = resolveInfo.activityInfo;
112                     } else if (resolveInfo.serviceInfo != null) {
113                         componentInfo = resolveInfo.serviceInfo;
114                     } else if (resolveInfo.providerInfo != null) {
115                         componentInfo = resolveInfo.providerInfo;
116                     }
117                     if (componentInfo != null) {
118                         UserAppInfo info = new UserAppInfo(userInfo, componentInfo.applicationInfo);
119                         if (uniqueApps.add(info)) {
120                             preferredActivities.add(info);
121                         }
122                     }
123                 }
124             } catch (RemoteException exception) {
125             }
126         }
127         return preferredActivities;
128     }
129 
130     @Override
getKeepEnabledPackages()131     public Set<String> getKeepEnabledPackages() {
132         // Find current default phone/sms app. We should keep them enabled.
133         final Set<String> keepEnabledPackages = new ArraySet<>();
134         final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext);
135         if (!TextUtils.isEmpty(defaultDialer)) {
136             keepEnabledPackages.add(defaultDialer);
137         }
138         final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(
139                 mContext, true /* updateIfNeeded */);
140         if (defaultSms != null) {
141             keepEnabledPackages.add(defaultSms.getPackageName());
142         }
143 
144         keepEnabledPackages.addAll(getEnabledPackageWhitelist());
145 
146         final LocationManager locationManager =
147                 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
148         final String locationHistoryPackage = locationManager.getExtraLocationControllerPackage();
149         if (locationHistoryPackage != null) {
150             keepEnabledPackages.add(locationHistoryPackage);
151         }
152         return keepEnabledPackages;
153     }
154 
getEnabledPackageWhitelist()155     private Set<String> getEnabledPackageWhitelist() {
156         final Set<String> keepEnabledPackages = new ArraySet<>();
157 
158         // Keep Settings intelligence enabled, otherwise search feature will be disabled.
159         keepEnabledPackages.add(
160                 mContext.getString(R.string.config_settingsintelligence_package_name));
161 
162         // Keep Package Installer enabled.
163         keepEnabledPackages.add(mContext.getString(R.string.config_package_installer_package_name));
164 
165         return keepEnabledPackages;
166     }
167 
168     private static class CurrentUserAndManagedProfilePolicyInstalledAppCounter
169             extends InstalledAppCounter {
170         private NumberOfAppsCallback mCallback;
171 
CurrentUserAndManagedProfilePolicyInstalledAppCounter(Context context, PackageManager packageManager, NumberOfAppsCallback callback)172         CurrentUserAndManagedProfilePolicyInstalledAppCounter(Context context,
173                 PackageManager packageManager, NumberOfAppsCallback callback) {
174             super(context, PackageManager.INSTALL_REASON_POLICY, packageManager);
175             mCallback = callback;
176         }
177 
178         @Override
onCountComplete(int num)179         protected void onCountComplete(int num) {
180             mCallback.onNumberOfAppsResult(num);
181         }
182     }
183 
184     private static class CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter
185             extends AppWithAdminGrantedPermissionsCounter {
186         private NumberOfAppsCallback mCallback;
187 
CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context, String[] permissions, PackageManager packageManager, IPackageManager packageManagerService, DevicePolicyManager devicePolicyManager, NumberOfAppsCallback callback)188         CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context,
189                 String[] permissions, PackageManager packageManager,
190                 IPackageManager packageManagerService,
191                 DevicePolicyManager devicePolicyManager, NumberOfAppsCallback callback) {
192             super(context, permissions, packageManager, packageManagerService, devicePolicyManager);
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 CurrentUserPolicyInstalledAppLister extends InstalledAppLister {
203         private ListOfAppsCallback mCallback;
204 
CurrentUserPolicyInstalledAppLister(PackageManager packageManager, UserManager userManager, ListOfAppsCallback callback)205         CurrentUserPolicyInstalledAppLister(PackageManager packageManager,
206                 UserManager userManager, ListOfAppsCallback callback) {
207             super(packageManager, userManager);
208             mCallback = callback;
209         }
210 
211         @Override
onAppListBuilt(List<UserAppInfo> list)212         protected void onAppListBuilt(List<UserAppInfo> list) {
213             mCallback.onListOfAppsResult(list);
214         }
215     }
216 
217     private static class CurrentUserAppWithAdminGrantedPermissionsLister extends
218             AppWithAdminGrantedPermissionsLister {
219         private ListOfAppsCallback mCallback;
220 
CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions, PackageManager packageManager, IPackageManager packageManagerService, DevicePolicyManager devicePolicyManager, UserManager userManager, ListOfAppsCallback callback)221         CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions,
222                 PackageManager packageManager, IPackageManager packageManagerService,
223                 DevicePolicyManager devicePolicyManager, UserManager userManager,
224                 ListOfAppsCallback callback) {
225             super(permissions, packageManager, packageManagerService, devicePolicyManager,
226                     userManager);
227             mCallback = callback;
228         }
229 
230         @Override
onAppListBuilt(List<UserAppInfo> list)231         protected void onAppListBuilt(List<UserAppInfo> list) {
232             mCallback.onListOfAppsResult(list);
233         }
234     }
235 }
236