Loading packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java +54 −15 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ package com.android.settingslib.location; import android.app.AppOpsManager; import android.content.Context; import android.content.PermissionChecker; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.text.format.DateUtils; Loading @@ -48,10 +48,15 @@ public class RecentLocationApps { private static final long RECENT_TIME_INTERVAL_MILLIS = DateUtils.DAY_IN_MILLIS; @VisibleForTesting static final int[] LOCATION_OPS = new int[] { static final int[] LOCATION_REQUEST_OPS = new int[]{ AppOpsManager.OP_MONITOR_LOCATION, AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, }; @VisibleForTesting static final int[] LOCATION_PERMISSION_OPS = new int[]{ AppOpsManager.OP_FINE_LOCATION, AppOpsManager.OP_COARSE_LOCATION, }; private final PackageManager mPackageManager; private final Context mContext; Loading @@ -67,11 +72,13 @@ public class RecentLocationApps { * Fills a list of applications which queried location recently within specified time. * Apps are sorted by recency. Apps with more recent location requests are in the front. */ public List<Request> getAppList() { public List<Request> getAppList(boolean showSystemApps) { // Retrieve a location usage list from AppOps PackageManager pm = mContext.getPackageManager(); // Retrieve a location usage list from AppOps AppOpsManager aoManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_OPS); List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_REQUEST_OPS); final int appOpsCount = appOps != null ? appOps.size() : 0; Loading @@ -83,26 +90,58 @@ public class RecentLocationApps { for (int i = 0; i < appOpsCount; ++i) { AppOpsManager.PackageOps ops = appOps.get(i); // Don't show the Android System in the list - it's not actionable for the user. // Also don't show apps belonging to background users except managed users. String packageName = ops.getPackageName(); int uid = ops.getUid(); int userId = UserHandle.getUserId(uid); boolean isAndroidOs = (uid == Process.SYSTEM_UID) && ANDROID_SYSTEM_PACKAGE_NAME.equals(packageName); if (isAndroidOs || !profiles.contains(new UserHandle(userId))) { final UserHandle user = UserHandle.getUserHandleForUid(uid); // Don't show apps belonging to background users except managed users. if (!profiles.contains(user)) { continue; } // Don't show apps that do not have user sensitive location permissions boolean showApp = true; if (!showSystemApps) { for (int op : LOCATION_PERMISSION_OPS) { final String permission = AppOpsManager.opToPermission(op); final int permissionFlags = pm.getPermissionFlags(permission, packageName, user); if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName) == PermissionChecker.PERMISSION_GRANTED) { if ((permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0) { showApp = false; break; } } else { if ((permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) == 0) { showApp = false; break; } } } } if (showApp) { Request request = getRequestFromOps(now, ops); if (request != null) { requests.add(request); } } } return requests; } public List<Request> getAppListSorted() { List<Request> requests = getAppList(); /** * Gets a list of apps that requested for location recently, sorting by recency. * * @param showSystemApps whether includes system apps in the list. * @return the list of apps that recently requested for location. */ public List<Request> getAppListSorted(boolean showSystemApps) { List<Request> requests = getAppList(showSystemApps); // Sort the list of Requests by recency. Most recent request first. Collections.sort(requests, Collections.reverseOrder(new Comparator<Request>() { @Override Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java +11 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,8 @@ import android.content.res.Resources; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.util.LongSparseLongArray; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading Loading @@ -75,7 +75,8 @@ public class RecentLocationAppsTest { long[] testRequestTime = {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO}; List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime); when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_OPS)).thenReturn(appOps); when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_REQUEST_OPS)).thenReturn( appOps); mockTestApplicationInfos(mTestUserId, TEST_PACKAGE_NAMES); mRecentLocationApps = new RecentLocationApps(mContext); Loading @@ -83,7 +84,7 @@ public class RecentLocationAppsTest { @Test public void testGetAppList_shouldFilterRecentApps() { List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(); List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(true); // Only two of the apps have requested location within 15 min. assertThat(requests).hasSize(2); // Make sure apps are ordered by recency Loading @@ -107,11 +108,12 @@ public class RecentLocationAppsTest { {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO, ONE_MIN_AGO}; List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime); appOps.add(androidSystemPackageOps); when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_OPS)).thenReturn(appOps); when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_REQUEST_OPS)).thenReturn( appOps); mockTestApplicationInfos( Process.SYSTEM_UID, RecentLocationApps.ANDROID_SYSTEM_PACKAGE_NAME); List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(); List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(true); // Android OS shouldn't show up in the list of apps. assertThat(requests).hasSize(2); // Make sure apps are ordered by recency Loading Loading
packages/SettingsLib/src/com/android/settingslib/location/RecentLocationApps.java +54 −15 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ package com.android.settingslib.location; import android.app.AppOpsManager; import android.content.Context; import android.content.PermissionChecker; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.text.format.DateUtils; Loading @@ -48,10 +48,15 @@ public class RecentLocationApps { private static final long RECENT_TIME_INTERVAL_MILLIS = DateUtils.DAY_IN_MILLIS; @VisibleForTesting static final int[] LOCATION_OPS = new int[] { static final int[] LOCATION_REQUEST_OPS = new int[]{ AppOpsManager.OP_MONITOR_LOCATION, AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION, }; @VisibleForTesting static final int[] LOCATION_PERMISSION_OPS = new int[]{ AppOpsManager.OP_FINE_LOCATION, AppOpsManager.OP_COARSE_LOCATION, }; private final PackageManager mPackageManager; private final Context mContext; Loading @@ -67,11 +72,13 @@ public class RecentLocationApps { * Fills a list of applications which queried location recently within specified time. * Apps are sorted by recency. Apps with more recent location requests are in the front. */ public List<Request> getAppList() { public List<Request> getAppList(boolean showSystemApps) { // Retrieve a location usage list from AppOps PackageManager pm = mContext.getPackageManager(); // Retrieve a location usage list from AppOps AppOpsManager aoManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_OPS); List<AppOpsManager.PackageOps> appOps = aoManager.getPackagesForOps(LOCATION_REQUEST_OPS); final int appOpsCount = appOps != null ? appOps.size() : 0; Loading @@ -83,26 +90,58 @@ public class RecentLocationApps { for (int i = 0; i < appOpsCount; ++i) { AppOpsManager.PackageOps ops = appOps.get(i); // Don't show the Android System in the list - it's not actionable for the user. // Also don't show apps belonging to background users except managed users. String packageName = ops.getPackageName(); int uid = ops.getUid(); int userId = UserHandle.getUserId(uid); boolean isAndroidOs = (uid == Process.SYSTEM_UID) && ANDROID_SYSTEM_PACKAGE_NAME.equals(packageName); if (isAndroidOs || !profiles.contains(new UserHandle(userId))) { final UserHandle user = UserHandle.getUserHandleForUid(uid); // Don't show apps belonging to background users except managed users. if (!profiles.contains(user)) { continue; } // Don't show apps that do not have user sensitive location permissions boolean showApp = true; if (!showSystemApps) { for (int op : LOCATION_PERMISSION_OPS) { final String permission = AppOpsManager.opToPermission(op); final int permissionFlags = pm.getPermissionFlags(permission, packageName, user); if (PermissionChecker.checkPermission(mContext, permission, -1, uid, packageName) == PermissionChecker.PERMISSION_GRANTED) { if ((permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED) == 0) { showApp = false; break; } } else { if ((permissionFlags & PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED) == 0) { showApp = false; break; } } } } if (showApp) { Request request = getRequestFromOps(now, ops); if (request != null) { requests.add(request); } } } return requests; } public List<Request> getAppListSorted() { List<Request> requests = getAppList(); /** * Gets a list of apps that requested for location recently, sorting by recency. * * @param showSystemApps whether includes system apps in the list. * @return the list of apps that recently requested for location. */ public List<Request> getAppListSorted(boolean showSystemApps) { List<Request> requests = getAppList(showSystemApps); // Sort the list of Requests by recency. Most recent request first. Collections.sort(requests, Collections.reverseOrder(new Comparator<Request>() { @Override Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/location/RecentLocationAppsTest.java +11 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,8 @@ import android.content.res.Resources; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; import android.util.LongSparseLongArray; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; Loading Loading @@ -75,7 +75,8 @@ public class RecentLocationAppsTest { long[] testRequestTime = {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO}; List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime); when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_OPS)).thenReturn(appOps); when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_REQUEST_OPS)).thenReturn( appOps); mockTestApplicationInfos(mTestUserId, TEST_PACKAGE_NAMES); mRecentLocationApps = new RecentLocationApps(mContext); Loading @@ -83,7 +84,7 @@ public class RecentLocationAppsTest { @Test public void testGetAppList_shouldFilterRecentApps() { List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(); List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(true); // Only two of the apps have requested location within 15 min. assertThat(requests).hasSize(2); // Make sure apps are ordered by recency Loading @@ -107,11 +108,12 @@ public class RecentLocationAppsTest { {ONE_MIN_AGO, TWENTY_THREE_HOURS_AGO, TWO_DAYS_AGO, ONE_MIN_AGO}; List<PackageOps> appOps = createTestPackageOpsList(TEST_PACKAGE_NAMES, testRequestTime); appOps.add(androidSystemPackageOps); when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_OPS)).thenReturn(appOps); when(mAppOpsManager.getPackagesForOps(RecentLocationApps.LOCATION_REQUEST_OPS)).thenReturn( appOps); mockTestApplicationInfos( Process.SYSTEM_UID, RecentLocationApps.ANDROID_SYSTEM_PACKAGE_NAME); List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(); List<RecentLocationApps.Request> requests = mRecentLocationApps.getAppList(true); // Android OS shouldn't show up in the list of apps. assertThat(requests).hasSize(2); // Make sure apps are ordered by recency Loading