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(getEnabledPackageAllowlist()); 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 getEnabledPackageAllowlist()173 private Set<String> getEnabledPackageAllowlist() { 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 if (mPm.getWellbeingPackageName() != null) { 184 keepEnabledPackages.add(mPm.getWellbeingPackageName()); 185 } 186 return keepEnabledPackages; 187 } 188 189 private static class CurrentUserAndManagedProfilePolicyInstalledAppCounter 190 extends InstalledAppCounter { 191 private NumberOfAppsCallback mCallback; 192 CurrentUserAndManagedProfilePolicyInstalledAppCounter(Context context, PackageManager packageManager, NumberOfAppsCallback callback)193 CurrentUserAndManagedProfilePolicyInstalledAppCounter(Context context, 194 PackageManager packageManager, NumberOfAppsCallback callback) { 195 super(context, PackageManager.INSTALL_REASON_POLICY, packageManager); 196 mCallback = callback; 197 } 198 199 @Override onCountComplete(int num)200 protected void onCountComplete(int num) { 201 mCallback.onNumberOfAppsResult(num); 202 } 203 } 204 205 private static class CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter 206 extends AppWithAdminGrantedPermissionsCounter { 207 private NumberOfAppsCallback mCallback; 208 CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context, String[] permissions, PackageManager packageManager, IPackageManager packageManagerService, DevicePolicyManager devicePolicyManager, NumberOfAppsCallback callback)209 CurrentUserAndManagedProfileAppWithAdminGrantedPermissionsCounter(Context context, 210 String[] permissions, PackageManager packageManager, 211 IPackageManager packageManagerService, 212 DevicePolicyManager devicePolicyManager, NumberOfAppsCallback callback) { 213 super(context, permissions, packageManager, packageManagerService, devicePolicyManager); 214 mCallback = callback; 215 } 216 217 @Override onCountComplete(int num)218 protected void onCountComplete(int num) { 219 mCallback.onNumberOfAppsResult(num); 220 } 221 } 222 223 private static class CurrentUserPolicyInstalledAppLister extends InstalledAppLister { 224 private ListOfAppsCallback mCallback; 225 CurrentUserPolicyInstalledAppLister(PackageManager packageManager, UserManager userManager, ListOfAppsCallback callback)226 CurrentUserPolicyInstalledAppLister(PackageManager packageManager, 227 UserManager userManager, ListOfAppsCallback callback) { 228 super(packageManager, userManager); 229 mCallback = callback; 230 } 231 232 @Override onAppListBuilt(List<UserAppInfo> list)233 protected void onAppListBuilt(List<UserAppInfo> list) { 234 mCallback.onListOfAppsResult(list); 235 } 236 } 237 238 private static class CurrentUserAppWithAdminGrantedPermissionsLister extends 239 AppWithAdminGrantedPermissionsLister { 240 private ListOfAppsCallback mCallback; 241 CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions, PackageManager packageManager, IPackageManager packageManagerService, DevicePolicyManager devicePolicyManager, UserManager userManager, ListOfAppsCallback callback)242 CurrentUserAppWithAdminGrantedPermissionsLister(String[] permissions, 243 PackageManager packageManager, IPackageManager packageManagerService, 244 DevicePolicyManager devicePolicyManager, UserManager userManager, 245 ListOfAppsCallback callback) { 246 super(permissions, packageManager, packageManagerService, devicePolicyManager, 247 userManager); 248 mCallback = callback; 249 } 250 251 @Override onAppListBuilt(List<UserAppInfo> list)252 protected void onAppListBuilt(List<UserAppInfo> list) { 253 mCallback.onListOfAppsResult(list); 254 } 255 } 256 257 /** 258 * Return the component info of the EuiccService to bind to, or null if none were found. 259 */ 260 @VisibleForTesting findEuiccService(PackageManager packageManager)261 ComponentInfo findEuiccService(PackageManager packageManager) { 262 final Intent intent = new Intent(EuiccService.EUICC_SERVICE_INTERFACE); 263 final List<ResolveInfo> resolveInfoList = 264 packageManager.queryIntentServices(intent, EUICC_QUERY_FLAGS); 265 final ComponentInfo bestComponent = findEuiccService(packageManager, resolveInfoList); 266 if (bestComponent == null) { 267 Log.w(TAG, "No valid EuiccService implementation found"); 268 } 269 return bestComponent; 270 } 271 findEuiccService( PackageManager packageManager, List<ResolveInfo> resolveInfoList)272 private ComponentInfo findEuiccService( 273 PackageManager packageManager, List<ResolveInfo> resolveInfoList) { 274 int bestPriority = Integer.MIN_VALUE; 275 ComponentInfo bestComponent = null; 276 if (resolveInfoList != null) { 277 for (ResolveInfo resolveInfo : resolveInfoList) { 278 if (!isValidEuiccComponent(packageManager, resolveInfo)) { 279 continue; 280 } 281 282 if (resolveInfo.filter.getPriority() > bestPriority) { 283 bestPriority = resolveInfo.filter.getPriority(); 284 bestComponent = getComponentInfo(resolveInfo); 285 } 286 } 287 } 288 289 return bestComponent; 290 } 291 isValidEuiccComponent( PackageManager packageManager, ResolveInfo resolveInfo)292 private boolean isValidEuiccComponent( 293 PackageManager packageManager, ResolveInfo resolveInfo) { 294 final ComponentInfo componentInfo = getComponentInfo(resolveInfo); 295 final String packageName = componentInfo.packageName; 296 297 // Verify that the app is privileged (via granting of a privileged permission). 298 if (packageManager.checkPermission( 299 Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS, packageName) 300 != PackageManager.PERMISSION_GRANTED) { 301 Log.e(TAG, "Package " + packageName 302 + " does not declare WRITE_EMBEDDED_SUBSCRIPTIONS"); 303 return false; 304 } 305 306 // Verify that only the system can access the component. 307 final String permission; 308 if (componentInfo instanceof ServiceInfo) { 309 permission = ((ServiceInfo) componentInfo).permission; 310 } else if (componentInfo instanceof ActivityInfo) { 311 permission = ((ActivityInfo) componentInfo).permission; 312 } else { 313 throw new IllegalArgumentException("Can only verify services/activities"); 314 } 315 if (!TextUtils.equals(permission, Manifest.permission.BIND_EUICC_SERVICE)) { 316 Log.e(TAG, "Package " + packageName 317 + " does not require the BIND_EUICC_SERVICE permission"); 318 return false; 319 } 320 321 // Verify that the component declares a priority. 322 if (resolveInfo.filter == null || resolveInfo.filter.getPriority() == 0) { 323 Log.e(TAG, "Package " + packageName + " does not specify a priority"); 324 return false; 325 } 326 return true; 327 } 328 getComponentInfo(ResolveInfo resolveInfo)329 private ComponentInfo getComponentInfo(ResolveInfo resolveInfo) { 330 if (resolveInfo.activityInfo != null) { 331 return resolveInfo.activityInfo; 332 } 333 if (resolveInfo.serviceInfo != null) { 334 return resolveInfo.serviceInfo; 335 } 336 if (resolveInfo.providerInfo != null) { 337 return resolveInfo.providerInfo; 338 } 339 throw new IllegalStateException("Missing ComponentInfo!"); 340 } 341 } 342