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