diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml index d829dc46943..992af92cc9a 100644 --- a/res/xml/language_settings.xml +++ b/res/xml/language_settings.xml @@ -27,11 +27,11 @@ - + 0); + } + + @Override + public void onInputDeviceAdded(int deviceId) { + updateGameControllers(); + } + + @Override + public void onInputDeviceRemoved(int deviceId) { + updateGameControllers(); + } + + @Override + public void onInputDeviceChanged(int deviceId) { + updateGameControllers(); + } + + private void updateGameControllers() { + if (isAvailable()) { + mScreen.addPreference(mCategory); + updateState(mPreference); + } else { + if (mCategory != null) { + mScreen.removePreference(mCategory); + } + } + } +} diff --git a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java index 9fa26455b5a..351f6b5470d 100644 --- a/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java +++ b/src/com/android/settings/inputmethod/InputMethodAndLanguageSettings.java @@ -17,7 +17,6 @@ package com.android.settings.inputmethod; import android.app.Activity; -import android.app.Fragment; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -25,52 +24,38 @@ import android.content.pm.ServiceInfo; import android.hardware.input.InputDeviceIdentifier; import android.hardware.input.InputManager; import android.hardware.input.KeyboardLayout; -import android.os.Bundle; -import android.provider.Settings; -import android.provider.Settings.System; import android.speech.tts.TtsEngines; -import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.Preference; -import android.support.v7.preference.Preference.OnPreferenceClickListener; -import android.support.v7.preference.PreferenceCategory; import android.view.InputDevice; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; -import android.view.textservice.SpellCheckerInfo; -import android.view.textservice.TextServicesManager; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.settings.R; import com.android.settings.Settings.KeyboardLayoutPickerActivity; -import com.android.settings.SettingsActivity; -import com.android.settings.SettingsPreferenceFragment; -import com.android.settings.SubSettings; -import com.android.settings.UserDictionarySettings; import com.android.settings.Utils; -import com.android.settings.VoiceInputOutputSettings; +import com.android.settings.core.PreferenceController; +import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.SummaryLoader; +import com.android.settings.language.PhoneLanguagePreferenceController; +import com.android.settings.language.TtsPreferenceController; +import com.android.settings.language.UserDictionaryPreferenceController; import com.android.settings.localepicker.LocaleFeatureProvider; import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settings.search.SearchIndexableRaw; +import com.android.settingslib.drawer.CategoryKey; import java.util.ArrayList; import java.util.List; -import java.util.TreeSet; -public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment - implements InputManager.InputDeviceListener, - KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener, Indexable { +public class InputMethodAndLanguageSettings extends DashboardFragment + implements KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener, Indexable { - private static final String KEY_SPELL_CHECKERS = "spellcheckers_settings"; - private static final String KEY_PHONE_LANGUAGE = "phone_language"; - private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings"; + private static final String TAG = "IMEAndLanguageSetting"; - private PreferenceCategory mGameControllerCategory; - private Preference mLanguagePref; - private InputManager mIm; private Intent mIntentWaitingForResult; @Override @@ -79,137 +64,33 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment } @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - addPreferencesFromResource(R.xml.language_settings); - - final Activity activity = getActivity(); - - if (activity.getAssets().getLocales().length == 1) { - // No "Select language" pref if there's only one system locale available. - getPreferenceScreen().removePreference(findPreference(KEY_PHONE_LANGUAGE)); - } else { - mLanguagePref = findPreference(KEY_PHONE_LANGUAGE); - } - - new VoiceInputOutputSettings(this).onCreate(); - - mGameControllerCategory = (PreferenceCategory)findPreference( - "game_controller_settings_category"); - - // Build hard keyboard and game controller preference categories. - mIm = (InputManager)activity.getSystemService(Context.INPUT_SERVICE); - updateInputDevices(); - - // Spell Checker - final Preference spellChecker = findPreference(KEY_SPELL_CHECKERS); - if (spellChecker != null) { - // Note: KEY_SPELL_CHECKERS preference is marked as persistent="false" in XML. - InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(spellChecker); - final Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setClass(activity, SubSettings.class); - intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, - SpellCheckersSettings.class.getName()); - intent.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, - R.string.spellcheckers_settings_title); - spellChecker.setIntent(intent); - } - } - - private void updateUserDictionaryPreference(Preference userDictionaryPreference) { - final Activity activity = getActivity(); - final TreeSet localeSet = UserDictionaryList.getUserDictionaryLocalesSet(activity); - if (null == localeSet) { - // The locale list is null if and only if the user dictionary service is - // not present or disabled. In this case we need to remove the preference. - getPreferenceScreen().removePreference(userDictionaryPreference); - } else { - userDictionaryPreference.setOnPreferenceClickListener( - new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference arg0) { - // Redirect to UserDictionarySettings if the user needs only one - // language. - final Bundle extras = new Bundle(); - final Class targetFragment; - if (localeSet.size() <= 1) { - if (!localeSet.isEmpty()) { - // If the size of localeList is 0, we don't set the locale - // parameter in the extras. This will be interpreted by the - // UserDictionarySettings class as meaning - // "the current locale". Note that with the current code for - // UserDictionaryList#getUserDictionaryLocalesSet() - // the locale list always has at least one element, since it - // always includes the current locale explicitly. - // @see UserDictionaryList.getUserDictionaryLocalesSet(). - extras.putString("locale", localeSet.first()); - } - targetFragment = UserDictionarySettings.class; - } else { - targetFragment = UserDictionaryList.class; - } - startFragment(InputMethodAndLanguageSettings.this, - targetFragment.getCanonicalName(), -1, -1, extras); - return true; - } - }); - } + protected String getCategoryKey() { + return CategoryKey.CATEGORY_SYSTEM_LANGUAGE; } @Override - public void onResume() { - super.onResume(); - - mIm.registerInputDeviceListener(this, null); - - final Preference spellChecker = findPreference(KEY_SPELL_CHECKERS); - if (spellChecker != null) { - final TextServicesManager tsm = (TextServicesManager) getSystemService( - Context.TEXT_SERVICES_MANAGER_SERVICE); - if (!tsm.isSpellCheckerEnabled()) { - spellChecker.setSummary(R.string.switch_off_text); - } else { - final SpellCheckerInfo sci = tsm.getCurrentSpellChecker(); - if (sci != null) { - spellChecker.setSummary(sci.loadLabel(getPackageManager())); - } else { - spellChecker.setSummary(R.string.spell_checker_not_selected); - } - } - } - - if (mLanguagePref != null) { - final String localeNames = FeatureFactory.getFactory(getContext()) - .getLocaleFeatureProvider().getLocaleNames(); - mLanguagePref.setSummary(localeNames); - } - - updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS)); - - updateInputDevices(); + protected String getLogTag() { + return TAG; } @Override - public void onPause() { - super.onPause(); - - mIm.unregisterInputDeviceListener(this); + protected int getPreferenceScreenResId() { + return R.xml.language_settings; } @Override - public void onInputDeviceAdded(int deviceId) { - updateInputDevices(); - } + protected List getPreferenceControllers(Context context) { + final GameControllerPreferenceController gameControllerPreferenceController = + new GameControllerPreferenceController(context); + getLifecycle().addObserver(gameControllerPreferenceController); - @Override - public void onInputDeviceChanged(int deviceId) { - updateInputDevices(); - } - - @Override - public void onInputDeviceRemoved(int deviceId) { - updateInputDevices(); + final List list = new ArrayList<>(); + list.add(gameControllerPreferenceController); + list.add(new PhoneLanguagePreferenceController(context)); + list.add(new SpellCheckerPreferenceController(context)); + list.add(new UserDictionaryPreferenceController(context)); + list.add(new TtsPreferenceController(context, new TtsEngines(context))); + return list; } @Override @@ -218,21 +99,9 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment if (Utils.isMonkeyRunning()) { return false; } - if (preference instanceof SwitchPreference) { - final SwitchPreference pref = (SwitchPreference) preference; - if (pref == mGameControllerCategory.findPreference("vibrate_input_devices")) { - System.putInt(getContentResolver(), Settings.System.VIBRATE_INPUT_DEVICES, - pref.isChecked() ? 1 : 0); - return true; - } - } return super.onPreferenceTreeClick(preference); } - private void updateInputDevices() { - updateGameControllers(); - } - private void showKeyboardLayoutDialog(InputDeviceIdentifier inputDeviceIdentifier) { KeyboardLayoutDialogFragment fragment = (KeyboardLayoutDialogFragment) getFragmentManager().findFragmentByTag("keyboardLayout"); @@ -265,38 +134,12 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment } } - private void updateGameControllers() { - if (haveInputDeviceWithVibrator()) { - getPreferenceScreen().addPreference(mGameControllerCategory); - - SwitchPreference pref = (SwitchPreference) - mGameControllerCategory.findPreference("vibrate_input_devices"); - pref.setChecked(System.getInt(getContentResolver(), - Settings.System.VIBRATE_INPUT_DEVICES, 1) > 0); - } else { - getPreferenceScreen().removePreference(mGameControllerCategory); - } - } - - private static boolean haveInputDeviceWithVibrator() { - final int[] devices = InputDevice.getDeviceIds(); - for (int i = 0; i < devices.length; i++) { - InputDevice device = InputDevice.getDevice(devices[i]); - if (device != null && !device.isVirtual() && device.getVibrator().hasVibrator()) { - return true; - } - } - return false; - } - private static class SummaryProvider implements SummaryLoader.SummaryProvider { - private final Context mContext; private final SummaryLoader mSummaryLoader; private LocaleFeatureProvider mLocaleFeatureProvider; public SummaryProvider(Context context, SummaryLoader summaryLoader) { - mContext = context; mSummaryLoader = summaryLoader; mLocaleFeatureProvider = FeatureFactory.getFactory(context).getLocaleFeatureProvider(); } @@ -328,11 +171,13 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment final String screenTitle = context.getString(R.string.language_keyboard_settings_title); // Locale picker. - if (context.getAssets().getLocales().length > 1) { + final PhoneLanguagePreferenceController mLanguagePrefController = + new PhoneLanguagePreferenceController(context); + if (mLanguagePrefController.isAvailable()) { String localeNames = FeatureFactory.getFactory(context).getLocaleFeatureProvider() .getLocaleNames(); SearchIndexableRaw indexable = new SearchIndexableRaw(context); - indexable.key = KEY_PHONE_LANGUAGE; + indexable.key = mLanguagePrefController.getPreferenceKey(); indexable.title = context.getString(R.string.phone_language); indexable.summaryOn = localeNames; indexable.summaryOff = localeNames; @@ -342,7 +187,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment // Spell checker. SearchIndexableRaw indexable = new SearchIndexableRaw(context); - indexable.key = KEY_SPELL_CHECKERS; + indexable.key = SpellCheckerPreferenceController.KEY_SPELL_CHECKERS; indexable.title = context.getString(R.string.spellcheckers_settings_title); indexable.screenTitle = screenTitle; indexable.keywords = context.getString(R.string.keywords_spell_checker); @@ -465,9 +310,9 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment indexables.add(indexable); // Game controllers. - if (haveInputDeviceWithVibrator()) { + if (!new GameControllerPreferenceController(context).isAvailable()) { indexable = new SearchIndexableRaw(context); - indexable.key = "vibrate_input_devices"; + indexable.key = GameControllerPreferenceController.PREF_KEY; indexable.title = context.getString(R.string.vibrate_input_devices); indexable.summaryOn = context.getString(R.string.vibrate_input_devices_summary); indexable.summaryOff = context.getString(R.string.vibrate_input_devices_summary); diff --git a/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java b/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java new file mode 100644 index 00000000000..17d3fdcd45a --- /dev/null +++ b/src/com/android/settings/inputmethod/SpellCheckerPreferenceController.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 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.inputmethod; + +import android.content.Context; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; +import android.view.textservice.SpellCheckerInfo; +import android.view.textservice.TextServicesManager; + +import com.android.settings.R; +import com.android.settings.core.PreferenceController; + +public class SpellCheckerPreferenceController extends PreferenceController { + + public static final String KEY_SPELL_CHECKERS = "spellcheckers_settings"; + + private final TextServicesManager mTextServicesManager; + + public SpellCheckerPreferenceController(Context context) { + super(context); + mTextServicesManager = (TextServicesManager) context.getSystemService( + Context.TEXT_SERVICES_MANAGER_SERVICE); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + final Preference preference = screen.findPreference(KEY_SPELL_CHECKERS); + if (preference != null) { + InputMethodAndSubtypeUtil.removeUnnecessaryNonPersistentPreference(preference); + } + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_SPELL_CHECKERS; + } + + @Override + public void updateState(Preference preference) { + if (preference == null) { + return; + } + if (!mTextServicesManager.isSpellCheckerEnabled()) { + preference.setSummary(R.string.switch_off_text); + } else { + final SpellCheckerInfo sci = mTextServicesManager.getCurrentSpellChecker(); + if (sci != null) { + preference.setSummary(sci.loadLabel(mContext.getPackageManager())); + } else { + preference.setSummary(R.string.spell_checker_not_selected); + } + } + } +} diff --git a/src/com/android/settings/language/PhoneLanguagePreferenceController.java b/src/com/android/settings/language/PhoneLanguagePreferenceController.java new file mode 100644 index 00000000000..2b87fd958dc --- /dev/null +++ b/src/com/android/settings/language/PhoneLanguagePreferenceController.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016 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.language; + +import android.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.core.PreferenceController; +import com.android.settings.overlay.FeatureFactory; + +public class PhoneLanguagePreferenceController extends PreferenceController { + + private static final String KEY_PHONE_LANGUAGE = "phone_language"; + + public PhoneLanguagePreferenceController(Context context) { + super(context); + } + + @Override + public boolean isAvailable() { + return mContext.getAssets().getLocales().length > 1; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public void updateState(Preference preference) { + if (preference == null) { + return; + } + final String localeNames = FeatureFactory.getFactory(mContext) + .getLocaleFeatureProvider().getLocaleNames(); + preference.setSummary(localeNames); + } + + @Override + public String getPreferenceKey() { + return KEY_PHONE_LANGUAGE; + } +} diff --git a/src/com/android/settings/language/TtsPreferenceController.java b/src/com/android/settings/language/TtsPreferenceController.java new file mode 100644 index 00000000000..ffc1eb1af9e --- /dev/null +++ b/src/com/android/settings/language/TtsPreferenceController.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 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.language; + +import android.content.Context; +import android.speech.tts.TtsEngines; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.core.PreferenceController; + +public class TtsPreferenceController extends PreferenceController { + + private static final String KEY_VOICE_CATEGORY = "voice_category"; + private static final String KEY_TTS_SETTINGS = "tts_settings"; + + private final TtsEngines mTtsEngines; + + public TtsPreferenceController(Context context, TtsEngines ttsEngines) { + super(context); + mTtsEngines = ttsEngines; + } + + @Override + public boolean isAvailable() { + return !mTtsEngines.getEngines().isEmpty(); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + if (!isAvailable()) { + removePreference(screen, KEY_VOICE_CATEGORY); + } + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_TTS_SETTINGS; + } +} diff --git a/src/com/android/settings/language/UserDictionaryPreferenceController.java b/src/com/android/settings/language/UserDictionaryPreferenceController.java new file mode 100644 index 00000000000..d26761b8a20 --- /dev/null +++ b/src/com/android/settings/language/UserDictionaryPreferenceController.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2016 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.language; + +import android.app.Fragment; +import android.content.Context; +import android.os.Bundle; +import android.support.v7.preference.Preference; + +import com.android.settings.UserDictionarySettings; +import com.android.settings.core.PreferenceController; +import com.android.settings.inputmethod.UserDictionaryList; + +import java.util.TreeSet; + +public class UserDictionaryPreferenceController extends PreferenceController { + + private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings"; + + public UserDictionaryPreferenceController(Context context) { + super(context); + } + + @Override + public boolean isAvailable() { + final TreeSet localeSet = getDictionaryLocales(); + // The locale list is null if and only if the user dictionary service is + // not present or disabled. In this case we need to remove the preference. + return localeSet != null; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public String getPreferenceKey() { + return KEY_USER_DICTIONARY_SETTINGS; + } + + @Override + public void updateState(Preference preference) { + if (!isAvailable() || preference == null) { + return; + } + final TreeSet localeSet = getDictionaryLocales(); + final Bundle extras = preference.getExtras(); + final Class targetFragment; + if (localeSet.size() <= 1) { + if (!localeSet.isEmpty()) { + // If the size of localeList is 0, we don't set the locale + // parameter in the extras. This will be interpreted by the + // UserDictionarySettings class as meaning + // "the current locale". Note that with the current code for + // UserDictionaryList#getUserDictionaryLocalesSet() + // the locale list always has at least one element, since it + // always includes the current locale explicitly. + // @see UserDictionaryList.getUserDictionaryLocalesSet(). + extras.putString("locale", localeSet.first()); + } + targetFragment = UserDictionarySettings.class; + } else { + targetFragment = UserDictionaryList.class; + } + preference.setFragment(targetFragment.getCanonicalName()); + } + + protected TreeSet getDictionaryLocales() { + return UserDictionaryList.getUserDictionaryLocalesSet(mContext); + } +} diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java index e2b44738f76..578b8538e76 100644 --- a/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/SwipeToNotificationPreferenceControllerTest.java @@ -22,6 +22,7 @@ import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.support.v7.preference.TwoStatePreference; +import com.android.settings.SettingsRobolectricTestRunner; import com.android.settings.TestConfig; import org.junit.Before; @@ -30,7 +31,6 @@ import org.junit.runner.RunWith; import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowApplication; @@ -41,7 +41,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -@RunWith(RobolectricTestRunner.class) +@RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class SwipeToNotificationPreferenceControllerTest { diff --git a/tests/robotests/src/com/android/settings/inputmethod/GameControllerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/GameControllerPreferenceControllerTest.java new file mode 100644 index 00000000000..c1bd0e0c5c0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/inputmethod/GameControllerPreferenceControllerTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2016 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.inputmethod; + +import android.content.Context; +import android.hardware.input.InputManager; +import android.view.InputDevice; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class GameControllerPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private InputManager mInputManager; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private InputDevice mInputDevice; + + private GameControllerPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mContext.getSystemService(Context.INPUT_SERVICE)).thenReturn(mInputManager); + mController = new GameControllerPreferenceController(mContext); + } + + @Test + public void testLifecycle_shouldRegisterInputManager() { + mController.onResume(); + + // register is called, but unregister should not be called. + verify(mInputManager).registerInputDeviceListener(mController, null); + verify(mInputManager, never()).unregisterInputDeviceListener(mController); + + mController.onPause(); + // register is not called any more times, but unregister should be called once. + verify(mInputManager).registerInputDeviceListener(mController, null); + verify(mInputManager).unregisterInputDeviceListener(mController); + } + + @Test + public void testIsAvailable_hasDeviceWithVibrator_shouldReturnTrue() { + when(mInputManager.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mInputManager.getInputDevice(1)).thenReturn(mInputDevice); + when(mInputDevice.isVirtual()).thenReturn(false); + when(mInputDevice.getVibrator().hasVibrator()).thenReturn(true); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void testIsAvailable_hasNoVibratingDevice_shouldReturnFalse() { + when(mInputManager.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mInputManager.getInputDevice(1)).thenReturn(mInputDevice); + when(mInputDevice.isVirtual()).thenReturn(false); + when(mInputDevice.getVibrator().hasVibrator()).thenReturn(false); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testIsAvailable_hasNoPhysicalDevice_shouldReturnFalse() { + when(mInputManager.getInputDeviceIds()).thenReturn(new int[]{1}); + when(mInputManager.getInputDevice(1)).thenReturn(mInputDevice); + when(mInputDevice.isVirtual()).thenReturn(true); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testIsAvailable_hasNoDevice_shouldReturnFalse() { + when(mInputManager.getInputDeviceIds()).thenReturn(new int[]{}); + + assertThat(mController.isAvailable()).isFalse(); + } +} diff --git a/tests/robotests/src/com/android/settings/inputmethod/SpellCheckerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/SpellCheckerPreferenceControllerTest.java new file mode 100644 index 00000000000..78c05901d15 --- /dev/null +++ b/tests/robotests/src/com/android/settings/inputmethod/SpellCheckerPreferenceControllerTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 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.inputmethod; + +import android.content.Context; +import android.support.v7.preference.Preference; +import android.view.textservice.SpellCheckerInfo; +import android.view.textservice.TextServicesManager; + +import com.android.settings.R; +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class SpellCheckerPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private TextServicesManager mTextServicesManager; + private Context mAppContext; + private Preference mPreference; + private SpellCheckerPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mAppContext = ShadowApplication.getInstance().getApplicationContext(); + when(mContext.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE)) + .thenReturn(mTextServicesManager); + mPreference = new Preference(mAppContext); + mController = new SpellCheckerPreferenceController(mContext); + } + + @Test + public void updateState_NoSpellerChecker_shouldSetSummaryToDefault() { + when(mTextServicesManager.isSpellCheckerEnabled()).thenReturn(true); + when(mTextServicesManager.getCurrentSpellChecker()).thenReturn(null); + + mController.updateState(mPreference); + + assertThat(mPreference.getSummary()) + .isEqualTo(mAppContext.getString(R.string.spell_checker_not_selected)); + } + + @Test + public void updateState_spellerCheckerDisabled_shouldSetSummaryToDisabledText() { + when(mTextServicesManager.isSpellCheckerEnabled()).thenReturn(false); + + mController.updateState(mPreference); + + assertThat(mPreference.getSummary()) + .isEqualTo(mAppContext.getString(R.string.switch_off_text)); + } + + @Test + public void updateState_hasSpellerChecker_shouldSetSummaryToAppName() { + final String spellCheckerAppLabel = "test"; + final SpellCheckerInfo sci = mock(SpellCheckerInfo.class); + when(mTextServicesManager.isSpellCheckerEnabled()).thenReturn(true); + when(mTextServicesManager.getCurrentSpellChecker()).thenReturn(sci); + when(sci.loadLabel(mContext.getPackageManager())).thenReturn(spellCheckerAppLabel); + + mController.updateState(mPreference); + + assertThat(mPreference.getSummary()).isEqualTo(spellCheckerAppLabel); + } +} diff --git a/tests/robotests/src/com/android/settings/language/PhoneLanguagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/language/PhoneLanguagePreferenceControllerTest.java new file mode 100644 index 00000000000..e7367bb8392 --- /dev/null +++ b/tests/robotests/src/com/android/settings/language/PhoneLanguagePreferenceControllerTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2016 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.language; + +import android.content.Context; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.testutils.FakeFeatureFactory; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class PhoneLanguagePreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private Preference mPreference; + private FakeFeatureFactory mFeatureFactory; + private PhoneLanguagePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory.setupForTest(mContext); + mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); + mController = new PhoneLanguagePreferenceController(mContext); + } + + @Test + public void testIsAvailable_hasMultipleLocales_shouldReturnTrue() { + when(mContext.getAssets().getLocales()).thenReturn(new String[]{"en", "de"}); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void testIsAvailable_hasSingleLocales_shouldReturnFalse() { + when(mContext.getAssets().getLocales()).thenReturn(new String[]{"en"}); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testUpdateState_shouldUpdateSummary() { + final String testSummary = "test"; + when(mFeatureFactory.localeFeatureProvider.getLocaleNames()).thenReturn(testSummary); + + mController.updateState(mPreference); + + verify(mPreference).setSummary(testSummary); + } +} diff --git a/tests/robotests/src/com/android/settings/language/TtsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/language/TtsPreferenceControllerTest.java new file mode 100644 index 00000000000..0e4178413e1 --- /dev/null +++ b/tests/robotests/src/com/android/settings/language/TtsPreferenceControllerTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2016 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.language; + +import android.content.Context; +import android.speech.tts.TextToSpeech; +import android.speech.tts.TtsEngines; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class TtsPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private TtsEngines mTtsEngines; + @Mock + private PreferenceScreen mScreen; + + private TtsPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mController = new TtsPreferenceController(mContext, mTtsEngines); + } + + @Test + public void testIsAvailable_ttsEngineEmpty_shouldReturnFalse() { + + // Not available when there is no engine. + when(mTtsEngines.getEngines()).thenReturn(new ArrayList<>()); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testIsAvailable_ttsEngineInstalled_shouldReturnTrue() { + final List infolist = new ArrayList<>(); + infolist.add(mock(TextToSpeech.EngineInfo.class)); + when(mTtsEngines.getEngines()).thenReturn(infolist); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void displayPreference_notAvailable_shouldRemoveCategory() { + when(mScreen.findPreference(anyString())).thenReturn(mock(Preference.class)); + + mController.displayPreference(mScreen); + + // Remove both category and preference. + verify(mScreen, times(2)).removePreference(any(Preference.class)); + } +} diff --git a/tests/robotests/src/com/android/settings/language/UserDictionaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/language/UserDictionaryPreferenceControllerTest.java new file mode 100644 index 00000000000..d2032ed4400 --- /dev/null +++ b/tests/robotests/src/com/android/settings/language/UserDictionaryPreferenceControllerTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2016 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.language; + +import android.content.Context; +import android.speech.tts.TtsEngines; +import android.support.v7.preference.Preference; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.UserDictionarySettings; +import com.android.settings.inputmethod.UserDictionaryList; +import com.android.settings.testutils.FakeFeatureFactory; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import java.util.TreeSet; + +import static com.google.common.truth.Truth.assertThat; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class UserDictionaryPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + @Mock + private TtsEngines mTtsEngines; + private Preference mPreference; + private TestController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory.setupForTest(mContext); + mController = new TestController(mContext); + mPreference = new Preference(ShadowApplication.getInstance().getApplicationContext()); + } + + @Test + public void testIsAvailable_noLocale_shouldReturnFalse() { + mController.mLocales = null; + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void testIsAvailable_hasLocale_shouldReturnTrue() { + mController.mLocales.add("en"); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void updateState_noLocale_setUserDictionarySettingsAsFragment() { + mController.updateState(mPreference); + + assertThat(mPreference.getFragment()) + .isEqualTo(UserDictionarySettings.class.getCanonicalName()); + } + + @Test + public void updateState_singleLocale_setUserDictionarySettingsAsFragment_setLocaleInExtra() { + mController.mLocales.add("en"); + + mController.updateState(mPreference); + + assertThat(mPreference.getFragment()) + .isEqualTo(UserDictionarySettings.class.getCanonicalName()); + assertThat(mPreference.getExtras().getString("locale")) + .isEqualTo("en"); + } + + @Test + public void updateState_multiLocale_setUserDictionaryListAsFragment() { + mController.mLocales.add("en"); + mController.mLocales.add("de"); + mController.updateState(mPreference); + + assertThat(mPreference.getFragment()) + .isEqualTo(UserDictionaryList.class.getCanonicalName()); + } + + /** + * Fake Controller that overrides getDictionaryLocales to make testing the rest of stuff easier. + */ + private class TestController extends UserDictionaryPreferenceController { + + private TreeSet mLocales = new TreeSet<>(); + + @Override + protected TreeSet getDictionaryLocales() { + return mLocales; + } + + public TestController(Context context) { + super(context); + } + } + +}