• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.car.settings.applications.performance;
18 
19 import static android.car.settings.CarSettings.Secure.KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE;
20 
21 import android.car.watchdog.CarWatchdogManager;
22 import android.car.watchdog.PackageKillableState;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.PackageManager;
28 import android.content.pm.ResolveInfo;
29 import android.os.Process;
30 import android.os.UserHandle;
31 import android.provider.Settings;
32 import android.text.TextUtils;
33 import android.util.ArraySet;
34 
35 import com.android.car.settings.R;
36 import com.android.car.settings.common.ConfirmationDialogFragment;
37 import com.android.car.settings.common.FragmentController;
38 
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.List;
42 import java.util.Objects;
43 import java.util.Set;
44 
45 /**
46  * Utility functions for use in Performance-impacting apps settings and Prioritize app settings.
47  */
48 public final class PerfImpactingAppsUtils {
49 
50     private static final String PACKAGES_DISABLED_ON_RESOURCE_OVERUSE_SEPARATOR = ";";
51 
PerfImpactingAppsUtils()52     private PerfImpactingAppsUtils() {}
53 
54     /**
55      * Returns the {@link android.car.watchdog.PackageKillableState.KillableState} for the package
56      * and user provided.
57      */
getKillableState(String packageName, UserHandle userHandle, CarWatchdogManager manager)58     public static int getKillableState(String packageName, UserHandle userHandle,
59             CarWatchdogManager manager) {
60         return Objects.requireNonNull(manager)
61                 .getPackageKillableStatesAsUser(userHandle).stream()
62                 .filter(pks -> pks.getPackageName().equals(packageName))
63                 .findFirst().map(PackageKillableState::getKillableState).orElse(-1);
64     }
65 
66     /**
67      * Shows confirmation dialog when user chooses to prioritize an app disabled because of resource
68      * overuse.
69      */
showPrioritizeAppConfirmationDialog(Context context, FragmentController fragmentController, ConfirmationDialogFragment.ConfirmListener listener, String dialogTag)70     public static void showPrioritizeAppConfirmationDialog(Context context,
71             FragmentController fragmentController,
72             ConfirmationDialogFragment.ConfirmListener listener, String dialogTag) {
73         ConfirmationDialogFragment dialogFragment =
74                 new ConfirmationDialogFragment.Builder(context)
75                         .setTitle(R.string.prioritize_app_performance_dialog_title)
76                         .setMessage(R.string.prioritize_app_performance_dialog_text)
77                         .setPositiveButton(R.string.prioritize_app_performance_dialog_action_on,
78                                 listener)
79                         .setNegativeButton(R.string.prioritize_app_performance_dialog_action_off,
80                                 /* rejectListener= */ null)
81                         .build();
82         fragmentController.showDialog(dialogFragment, dialogTag);
83     }
84 
85     /**
86      * Returns the set of package names disabled due to resource overuse.
87      */
getDisabledPackages(Context context)88     public static Set<String> getDisabledPackages(Context context) {
89         ContentResolver contentResolverForUser = context.createContextAsUser(
90                         UserHandle.getUserHandleForUid(Process.myUid()), /* flags= */ 0)
91                 .getContentResolver();
92         return extractPackages(Settings.Secure.getString(contentResolverForUser,
93                         KEY_PACKAGES_DISABLED_ON_RESOURCE_OVERUSE));
94     }
95 
96     /**
97      * Returns a list of application infos disabled due to resource overuse.
98      */
getDisabledAppInfos(Context context)99     public static List<ApplicationInfo> getDisabledAppInfos(Context context) {
100         Set<String> disabledPackageNames = getDisabledPackages(context);
101         if (disabledPackageNames.isEmpty()) {
102             return new ArrayList<>(0);
103         }
104         PackageManager packageManager = context.getPackageManager();
105         List<ResolveInfo> allPackages = packageManager.queryIntentActivities(
106                 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER),
107                 PackageManager.ResolveInfoFlags.of(PackageManager.GET_RESOLVED_FILTER
108                         | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS));
109         List<ApplicationInfo> disabledAppInfos = new ArrayList<>(allPackages.size());
110         for (int idx = 0; idx < allPackages.size(); idx++) {
111             ApplicationInfo applicationInfo = allPackages.get(idx).activityInfo.applicationInfo;
112             if (disabledPackageNames.contains(applicationInfo.packageName)) {
113                 disabledAppInfos.add(applicationInfo);
114                 // Match only the first occurrence of a package.
115                 // |PackageManager#queryIntentActivities| can return duplicate packages.
116                 disabledPackageNames.remove(applicationInfo.packageName);
117             }
118         }
119         return disabledAppInfos;
120     }
121 
extractPackages(String settingsString)122     private static ArraySet<String> extractPackages(String settingsString) {
123         return TextUtils.isEmpty(settingsString) ? new ArraySet<>()
124                 : new ArraySet<>(Arrays.asList(settingsString.split(
125                         PACKAGES_DISABLED_ON_RESOURCE_OVERUSE_SEPARATOR)));
126     }
127 }
128