• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.settings.location;
2 
3 import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
4 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
5 
6 import android.content.Context;
7 import android.location.LocationManager;
8 import android.os.UserHandle;
9 import android.os.UserManager;
10 import android.permission.PermissionControllerManager;
11 import android.provider.Settings;
12 
13 import androidx.annotation.VisibleForTesting;
14 import androidx.preference.Preference;
15 
16 import com.android.settings.R;
17 import com.android.settings.Utils;
18 import com.android.settings.core.PreferenceControllerMixin;
19 import com.android.settingslib.core.lifecycle.Lifecycle;
20 
21 import java.util.Arrays;
22 import java.util.List;
23 import java.util.concurrent.atomic.AtomicInteger;
24 
25 public class AppLocationPermissionPreferenceController extends
26         LocationBasePreferenceController implements PreferenceControllerMixin {
27 
28     private static final String KEY_APP_LEVEL_PERMISSIONS = "app_level_permissions";
29     /** Total number of apps that has location permission. */
30     @VisibleForTesting
31     int mNumTotal = -1;
32     /** Total number of apps that has background location permission. */
33     @VisibleForTesting
34     int mNumHasLocation = -1;
35 
36     final AtomicInteger loadingInProgress = new AtomicInteger(0);
37     private int mNumTotalLoading = 0;
38     private int mNumHasLocationLoading = 0;
39 
40     private final LocationManager mLocationManager;
41     private Preference mPreference;
42 
AppLocationPermissionPreferenceController(Context context, Lifecycle lifecycle)43     public AppLocationPermissionPreferenceController(Context context, Lifecycle lifecycle) {
44         super(context, lifecycle);
45         mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
46     }
47 
48     @Override
getPreferenceKey()49     public String getPreferenceKey() {
50         return KEY_APP_LEVEL_PERMISSIONS;
51     }
52 
53     @Override
isAvailable()54     public boolean isAvailable() {
55         return Settings.Global.getInt(mContext.getContentResolver(),
56                 Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED, 1) == 1;
57     }
58 
59     @Override
getSummary()60     public CharSequence getSummary() {
61         if (mLocationManager.isLocationEnabled()) {
62             if (mNumTotal == -1 || mNumHasLocation == -1) {
63                 return mContext.getString(R.string.location_settings_loading_app_permission_stats);
64             }
65             return mContext.getResources().getQuantityString(
66                     R.plurals.location_app_permission_summary_location_on, mNumHasLocation,
67                     mNumHasLocation, mNumTotal);
68         } else {
69             return mContext.getString(R.string.location_app_permission_summary_location_off);
70         }
71     }
72 
setAppCounts(int numTotal, int numHasLocation)73     private void setAppCounts(int numTotal, int numHasLocation) {
74         mNumTotal = numTotal;
75         mNumHasLocation = numHasLocation;
76         refreshSummary(mPreference);
77     }
78 
79     @Override
updateState(Preference preference)80     public void updateState(Preference preference) {
81         super.updateState(preference);
82         mPreference = preference;
83         refreshSummary(preference);
84         // Bail out if location has been disabled, or there's another loading request in progress.
85         if (!mLocationManager.isLocationEnabled() ||
86                 loadingInProgress.get() != 0) {
87             return;
88         }
89         mNumTotalLoading = 0;
90         mNumHasLocationLoading = 0;
91         // Retrieve a list of users inside the current user profile group.
92         final List<UserHandle> users = mContext.getSystemService(
93                 UserManager.class).getUserProfiles();
94         loadingInProgress.set(2 * users.size());
95         for (UserHandle user : users) {
96             final Context userContext = Utils.createPackageContextAsUser(mContext,
97                     user.getIdentifier());
98             if (userContext == null) {
99                 for (int i = 0; i < 2; ++i) {
100                     if (loadingInProgress.decrementAndGet() == 0) {
101                         setAppCounts(mNumTotalLoading, mNumHasLocationLoading);
102                     }
103                 }
104                 continue;
105             }
106             final PermissionControllerManager permController =
107                     userContext.getSystemService(PermissionControllerManager.class);
108             permController.countPermissionApps(
109                     Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), 0,
110                     (numApps) -> {
111                         mNumTotalLoading += numApps;
112                         if (loadingInProgress.decrementAndGet() == 0) {
113                             setAppCounts(mNumTotalLoading, mNumHasLocationLoading);
114                         }
115                     }, null);
116             permController.countPermissionApps(
117                     Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION),
118                     PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED,
119                     (numApps) -> {
120                         mNumHasLocationLoading += numApps;
121                         if (loadingInProgress.decrementAndGet() == 0) {
122                             setAppCounts(mNumTotalLoading, mNumHasLocationLoading);
123                         }
124                     }, null);
125         }
126     }
127 
128     @Override
onLocationModeChanged(int mode, boolean restricted)129     public void onLocationModeChanged(int mode, boolean restricted) {
130         if (mPreference != null) {
131             updateState(mPreference);
132         }
133     }
134 }
135