From d984e90b63eef8a372012edeb429bf100c8a8ebf Mon Sep 17 00:00:00 2001 From: "Philip P. Moltmann" Date: Mon, 24 Apr 2017 16:13:21 -0700 Subject: [PATCH] Don't show autofill settings if not enabled The non-indexable keys of language-and-input on my angler are: game_controller_settings_category, gesture_assist, gesture_double_tap_screen, default_autofill Fixes: 35956220 Test: Disabled auto-fill and looked at settings: did not find autofill button and could not find auto-fill in search Settings robolectric test Merged-In: I0923e707422d1b1de5153a63fa3a5fe4773c055d Change-Id: I0923e707422d1b1de5153a63fa3a5fe4773c055d --- .../applications/AutofillManagerWrapper.java | 41 +++++++++++++++++ .../AutofillManagerWrapperImpl.java | 45 +++++++++++++++++++ .../DefaultAutofillPreferenceController.java | 11 ++++- .../language/LanguageAndInputSettings.java | 30 ++++++++++--- ...faultAutofillPreferenceControllerTest.java | 19 +++++++- .../LanguageAndInputSettingsTest.java | 4 ++ 6 files changed, 141 insertions(+), 9 deletions(-) create mode 100644 src/com/android/settings/applications/AutofillManagerWrapper.java create mode 100644 src/com/android/settings/applications/AutofillManagerWrapperImpl.java diff --git a/src/com/android/settings/applications/AutofillManagerWrapper.java b/src/com/android/settings/applications/AutofillManagerWrapper.java new file mode 100644 index 00000000000..04091b01d4c --- /dev/null +++ b/src/com/android/settings/applications/AutofillManagerWrapper.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 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; + +import android.view.autofill.AutofillManager; + +/** + * This interface replicates a subset of the android.view.autofill.AutofillManager (AFM). The + * interface exists so that we can use a thin wrapper around the AFM in production code and a mock + * in tests. We cannot directly mock or shadow the AFM, because some of the methods we rely on are + * newer than the API version supported by Robolectric. + */ +public interface AutofillManagerWrapper { + /** + * Calls {@code AutofillManager.hasAutofillFeature()}. + * + * @see AutofillManager#hasAutofillFeature + */ + public boolean hasAutofillFeature(); + + /** + * Calls {@code AutofillManager.isAutofillSupported()}. + * + * @see AutofillManager#isAutofillSupported + */ + public boolean isAutofillSupported(); +} diff --git a/src/com/android/settings/applications/AutofillManagerWrapperImpl.java b/src/com/android/settings/applications/AutofillManagerWrapperImpl.java new file mode 100644 index 00000000000..9dd1b33b80b --- /dev/null +++ b/src/com/android/settings/applications/AutofillManagerWrapperImpl.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2017 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; + +import android.view.autofill.AutofillManager; + +public class AutofillManagerWrapperImpl implements AutofillManagerWrapper { + private final AutofillManager mAfm; + + public AutofillManagerWrapperImpl(AutofillManager afm) { + mAfm = afm; + } + + @Override + public boolean hasAutofillFeature() { + if (mAfm == null) { + return false; + } + + return mAfm.hasAutofillFeature(); + } + + @Override + public boolean isAutofillSupported() { + if (mAfm == null) { + return false; + } + + return mAfm.isAutofillSupported(); + } +} diff --git a/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceController.java index 161f2df4d80..1fd10ffea72 100644 --- a/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceController.java +++ b/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceController.java @@ -21,16 +21,25 @@ import android.content.Context; import android.content.Intent; import android.provider.Settings; import android.text.TextUtils; +import android.view.autofill.AutofillManager; + +import com.android.settings.applications.AutofillManagerWrapper; +import com.android.settings.applications.AutofillManagerWrapperImpl; public class DefaultAutofillPreferenceController extends DefaultAppPreferenceController { + private AutofillManagerWrapper mAutofillManager; public DefaultAutofillPreferenceController(Context context) { super(context); + + mAutofillManager = new AutofillManagerWrapperImpl( + mContext.getSystemService(AutofillManager.class)); } @Override public boolean isAvailable() { - return true; + return mAutofillManager.hasAutofillFeature() + && mAutofillManager.isAutofillSupported(); } @Override diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java index 86ce118fb98..19999707f69 100644 --- a/src/com/android/settings/language/LanguageAndInputSettings.java +++ b/src/com/android/settings/language/LanguageAndInputSettings.java @@ -23,6 +23,8 @@ import android.os.UserHandle; import android.provider.SearchIndexableResource; import android.provider.Settings; import android.speech.tts.TtsEngines; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.view.inputmethod.InputMethodInfo; @@ -81,7 +83,16 @@ public class LanguageAndInputSettings extends DashboardFragment { @Override protected List getPreferenceControllers(Context context) { - final Lifecycle lifecycle = getLifecycle(); + if (mAmbientDisplayConfig == null) { + mAmbientDisplayConfig = new AmbientDisplayConfiguration(context); + } + + return buildPreferenceControllers(context, getLifecycle(), mAmbientDisplayConfig); + } + + private static List buildPreferenceControllers(@NonNull Context context, + @Nullable Lifecycle lifecycle, + @NonNull AmbientDisplayConfiguration ambientDisplayConfiguration) { final List controllers = new ArrayList<>(); // Language controllers.add(new PhoneLanguagePreferenceController(context)); @@ -93,11 +104,10 @@ public class LanguageAndInputSettings extends DashboardFragment { controllers.add(new PhysicalKeyboardPreferenceController(context, lifecycle)); final GameControllerPreferenceController gameControllerPreferenceController = new GameControllerPreferenceController(context); - lifecycle.addObserver(gameControllerPreferenceController); - - if (mAmbientDisplayConfig == null) { - mAmbientDisplayConfig = new AmbientDisplayConfiguration(context); + if (lifecycle != null) { + lifecycle.addObserver(gameControllerPreferenceController); } + controllers.add(gameControllerPreferenceController); // Gestures controllers.add(new AssistGesturePreferenceController(context, lifecycle)); @@ -105,9 +115,9 @@ public class LanguageAndInputSettings extends DashboardFragment { controllers.add(new DoubleTwistPreferenceController(context, lifecycle)); controllers.add(new DoubleTapPowerPreferenceController(context, lifecycle)); controllers.add(new PickupGesturePreferenceController( - context, lifecycle, mAmbientDisplayConfig, UserHandle.myUserId())); + context, lifecycle, ambientDisplayConfiguration, UserHandle.myUserId())); controllers.add(new DoubleTapScreenPreferenceController( - context, lifecycle, mAmbientDisplayConfig, UserHandle.myUserId())); + context, lifecycle, ambientDisplayConfiguration, UserHandle.myUserId())); controllers.add(new DefaultAutofillPreferenceController(context)); return controllers; } @@ -163,5 +173,11 @@ public class LanguageAndInputSettings extends DashboardFragment { sir.xmlResId = R.xml.language_and_input; return Arrays.asList(sir); } + + @Override + public List getPreferenceControllers(Context context) { + return buildPreferenceControllers(context, null, + new AmbientDisplayConfiguration(context)); + } }; } diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceControllerTest.java index 74612e38de2..a7912c4923a 100644 --- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultAutofillPreferenceControllerTest.java @@ -22,10 +22,12 @@ import android.content.pm.PackageManager; import android.os.UserManager; import android.provider.Settings; import android.support.v7.preference.Preference; +import android.view.autofill.AutofillManager; import com.android.settings.R; import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; +import com.android.settings.applications.AutofillManagerWrapper; import com.android.settings.applications.PackageManagerWrapper; import org.junit.Before; @@ -54,6 +56,8 @@ public class DefaultAutofillPreferenceControllerTest { private UserManager mUserManager; @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PackageManagerWrapper mPackageManager; + @Mock + private AutofillManagerWrapper mAutofillManager; private DefaultAutofillPreferenceController mController; @@ -64,10 +68,23 @@ public class DefaultAutofillPreferenceControllerTest { mController = spy(new DefaultAutofillPreferenceController(mContext)); ReflectionHelpers.setField(mController, "mPackageManager", mPackageManager); + ReflectionHelpers.setField(mController, "mAutofillManager", mAutofillManager); } @Test - public void isAlwaysAvailable() { + public void isAvailableIfHasFeatureAndSupported() { + when(mContext.getSystemService(AutofillManager.class)).thenReturn(null); + assertThat(mController.isAvailable()).isFalse(); + + when(mAutofillManager.hasAutofillFeature()).thenReturn(false); + assertThat(mController.isAvailable()).isFalse(); + + when(mAutofillManager.hasAutofillFeature()).thenReturn(true); + when(mAutofillManager.isAutofillSupported()).thenReturn(false); + assertThat(mController.isAvailable()).isFalse(); + + when(mAutofillManager.hasAutofillFeature()).thenReturn(true); + when(mAutofillManager.isAutofillSupported()).thenReturn(true); assertThat(mController.isAvailable()).isTrue(); } diff --git a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java index 643e3051e7b..8c23cbfa94f 100644 --- a/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java +++ b/tests/robotests/src/com/android/settings/language/LanguageAndInputSettingsTest.java @@ -31,6 +31,7 @@ import android.content.pm.PackageManager; import android.hardware.input.InputManager; import android.os.UserManager; import android.provider.Settings; +import android.view.autofill.AutofillManager; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.textservice.TextServicesManager; @@ -72,6 +73,8 @@ public class LanguageAndInputSettingsTest { private DevicePolicyManager mDpm; @Mock private InputMethodManager mInputMethodManager; + @Mock + private AutofillManager mAutofillManager; private TestFragment mFragment; @Before @@ -84,6 +87,7 @@ public class LanguageAndInputSettingsTest { .thenReturn(mock(TextServicesManager.class)); when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn(mDpm); when(mContext.getSystemService(Context.INPUT_METHOD_SERVICE)).thenReturn(mImm); + when(mContext.getSystemService(AutofillManager.class)).thenReturn(mAutofillManager); mFragment = new TestFragment(mContext); }