Merge "Merge credential manager providers by package name"
This commit is contained in:
@@ -24,7 +24,9 @@ import android.app.Dialog;
|
|||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.ServiceInfo;
|
||||||
import android.credentials.CredentialManager;
|
import android.credentials.CredentialManager;
|
||||||
import android.credentials.CredentialProviderInfo;
|
import android.credentials.CredentialProviderInfo;
|
||||||
import android.credentials.SetEnabledProvidersException;
|
import android.credentials.SetEnabledProvidersException;
|
||||||
@@ -32,6 +34,7 @@ import android.graphics.drawable.Drawable;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.OutcomeReceiver;
|
import android.os.OutcomeReceiver;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.IconDrawableFactory;
|
import android.util.IconDrawableFactory;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -162,22 +165,64 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
|
|
||||||
PreferenceGroup group = screen.findPreference(getPreferenceKey());
|
PreferenceGroup group = screen.findPreference(getPreferenceKey());
|
||||||
Context context = screen.getContext();
|
Context context = screen.getContext();
|
||||||
|
mPrefs.putAll(buildPreferenceList(context, group));
|
||||||
|
}
|
||||||
|
|
||||||
for (CredentialProviderInfo service : mServices) {
|
/** Aggregates the list of services and builds a list of UI prefs to show. */
|
||||||
group.addPreference(createPreference(context, service));
|
@VisibleForTesting
|
||||||
|
public Map<String, SwitchPreference> buildPreferenceList(
|
||||||
|
Context context, PreferenceGroup group) {
|
||||||
|
// Group the services by package name.
|
||||||
|
Map<String, List<CredentialProviderInfo>> groupedInfos = new HashMap<>();
|
||||||
|
for (CredentialProviderInfo cpi : mServices) {
|
||||||
|
String packageName = cpi.getServiceInfo().packageName;
|
||||||
|
if (!groupedInfos.containsKey(packageName)) {
|
||||||
|
groupedInfos.put(packageName, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
groupedInfos.get(packageName).add(cpi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build the pref list.
|
||||||
|
Map<String, SwitchPreference> output = new HashMap<>();
|
||||||
|
for (String packageName : groupedInfos.keySet()) {
|
||||||
|
List<CredentialProviderInfo> infos = groupedInfos.get(packageName);
|
||||||
|
SwitchPreference pref = createPreference(context, groupedInfos.get(packageName));
|
||||||
|
if (pref != null) {
|
||||||
|
output.put(packageName, pref);
|
||||||
|
group.addPreference(pref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a preference object based on the provider info. */
|
/** Creates a preference object based on the provider info. */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public SwitchPreference createPreference(Context context, CredentialProviderInfo service) {
|
public @Nullable SwitchPreference createPreference(
|
||||||
CharSequence label = service.getLabel(context);
|
Context context, List<CredentialProviderInfo> infos) {
|
||||||
|
final CredentialProviderInfo firstInfo = infos.get(0);
|
||||||
|
final ServiceInfo firstServiceInfo = firstInfo.getServiceInfo();
|
||||||
|
final String packageName = firstServiceInfo.packageName;
|
||||||
|
CharSequence title = firstInfo.getLabel(context);
|
||||||
|
Drawable icon = firstInfo.getServiceIcon(context);
|
||||||
|
|
||||||
|
if (infos.size() > 1) {
|
||||||
|
// If there is more than one then group them under the package.
|
||||||
|
ApplicationInfo appInfo = firstServiceInfo.applicationInfo;
|
||||||
|
if (appInfo.nonLocalizedLabel != null) {
|
||||||
|
title = appInfo.loadLabel(mPm);
|
||||||
|
}
|
||||||
|
icon = mIconFactory.getBadgedIcon(appInfo, getUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no title then don't show anything.
|
||||||
|
if (TextUtils.isEmpty(title)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return addProviderPreference(
|
return addProviderPreference(
|
||||||
context,
|
context, title, icon, packageName, firstInfo.getSettingsSubtitle());
|
||||||
label == null ? "" : label,
|
|
||||||
service.getServiceIcon(mContext),
|
|
||||||
service.getServiceInfo().packageName,
|
|
||||||
service.getSettingsSubtitle());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,7 +285,6 @@ public class CredentialManagerPreferenceController extends BasePreferenceControl
|
|||||||
final SwitchPreference pref = new SwitchPreference(prefContext);
|
final SwitchPreference pref = new SwitchPreference(prefContext);
|
||||||
pref.setTitle(title);
|
pref.setTitle(title);
|
||||||
pref.setChecked(mEnabledPackageNames.contains(packageName));
|
pref.setChecked(mEnabledPackageNames.contains(packageName));
|
||||||
mPrefs.put(packageName, pref);
|
|
||||||
|
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
pref.setIcon(Utils.getSafeIcon(icon));
|
pref.setIcon(Utils.getSafeIcon(icon));
|
||||||
|
@@ -44,8 +44,10 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -55,6 +57,13 @@ public class CredentialManagerPreferenceControllerTest {
|
|||||||
private PreferenceScreen mScreen;
|
private PreferenceScreen mScreen;
|
||||||
private PreferenceCategory mCredentialsPreferenceCategory;
|
private PreferenceCategory mCredentialsPreferenceCategory;
|
||||||
|
|
||||||
|
private static final String TEST_PACKAGE_NAME_A = "com.android.providerA";
|
||||||
|
private static final String TEST_PACKAGE_NAME_B = "com.android.providerB";
|
||||||
|
private static final String TEST_PACKAGE_NAME_C = "com.android.providerC";
|
||||||
|
private static final String TEST_TITLE_APP_A = "test app A";
|
||||||
|
private static final String TEST_TITLE_APP_B = "test app B";
|
||||||
|
private static final String TEST_TITLE_SERVICE_C = "test service C1";
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mContext = spy(ApplicationProvider.getApplicationContext());
|
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||||
@@ -114,11 +123,11 @@ public class CredentialManagerPreferenceControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void buildSwitchPreference() {
|
public void buildSwitchPreference() {
|
||||||
CredentialProviderInfo providerInfo1 =
|
CredentialProviderInfo providerInfo1 =
|
||||||
createCredentialProviderInfo(
|
createCredentialProviderInfoWithSettingsSubtitle(
|
||||||
"com.android.provider1", "ClassA", "Service Title", false, null);
|
"com.android.provider1", "ClassA", "Service Title", null);
|
||||||
CredentialProviderInfo providerInfo2 =
|
CredentialProviderInfo providerInfo2 =
|
||||||
createCredentialProviderInfo(
|
createCredentialProviderInfoWithSettingsSubtitle(
|
||||||
"com.android.provider2", "ClassA", "Service Title", false, "Summary Text");
|
"com.android.provider2", "ClassA", "Service Title", "Summary Text");
|
||||||
CredentialManagerPreferenceController controller =
|
CredentialManagerPreferenceController controller =
|
||||||
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
|
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
|
||||||
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
|
||||||
@@ -136,13 +145,14 @@ public class CredentialManagerPreferenceControllerTest {
|
|||||||
assertThat(enabledProviders.contains("com.android.provider1")).isTrue();
|
assertThat(enabledProviders.contains("com.android.provider1")).isTrue();
|
||||||
|
|
||||||
// Create the pref (checked).
|
// Create the pref (checked).
|
||||||
SwitchPreference pref = controller.createPreference(mContext, providerInfo1);
|
SwitchPreference pref = controller.createPreference(mContext, Arrays.asList(providerInfo1));
|
||||||
assertThat(pref.getTitle().toString()).isEqualTo("Service Title");
|
assertThat(pref.getTitle().toString()).isEqualTo("Service Title");
|
||||||
assertThat(pref.isChecked()).isTrue();
|
assertThat(pref.isChecked()).isTrue();
|
||||||
assertThat(pref.getSummary()).isNull();
|
assertThat(pref.getSummary()).isNull();
|
||||||
|
|
||||||
// Create the pref (not checked).
|
// Create the pref (not checked).
|
||||||
SwitchPreference pref2 = controller.createPreference(mContext, providerInfo2);
|
SwitchPreference pref2 =
|
||||||
|
controller.createPreference(mContext, Arrays.asList(providerInfo2));
|
||||||
assertThat(pref2.getTitle().toString()).isEqualTo("Service Title");
|
assertThat(pref2.getTitle().toString()).isEqualTo("Service Title");
|
||||||
assertThat(pref2.isChecked()).isFalse();
|
assertThat(pref2.isChecked()).isFalse();
|
||||||
assertThat(pref2.getSummary().toString()).isEqualTo("Summary Text");
|
assertThat(pref2.getSummary().toString()).isEqualTo("Summary Text");
|
||||||
@@ -219,10 +229,10 @@ public class CredentialManagerPreferenceControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void handlesCredentialProviderInfoEnabledDisabled() {
|
public void handlesCredentialProviderInfoEnabledDisabled() {
|
||||||
CredentialProviderInfo providerInfo1 =
|
CredentialProviderInfo providerInfo1 =
|
||||||
createCredentialProviderInfo(
|
createCredentialProviderInfoWithIsEnabled(
|
||||||
"com.android.provider1", "ClassA", "Service Title", false);
|
"com.android.provider1", "ClassA", "Service Title", false);
|
||||||
CredentialProviderInfo providerInfo2 =
|
CredentialProviderInfo providerInfo2 =
|
||||||
createCredentialProviderInfo(
|
createCredentialProviderInfoWithIsEnabled(
|
||||||
"com.android.provider2", "ClassA", "Service Title", true);
|
"com.android.provider2", "ClassA", "Service Title", true);
|
||||||
CredentialManagerPreferenceController controller =
|
CredentialManagerPreferenceController controller =
|
||||||
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
|
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
|
||||||
@@ -246,6 +256,66 @@ public class CredentialManagerPreferenceControllerTest {
|
|||||||
assertThat(enabledServices.contains("com.android.provider2/ClassA")).isTrue();
|
assertThat(enabledServices.contains("com.android.provider2/ClassA")).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void displayPreference_withServices_preferencesAdded_sameAppShouldBeMerged() {
|
||||||
|
CredentialProviderInfo serviceA1 =
|
||||||
|
createCredentialProviderInfoWithAppLabel(
|
||||||
|
TEST_PACKAGE_NAME_A,
|
||||||
|
"CredManProviderA1",
|
||||||
|
TEST_TITLE_APP_A,
|
||||||
|
"test service A1");
|
||||||
|
CredentialProviderInfo serviceB1 =
|
||||||
|
createCredentialProviderInfoWithAppLabel(
|
||||||
|
TEST_PACKAGE_NAME_B,
|
||||||
|
"CredManProviderB1",
|
||||||
|
TEST_TITLE_APP_B,
|
||||||
|
"test service B");
|
||||||
|
CredentialProviderInfo serviceC1 =
|
||||||
|
createCredentialProviderInfoWithAppLabel(
|
||||||
|
TEST_PACKAGE_NAME_C,
|
||||||
|
"CredManProviderC1",
|
||||||
|
"test app C1",
|
||||||
|
TEST_TITLE_SERVICE_C);
|
||||||
|
CredentialProviderInfo serviceC2 =
|
||||||
|
createCredentialProviderInfoWithAppLabel(
|
||||||
|
TEST_PACKAGE_NAME_C,
|
||||||
|
"CredManProviderC2",
|
||||||
|
"test app C2",
|
||||||
|
TEST_TITLE_SERVICE_C);
|
||||||
|
CredentialProviderInfo serviceC3 =
|
||||||
|
createCredentialProviderInfoBuilder(
|
||||||
|
TEST_PACKAGE_NAME_C,
|
||||||
|
"CredManProviderC3",
|
||||||
|
"test app C3",
|
||||||
|
TEST_TITLE_SERVICE_C)
|
||||||
|
.setEnabled(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
CredentialManagerPreferenceController controller =
|
||||||
|
createControllerWithServices(
|
||||||
|
Lists.newArrayList(serviceA1, serviceB1, serviceC1, serviceC2, serviceC3));
|
||||||
|
controller.displayPreference(mScreen);
|
||||||
|
|
||||||
|
assertThat(controller.isConnected()).isFalse();
|
||||||
|
assertThat(mCredentialsPreferenceCategory.getPreferenceCount()).isEqualTo(3);
|
||||||
|
|
||||||
|
Map<String, SwitchPreference> prefs =
|
||||||
|
controller.buildPreferenceList(mContext, mCredentialsPreferenceCategory);
|
||||||
|
assertThat(prefs.size()).isEqualTo(3);
|
||||||
|
SwitchPreference pref1 = prefs.get(TEST_PACKAGE_NAME_C);
|
||||||
|
assertThat(pref1).isNotNull();
|
||||||
|
assertThat(pref1.getTitle()).isEqualTo(TEST_TITLE_APP_A);
|
||||||
|
assertThat(pref1.isChecked()).isFalse();
|
||||||
|
SwitchPreference pref2 = prefs.get(TEST_PACKAGE_NAME_C);
|
||||||
|
assertThat(pref2).isNotNull();
|
||||||
|
assertThat(pref2.getTitle()).isEqualTo(TEST_TITLE_APP_B);
|
||||||
|
assertThat(pref2.isChecked()).isFalse();
|
||||||
|
SwitchPreference pref3 = prefs.get(TEST_PACKAGE_NAME_C);
|
||||||
|
assertThat(pref3).isNotNull();
|
||||||
|
assertThat(pref3.getTitle()).isEqualTo(TEST_TITLE_SERVICE_C);
|
||||||
|
assertThat(pref3.isChecked()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
private CredentialManagerPreferenceController createControllerWithServices(
|
private CredentialManagerPreferenceController createControllerWithServices(
|
||||||
List<CredentialProviderInfo> availableServices) {
|
List<CredentialProviderInfo> availableServices) {
|
||||||
CredentialManagerPreferenceController controller =
|
CredentialManagerPreferenceController controller =
|
||||||
@@ -261,7 +331,8 @@ public class CredentialManagerPreferenceControllerTest {
|
|||||||
|
|
||||||
private CredentialProviderInfo createCredentialProviderInfo(
|
private CredentialProviderInfo createCredentialProviderInfo(
|
||||||
String packageName, String className) {
|
String packageName, String className) {
|
||||||
return createCredentialProviderInfo(packageName, className, null, false);
|
return createCredentialProviderInfoBuilder(packageName, className, null, "App Name")
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private CredentialProviderInfo createCredentialProviderInfo(
|
private CredentialProviderInfo createCredentialProviderInfo(
|
||||||
@@ -286,8 +357,41 @@ public class CredentialManagerPreferenceControllerTest {
|
|||||||
|
|
||||||
return new CredentialProviderInfo.Builder(si)
|
return new CredentialProviderInfo.Builder(si)
|
||||||
.setOverrideLabel(label)
|
.setOverrideLabel(label)
|
||||||
.setEnabled(isEnabled)
|
|
||||||
.setSettingsSubtitle(subtitle)
|
.setSettingsSubtitle(subtitle)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CredentialProviderInfo createCredentialProviderInfoWithIsEnabled(
|
||||||
|
String packageName, String className, CharSequence serviceLabel, boolean isEnabled) {
|
||||||
|
return createCredentialProviderInfoBuilder(packageName, className, serviceLabel, "App Name")
|
||||||
|
.setEnabled(isEnabled)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CredentialProviderInfo createCredentialProviderInfoWithSettingsSubtitle(
|
||||||
|
String packageName, String className, CharSequence serviceLabel, String subtitle) {
|
||||||
|
return createCredentialProviderInfoBuilder(packageName, className, serviceLabel, "App Name")
|
||||||
|
.setSettingsSubtitle(subtitle)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CredentialProviderInfo createCredentialProviderInfoWithAppLabel(
|
||||||
|
String packageName, String className, CharSequence serviceLabel, String appLabel) {
|
||||||
|
return createCredentialProviderInfoBuilder(packageName, className, serviceLabel, appLabel)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CredentialProviderInfo.Builder createCredentialProviderInfoBuilder(
|
||||||
|
String packageName, String className, CharSequence serviceLabel, String appLabel) {
|
||||||
|
ServiceInfo si = new ServiceInfo();
|
||||||
|
si.packageName = packageName;
|
||||||
|
si.name = className;
|
||||||
|
si.nonLocalizedLabel = serviceLabel;
|
||||||
|
|
||||||
|
si.applicationInfo = new ApplicationInfo();
|
||||||
|
si.applicationInfo.packageName = packageName;
|
||||||
|
si.applicationInfo.nonLocalizedLabel = appLabel;
|
||||||
|
|
||||||
|
return new CredentialProviderInfo.Builder(si).setOverrideLabel(serviceLabel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user