Only add entry with unique package name to default browser list.

When we query the package manager for activities that can handle the
web data uri, different capable activities within the same package will
be returned as separate entries. However, when we show the default
browser apps to the user, the entries are simply base on package name.
So, if there are multiple activities within the same package that can
handle the web data, they will be shown as duplicate entries.

When we process the resolved activities, check the corresponding package
name for duplicate entries before adding it to the default browser list.

Change-Id: I4e1f1e1ea22781efe24d791b367246423ca7a3c4
Merged-In: I70c88866eb3d5fe6466554749e23c85f429dd30c
Fixes: 84207432
Test: make RunSettingsRoboTests
diff --git a/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java b/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
index 8153be2..c243970 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultBrowserPicker.java
@@ -17,9 +17,11 @@
 package com.android.settings.applications.defaultapps;
 
 import android.content.Context;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 
+import android.util.ArraySet;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 
@@ -27,6 +29,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Fragment for choosing default browser.
@@ -62,14 +65,20 @@
                 DefaultBrowserPreferenceController.BROWSE_PROBE, PackageManager.MATCH_ALL, mUserId);
 
         final int count = list.size();
+        final Set<String> addedPackages = new ArraySet<>();
         for (int i = 0; i < count; i++) {
             ResolveInfo info = list.get(i);
             if (info.activityInfo == null || !info.handleAllWebDataURI) {
                 continue;
             }
+            final String packageName = info.activityInfo.packageName;
+            if (addedPackages.contains(packageName)) {
+                continue;
+            }
             try {
                 candidates.add(new DefaultAppInfo(context, mPm,
-                        mPm.getApplicationInfoAsUser(info.activityInfo.packageName, 0, mUserId)));
+                        mPm.getApplicationInfoAsUser(packageName, 0, mUserId)));
+                addedPackages.add(packageName);
             } catch (PackageManager.NameNotFoundException e) {
                 // Skip unknown packages.
             }
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPickerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPickerTest.java
index 4f4c90e..15a1a67 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPickerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPickerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.applications.defaultapps;
 
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
@@ -23,11 +25,20 @@
 
 import android.app.Activity;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.os.UserManager;
 
+import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.DefaultAppInfo;
 import com.android.settingslib.wrapper.PackageManagerWrapper;
 
+import java.util.ArrayList;
+import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,6 +64,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        FakeFeatureFactory.setupForTest();
         when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
 
         mPicker = new DefaultBrowserPicker();
@@ -72,4 +84,39 @@
         mPicker.getDefaultKey();
         verify(mPackageManager).getDefaultBrowserPackageNameAsUser(anyInt());
     }
+
+    @Test
+    public void getCandidates_shouldNotIncludeDuplicatePackageName() throws NameNotFoundException {
+        final List<ResolveInfo> resolveInfos = new ArrayList<>();
+        final String PACKAGE_ONE = "com.first.package";
+        final String PACKAGE_TWO = "com.second.package";
+        resolveInfos.add(createResolveInfo(PACKAGE_ONE));
+        resolveInfos.add(createResolveInfo(PACKAGE_TWO));
+        resolveInfos.add(createResolveInfo(PACKAGE_ONE));
+        resolveInfos.add(createResolveInfo(PACKAGE_TWO));
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+            .thenReturn(resolveInfos);
+        when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_ONE), anyInt(), anyInt()))
+            .thenReturn(createApplicationInfo(PACKAGE_ONE));
+        when(mPackageManager.getApplicationInfoAsUser(eq(PACKAGE_TWO), anyInt(), anyInt()))
+            .thenReturn(createApplicationInfo(PACKAGE_TWO));
+
+        final List<DefaultAppInfo> defaultBrowserInfo = mPicker.getCandidates();
+
+        assertThat(defaultBrowserInfo.size()).isEqualTo(2);
+    }
+
+    private ResolveInfo createResolveInfo(String packageName) {
+        final ResolveInfo info = new ResolveInfo();
+        info.handleAllWebDataURI = true;
+        info.activityInfo = new ActivityInfo();
+        info.activityInfo.packageName = packageName;
+        return info;
+    }
+
+    private ApplicationInfo createApplicationInfo(String packageName) {
+        final ApplicationInfo info = new ApplicationInfo();
+        info.packageName = packageName;
+        return info;
+    }
 }