Merge "Use PermissionControllerManager to get permission groups" into qt-dev
diff --git a/src/com/android/settings/applications/AppPermissionsPreferenceController.java b/src/com/android/settings/applications/AppPermissionsPreferenceController.java
index 0137276..751e338 100644
--- a/src/com/android/settings/applications/AppPermissionsPreferenceController.java
+++ b/src/com/android/settings/applications/AppPermissionsPreferenceController.java
@@ -16,38 +16,47 @@
 import android.content.Context;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
 import android.icu.text.ListFormatter;
 import android.util.ArraySet;
-import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.applications.PermissionsSummaryHelper;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 public class AppPermissionsPreferenceController extends BasePreferenceController {
 
     private static final String TAG = "AppPermissionPrefCtrl";
-    private static final String[] PERMISSION_GROUPS = new String[]{
-            "android.permission-group.LOCATION",
-            "android.permission-group.MICROPHONE",
-            "android.permission-group.CAMERA",
-            "android.permission-group.SMS",
-            "android.permission-group.CONTACTS",
-            "android.permission-group.PHONE"};
-
-    private static final int NUM_PERMISSION_TO_USE = 3;
+    private static int NUM_PACKAGE_TO_CHECK = 3;
 
     private final PackageManager mPackageManager;
+    private final Set<CharSequence> mPermissionGroups;
+
+    private final PermissionsSummaryHelper.PermissionsResultCallback mPermissionsCallback =
+            new PermissionsSummaryHelper.PermissionsResultCallback() {
+                @Override
+                public void onPermissionSummaryResult(int standardGrantedPermissionCount,
+                        int requestedPermissionCount, int additionalGrantedPermissionCount,
+                        List<CharSequence> grantedGroupLabels) {
+                    updateSummary(grantedGroupLabels);
+                }
+            };
+
+    @VisibleForTesting
+    int mNumPackageChecked;
+
+    private Preference mPreference;
 
     public AppPermissionsPreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
         mPackageManager = context.getPackageManager();
+        mPermissionGroups = new ArraySet<>();
     }
 
     @Override
@@ -55,72 +64,41 @@
         return AVAILABLE;
     }
 
-    /*
-       Summary text looks like: Apps using Permission1, Permission2, Permission3
-       The 3 permissions are the first three from the list which any app has granted:
-       Location, Microphone, Camera, Sms, Contacts, and Phone
-     */
     @Override
-    public CharSequence getSummary() {
-        final Set<String> permissions = getAllPermissionsInGroups();
-        Set<String> grantedPermissionGroups = getGrantedPermissionGroups(permissions);
-        int count = 0;
-        final List<String> summaries = new ArrayList<>();
-
-        for (String group : PERMISSION_GROUPS) {
-            if (!grantedPermissionGroups.contains(group)) {
-                continue;
-            }
-            summaries.add(getPermissionGroupLabel(group).toString().toLowerCase());
-            if (++count >= NUM_PERMISSION_TO_USE) {
-                break;
-            }
-        }
-        return count > 0 ? mContext.getString(R.string.app_permissions_summary,
-                ListFormatter.getInstance().format(summaries)) : null;
+    public void updateState(Preference preference) {
+        mPreference = preference;
+        mNumPackageChecked = 0;
+        queryPermissionSummary();
     }
 
-    private Set<String> getGrantedPermissionGroups(Set<String> permissions) {
-        ArraySet<String> grantedPermissionGroups = new ArraySet<>();
-        List<PackageInfo> installedPackages =
+    @VisibleForTesting
+    void queryPermissionSummary() {
+        final List<PackageInfo> installedPackages =
                 mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS);
-        for (PackageInfo installedPackage : installedPackages) {
-            if (installedPackage.permissions == null) {
-                continue;
-            }
-            for (PermissionInfo permissionInfo : installedPackage.permissions) {
-                if (permissions.contains(permissionInfo.name)
-                        && !grantedPermissionGroups.contains(permissionInfo.group)) {
-                    grantedPermissionGroups.add(permissionInfo.group);
-                }
-            }
+        // Here we only get the first three apps and check their permissions.
+        final List<PackageInfo> packagesWithPermission = installedPackages.stream()
+                .filter(pInfo -> pInfo.permissions != null)
+                .limit(NUM_PACKAGE_TO_CHECK)
+                .collect(Collectors.toList());
+
+        for (PackageInfo installedPackage : packagesWithPermission) {
+            PermissionsSummaryHelper.getPermissionSummary(mContext,
+                    installedPackage.packageName, mPermissionsCallback);
         }
-        return grantedPermissionGroups;
     }
 
-    private CharSequence getPermissionGroupLabel(String group) {
-        try {
-            final PermissionGroupInfo groupInfo = mPackageManager.getPermissionGroupInfo(group, 0);
-            return groupInfo.loadLabel(mPackageManager);
-        } catch (NameNotFoundException e) {
-            Log.e(TAG, "Error getting permissions label.", e);
-        }
-        return group;
-    }
+    @VisibleForTesting
+    void updateSummary(List<CharSequence> grantedGroupLabels) {
+        mPermissionGroups.addAll(grantedGroupLabels);
+        mNumPackageChecked++;
 
-    private Set<String> getAllPermissionsInGroups() {
-        ArraySet<String> result = new ArraySet<>();
-        for (String group : PERMISSION_GROUPS) {
-            try {
-                final List<PermissionInfo> permissions =
-                        mPackageManager.queryPermissionsByGroup(group, 0);
-                for (PermissionInfo permissionInfo : permissions) {
-                    result.add(permissionInfo.name);
-                }
-            } catch (NameNotFoundException e) {
-                Log.e(TAG, "Error getting permissions in group " + group, e);
-            }
+        if (mNumPackageChecked < NUM_PACKAGE_TO_CHECK) {
+            return;
         }
-        return result;
+        final CharSequence summary = !mPermissionGroups.isEmpty()
+                ? mContext.getString(R.string.app_permissions_summary,
+                ListFormatter.getInstance().format(mPermissionGroups).toLowerCase())
+                : null;
+        mPreference.setSummary(summary);
     }
-}
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/applications/AppPermissionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/AppPermissionsPreferenceControllerTest.java
index 4343e16..107821c 100644
--- a/tests/robotests/src/com/android/settings/applications/AppPermissionsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/AppPermissionsPreferenceControllerTest.java
@@ -18,130 +18,38 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
 
 import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
 
 import androidx.preference.Preference;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
 import java.util.ArrayList;
-import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
 public class AppPermissionsPreferenceControllerTest {
 
-    private static final String PERM_LOCATION = "android.permission-group.LOCATION";
-    private static final String PERM_MICROPHONE = "android.permission-group.MICROPHONE";
-    private static final String PERM_CAMERA = "android.permission-group.CAMERA";
-    private static final String PERM_SMS = "android.permission-group.SMS";
-    private static final String PERM_CONTACTS = "android.permission-group.CONTACTS";
-    private static final String PERM_PHONE = "android.permission-group.PHONE";
-    private static final String LABEL_LOCATION = "Location";
-    private static final String LABEL_MICROPHONE = "Microphone";
-    private static final String LABEL_CAMERA = "Camera";
-    private static final String LABEL_SMS = "Sms";
-    private static final String LABEL_CONTACTS = "Contacts";
-    private static final String LABEL_PHONE = "Phone";
-
-    @Mock
-    private Preference mPreference;
-    @Mock
-    private PackageManager mPackageManager;
-    @Mock
-    private PermissionGroupInfo mGroupLocation;
-    @Mock
-    private PermissionGroupInfo mGroupMic;
-    @Mock
-    private PermissionGroupInfo mGroupCamera;
-    @Mock
-    private PermissionGroupInfo mGroupSms;
-    @Mock
-    private PermissionGroupInfo mGroupContacts;
-    @Mock
-    private PermissionGroupInfo mGroupPhone;
-
     private Context mContext;
     private AppPermissionsPreferenceController mController;
-    private PermissionInfo mPermLocation;
-    private PermissionInfo mPermMic;
-    private PermissionInfo mPermCamera;
-    private PermissionInfo mPermSms;
-    private PermissionInfo mPermContacts;
-    private PermissionInfo mPermPhone;
+    private Preference mPreference;
 
     @Before
     public void setUp() throws NameNotFoundException {
         MockitoAnnotations.initMocks(this);
-        mContext = spy(RuntimeEnvironment.application);
-        when(mContext.getPackageManager()).thenReturn(mPackageManager);
-
-        // create permission groups
-        when(mPackageManager.getPermissionGroupInfo(eq(PERM_LOCATION), anyInt()))
-                .thenReturn(mGroupLocation);
-        when(mGroupLocation.loadLabel(mPackageManager)).thenReturn(LABEL_LOCATION);
-        when(mPackageManager.getPermissionGroupInfo(eq(PERM_MICROPHONE), anyInt()))
-                .thenReturn(mGroupMic);
-        when(mGroupMic.loadLabel(mPackageManager)).thenReturn(LABEL_MICROPHONE);
-        when(mPackageManager.getPermissionGroupInfo(eq(PERM_CAMERA), anyInt()))
-                .thenReturn(mGroupCamera);
-        when(mGroupCamera.loadLabel(mPackageManager)).thenReturn(LABEL_CAMERA);
-        when(mPackageManager.getPermissionGroupInfo(eq(PERM_SMS), anyInt())).thenReturn(mGroupSms);
-        when(mGroupSms.loadLabel(mPackageManager)).thenReturn(LABEL_SMS);
-        when(mPackageManager.getPermissionGroupInfo(eq(PERM_CONTACTS), anyInt()))
-                .thenReturn(mGroupContacts);
-        when(mGroupContacts.loadLabel(mPackageManager)).thenReturn(LABEL_CONTACTS);
-        when(mPackageManager.getPermissionGroupInfo(eq(PERM_PHONE), anyInt()))
-                .thenReturn(mGroupPhone);
-        when(mGroupPhone.loadLabel(mPackageManager)).thenReturn(LABEL_PHONE);
-
-        // create permissions
-        mPermLocation = new PermissionInfo();
-        mPermLocation.name = "Permission1";
-        mPermLocation.group = PERM_LOCATION;
-        mPermMic = new PermissionInfo();
-        mPermMic.name = "Permission2";
-        mPermMic.group = PERM_MICROPHONE;
-        mPermCamera = new PermissionInfo();
-        mPermCamera.name = "Permission3";
-        mPermCamera.group = PERM_CAMERA;
-        mPermSms = new PermissionInfo();
-        mPermSms.name = "Permission4";
-        mPermSms.group = PERM_SMS;
-        mPermContacts = new PermissionInfo();
-        mPermContacts.name = "Permission4";
-        mPermContacts.group = PERM_CONTACTS;
-        mPermPhone = new PermissionInfo();
-        mPermPhone.name = "Permission4";
-        mPermPhone.group = PERM_PHONE;
-        final List<PermissionInfo> permissions = new ArrayList<>();
-        permissions.add(mPermLocation);
-        permissions.add(mPermMic);
-        permissions.add(mPermCamera);
-        permissions.add(mPermSms);
-        permissions.add(mPermContacts);
-        permissions.add(mPermPhone);
-        when(mPackageManager.queryPermissionsByGroup(anyString(), anyInt()))
-                .thenReturn(permissions);
-
+        mContext = RuntimeEnvironment.application;
+        mPreference = spy(new Preference(mContext));
         mController = spy(new AppPermissionsPreferenceController(mContext, "pref_key"));
     }
 
@@ -151,65 +59,51 @@
     }
 
     @Test
-    public void updateState_noGrantedPermissions_shouldNotSetSummary() {
-        final List<PackageInfo> installedPackages = new ArrayList<>();
-        final PackageInfo info = new PackageInfo();
-        installedPackages.add(info);
-        when(mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS))
-                .thenReturn(installedPackages);
+    public void updateState_shouldResetNumPackageChecked() {
+        doNothing().when(mController).queryPermissionSummary();
+        mController.mNumPackageChecked = 3;
 
         mController.updateState(mPreference);
 
-        verify(mPreference, never()).setSummary(anyString());
+        assertThat(mController.mNumPackageChecked).isEqualTo(0);
     }
 
     @Test
-    public void updateState_hasPermissions_shouldSetSummary() {
-        final List<PackageInfo> installedPackages = new ArrayList<>();
-        final PackageInfo info = new PackageInfo();
-        installedPackages.add(info);
-        when(mPackageManager.getInstalledPackages(PackageManager.GET_PERMISSIONS))
-                .thenReturn(installedPackages);
-        PermissionInfo[] permissions = new PermissionInfo[4];
-        info.permissions = permissions;
-
-        permissions[0] = mPermLocation;
-        permissions[1] = mPermMic;
-        permissions[2] = mPermCamera;
-        permissions[3] = mPermSms;
+    public void updateSummary_noGrantedPermission_shouldSetNullSummary() {
+        doNothing().when(mController).queryPermissionSummary();
         mController.updateState(mPreference);
+        mController.mNumPackageChecked = 2;
 
-        verify(mPreference).setSummary("Apps using location, microphone, and camera");
+        mController.updateSummary(new ArrayList<>());
 
-        permissions[0] = mPermPhone;
-        permissions[1] = mPermMic;
-        permissions[2] = mPermCamera;
-        permissions[3] = mPermSms;
+        assertThat(mPreference.getSummary()).isNull();
+    }
+
+    @Test
+    public void updateSummary_hasPermissionGroups_shouldSetPermissionAsSummary() {
+        doNothing().when(mController).queryPermissionSummary();
         mController.updateState(mPreference);
+        final String permission = "location";
+        final ArrayList<CharSequence> labels = new ArrayList<>();
+        labels.add(permission);
+        final String summary = "Apps using " + permission;
+        mController.mNumPackageChecked = 2;
 
-        verify(mPreference).setSummary("Apps using microphone, camera, and sms");
+        mController.updateSummary(labels);
 
-        permissions[0] = mPermPhone;
-        permissions[1] = mPermMic;
-        permissions[2] = mPermContacts;
-        permissions[3] = mPermSms;
+        assertThat(mPreference.getSummary()).isEqualTo(summary);
+    }
+
+    @Test
+    public void updateSummary_notReachCallbackCount_shouldNotSetSummary() {
+        doNothing().when(mController).queryPermissionSummary();
         mController.updateState(mPreference);
+        final String permission = "location";
+        final ArrayList<CharSequence> labels = new ArrayList<>();
+        labels.add(permission);
 
-        verify(mPreference).setSummary("Apps using microphone, sms, and contacts");
+        mController.updateSummary(labels);
 
-        permissions = new PermissionInfo[2];
-        info.permissions = permissions;
-        permissions[0] = mPermLocation;
-        permissions[1] = mPermCamera;
-        mController.updateState(mPreference);
-
-        verify(mPreference).setSummary("Apps using location and camera");
-
-        permissions = new PermissionInfo[1];
-        info.permissions = permissions;
-        permissions[0] = mPermCamera;
-        mController.updateState(mPreference);
-
-        verify(mPreference).setSummary("Apps using camera");
+        verify(mPreference, never()).setSummary(anyString());
     }
 }