• 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.BroadcastReceiver;
7 import android.content.Context;
8 import android.content.Intent;
9 import android.content.IntentFilter;
10 import android.location.LocationManager;
11 import android.os.UserHandle;
12 import android.os.UserManager;
13 import android.permission.PermissionControllerManager;
14 
15 import androidx.annotation.VisibleForTesting;
16 import androidx.preference.Preference;
17 
18 import com.android.settings.R;
19 import com.android.settings.Utils;
20 import com.android.settings.core.BasePreferenceController;
21 import com.android.settingslib.core.lifecycle.LifecycleObserver;
22 import com.android.settingslib.core.lifecycle.events.OnStart;
23 import com.android.settingslib.core.lifecycle.events.OnStop;
24 
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.concurrent.atomic.AtomicInteger;
28 
29 public class TopLevelLocationPreferenceController extends BasePreferenceController implements
30         LifecycleObserver, OnStart, OnStop {
31     private static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED =
32             new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
33     private final LocationManager mLocationManager;
34     /** Total number of apps that has location permission. */
35     private int mNumTotal = -1;
36     private int mNumTotalLoading = 0;
37     private BroadcastReceiver mReceiver;
38     private Preference mPreference;
39     private AtomicInteger loadingInProgress = new AtomicInteger(0);
40 
TopLevelLocationPreferenceController(Context context, String preferenceKey)41     public TopLevelLocationPreferenceController(Context context, String preferenceKey) {
42         super(context, preferenceKey);
43         mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
44     }
45 
46     @Override
getAvailabilityStatus()47     public int getAvailabilityStatus() {
48         return AVAILABLE;
49     }
50 
51     @Override
getSummary()52     public CharSequence getSummary() {
53         if (mLocationManager.isLocationEnabled()) {
54             if (mNumTotal == -1) {
55                 return mContext.getString(R.string.location_settings_loading_app_permission_stats);
56             }
57             return mContext.getResources().getQuantityString(
58                     R.plurals.location_settings_summary_location_on,
59                     mNumTotal, mNumTotal);
60         } else {
61             return mContext.getString(R.string.location_settings_summary_location_off);
62         }
63     }
64 
65     @VisibleForTesting
setLocationAppCount(int numApps)66     void setLocationAppCount(int numApps) {
67         mNumTotal = numApps;
68         refreshSummary(mPreference);
69     }
70 
71     @Override
updateState(Preference preference)72     public void updateState(Preference preference) {
73         super.updateState(preference);
74         mPreference = preference;
75         refreshSummary(preference);
76         // Bail out if location has been disabled, or there's another loading request in progress.
77         if (!mLocationManager.isLocationEnabled() ||
78                 loadingInProgress.get() != 0) {
79             return;
80         }
81         mNumTotalLoading = 0;
82         // Retrieve a list of users inside the current user profile group.
83         final List<UserHandle> users = mContext.getSystemService(
84                 UserManager.class).getUserProfiles();
85         loadingInProgress.set(users.size());
86         for (UserHandle user : users) {
87             final Context userContext = Utils.createPackageContextAsUser(mContext,
88                     user.getIdentifier());
89             if (userContext == null) {
90                 if (loadingInProgress.decrementAndGet() == 0) {
91                     setLocationAppCount(mNumTotalLoading);
92                 }
93                 continue;
94             }
95             final PermissionControllerManager permController =
96                     userContext.getSystemService(PermissionControllerManager.class);
97             permController.countPermissionApps(
98                     Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION),
99                     PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED,
100                     (numApps) -> {
101                         mNumTotalLoading += numApps;
102                         if (loadingInProgress.decrementAndGet() == 0) {
103                             setLocationAppCount(mNumTotalLoading);
104                         }
105                     }, null);
106         }
107     }
108 
109     @Override
onStart()110     public void onStart() {
111         if (mReceiver == null) {
112             mReceiver = new BroadcastReceiver() {
113                 @Override
114                 public void onReceive(Context context, Intent intent) {
115                     refreshLocationMode();
116                 }
117             };
118         }
119         mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED);
120         refreshLocationMode();
121     }
122 
123     @Override
onStop()124     public void onStop() {
125         mContext.unregisterReceiver(mReceiver);
126     }
127 
refreshLocationMode()128     private void refreshLocationMode() {
129         if (mPreference != null) {
130             updateState(mPreference);
131         }
132     }
133 }
134