Home | History | Annotate | Download | only in pm
      1 /*
      2  * Copyright (C) 2015 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 android.content.pm;
     18 
     19 import android.Manifest;
     20 import android.app.AppGlobals;
     21 import android.content.Intent;
     22 import android.os.RemoteException;
     23 import android.os.UserHandle;
     24 import android.util.ArraySet;
     25 import android.view.inputmethod.InputMethod;
     26 
     27 import com.android.internal.annotations.VisibleForTesting;
     28 
     29 import java.util.ArrayList;
     30 import java.util.List;
     31 
     32 /**
     33  * Helper class for querying installed applications using multiple criteria.
     34  *
     35  * @hide
     36  */
     37 public class AppsQueryHelper {
     38 
     39     /**
     40      * Return apps without launcher icon
     41      */
     42     public static int GET_NON_LAUNCHABLE_APPS = 1;
     43 
     44     /**
     45      * Return apps with {@link Manifest.permission#INTERACT_ACROSS_USERS} permission
     46      */
     47     public static int GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM = 1 << 1;
     48 
     49     /**
     50      * Return all input methods available for the current user.
     51      */
     52     public static int GET_IMES = 1 << 2;
     53 
     54     /**
     55      * Return all apps that are flagged as required for the system user.
     56      */
     57     public static int GET_REQUIRED_FOR_SYSTEM_USER = 1 << 3;
     58 
     59     private final IPackageManager mPackageManager;
     60     private List<ApplicationInfo> mAllApps;
     61 
     62     public AppsQueryHelper(IPackageManager packageManager) {
     63         mPackageManager = packageManager;
     64     }
     65 
     66     public AppsQueryHelper() {
     67         this(AppGlobals.getPackageManager());
     68     }
     69 
     70     /**
     71      * Return a List of all packages that satisfy a specified criteria.
     72      * @param flags search flags. Use any combination of {@link #GET_NON_LAUNCHABLE_APPS},
     73      * {@link #GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM} or {@link #GET_IMES}.
     74      * @param systemAppsOnly if true, only system apps will be returned
     75      * @param user user, whose apps are queried
     76      */
     77     public List<String> queryApps(int flags, boolean systemAppsOnly, UserHandle user) {
     78         boolean nonLaunchableApps = (flags & GET_NON_LAUNCHABLE_APPS) > 0;
     79         boolean interactAcrossUsers = (flags & GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM) > 0;
     80         boolean imes = (flags & GET_IMES) > 0;
     81         boolean requiredForSystemUser = (flags & GET_REQUIRED_FOR_SYSTEM_USER) > 0;
     82         if (mAllApps == null) {
     83             mAllApps = getAllApps(user.getIdentifier());
     84         }
     85 
     86         List<String> result = new ArrayList<>();
     87         if (flags == 0) {
     88             final int allAppsSize = mAllApps.size();
     89             for (int i = 0; i < allAppsSize; i++) {
     90                 final ApplicationInfo appInfo = mAllApps.get(i);
     91                 if (systemAppsOnly && !appInfo.isSystemApp()) {
     92                     continue;
     93                 }
     94                 result.add(appInfo.packageName);
     95             }
     96             return result;
     97         }
     98 
     99         if (nonLaunchableApps) {
    100             Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER);
    101             final List<ResolveInfo> resolveInfos = queryIntentActivitiesAsUser(intent,
    102                     user.getIdentifier());
    103 
    104             ArraySet<String> appsWithLaunchers = new ArraySet<>();
    105             final int resolveInfosSize = resolveInfos.size();
    106             for (int i = 0; i < resolveInfosSize; i++) {
    107                 appsWithLaunchers.add(resolveInfos.get(i).activityInfo.packageName);
    108             }
    109             final int allAppsSize = mAllApps.size();
    110             for (int i = 0; i < allAppsSize; i++) {
    111                 final ApplicationInfo appInfo = mAllApps.get(i);
    112                 if (systemAppsOnly && !appInfo.isSystemApp()) {
    113                     continue;
    114                 }
    115                 final String packageName = appInfo.packageName;
    116                 if (!appsWithLaunchers.contains(packageName)) {
    117                     result.add(packageName);
    118                 }
    119             }
    120         }
    121         if (interactAcrossUsers) {
    122             final List<PackageInfo> packagesHoldingPermissions = getPackagesHoldingPermission(
    123                     Manifest.permission.INTERACT_ACROSS_USERS, user.getIdentifier());
    124             final int packagesHoldingPermissionsSize = packagesHoldingPermissions.size();
    125             for (int i = 0; i < packagesHoldingPermissionsSize; i++) {
    126                 PackageInfo packageInfo = packagesHoldingPermissions.get(i);
    127                 if (systemAppsOnly && !packageInfo.applicationInfo.isSystemApp()) {
    128                     continue;
    129                 }
    130                 if (!result.contains(packageInfo.packageName)) {
    131                     result.add(packageInfo.packageName);
    132                 }
    133             }
    134         }
    135 
    136         if (imes) {
    137             final List<ResolveInfo> resolveInfos = queryIntentServicesAsUser(
    138                     new Intent(InputMethod.SERVICE_INTERFACE), user.getIdentifier());
    139             final int resolveInfosSize = resolveInfos.size();
    140 
    141             for (int i = 0; i < resolveInfosSize; i++) {
    142                 ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
    143                 if (systemAppsOnly && !serviceInfo.applicationInfo.isSystemApp()) {
    144                     continue;
    145                 }
    146                 if (!result.contains(serviceInfo.packageName)) {
    147                     result.add(serviceInfo.packageName);
    148                 }
    149             }
    150         }
    151 
    152         if (requiredForSystemUser) {
    153             final int allAppsSize = mAllApps.size();
    154             for (int i = 0; i < allAppsSize; i++) {
    155                 final ApplicationInfo appInfo = mAllApps.get(i);
    156                 if (systemAppsOnly && !appInfo.isSystemApp()) {
    157                     continue;
    158                 }
    159                 if (appInfo.isRequiredForSystemUser()) {
    160                     result.add(appInfo.packageName);
    161                 }
    162             }
    163         }
    164         return result;
    165     }
    166 
    167     @VisibleForTesting
    168     @SuppressWarnings("unchecked")
    169     protected List<ApplicationInfo> getAllApps(int userId) {
    170         try {
    171             return mPackageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES
    172                     | PackageManager.GET_DISABLED_COMPONENTS, userId).getList();
    173         } catch (RemoteException e) {
    174             throw e.rethrowFromSystemServer();
    175         }
    176     }
    177 
    178     @VisibleForTesting
    179     protected List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int userId) {
    180         try {
    181             return mPackageManager.queryIntentActivities(intent, null,
    182                     PackageManager.GET_DISABLED_COMPONENTS
    183                             | PackageManager.GET_UNINSTALLED_PACKAGES,
    184                     userId).getList();
    185         } catch (RemoteException e) {
    186             throw e.rethrowFromSystemServer();
    187         }
    188     }
    189 
    190     @VisibleForTesting
    191     protected List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int userId) {
    192         try {
    193             return mPackageManager.queryIntentServices(intent, null,
    194                     PackageManager.GET_META_DATA
    195                             | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, userId).getList();
    196         } catch (RemoteException e) {
    197             throw e.rethrowFromSystemServer();
    198         }
    199     }
    200 
    201     @VisibleForTesting
    202     @SuppressWarnings("unchecked")
    203     protected List<PackageInfo> getPackagesHoldingPermission(String perm, int userId) {
    204         try {
    205             return mPackageManager.getPackagesHoldingPermissions(new String[]{perm}, 0,
    206                     userId).getList();
    207         } catch (RemoteException e) {
    208             throw e.rethrowFromSystemServer();
    209         }
    210     }
    211 }
    212