blob: ec58a3422d2be036461a1c3751d430937c903b32 [file] [log] [blame]
Lifu Tang3da8f8d2018-12-11 13:50:34 -08001package com.android.settings.location;
2
Lifu Tang3da8f8d2018-12-11 13:50:34 -08003import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
4import static android.Manifest.permission.ACCESS_FINE_LOCATION;
5
6import android.content.BroadcastReceiver;
7import android.content.Context;
8import android.content.Intent;
9import android.content.IntentFilter;
10import android.location.LocationManager;
Lifu Tangd3a6d5e2019-04-25 14:41:41 -070011import android.os.UserHandle;
12import android.os.UserManager;
Philip P. Moltmann70e81da2018-12-21 10:22:50 -080013import android.permission.PermissionControllerManager;
Lifu Tang3da8f8d2018-12-11 13:50:34 -080014
Lifu Tange35f24b2018-12-27 11:43:50 -080015import androidx.annotation.VisibleForTesting;
Lifu Tang3da8f8d2018-12-11 13:50:34 -080016import androidx.preference.Preference;
17
18import com.android.settings.R;
Lifu Tangd3a6d5e2019-04-25 14:41:41 -070019import com.android.settings.Utils;
Lifu Tang3da8f8d2018-12-11 13:50:34 -080020import com.android.settings.core.BasePreferenceController;
21import com.android.settingslib.core.lifecycle.LifecycleObserver;
22import com.android.settingslib.core.lifecycle.events.OnStart;
23import com.android.settingslib.core.lifecycle.events.OnStop;
24
25import java.util.Arrays;
Lifu Tangd3a6d5e2019-04-25 14:41:41 -070026import java.util.List;
27import java.util.concurrent.atomic.AtomicInteger;
Lifu Tang3da8f8d2018-12-11 13:50:34 -080028
29public 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;
Lifu Tangd3a6d5e2019-04-25 14:41:41 -070036 private int mNumTotalLoading = 0;
Lifu Tang3da8f8d2018-12-11 13:50:34 -080037 private BroadcastReceiver mReceiver;
38 private Preference mPreference;
Lifu Tangd3a6d5e2019-04-25 14:41:41 -070039 private AtomicInteger loadingInProgress = new AtomicInteger(0);
Lifu Tang3da8f8d2018-12-11 13:50:34 -080040
41 public TopLevelLocationPreferenceController(Context context, String preferenceKey) {
42 super(context, preferenceKey);
43 mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
44 }
45
46 @Override
47 public int getAvailabilityStatus() {
48 return AVAILABLE;
49 }
50
51 @Override
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
Lifu Tange35f24b2018-12-27 11:43:50 -080065 @VisibleForTesting
66 void setLocationAppCount(int numApps) {
67 mNumTotal = numApps;
68 refreshSummary(mPreference);
69 }
70
Lifu Tang3da8f8d2018-12-11 13:50:34 -080071 @Override
72 public void updateState(Preference preference) {
73 super.updateState(preference);
74 mPreference = preference;
75 refreshSummary(preference);
Lifu Tangd3a6d5e2019-04-25 14:41:41 -070076 // Bail out if location has been disabled, or there's another loading request in progress.
77 if (!mLocationManager.isLocationEnabled() ||
78 loadingInProgress.get() != 0) {
Lifu Tang3da8f8d2018-12-11 13:50:34 -080079 return;
80 }
Lifu Tangd3a6d5e2019-04-25 14:41:41 -070081 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 }
Lifu Tang3da8f8d2018-12-11 13:50:34 -0800107 }
108
109 @Override
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
124 public void onStop() {
125 mContext.unregisterReceiver(mReceiver);
126 }
127
128 private void refreshLocationMode() {
Lifu Tangd3a6d5e2019-04-25 14:41:41 -0700129 if (mPreference != null) {
130 updateState(mPreference);
131 }
Lifu Tang3da8f8d2018-12-11 13:50:34 -0800132 }
133}