diff --git a/OWNERS b/OWNERS index c2ff69265da..cc33111f011 100644 --- a/OWNERS +++ b/OWNERS @@ -12,6 +12,7 @@ stanleytfwang@google.com sunnyshao@google.com tmfang@google.com yantingyang@google.com +ykhung@google.com # Emergency only hanxu@google.com diff --git a/res/values/strings.xml b/res/values/strings.xml index f397b478562..cc7690e2c1e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -606,7 +606,7 @@ Set time automatically - Set time zone automatically + Set automatically Use locale default @@ -4254,7 +4254,7 @@ Location services for work - Use location to set time zone + Use location Device location needed @@ -4280,6 +4280,8 @@ Location time zone detection changes are not allowed + + Location may be used to set time zone Wi\u2011Fi & mobile network location @@ -6835,6 +6837,14 @@ behalf. It comes from the %s application. Enable the use of this service? + + + On-device recognition settings + + On-device recognition + + On-device speech recognition + Preferred engine diff --git a/res/xml/date_time_prefs.xml b/res/xml/date_time_prefs.xml index a0801f9df1b..e3d0a7e2e23 100644 --- a/res/xml/date_time_prefs.xml +++ b/res/xml/date_time_prefs.xml @@ -45,7 +45,6 @@ diff --git a/res/xml/language_and_input.xml b/res/xml/language_and_input.xml index 770a862f3d1..64b5003bcef 100644 --- a/res/xml/language_and_input.xml +++ b/res/xml/language_and_input.xml @@ -63,6 +63,13 @@ android:title="@string/voice_input_settings_title" android:fragment="com.android.settings.language.DefaultVoiceInputPicker" /> + + = PROGRESS_BAR_MAX) { mProgressBar.postDelayed(mDelayedFinishRunnable, getFinishDelay()); } diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java index 7e6eefe2e41..ea8a5f560f9 100644 --- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java @@ -25,9 +25,9 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; import com.android.settings.R; +import com.android.settings.SettingsActivity; import com.android.settings.core.SettingsUIDeviceConfig; import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.password.PasswordUtils; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.slices.SlicePreferenceController; import com.android.settingslib.search.SearchIndexable; @@ -71,8 +71,8 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { super.onAttach(context); final boolean nearbyEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SETTINGS_UI, SettingsUIDeviceConfig.BT_NEAR_BY_SUGGESTION_ENABLED, true); - String callingAppPackageName = PasswordUtils.getCallingAppPackageName( - getActivity().getActivityToken()); + String callingAppPackageName = ((SettingsActivity) getActivity()) + .getInitialCallingPackage(); String action = getIntent() != null ? getIntent().getAction() : ""; if (DEBUG) { Log.d(TAG, "onAttach() calling package name is : " + callingAppPackageName diff --git a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java index 93e6d0a9644..36cbc9e0b80 100644 --- a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java +++ b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java @@ -174,7 +174,7 @@ public class LocationTimeZoneDetectionPreferenceController // If capability is possessed, toggle status already tells all the information needed. // Returning null will make previous text stick on toggling. // See AbstractPreferenceController#refreshSummary. - return ""; + summaryResId = R.string.location_time_zone_detection_auto_is_on; } else { // This is unexpected: getAvailabilityStatus() should ensure that the UI element isn't // even shown for known cases, or the capability is unknown. diff --git a/src/com/android/settings/language/LanguageAndInputSettings.java b/src/com/android/settings/language/LanguageAndInputSettings.java index 71b48f9b89f..2d80da59447 100644 --- a/src/com/android/settings/language/LanguageAndInputSettings.java +++ b/src/com/android/settings/language/LanguageAndInputSettings.java @@ -50,6 +50,7 @@ public class LanguageAndInputSettings extends DashboardFragment { private static final String KEY_KEYBOARDS_CATEGORY = "keyboards_category"; private static final String KEY_SPEECH_CATEGORY = "speech_category"; + private static final String KEY_ON_DEVICE_RECOGNITION = "odsr_settings"; private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary"; private static final String KEY_POINTER_CATEGORY = "pointer_category"; @@ -123,11 +124,21 @@ public class LanguageAndInputSettings extends DashboardFragment { new DefaultVoiceInputPreferenceController(context, lifecycle); final TtsPreferenceController ttsPreferenceController = new TtsPreferenceController(context, KEY_TEXT_TO_SPEECH); + final OnDeviceRecognitionPreferenceController onDeviceRecognitionPreferenceController = + new OnDeviceRecognitionPreferenceController(context, KEY_ON_DEVICE_RECOGNITION); + controllers.add(defaultVoiceInputPreferenceController); controllers.add(ttsPreferenceController); - controllers.add(new PreferenceCategoryController(context, - KEY_SPEECH_CATEGORY).setChildren( - Arrays.asList(defaultVoiceInputPreferenceController, ttsPreferenceController))); + List speechCategoryChildren = new ArrayList<>( + List.of(defaultVoiceInputPreferenceController, ttsPreferenceController)); + + if (onDeviceRecognitionPreferenceController.isAvailable()) { + controllers.add(onDeviceRecognitionPreferenceController); + speechCategoryChildren.add(onDeviceRecognitionPreferenceController); + } + + controllers.add(new PreferenceCategoryController(context, KEY_SPEECH_CATEGORY) + .setChildren(speechCategoryChildren)); // Pointer final PointerSpeedController pointerController = new PointerSpeedController(context); diff --git a/src/com/android/settings/language/OnDeviceRecognitionPreferenceController.java b/src/com/android/settings/language/OnDeviceRecognitionPreferenceController.java new file mode 100644 index 00000000000..318663957c9 --- /dev/null +++ b/src/com/android/settings/language/OnDeviceRecognitionPreferenceController.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2022 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.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import androidx.annotation.Nullable; +import androidx.preference.Preference; + +import com.android.internal.R; +import com.android.settings.core.BasePreferenceController; + +import java.util.ArrayList; +import java.util.Optional; + +/** Controller of the On-device recognition preference. */ +public class OnDeviceRecognitionPreferenceController extends BasePreferenceController { + + private static final String TAG = "OnDeviceRecognitionPreferenceController"; + + private Optional mIntent; + + public OnDeviceRecognitionPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + if (mIntent == null) { + mIntent = Optional.ofNullable(onDeviceRecognitionIntent()); + } + return mIntent.isPresent() + ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (mIntent != null && mIntent.isPresent()) { + preference.setIntent(mIntent.get()); + } + } + + /** + * Create an {@link Intent} for the activity in the default on-device recognizer service if + * there is a properly defined speech recognition xml meta-data for that service. + * + * @return {@link Intent} if the proper activity is fount, {@code null} otherwise. + */ + @Nullable + private Intent onDeviceRecognitionIntent() { + final String resString = mContext.getString( + R.string.config_defaultOnDeviceSpeechRecognitionService); + + if (resString == null) { + Log.v(TAG, "No on-device recognizer, intent not created."); + return null; + } + + final ComponentName defaultOnDeviceRecognizerComponentName = + ComponentName.unflattenFromString(resString); + + if (defaultOnDeviceRecognizerComponentName == null) { + Log.v(TAG, "Invalid on-device recognizer string format, intent not created."); + return null; + } + + final ArrayList validRecognitionServices = + VoiceInputHelper.validRecognitionServices(mContext); + + if (validRecognitionServices.isEmpty()) { + Log.v(TAG, "No speech recognition services" + + "with proper `recognition-service` meta-data found."); + return null; + } + + // Filter the recognizer services which are in the same package as the default on-device + // speech recognizer and have a settings activity defined in the meta-data. + final ArrayList validOnDeviceRecognitionServices = + new ArrayList<>(); + for (VoiceInputHelper.RecognizerInfo recognizerInfo: validRecognitionServices) { + if (!defaultOnDeviceRecognizerComponentName.getPackageName().equals( + recognizerInfo.mService.packageName)) { + Log.v(TAG, String.format("Recognition service not in the same package as the " + + "default on-device recognizer: %s.", + recognizerInfo.mComponentName.flattenToString())); + } else if (recognizerInfo.mSettings == null) { + Log.v(TAG, String.format("Recognition service with no settings activity: %s.", + recognizerInfo.mComponentName.flattenToString())); + } else { + validOnDeviceRecognitionServices.add(recognizerInfo); + Log.v(TAG, String.format("Recognition service in the same package as the default " + + "on-device recognizer with settings activity: %s.", + recognizerInfo.mSettings.flattenToString())); + } + } + + if (validOnDeviceRecognitionServices.isEmpty()) { + Log.v(TAG, "No speech recognition services with proper `recognition-service` " + + "meta-data found in the same package as the default on-device recognizer."); + return null; + } + + // Not more than one proper recognition services should be found in the same + // package as the default on-device recognizer. If that happens, + // the first one which passed the filter will be selected. + if (validOnDeviceRecognitionServices.size() > 1) { + Log.w(TAG, "More than one recognition services with proper `recognition-service` " + + "meta-data found in the same package as the default on-device recognizer."); + } + VoiceInputHelper.RecognizerInfo chosenRecognizer = validOnDeviceRecognitionServices.get(0); + + return new Intent(Intent.ACTION_MAIN).setComponent(chosenRecognizer.mSettings); + } +} diff --git a/src/com/android/settings/language/VoiceInputHelper.java b/src/com/android/settings/language/VoiceInputHelper.java index 7915ba479ec..289a2f91ec3 100644 --- a/src/com/android/settings/language/VoiceInputHelper.java +++ b/src/com/android/settings/language/VoiceInputHelper.java @@ -29,6 +29,7 @@ import android.provider.Settings; import android.speech.RecognitionService; import android.util.AttributeSet; import android.util.Log; +import android.util.Pair; import android.util.Xml; import org.xmlpull.v1.XmlPullParser; @@ -44,12 +45,11 @@ public final class VoiceInputHelper { static final String TAG = "VoiceInputHelper"; final Context mContext; - final List mAvailableRecognition; - /** * Base info of the Voice Input provider. * * TODO: Remove this superclass as we only have 1 class now (RecognizerInfo). + * TODO: Group recognition service xml meta-data attributes in a single class. */ public static class BaseInfo implements Comparable { public final ServiceInfo mService; @@ -90,16 +90,12 @@ public final class VoiceInputHelper { } } - final ArrayList mAvailableRecognizerInfos = new ArrayList<>(); + ArrayList mAvailableRecognizerInfos = new ArrayList<>(); ComponentName mCurrentRecognizer; public VoiceInputHelper(Context context) { mContext = context; - - mAvailableRecognition = mContext.getPackageManager().queryIntentServices( - new Intent(RecognitionService.SERVICE_INTERFACE), - PackageManager.GET_META_DATA); } /** Draws the UI of the Voice Input picker page. */ @@ -113,63 +109,120 @@ public final class VoiceInputHelper { mCurrentRecognizer = null; } - // Iterate through all the available recognizers and load up their info to show - // in the preference. - int size = mAvailableRecognition.size(); - for (int i = 0; i < size; i++) { - ResolveInfo resolveInfo = mAvailableRecognition.get(i); - ComponentName comp = new ComponentName(resolveInfo.serviceInfo.packageName, - resolveInfo.serviceInfo.name); - ServiceInfo si = resolveInfo.serviceInfo; - String settingsActivity = null; - // Always show in voice input settings unless specifically set to False. - boolean selectableAsDefault = true; - try (XmlResourceParser parser = si.loadXmlMetaData(mContext.getPackageManager(), - RecognitionService.SERVICE_META_DATA)) { - if (parser == null) { - throw new XmlPullParserException("No " + RecognitionService.SERVICE_META_DATA - + " meta-data for " + si.packageName); - } + final ArrayList validRecognitionServices = + validRecognitionServices(mContext); - Resources res = mContext.getPackageManager().getResourcesForApplication( - si.applicationInfo); - - AttributeSet attrs = Xml.asAttributeSet(parser); - - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && type != XmlPullParser.START_TAG) { - // Intentionally do nothing. - } - - String nodeName = parser.getName(); - if (!"recognition-service".equals(nodeName)) { - throw new XmlPullParserException( - "Meta-data does not start with recognition-service tag"); - } - - TypedArray array = res.obtainAttributes(attrs, - com.android.internal.R.styleable.RecognitionService); - settingsActivity = array.getString( - com.android.internal.R.styleable.RecognitionService_settingsActivity); - selectableAsDefault = array.getBoolean( - com.android.internal.R.styleable.RecognitionService_selectableAsDefault, - true); - array.recycle(); - } catch (XmlPullParserException e) { - Log.e(TAG, "error parsing recognition service meta-data", e); - } catch (IOException e) { - Log.e(TAG, "error parsing recognition service meta-data", e); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "error parsing recognition service meta-data", e); - } - // The current recognizer must always be shown in the settings, whatever its - // selectableAsDefault value is. - if (selectableAsDefault || comp.equals(mCurrentRecognizer)) { - mAvailableRecognizerInfos.add(new RecognizerInfo(mContext.getPackageManager(), - resolveInfo.serviceInfo, settingsActivity, selectableAsDefault)); + // Filter all recognizers which can be selected as default or are the current recognizer. + mAvailableRecognizerInfos = new ArrayList<>(); + for (RecognizerInfo recognizerInfo: validRecognitionServices) { + if (recognizerInfo.mSelectableAsDefault || new ComponentName( + recognizerInfo.mService.packageName, recognizerInfo.mService.name) + .equals(mCurrentRecognizer)) { + mAvailableRecognizerInfos.add(recognizerInfo); } } + Collections.sort(mAvailableRecognizerInfos); } + + /** + * Query all services with {@link RecognitionService#SERVICE_INTERFACE} intent. Filter only + * those which have proper xml meta-data which start with a `recognition-service` tag. + * Filtered services are sorted by their labels in the ascending order. + * + * @param context {@link Context} inside which the settings app is run. + * + * @return {@link ArrayList}<{@link RecognizerInfo}> + * containing info about the filtered speech recognition services. + */ + static ArrayList validRecognitionServices(Context context) { + final List resolvedRecognitionServices = + context.getPackageManager().queryIntentServices( + new Intent(RecognitionService.SERVICE_INTERFACE), + PackageManager.GET_META_DATA); + + final ArrayList validRecognitionServices = new ArrayList<>(); + + for (ResolveInfo resolveInfo: resolvedRecognitionServices) { + final ServiceInfo serviceInfo = resolveInfo.serviceInfo; + + final Pair recognitionServiceAttributes = + parseRecognitionServiceXmlMetadata(context, serviceInfo); + + if (recognitionServiceAttributes != null) { + validRecognitionServices.add(new RecognizerInfo( + context.getPackageManager(), + serviceInfo, + recognitionServiceAttributes.first /* settingsActivity */, + recognitionServiceAttributes.second /* selectableAsDefault */)); + } + } + + return validRecognitionServices; + } + + /** + * Load recognition service's xml meta-data and parse it. Return the meta-data attributes, + * namely, `settingsActivity` {@link String} and `selectableAsDefault` {@link Boolean}. + * + *

Parsing fails if the meta-data for the given service is not found + * or the found meta-data does not start with a `recognition-service`.

+ * + * @param context {@link Context} inside which the settings app is run. + * @param serviceInfo {@link ServiceInfo} containing info + * about the speech recognition service in question. + * + * @return {@link Pair}<{@link String}, {@link Boolean}> containing `settingsActivity` + * and `selectableAsDefault` attributes if the parsing was successful, {@code null} otherwise. + */ + private static Pair parseRecognitionServiceXmlMetadata( + Context context, ServiceInfo serviceInfo) { + // Default recognition service attribute values. + // Every recognizer can be selected unless specified otherwise. + String settingsActivity; + boolean selectableAsDefault = true; + + // Parse xml meta-data. + try (XmlResourceParser parser = serviceInfo.loadXmlMetaData( + context.getPackageManager(), RecognitionService.SERVICE_META_DATA)) { + if (parser == null) { + throw new XmlPullParserException(String.format("No %s meta-data for %s package", + RecognitionService.SERVICE_META_DATA, serviceInfo.packageName)); + } + + final Resources res = context.getPackageManager().getResourcesForApplication( + serviceInfo.applicationInfo); + final AttributeSet attrs = Xml.asAttributeSet(parser); + + // Xml meta-data must start with a `recognition-service tag`. + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && type != XmlPullParser.START_TAG) { + // Intentionally do nothing. + } + + final String nodeName = parser.getName(); + if (!"recognition-service".equals(nodeName)) { + throw new XmlPullParserException(String.format( + "%s package meta-data does not start with a `recognition-service` tag", + serviceInfo.packageName)); + } + + final TypedArray array = res.obtainAttributes(attrs, + com.android.internal.R.styleable.RecognitionService); + settingsActivity = array.getString( + com.android.internal.R.styleable.RecognitionService_settingsActivity); + selectableAsDefault = array.getBoolean( + com.android.internal.R.styleable.RecognitionService_selectableAsDefault, + selectableAsDefault); + array.recycle(); + } catch (XmlPullParserException | IOException + | PackageManager.NameNotFoundException e) { + Log.e(TAG, String.format("Error parsing %s package recognition service meta-data", + serviceInfo.packageName), e); + return null; + } + + return Pair.create(settingsActivity, selectableAsDefault); + } } diff --git a/src/com/android/settings/shortcut/CreateShortcutPreferenceController.java b/src/com/android/settings/shortcut/CreateShortcutPreferenceController.java index c871e9fc219..89ee19bc8a7 100644 --- a/src/com/android/settings/shortcut/CreateShortcutPreferenceController.java +++ b/src/com/android/settings/shortcut/CreateShortcutPreferenceController.java @@ -46,6 +46,7 @@ import androidx.preference.PreferenceGroup; import com.android.settings.R; import com.android.settings.Settings; import com.android.settings.Settings.TetherSettingsActivity; +import com.android.settings.activityembedding.ActivityEmbeddingUtils; import com.android.settings.core.BasePreferenceController; import com.android.settings.gestures.OneHandedSettingsUtils; import com.android.settings.overlay.FeatureFactory; @@ -127,7 +128,7 @@ public class CreateShortcutPreferenceController extends BasePreferenceController return false; } final Intent shortcutIntent = createResultIntent( - buildShortcutIntent(info), + buildShortcutIntent(uiContext, info), info, clickTarget.getTitle()); mHost.setResult(Activity.RESULT_OK, shortcutIntent); logCreateShortcut(info); @@ -210,10 +211,14 @@ public class CreateShortcutPreferenceController extends BasePreferenceController info.activityInfo.name); } - private static Intent buildShortcutIntent(ResolveInfo info) { - return new Intent(SHORTCUT_PROBE) + private static Intent buildShortcutIntent(Context context, ResolveInfo info) { + Intent intent = new Intent(SHORTCUT_PROBE) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP) .setClassName(info.activityInfo.packageName, info.activityInfo.name); + if (ActivityEmbeddingUtils.isEmbeddingActivityEnabled(context)) { + intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); + } + return intent; } private static ShortcutInfo createShortcutInfo(Context context, Intent shortcutIntent, @@ -277,8 +282,8 @@ public class CreateShortcutPreferenceController extends BasePreferenceController ResolveInfo ri = context.getPackageManager().resolveActivity(si.getIntent(), 0); if (ri != null) { - updatedShortcuts.add(createShortcutInfo(context, buildShortcutIntent(ri), ri, - si.getShortLabel())); + updatedShortcuts.add(createShortcutInfo(context, + buildShortcutIntent(context, ri), ri, si.getShortLabel())); } } } diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java index 473b56687bf..e34767e7d0b 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java @@ -16,26 +16,83 @@ package com.android.settings.accessibility; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; + import static com.google.common.truth.Truth.assertThat; -import android.content.Context; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import android.content.Context; +import android.content.res.Resources; +import android.os.Bundle; + +import androidx.fragment.app.FragmentActivity; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settings.testutils.XmlTestUtils; +import com.android.settings.testutils.shadow.ShadowFragment; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; import java.util.List; /** Tests for {@link AccessibilityButtonFragment}. */ +@Config(shadows = ShadowFragment.class) @RunWith(RobolectricTestRunner.class) public class AccessibilityButtonFragmentTest { - private Context mContext = ApplicationProvider.getApplicationContext(); + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + private final Context mContext = ApplicationProvider.getApplicationContext(); + @Spy + private Resources mResources = spy(mContext.getResources()); + private AccessibilityButtonFragment mFragment; + + @Before + public void setUp() { + mFragment = spy(new TestAccessibilityButtonFragment(mContext)); + when(mFragment.getResources()).thenReturn(mResources); + when(mFragment.getActivity()).thenReturn(Robolectric.setupActivity(FragmentActivity.class)); + } + + @Test + public void onCreate_navigationGestureEnabled_setCorrectTitle() { + when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode)) + .thenReturn(NAV_BAR_MODE_GESTURAL); + + mFragment.onAttach(mContext); + mFragment.onCreate(Bundle.EMPTY); + + assertThat(mFragment.getActivity().getTitle().toString()).isEqualTo( + mContext.getString(R.string.accessibility_button_gesture_title)); + } + + @Test + public void onCreate_navigationGestureDisabled_setCorrectTitle() { + when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode)) + .thenReturn(NAV_BAR_MODE_2BUTTON); + + mFragment.onAttach(mContext); + mFragment.onCreate(Bundle.EMPTY); + + assertThat(mFragment.getActivity().getTitle().toString()).isEqualTo( + mContext.getString(R.string.accessibility_button_title)); + } @Test public void getNonIndexableKeys_existInXmlLayout() { @@ -47,4 +104,37 @@ public class AccessibilityButtonFragmentTest { assertThat(keys).containsAtLeastElementsIn(niks); } + + private static class TestAccessibilityButtonFragment extends AccessibilityButtonFragment { + + private final Context mContext; + private final PreferenceManager mPreferenceManager; + + TestAccessibilityButtonFragment(Context context) { + super(); + mContext = context; + mPreferenceManager = new PreferenceManager(context); + mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context)); + } + + @Override + public int getPreferenceScreenResId() { + return R.xml.placeholder_prefs; + } + + @Override + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + @Override + public PreferenceManager getPreferenceManager() { + return mPreferenceManager; + } + + @Override + public Context getContext() { + return mContext; + } + } } diff --git a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java index b9c4edc9af2..1f50bed2b5c 100644 --- a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java @@ -150,7 +150,8 @@ public class LocationTimeZoneDetectionPreferenceControllerTest { new TimeZoneCapabilitiesAndConfig(capabilities, configuration); when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig); - assertThat(mController.getSummary().toString()).isEmpty(); + assertThat(mController.getSummary()).isEqualTo( + mContext.getString(R.string.location_time_zone_detection_auto_is_on)); } @Test