Make provider icon sizes consistent
Fixes an issue where the icons under "additional providers"
are not the same size. Also, fixes the unit tests for
CredentialManagerPreferenceController.
https://hsv.googleplex.com/4797855484084224
Test: unit tests and manual on device tests
Bug: 278772478
Change-Id: I88d8694189a7529ccc2d92bf1b74bb5bf2268f46
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index b0905ba..97a7f16 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -34,6 +34,7 @@
import android.credentials.CredentialManager;
import android.credentials.CredentialProviderInfo;
import android.credentials.SetEnabledProvidersException;
+import android.credentials.flags.Flags;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.net.Uri;
@@ -108,6 +109,7 @@
private final List<ServiceInfo> mPendingServiceInfos = new ArrayList<>();
private final Handler mHandler = new Handler();
private final SettingContentObserver mSettingsContentObserver;
+ private final ImageUtils.IconResizer mIconResizer;
private @Nullable FragmentManager mFragmentManager = null;
private @Nullable Delegate mDelegate = null;
@@ -116,6 +118,7 @@
private boolean mVisibility = false;
private boolean mIsWorkProfile = false;
+ private boolean mSimulateConnectedForTests = false;
public CredentialManagerPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
@@ -129,6 +132,13 @@
new SettingContentObserver(mHandler, context.getContentResolver());
mSettingsContentObserver.register();
mSettingsPackageMonitor.register(context, context.getMainLooper(), false);
+ mIconResizer = getResizer(context);
+ }
+
+ private static ImageUtils.IconResizer getResizer(Context context) {
+ final Resources resources = context.getResources();
+ int size = (int) resources.getDimension(android.R.dimen.app_icon_size);
+ return new ImageUtils.IconResizer(size, size, resources.getDisplayMetrics());
}
private @Nullable CredentialManager getCredentialManager(Context context, boolean isTest) {
@@ -147,7 +157,7 @@
@Override
public int getAvailabilityStatus() {
- if (mCredentialManager == null) {
+ if (!isConnected()) {
return UNSUPPORTED_ON_DEVICE;
}
@@ -174,7 +184,11 @@
@VisibleForTesting
public boolean isConnected() {
- return mCredentialManager != null;
+ return mCredentialManager != null || mSimulateConnectedForTests;
+ }
+
+ public void setSimulateConnectedForTests(boolean simulateConnectedForTests) {
+ mSimulateConnectedForTests = simulateConnectedForTests;
}
/**
@@ -293,7 +307,7 @@
NewProviderConfirmationDialogFragment fragment =
newNewProviderConfirmationDialogFragment(
- serviceInfo.packageName, appName, /* setActivityResult= */ true);
+ serviceInfo.packageName, appName, /* shouldSetActivityResult= */ true);
if (fragment == null || mFragmentManager == null) {
return;
}
@@ -365,7 +379,8 @@
}
}
- private void setVisibility(boolean newVisibility) {
+ @VisibleForTesting
+ public void setVisibility(boolean newVisibility) {
if (newVisibility == mVisibility) {
return;
}
@@ -377,6 +392,11 @@
}
@VisibleForTesting
+ public boolean getVisibility() {
+ return mVisibility;
+ }
+
+ @VisibleForTesting
void setAvailableServices(
List<CredentialProviderInfo> availableServices, String flagOverrideForTest) {
mFlagOverrideForTest = flagOverrideForTest;
@@ -574,6 +594,17 @@
return enabledServices;
}
+ @VisibleForTesting
+ public @NonNull Drawable processIcon(@Nullable Drawable icon) {
+ // If we didn't get an icon then we should use the default app icon.
+ if (icon == null) {
+ icon = mPm.getDefaultActivityIcon();
+ }
+
+ Drawable providerIcon = Utils.getSafeIcon(icon);
+ return mIconResizer.createIconThumbnail(providerIcon);
+ }
+
private CombiPreference addProviderPreference(
@NonNull Context prefContext,
@NonNull CharSequence title,
@@ -584,13 +615,14 @@
final CombiPreference pref =
new CombiPreference(prefContext, mEnabledPackageNames.contains(packageName));
pref.setTitle(title);
+ pref.setLayoutResource(R.layout.preference_icon_credman);
- if (icon != null) {
+ if (Flags.newSettingsUi()) {
+ pref.setIcon(processIcon(icon));
+ } else if (icon != null) {
pref.setIcon(icon);
}
- pref.setLayoutResource(R.layout.preference_icon_credman);
-
if (subtitle != null) {
pref.setSummary(subtitle);
}
@@ -711,13 +743,13 @@
newNewProviderConfirmationDialogFragment(
@NonNull String packageName,
@NonNull CharSequence appName,
- boolean setActivityResult) {
+ boolean shouldSetActivityResult) {
DialogHost host =
new DialogHost() {
@Override
public void onDialogClick(int whichButton) {
completeEnableProviderDialogBox(
- whichButton, packageName, setActivityResult);
+ whichButton, packageName, shouldSetActivityResult);
}
@Override
@@ -728,8 +760,8 @@
}
@VisibleForTesting
- void completeEnableProviderDialogBox(
- int whichButton, String packageName, boolean setActivityResult) {
+ int completeEnableProviderDialogBox(
+ int whichButton, String packageName, boolean shouldSetActivityResult) {
int activityResult = -1;
if (whichButton == DialogInterface.BUTTON_POSITIVE) {
if (togglePackageNameEnabled(packageName)) {
@@ -746,7 +778,7 @@
final DialogFragment fragment = newErrorDialogFragment();
if (fragment == null || mFragmentManager == null) {
- return;
+ return activityResult;
}
fragment.show(mFragmentManager, ErrorDialogFragment.TAG);
@@ -758,9 +790,11 @@
// If the dialog is being shown because of the intent we should
// return a result.
- if (activityResult == -1 || !setActivityResult) {
+ if (activityResult == -1 || !shouldSetActivityResult) {
setActivityResult(activityResult);
}
+
+ return activityResult;
}
private @Nullable ErrorDialogFragment newErrorDialogFragment() {
@@ -1002,6 +1036,7 @@
}
}
+ @VisibleForTesting
public boolean isChecked() {
return mChecked;
}
diff --git a/src/com/android/settings/applications/credentials/ImageUtils.java b/src/com/android/settings/applications/credentials/ImageUtils.java
new file mode 100644
index 0000000..a7803a8
--- /dev/null
+++ b/src/com/android/settings/applications/credentials/ImageUtils.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.credentials;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.PaintDrawable;
+import android.util.DisplayMetrics;
+
+import androidx.annotation.NonNull;
+
+/** Handles resizing of images for CredMan settings. */
+public class ImageUtils {
+
+ /**
+ * Utility class to resize icons to match default icon size. Code is mostly borrowed from
+ * Launcher and ActivityPicker.
+ */
+ public static class IconResizer {
+ private final int mIconWidth;
+ private final int mIconHeight;
+
+ private final DisplayMetrics mMetrics;
+ private final Rect mOldBounds = new Rect();
+ private final Canvas mCanvas = new Canvas();
+
+ public IconResizer(int width, int height, DisplayMetrics metrics) {
+ mCanvas.setDrawFilter(
+ new PaintFlagsDrawFilter(Paint.DITHER_FLAG, Paint.FILTER_BITMAP_FLAG));
+
+ mMetrics = metrics;
+ mIconWidth = width;
+ mIconHeight = height;
+ }
+
+ /**
+ * Returns a Drawable representing the thumbnail of the specified Drawable. The size of the
+ * thumbnail is defined by the dimension android.R.dimen.app_icon_size.
+ *
+ * <p>This method is not thread-safe and should be invoked on the UI thread only.
+ *
+ * @param icon The icon to get a thumbnail of.
+ * @return A thumbnail for the specified icon or the icon itself if the thumbnail could not
+ * be created.
+ */
+ public Drawable createIconThumbnail(Drawable icon) {
+ int width = mIconWidth;
+ int height = mIconHeight;
+
+ if (icon == null) {
+ return new EmptyDrawable(width, height);
+ }
+
+ try {
+ if (icon instanceof PaintDrawable) {
+ PaintDrawable painter = (PaintDrawable) icon;
+ painter.setIntrinsicWidth(width);
+ painter.setIntrinsicHeight(height);
+ } else if (icon instanceof BitmapDrawable) {
+ // Ensure the bitmap has a density.
+ BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
+ Bitmap bitmap = bitmapDrawable.getBitmap();
+ if (bitmap.getDensity() == Bitmap.DENSITY_NONE) {
+ bitmapDrawable.setTargetDensity(mMetrics);
+ }
+ }
+ int iconWidth = icon.getIntrinsicWidth();
+ int iconHeight = icon.getIntrinsicHeight();
+
+ if (iconWidth > 0 && iconHeight > 0) {
+ if (width < iconWidth || height < iconHeight) {
+ final float ratio = (float) iconWidth / iconHeight;
+
+ if (iconWidth > iconHeight) {
+ height = (int) (width / ratio);
+ } else if (iconHeight > iconWidth) {
+ width = (int) (height * ratio);
+ }
+
+ final Bitmap.Config c =
+ icon.getOpacity() != PixelFormat.OPAQUE
+ ? Bitmap.Config.ARGB_8888
+ : Bitmap.Config.RGB_565;
+ final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
+ final Canvas canvas = mCanvas;
+ canvas.setBitmap(thumb);
+
+ // Copy the old bounds to restore them later
+ // If we were to do oldBounds = icon.getBounds(),
+ // the call to setBounds() that follows would
+ // change the same instance and we would lose the
+ // old bounds.
+ mOldBounds.set(icon.getBounds());
+ final int x = (mIconWidth - width) / 2;
+ final int y = (mIconHeight - height) / 2;
+ icon.setBounds(x, y, x + width, y + height);
+ icon.draw(canvas);
+ icon.setBounds(mOldBounds);
+
+ // Create the new resized drawable.
+ icon = createBitmapDrawable(thumb);
+ } else if (iconWidth < width && iconHeight < height) {
+ final Bitmap.Config c = Bitmap.Config.ARGB_8888;
+ final Bitmap thumb = Bitmap.createBitmap(mIconWidth, mIconHeight, c);
+ final Canvas canvas = mCanvas;
+ canvas.setBitmap(thumb);
+ mOldBounds.set(icon.getBounds());
+
+ // Set the bounds for the new icon.
+ final int x = (width - iconWidth) / 2;
+ final int y = (height - iconHeight) / 2;
+ icon.setBounds(x, y, x + iconWidth, y + iconHeight);
+ icon.draw(canvas);
+ icon.setBounds(mOldBounds);
+
+ // Create the new resized drawable.
+ icon = createBitmapDrawable(thumb);
+ }
+ }
+
+ } catch (Throwable t) {
+ icon = new EmptyDrawable(width, height);
+ }
+
+ return icon;
+ }
+
+ private BitmapDrawable createBitmapDrawable(Bitmap thumb) {
+ BitmapDrawable icon = new BitmapDrawable(thumb);
+ icon.setTargetDensity(mMetrics);
+ mCanvas.setBitmap(null);
+ return icon;
+ }
+ }
+
+ public static class EmptyDrawable extends Drawable {
+ private final int mWidth;
+ private final int mHeight;
+
+ EmptyDrawable(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mWidth;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mHeight;
+ }
+
+ @Override
+ public int getMinimumWidth() {
+ return mWidth;
+ }
+
+ @Override
+ public int getMinimumHeight() {
+ return mHeight;
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {}
+
+ @Override
+ public void setAlpha(int alpha) {}
+
+ @Override
+ public void setColorFilter(@NonNull ColorFilter cf) {}
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+ }
+}
diff --git a/tests/unit/res/drawable/credman_icon_1_1.xml b/tests/unit/res/drawable/credman_icon_1_1.xml
new file mode 100644
index 0000000..49f2d2e
--- /dev/null
+++ b/tests/unit/res/drawable/credman_icon_1_1.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#ff0000"/>
+ <size android:width="1dp" android:height="1dp" />
+</shape>
diff --git a/tests/unit/res/drawable/credman_icon_32_32.xml b/tests/unit/res/drawable/credman_icon_32_32.xml
new file mode 100644
index 0000000..2612ed2
--- /dev/null
+++ b/tests/unit/res/drawable/credman_icon_32_32.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="#ff0000"/>
+ <size android:width="128dp" android:height="128dp" />
+</shape>
diff --git a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
index 7d400ad..acf590b 100644
--- a/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/credentials/CredentialManagerPreferenceControllerTest.java
@@ -17,8 +17,10 @@
package com.android.settings.applications.credentials;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.spy;
import android.app.Activity;
@@ -27,7 +29,9 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
import android.credentials.CredentialProviderInfo;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Looper;
import android.provider.Settings;
@@ -38,6 +42,9 @@
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.settings.tests.unit.R;
import com.google.android.collect.Lists;
@@ -48,7 +55,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.Set;
@RunWith(AndroidJUnit4.class)
@@ -58,14 +64,13 @@
private PreferenceScreen mScreen;
private PreferenceCategory mCredentialsPreferenceCategory;
private CredentialManagerPreferenceController.Delegate mDelegate;
- private Optional<Integer> mReceivedResultCode;
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";
+ private static final String TEST_TITLE_APP_C = "test app C1";
private static final String PRIMARY_INTENT = "android.settings.CREDENTIAL_PROVIDER";
private static final String ALTERNATE_INTENT = "android.settings.SYNC_SETTINGS";
@@ -79,12 +84,9 @@
mCredentialsPreferenceCategory = new PreferenceCategory(mContext);
mCredentialsPreferenceCategory.setKey("credentials_test");
mScreen.addPreference(mCredentialsPreferenceCategory);
- mReceivedResultCode = Optional.empty();
mDelegate =
new CredentialManagerPreferenceController.Delegate() {
- public void setActivityResult(int resultCode) {
- mReceivedResultCode = Optional.of(resultCode);
- }
+ public void setActivityResult(int resultCode) {}
public void forceDelegateRefresh() {}
};
@@ -94,11 +96,15 @@
// Tests that getAvailabilityStatus() does not throw an exception if it's called before the
// Controller is initialized (this can happen during indexing).
public void getAvailabilityStatus_withoutInit_returnsUnavailable() {
+ if (Looper.myLooper() == null) {
+ Looper.prepare(); // needed to create the preference screen
+ }
+
CredentialManagerPreferenceController controller =
new CredentialManagerPreferenceController(
mContext, mCredentialsPreferenceCategory.getKey());
assertThat(controller.isConnected()).isFalse();
- assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+ assertThat(controller.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
@@ -106,14 +112,17 @@
CredentialManagerPreferenceController controller =
createControllerWithServices(Collections.emptyList());
assertThat(controller.isConnected()).isFalse();
- assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+ assertThat(controller.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_withServices_returnsAvailable() {
CredentialManagerPreferenceController controller =
createControllerWithServices(Lists.newArrayList(createCredentialProviderInfo()));
- assertThat(controller.isConnected()).isFalse();
+ controller.setSimulateConnectedForTests(true);
+ assertThat(controller.isConnected()).isTrue();
+ controller.setVisibility(true);
+ assertThat(controller.getVisibility()).isTrue();
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@@ -139,8 +148,11 @@
"com.android.provider2", "ClassA", "Service Title", "Summary Text");
CredentialManagerPreferenceController controller =
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
+ controller.setSimulateConnectedForTests(true);
+ assertThat(controller.isConnected()).isTrue();
+ controller.setVisibility(true);
+ assertThat(controller.getVisibility()).isTrue();
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- assertThat(controller.isConnected()).isFalse();
// Test the data is correct.
assertThat(providerInfo1.isEnabled()).isFalse();
@@ -180,8 +192,11 @@
createCredentialProviderInfo("com.android.provider4", "ClassA"),
createCredentialProviderInfo("com.android.provider5", "ClassA"),
createCredentialProviderInfo("com.android.provider6", "ClassA")));
+ controller.setSimulateConnectedForTests(true);
+ assertThat(controller.isConnected()).isTrue();
+ controller.setVisibility(true);
+ assertThat(controller.getVisibility()).isTrue();
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- assertThat(controller.isConnected()).isFalse();
// Ensure that we stay under 5 providers.
assertThat(controller.togglePackageNameEnabled("com.android.provider1")).isTrue();
@@ -246,8 +261,11 @@
"com.android.provider2", "ClassA", "Service Title", true);
CredentialManagerPreferenceController controller =
createControllerWithServices(Lists.newArrayList(providerInfo1, providerInfo2));
+ controller.setSimulateConnectedForTests(true);
+ assertThat(controller.isConnected()).isTrue();
+ controller.setVisibility(true);
+ assertThat(controller.getVisibility()).isTrue();
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE);
- assertThat(controller.isConnected()).isFalse();
// Test the data is correct.
assertThat(providerInfo1.isEnabled()).isFalse();
@@ -282,22 +300,16 @@
"test service B");
CredentialProviderInfo serviceC1 =
createCredentialProviderInfoWithAppLabel(
- TEST_PACKAGE_NAME_C,
- "CredManProviderC1",
- "test app C1",
- TEST_TITLE_SERVICE_C);
+ TEST_PACKAGE_NAME_C, "CredManProviderC1", "test app C1", TEST_TITLE_APP_C);
CredentialProviderInfo serviceC2 =
createCredentialProviderInfoWithAppLabel(
- TEST_PACKAGE_NAME_C,
- "CredManProviderC2",
- "test app C2",
- TEST_TITLE_SERVICE_C);
+ TEST_PACKAGE_NAME_C, "CredManProviderC2", "test app C2", TEST_TITLE_APP_C);
CredentialProviderInfo serviceC3 =
createCredentialProviderInfoBuilder(
TEST_PACKAGE_NAME_C,
"CredManProviderC3",
"test app C3",
- TEST_TITLE_SERVICE_C)
+ TEST_TITLE_APP_C)
.setEnabled(true)
.build();
@@ -321,7 +333,7 @@
assertThat(prefs.get(TEST_PACKAGE_NAME_B).getTitle()).isEqualTo(TEST_TITLE_APP_B);
assertThat(prefs.get(TEST_PACKAGE_NAME_B).isChecked()).isFalse();
assertThat(prefs.containsKey(TEST_PACKAGE_NAME_C)).isTrue();
- assertThat(prefs.get(TEST_PACKAGE_NAME_C).getTitle()).isEqualTo(TEST_TITLE_SERVICE_C);
+ assertThat(prefs.get(TEST_PACKAGE_NAME_C).getTitle()).isEqualTo(TEST_TITLE_APP_C);
assertThat(prefs.get(TEST_PACKAGE_NAME_C).isChecked()).isTrue();
}
@@ -347,9 +359,10 @@
Intent intent = new Intent(PRIMARY_INTENT);
intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isTrue();
- controller.completeEnableProviderDialogBox(
- DialogInterface.BUTTON_POSITIVE, packageName, true);
- assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_OK);
+ int resultCode =
+ controller.completeEnableProviderDialogBox(
+ DialogInterface.BUTTON_POSITIVE, packageName, true);
+ assertThat(resultCode).isEqualTo(Activity.RESULT_OK);
}
@Test
@@ -363,9 +376,10 @@
Intent intent = new Intent(PRIMARY_INTENT);
intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isTrue();
- controller.completeEnableProviderDialogBox(
- DialogInterface.BUTTON_NEGATIVE, packageName, true);
- assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_CANCELED);
+ int resultCode =
+ controller.completeEnableProviderDialogBox(
+ DialogInterface.BUTTON_NEGATIVE, packageName, true);
+ assertThat(resultCode).isEqualTo(Activity.RESULT_CANCELED);
}
@Test
@@ -390,9 +404,10 @@
Intent intent = new Intent(ALTERNATE_INTENT);
intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isTrue();
- controller.completeEnableProviderDialogBox(
- DialogInterface.BUTTON_POSITIVE, packageName, true);
- assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_OK);
+ int resultCode =
+ controller.completeEnableProviderDialogBox(
+ DialogInterface.BUTTON_POSITIVE, packageName, true);
+ assertThat(resultCode).isEqualTo(Activity.RESULT_OK);
}
@Test
@@ -406,9 +421,10 @@
Intent intent = new Intent(ALTERNATE_INTENT);
intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isTrue();
- controller.completeEnableProviderDialogBox(
- DialogInterface.BUTTON_NEGATIVE, packageName, true);
- assertThat(mReceivedResultCode.get()).isEqualTo(Activity.RESULT_CANCELED);
+ int resultCode =
+ controller.completeEnableProviderDialogBox(
+ DialogInterface.BUTTON_NEGATIVE, packageName, true);
+ assertThat(resultCode).isEqualTo(Activity.RESULT_CANCELED);
}
@Test
@@ -422,7 +438,6 @@
Intent intent = new Intent(Settings.ACTION_REQUEST_SET_AUTOFILL_SERVICE);
intent.setData(Uri.parse("package:" + packageName));
assertThat(controller.verifyReceivedIntent(intent)).isFalse();
- assertThat(mReceivedResultCode.isPresent()).isFalse();
}
@Test
@@ -433,7 +448,65 @@
// Use a null intent.
assertThat(controller.verifyReceivedIntent(null)).isFalse();
- assertThat(mReceivedResultCode.isPresent()).isFalse();
+ }
+
+ @Test
+ public void testIconResizer_resizeLargeImage() throws Throwable {
+ CredentialProviderInfo cpi = createCredentialProviderInfo();
+ CredentialManagerPreferenceController controller =
+ createControllerWithServices(Lists.newArrayList(cpi));
+
+ final Drawable d =
+ InstrumentationRegistry.getInstrumentation()
+ .getContext()
+ .getResources()
+ .getDrawable(R.drawable.credman_icon_32_32);
+ assertThat(d).isNotNull();
+ assertThat(d.getIntrinsicHeight() >= 0).isTrue();
+ assertThat(d.getIntrinsicWidth() >= 0).isTrue();
+
+ Drawable thumbnail = controller.processIcon(d);
+ assertThat(thumbnail).isNotNull();
+ assertThat(thumbnail.getIntrinsicHeight()).isEqualTo(getIconSize());
+ assertThat(thumbnail.getIntrinsicWidth()).isEqualTo(getIconSize());
+ }
+
+ @Test
+ public void testIconResizer_resizeNullImage() throws Throwable {
+ CredentialProviderInfo cpi = createCredentialProviderInfo();
+ CredentialManagerPreferenceController controller =
+ createControllerWithServices(Lists.newArrayList(cpi));
+
+ Drawable thumbnail = controller.processIcon(null);
+ assertThat(thumbnail).isNotNull();
+ assertThat(thumbnail.getIntrinsicHeight()).isEqualTo(getIconSize());
+ assertThat(thumbnail.getIntrinsicWidth()).isEqualTo(getIconSize());
+ }
+
+ @Test
+ public void testIconResizer_resizeSmallImage() throws Throwable {
+ CredentialProviderInfo cpi = createCredentialProviderInfo();
+ CredentialManagerPreferenceController controller =
+ createControllerWithServices(Lists.newArrayList(cpi));
+
+ final Drawable d =
+ InstrumentationRegistry.getInstrumentation()
+ .getContext()
+ .getResources()
+ .getDrawable(R.drawable.credman_icon_1_1);
+ assertThat(d).isNotNull();
+ assertThat(d.getIntrinsicHeight() >= 0).isTrue();
+ assertThat(d.getIntrinsicWidth() >= 0).isTrue();
+
+ Drawable thumbnail = controller.processIcon(null);
+ assertThat(thumbnail).isNotNull();
+ assertThat(thumbnail.getIntrinsicHeight()).isEqualTo(getIconSize());
+ assertThat(thumbnail.getIntrinsicWidth()).isEqualTo(getIconSize());
+ }
+
+ private int getIconSize() {
+ final Resources resources = mContext.getResources();
+ return (int) resources.getDimension(android.R.dimen.app_icon_size);
}
private CredentialManagerPreferenceController createControllerWithServices(
@@ -443,6 +516,10 @@
private CredentialManagerPreferenceController createControllerWithServicesAndAddServiceOverride(
List<CredentialProviderInfo> availableServices, String addServiceOverride) {
+ if (Looper.myLooper() == null) {
+ Looper.prepare(); // needed to create the preference screen
+ }
+
CredentialManagerPreferenceController controller =
new CredentialManagerPreferenceController(
mContext, mCredentialsPreferenceCategory.getKey());