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