diff options
author | Lifu Tang <lifu@google.com> | 2018-12-11 13:50:34 -0800 |
---|---|---|
committer | Lifu Tang <lifu@google.com> | 2018-12-17 21:13:08 -0800 |
commit | 3da8f8d31dc78f39cc598cce6b0c9012da1e64af (patch) | |
tree | 85563ad36c5dc439d361326603f231e1245f2d21 /src/com/android/settings/location | |
parent | 811d95c373f94c0aef9795634fa9de2283465165 (diff) | |
download | packages_apps_Settings-3da8f8d31dc78f39cc598cce6b0c9012da1e64af.tar.gz packages_apps_Settings-3da8f8d31dc78f39cc598cce6b0c9012da1e64af.tar.bz2 packages_apps_Settings-3da8f8d31dc78f39cc598cce6b0c9012da1e64af.zip |
Display app stats for location permission
Bug: 120221631
Test: manually
Change-Id: I53f43079807759c50eeb62029bb0d8d1f84e1118
Diffstat (limited to 'src/com/android/settings/location')
4 files changed, 179 insertions, 15 deletions
diff --git a/src/com/android/settings/location/AppLocationPermissionPreferenceController.java b/src/com/android/settings/location/AppLocationPermissionPreferenceController.java index f920fdc7dc..5bfc58447e 100644 --- a/src/com/android/settings/location/AppLocationPermissionPreferenceController.java +++ b/src/com/android/settings/location/AppLocationPermissionPreferenceController.java @@ -1,18 +1,38 @@ package com.android.settings.location; +import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION; +import static android.Manifest.permission.ACCESS_COARSE_LOCATION; +import static android.Manifest.permission.ACCESS_FINE_LOCATION; + import android.content.Context; +import android.location.LocationManager; +import android.permission.RuntimePermissionPresenter; import android.provider.Settings; +import androidx.preference.Preference; + +import com.android.settings.R; import com.android.settings.core.PreferenceControllerMixin; -import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicInteger; public class AppLocationPermissionPreferenceController extends - AbstractPreferenceController implements PreferenceControllerMixin { + LocationBasePreferenceController implements PreferenceControllerMixin { private static final String KEY_APP_LEVEL_PERMISSIONS = "app_level_permissions"; + /** Total number of apps that has location permission. */ + private int mNumTotal = -1; + /** Total number of apps that has background location permission. */ + private int mNumBackground = -1; + private final LocationManager mLocationManager; + private Preference mPreference; - public AppLocationPermissionPreferenceController(Context context) { - super(context); + public AppLocationPermissionPreferenceController(Context context, Lifecycle lifecycle) { + super(context, lifecycle); + mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); } @Override @@ -25,4 +45,53 @@ public class AppLocationPermissionPreferenceController extends return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED, 1) == 1; } + + @Override + public CharSequence getSummary() { + if (mLocationManager.isLocationEnabled()) { + if (mNumTotal == -1 || mNumBackground == -1) { + return mContext.getString(R.string.location_settings_loading_app_permission_stats); + } + return mContext.getResources().getQuantityString( + R.plurals.location_app_permission_summary_location_on, mNumBackground, + mNumBackground, mNumTotal); + } else { + return mContext.getString(R.string.location_app_permission_summary_location_off); + } + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + mPreference = preference; + final AtomicInteger loadingInProgress = new AtomicInteger(2); + refreshSummary(preference); + // Bail out if location has been disabled. + if (!mLocationManager.isLocationEnabled()) { + return; + } + RuntimePermissionPresenter.getInstance(mContext).countPermissionApps( + Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), false, false, + (numApps) -> { + mNumTotal = numApps; + if (loadingInProgress.decrementAndGet() == 0) { + refreshSummary(preference); + } + }, null); + + RuntimePermissionPresenter.getInstance(mContext).countPermissionApps( + Collections.singletonList(ACCESS_BACKGROUND_LOCATION), true, false, + (numApps) -> { + mNumBackground = numApps; + if (loadingInProgress.decrementAndGet() == 0) { + refreshSummary(preference); + } + }, null); + } + + @Override + public void onLocationModeChanged(int mode, boolean restricted) { + // 'null' is checked inside updateState(), so no need to check here. + updateState(mPreference); + } } diff --git a/src/com/android/settings/location/LocationEnabler.java b/src/com/android/settings/location/LocationEnabler.java index 20c228024f..e1bdf162ef 100644 --- a/src/com/android/settings/location/LocationEnabler.java +++ b/src/com/android/settings/location/LocationEnabler.java @@ -35,15 +35,15 @@ import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnPause; -import com.android.settingslib.core.lifecycle.events.OnResume; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; /** * A class that listens to location settings change and modifies location settings * settings. */ -public class LocationEnabler implements LifecycleObserver, OnResume, OnPause { +public class LocationEnabler implements LifecycleObserver, OnStart, OnStop { private static final String TAG = "LocationEnabler"; @VisibleForTesting @@ -73,7 +73,7 @@ public class LocationEnabler implements LifecycleObserver, OnResume, OnPause { } @Override - public void onResume() { + public void onStart() { if (mReceiver == null) { mReceiver = new BroadcastReceiver() { @Override @@ -90,12 +90,8 @@ public class LocationEnabler implements LifecycleObserver, OnResume, OnPause { } @Override - public void onPause() { - try { - mContext.unregisterReceiver(mReceiver); - } catch (RuntimeException e) { - // Ignore exceptions caused by race condition - } + public void onStop() { + mContext.unregisterReceiver(mReceiver); } void refreshLocationMode() { diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java index 8a92f4706e..4112340203 100644 --- a/src/com/android/settings/location/LocationSettings.java +++ b/src/com/android/settings/location/LocationSettings.java @@ -122,7 +122,7 @@ public class LocationSettings extends DashboardFragment { private static List<AbstractPreferenceController> buildPreferenceControllers( Context context, LocationSettings fragment, Lifecycle lifecycle) { final List<AbstractPreferenceController> controllers = new ArrayList<>(); - controllers.add(new AppLocationPermissionPreferenceController(context)); + controllers.add(new AppLocationPermissionPreferenceController(context, lifecycle)); controllers.add(new LocationForWorkPreferenceController(context, lifecycle)); controllers.add(new RecentLocationAccessPreferenceController(context)); controllers.add(new LocationScanningPreferenceController(context)); diff --git a/src/com/android/settings/location/TopLevelLocationPreferenceController.java b/src/com/android/settings/location/TopLevelLocationPreferenceController.java new file mode 100644 index 0000000000..d0bd9a9284 --- /dev/null +++ b/src/com/android/settings/location/TopLevelLocationPreferenceController.java @@ -0,0 +1,99 @@ +package com.android.settings.location; + +import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION; +import static android.Manifest.permission.ACCESS_COARSE_LOCATION; +import static android.Manifest.permission.ACCESS_FINE_LOCATION; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.location.LocationManager; +import android.permission.RuntimePermissionPresenter; + +import androidx.preference.Preference; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +import java.util.Arrays; +import java.util.Collections; + +public class TopLevelLocationPreferenceController extends BasePreferenceController implements + LifecycleObserver, OnStart, OnStop { + private static final IntentFilter INTENT_FILTER_LOCATION_MODE_CHANGED = + new IntentFilter(LocationManager.MODE_CHANGED_ACTION); + private final LocationManager mLocationManager; + /** Total number of apps that has location permission. */ + private int mNumTotal = -1; + private BroadcastReceiver mReceiver; + private Preference mPreference; + + public TopLevelLocationPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public CharSequence getSummary() { + if (mLocationManager.isLocationEnabled()) { + if (mNumTotal == -1) { + return mContext.getString(R.string.location_settings_loading_app_permission_stats); + } + return mContext.getResources().getQuantityString( + R.plurals.location_settings_summary_location_on, + mNumTotal, mNumTotal); + } else { + return mContext.getString(R.string.location_settings_summary_location_off); + } + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + mPreference = preference; + refreshSummary(preference); + // Bail out if location has been disabled. + if (!mLocationManager.isLocationEnabled()) { + return; + } + RuntimePermissionPresenter.getInstance(mContext).countPermissionApps( + Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), false, false, + (numApps) -> { + mNumTotal = numApps; + refreshSummary(preference); + }, null); + } + + @Override + public void onStart() { + if (mReceiver == null) { + mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + refreshLocationMode(); + } + }; + } + mContext.registerReceiver(mReceiver, INTENT_FILTER_LOCATION_MODE_CHANGED); + refreshLocationMode(); + } + + @Override + public void onStop() { + mContext.unregisterReceiver(mReceiver); + } + + private void refreshLocationMode() { + // 'null' is checked inside updateState(), so no need to check here. + updateState(mPreference); + } +} |