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