Merge "Fix disabled WebView packages being shown as enabled in Dev Setting."

This commit is contained in:
TreeHugger Robot
2017-03-08 18:39:02 +00:00
committed by Android (Google) Code Review
4 changed files with 97 additions and 32 deletions

View File

@@ -35,8 +35,6 @@ public class DefaultAppInfo {
public final ComponentName componentName; public final ComponentName componentName;
public final PackageItemInfo packageItemInfo; public final PackageItemInfo packageItemInfo;
public final String summary; public final String summary;
// Description for why this item is disabled, if null, the item is enabled.
public final String disabledDescription;
public final boolean enabled; public final boolean enabled;
public DefaultAppInfo(int uid, ComponentName cn) { public DefaultAppInfo(int uid, ComponentName cn) {
@@ -52,21 +50,19 @@ public class DefaultAppInfo {
userId = uid; userId = uid;
componentName = cn; componentName = cn;
this.summary = summary; this.summary = summary;
this.disabledDescription = null;
this.enabled = enabled; this.enabled = enabled;
} }
public DefaultAppInfo(PackageItemInfo info, String description) { public DefaultAppInfo(PackageItemInfo info, String summary, boolean enabled) {
userId = UserHandle.myUserId(); userId = UserHandle.myUserId();
packageItemInfo = info; packageItemInfo = info;
componentName = null; componentName = null;
summary = null; this.summary = summary;
this.disabledDescription = description; this.enabled = enabled;
enabled = true;
} }
public DefaultAppInfo(PackageItemInfo info) { public DefaultAppInfo(PackageItemInfo info) {
this(info, null); this(info, null /* summary */, true /* enabled */);
} }
public CharSequence loadLabel(PackageManager pm) { public CharSequence loadLabel(PackageManager pm) {

View File

@@ -116,26 +116,9 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
screen.addPreference(nonePref); screen.addPreference(nonePref);
} }
for (Map.Entry<String, DefaultAppInfo> app : mCandidates.entrySet()) { for (Map.Entry<String, DefaultAppInfo> app : mCandidates.entrySet()) {
final RadioButtonPreference pref = new RadioButtonPreference(getPrefContext()); RadioButtonPreference pref = new RadioButtonPreference(getPrefContext());
final String appKey = app.getKey(); configurePreferenceFromAppInfo(
final DefaultAppInfo info = app.getValue(); pref, app.getKey(), app.getValue(), defaultAppKey, systemDefaultAppKey);
pref.setTitle(info.loadLabel(mPm.getPackageManager()));
pref.setIcon(info.loadIcon(mPm.getPackageManager()));
pref.setKey(appKey);
if (TextUtils.equals(defaultAppKey, appKey)) {
pref.setChecked(true);
}
if (TextUtils.equals(systemDefaultAppKey, appKey)) {
pref.setSummary(R.string.system_app);
} else if (!TextUtils.isEmpty(info.summary)) {
pref.setSummary(info.summary);
}
if (!TextUtils.isEmpty(app.getValue().disabledDescription)) {
pref.setEnabled(false);
pref.setSummary(app.getValue().disabledDescription);
}
pref.setEnabled(info.enabled);
pref.setOnClickListener(this);
screen.addPreference(pref); screen.addPreference(pref);
} }
mayCheckOnlyRadioButton(); mayCheckOnlyRadioButton();
@@ -259,4 +242,22 @@ public abstract class DefaultAppPickerFragment extends InstrumentedPreferenceFra
} }
} }
@VisibleForTesting
public RadioButtonPreference configurePreferenceFromAppInfo(RadioButtonPreference pref,
String appKey, DefaultAppInfo info, String defaultAppKey, String systemDefaultAppKey) {
pref.setTitle(info.loadLabel(mPm.getPackageManager()));
pref.setIcon(info.loadIcon(mPm.getPackageManager()));
pref.setKey(appKey);
if (TextUtils.equals(defaultAppKey, appKey)) {
pref.setChecked(true);
}
if (TextUtils.equals(systemDefaultAppKey, appKey)) {
pref.setSummary(R.string.system_app);
} else if (!TextUtils.isEmpty(info.summary)) {
pref.setSummary(info.summary);
}
pref.setEnabled(info.enabled);
pref.setOnClickListener(this);
return pref;
}
} }

View File

@@ -24,6 +24,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.Context; import android.content.Context;
import android.support.annotation.VisibleForTesting; import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
@@ -58,7 +59,7 @@ public class WebViewAppPicker extends DefaultAppPickerFragment {
List<ApplicationInfo> pkgs = List<ApplicationInfo> pkgs =
getWebViewUpdateServiceWrapper().getValidWebViewApplicationInfos(getContext()); getWebViewUpdateServiceWrapper().getValidWebViewApplicationInfos(getContext());
for (ApplicationInfo ai : pkgs) { for (ApplicationInfo ai : pkgs) {
packageInfoList.add(new DefaultAppInfo(ai, packageInfoList.add(createDefaultAppInfo(ai,
getDisabledReason(getWebViewUpdateServiceWrapper(), getDisabledReason(getWebViewUpdateServiceWrapper(),
getContext(), ai.packageName))); getContext(), ai.packageName)));
} }
@@ -92,7 +93,6 @@ public class WebViewAppPicker extends DefaultAppPickerFragment {
} }
} }
private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() { private WebViewUpdateServiceWrapper createDefaultWebViewUpdateServiceWrapper() {
return new WebViewUpdateServiceWrapper(); return new WebViewUpdateServiceWrapper();
} }
@@ -107,6 +107,13 @@ public class WebViewAppPicker extends DefaultAppPickerFragment {
return MetricsEvent.WEBVIEW_IMPLEMENTATION; return MetricsEvent.WEBVIEW_IMPLEMENTATION;
} }
@VisibleForTesting
DefaultAppInfo createDefaultAppInfo(
ApplicationInfo applicationInfo, String disabledReason) {
return new DefaultAppInfo(applicationInfo, disabledReason,
TextUtils.isEmpty(disabledReason) /* enabled */);
}
/** /**
* Returns the reason why a package cannot be used as WebView implementation. * Returns the reason why a package cannot be used as WebView implementation.
* This is either because of it being disabled, uninstalled, or hidden for any user. * This is either because of it being disabled, uninstalled, or hidden for any user.

View File

@@ -35,11 +35,13 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.os.UserManager; import android.os.UserManager;
import android.support.v7.preference.PreferenceManager;
import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig; import com.android.settings.TestConfig;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settings.applications.PackageManagerWrapper; import com.android.settings.applications.PackageManagerWrapper;
import com.android.settings.applications.defaultapps.DefaultAppInfo;
import com.android.settings.widget.RadioButtonPreference;
import java.util.Arrays; import java.util.Arrays;
@@ -51,6 +53,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment; import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class) @RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -66,7 +69,7 @@ public class WebViewAppPickerTest {
private Activity mActivity; private Activity mActivity;
@Mock @Mock
private UserManager mUserManager; private UserManager mUserManager;
@Mock @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PackageManagerWrapper mPackageManager; private PackageManagerWrapper mPackageManager;
private WebViewAppPicker mPicker; private WebViewAppPicker mPicker;
@@ -89,6 +92,8 @@ public class WebViewAppPickerTest {
doNothing().when(mPicker).updateCheckedState(any()); doNothing().when(mPicker).updateCheckedState(any());
doReturn(mActivity).when(mPicker).getActivity(); doReturn(mActivity).when(mPicker).getActivity();
ReflectionHelpers.setField(mPicker, "mPm", mPackageManager);
mWvusWrapper = mock(WebViewUpdateServiceWrapper.class); mWvusWrapper = mock(WebViewUpdateServiceWrapper.class);
mPicker.setWebViewUpdateServiceWrapper(mWvusWrapper); mPicker.setWebViewUpdateServiceWrapper(mWvusWrapper);
} }
@@ -151,6 +156,62 @@ public class WebViewAppPickerTest {
verify(mWvusWrapper, times(1)).showInvalidChoiceToast(any()); verify(mWvusWrapper, times(1)).showInvalidChoiceToast(any());
} }
@Test
public void testDisabledPackageShownAsDisabled() {
String disabledReason = "disabled";
DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(
createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
mPicker.configurePreferenceFromAppInfo(mockPreference,
DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
verify(mockPreference, times(1)).setEnabled(eq(false));
verify(mockPreference, never()).setEnabled(eq(true));
}
@Test
public void testEnabledPackageShownAsEnabled() {
String disabledReason = "";
DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(
createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
mPicker.configurePreferenceFromAppInfo(mockPreference,
DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
verify(mockPreference, times(1)).setEnabled(eq(true));
verify(mockPreference, never()).setEnabled(eq(false));
}
@Test
public void testDisabledPackageShowsDisabledReasonSummary() {
String disabledReason = "disabled";
DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(
createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
mPicker.configurePreferenceFromAppInfo(mockPreference,
DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
verify(mockPreference, times(1)).setSummary(eq(disabledReason));
// Ensure we haven't called setSummary several times.
verify(mockPreference, times(1)).setSummary(any());
}
@Test
public void testEnabledPackageShowsEmptySummary() {
String disabledReason = null;
DefaultAppInfo webviewAppInfo = mPicker.createDefaultAppInfo(
createApplicationInfo(DEFAULT_PACKAGE_NAME), disabledReason);
RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
mPicker.configurePreferenceFromAppInfo(mockPreference,
DEFAULT_PACKAGE_NAME, webviewAppInfo, null, null);
verify(mockPreference, never()).setSummary(any());
}
@Test @Test
public void testFinishIfNotAdmin() { public void testFinishIfNotAdmin() {
doReturn(false).when(mUserManager).isAdminUser(); doReturn(false).when(mUserManager).isAdminUser();