Merge "Update location app stats" into qt-dev

This commit is contained in:
TreeHugger Robot
2019-04-30 02:50:58 +00:00
committed by Android (Google) Code Review
4 changed files with 110 additions and 54 deletions

View File

@@ -842,8 +842,8 @@
<string name="location_settings_summary_location_off">Off</string>
<!-- Summary for Location settings when location is on, explaining how many apps have location permission [CHAR LIMIT=NONE]-->
<plurals name="location_settings_summary_location_on">
<item quantity="one">On - <xliff:g id="count">%1$d</xliff:g> app can access location</item>
<item quantity="other">On - <xliff:g id="count">%1$d</xliff:g> apps can access location</item>
<item quantity="one">On - <xliff:g id="count">%1$d</xliff:g> app has access to location</item>
<item quantity="other">On - <xliff:g id="count">%1$d</xliff:g> apps have access to location</item>
</plurals>
<!-- Location settings, loading the number of apps which have location permission [CHAR LIMIT=30] -->
<string name="location_settings_loading_app_permission_stats">Loading\u2026</string>
@@ -3838,29 +3838,25 @@
<!-- Summary for app permission on Location settings page when location is off [CHAR LIMIT=NONE] -->
<string name="location_app_permission_summary_location_off">Location is off</string>
<!--
Summary for Location settings when location is on, explaining how many apps have unlimited
location permission.
"Unlimited access" means the app can access the device location even when it's not being used
(on background), while "limited" means the app can only access the device location when the user
is using it (foreground only).
Summary for Location settings when location is on, explaining how many apps have location
permission.
Please note that the distinction between singular and plural of this sentence only depends on
the quantity of "background_location_app_count" ("has" vs "have"). The quantity of
the quantity of "permitted_location_app_count" ("has" vs "have"). The quantity of
"total_location_app_count" is almost always greater than 1, so "apps" is always in plural form.
[CHAR LIMIT=NONE]-->
<plurals name="location_app_permission_summary_location_on">
<item quantity="one">
<xliff:g id="background_location_app_count">%1$d</xliff:g>
<xliff:g id="permitted_location_app_count">%1$d</xliff:g>
of
<xliff:g id="total_location_app_count">%2$d</xliff:g>
apps has unlimited access</item>
apps has access to location</item>
<item quantity="other">
<xliff:g id="background_location_app_count">%1$d</xliff:g>
<xliff:g id="permitted_location_app_count">%1$d</xliff:g>
of
<xliff:g id="total_location_app_count">%2$d</xliff:g>
apps have unlimited access</item>
apps have access to location</item>
</plurals>
<!-- [CHAR LIMIT=50] Location settings screen, sub category for recent location access -->
<string name="location_category_recent_location_access">Recent location access</string>

View File

@@ -1,11 +1,12 @@
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.os.UserHandle;
import android.os.UserManager;
import android.permission.PermissionControllerManager;
import android.provider.Settings;
@@ -13,11 +14,12 @@ import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class AppLocationPermissionPreferenceController extends
@@ -29,7 +31,12 @@ public class AppLocationPermissionPreferenceController extends
int mNumTotal = -1;
/** Total number of apps that has background location permission. */
@VisibleForTesting
int mNumBackground = -1;
int mNumHasLocation = -1;
final AtomicInteger loadingInProgress = new AtomicInteger(0);
private int mNumTotalLoading = 0;
private int mNumHasLocationLoading = 0;
private final LocationManager mLocationManager;
private Preference mPreference;
@@ -52,52 +59,76 @@ public class AppLocationPermissionPreferenceController extends
@Override
public CharSequence getSummary() {
if (mLocationManager.isLocationEnabled()) {
if (mNumTotal == -1 || mNumBackground == -1) {
if (mNumTotal == -1 || mNumHasLocation == -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);
R.plurals.location_app_permission_summary_location_on, mNumHasLocation,
mNumHasLocation, mNumTotal);
} else {
return mContext.getString(R.string.location_app_permission_summary_location_off);
}
}
private void setAppCounts(int numTotal, int numHasLocation) {
mNumTotal = numTotal;
mNumHasLocation = numHasLocation;
refreshSummary(mPreference);
}
@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()) {
// Bail out if location has been disabled, or there's another loading request in progress.
if (!mLocationManager.isLocationEnabled() ||
loadingInProgress.get() != 0) {
return;
}
PermissionControllerManager permController =
mContext.getSystemService(PermissionControllerManager.class);
permController.countPermissionApps(
Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), 0,
(numApps) -> {
mNumTotal = numApps;
mNumTotalLoading = 0;
mNumHasLocationLoading = 0;
// Retrieve a list of users inside the current user profile group.
final List<UserHandle> users = mContext.getSystemService(
UserManager.class).getUserProfiles();
loadingInProgress.set(2 * users.size());
for (UserHandle user : users) {
final Context userContext = Utils.createPackageContextAsUser(mContext,
user.getIdentifier());
if (userContext == null) {
for (int i = 0; i < 2; ++i) {
if (loadingInProgress.decrementAndGet() == 0) {
refreshSummary(preference);
setAppCounts(mNumTotalLoading, mNumHasLocationLoading);
}
}, null);
permController.countPermissionApps(
Collections.singletonList(ACCESS_BACKGROUND_LOCATION),
PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED,
(numApps) -> {
mNumBackground = numApps;
if (loadingInProgress.decrementAndGet() == 0) {
refreshSummary(preference);
}
}, null);
}
continue;
}
final PermissionControllerManager permController =
userContext.getSystemService(PermissionControllerManager.class);
permController.countPermissionApps(
Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION), 0,
(numApps) -> {
mNumTotalLoading += numApps;
if (loadingInProgress.decrementAndGet() == 0) {
setAppCounts(mNumTotalLoading, mNumHasLocationLoading);
}
}, null);
permController.countPermissionApps(
Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION),
PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED,
(numApps) -> {
mNumHasLocationLoading += numApps;
if (loadingInProgress.decrementAndGet() == 0) {
setAppCounts(mNumTotalLoading, mNumHasLocationLoading);
}
}, null);
}
}
@Override
public void onLocationModeChanged(int mode, boolean restricted) {
// 'null' is checked inside updateState(), so no need to check here.
updateState(mPreference);
if (mPreference != null) {
updateState(mPreference);
}
}
}

View File

@@ -8,18 +8,23 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.permission.PermissionControllerManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.Utils;
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.List;
import java.util.concurrent.atomic.AtomicInteger;
public class TopLevelLocationPreferenceController extends BasePreferenceController implements
LifecycleObserver, OnStart, OnStop {
@@ -28,8 +33,10 @@ public class TopLevelLocationPreferenceController extends BasePreferenceControll
private final LocationManager mLocationManager;
/** Total number of apps that has location permission. */
private int mNumTotal = -1;
private int mNumTotalLoading = 0;
private BroadcastReceiver mReceiver;
private Preference mPreference;
private AtomicInteger loadingInProgress = new AtomicInteger(0);
public TopLevelLocationPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
@@ -66,16 +73,37 @@ public class TopLevelLocationPreferenceController extends BasePreferenceControll
super.updateState(preference);
mPreference = preference;
refreshSummary(preference);
// Bail out if location has been disabled.
if (!mLocationManager.isLocationEnabled()) {
// Bail out if location has been disabled, or there's another loading request in progress.
if (!mLocationManager.isLocationEnabled() ||
loadingInProgress.get() != 0) {
return;
}
mContext.getSystemService(PermissionControllerManager.class).countPermissionApps(
Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION),
PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED,
(numApps) -> {
setLocationAppCount(numApps);
}, null);
mNumTotalLoading = 0;
// Retrieve a list of users inside the current user profile group.
final List<UserHandle> users = mContext.getSystemService(
UserManager.class).getUserProfiles();
loadingInProgress.set(users.size());
for (UserHandle user : users) {
final Context userContext = Utils.createPackageContextAsUser(mContext,
user.getIdentifier());
if (userContext == null) {
if (loadingInProgress.decrementAndGet() == 0) {
setLocationAppCount(mNumTotalLoading);
}
continue;
}
final PermissionControllerManager permController =
userContext.getSystemService(PermissionControllerManager.class);
permController.countPermissionApps(
Arrays.asList(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION),
PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED,
(numApps) -> {
mNumTotalLoading += numApps;
if (loadingInProgress.decrementAndGet() == 0) {
setLocationAppCount(mNumTotalLoading);
}
}, null);
}
}
@Override
@@ -98,7 +126,8 @@ public class TopLevelLocationPreferenceController extends BasePreferenceControll
}
private void refreshLocationMode() {
// 'null' is checked inside updateState(), so no need to check here.
updateState(mPreference);
if (mPreference != null) {
updateState(mPreference);
}
}
}

View File

@@ -76,7 +76,7 @@ public class AppLocationPermissionPreferenceControllerTest {
@Test
public void getSummary_whenLocationAppCountIsOne_shouldShowSingularString() {
mLocationManager.setLocationEnabledForUser(true, android.os.Process.myUserHandle());
mController.mNumBackground = 1;
mController.mNumHasLocation = 1;
mController.mNumTotal = 1;
assertThat(mController.getSummary()).isEqualTo(mContext.getResources().getQuantityString(
@@ -86,7 +86,7 @@ public class AppLocationPermissionPreferenceControllerTest {
@Test
public void getSummary_whenLocationAppCountIsGreaterThanOne_shouldShowPluralString() {
mLocationManager.setLocationEnabledForUser(true, android.os.Process.myUserHandle());
mController.mNumBackground = 5;
mController.mNumHasLocation = 5;
mController.mNumTotal = 10;
assertThat(mController.getSummary()).isEqualTo(mContext.getResources().getQuantityString(