From 0d6909dc0f6f804d19eadbc92f9104a033aa8905 Mon Sep 17 00:00:00 2001 From: menghanli Date: Tue, 25 Jan 2022 06:32:26 +0800 Subject: [PATCH] Support accessibility settings load title from quick settings panel - ToggleAccessibilityServicePreferenceFragment for unbundle accessibility service - LaunchAccessibilityActivityPreferenceFragment for unbundle accessibility shortcut-activity Bug: 210356011 Test: make RunSettingsRoboTests ROBOTEST_FILTER=LaunchAccessibilityActivityPreferenceFragmentTest ToggleAccessibilityServicePreferenceFragmentTest Change-Id: I78dcb8dcb2778819ec4bb130a041211598f6d9c --- ...cessibilityActivityPreferenceFragment.java | 6 +- ...ccessibilityServicePreferenceFragment.java | 6 +- .../ToggleFeaturePreferenceFragment.java | 19 +++ ...ibilityActivityPreferenceFragmentTest.java | 145 ++++++++++++++++++ ...sibilityServicePreferenceFragmentTest.java | 145 ++++++++++++++++++ 5 files changed, 319 insertions(+), 2 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java index 8e2ed48826a..afd334e199e 100644 --- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java +++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java @@ -123,7 +123,11 @@ public class LaunchAccessibilityActivityPreferenceFragment extends ToggleFeature @Override CharSequence getTileName() { - return null; + final ComponentName componentName = getTileComponentName(); + if (componentName == null) { + return null; + } + return loadTileLabel(getPrefContext(), componentName); } @Override diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java index 0e0eedae02b..d4d2f4cbce1 100644 --- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java @@ -245,7 +245,11 @@ public class ToggleAccessibilityServicePreferenceFragment extends @Override CharSequence getTileName() { - return null; + final ComponentName componentName = getTileComponentName(); + if (componentName == null) { + return null; + } + return loadTileLabel(getPrefContext(), componentName); } @Override diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index d36764b61c2..08e9b88878a 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -25,7 +25,9 @@ import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; import android.graphics.drawable.Drawable; import android.icu.text.CaseMap; import android.net.Uri; @@ -33,6 +35,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; +import android.service.quicksettings.TileService; import android.text.Html; import android.text.TextUtils; import android.view.LayoutInflater; @@ -843,4 +846,20 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference tileComponentName); mNeedsQSTooltipReshow = false; } + + /** Returns user visible name of the tile by given {@link ComponentName}. */ + protected CharSequence loadTileLabel(Context context, ComponentName componentName) { + final PackageManager packageManager = context.getPackageManager(); + final Intent queryIntent = new Intent(TileService.ACTION_QS_TILE); + final List resolveInfos = + packageManager.queryIntentServices(queryIntent, PackageManager.GET_META_DATA); + for (ResolveInfo info : resolveInfos) { + final ServiceInfo serviceInfo = info.serviceInfo; + if (TextUtils.equals(componentName.getPackageName(), serviceInfo.packageName) + && TextUtils.equals(componentName.getClassName(), serviceInfo.name)) { + return serviceInfo.loadLabel(packageManager); + } + } + return null; + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java new file mode 100644 index 00000000000..0c656b37604 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragmentTest.java @@ -0,0 +1,145 @@ +/* + * 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.accessibility; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.service.quicksettings.TileService; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +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.RobolectricTestRunner; +import org.robolectric.Shadows; +import org.robolectric.shadows.ShadowPackageManager; + +import java.util.Arrays; + +/** Tests for {@link LaunchAccessibilityActivityPreferenceFragment} */ +@RunWith(RobolectricTestRunner.class) +public class LaunchAccessibilityActivityPreferenceFragmentTest { + + private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example"; + private static final String PLACEHOLDER_TILE_CLASS_NAME = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; + private static final String PLACEHOLDER_TILE_CLASS_NAME2 = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder2"; + private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName( + PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME); + private static final String PLACEHOLDER_TILE_NAME = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; + private static final String PLACEHOLDER_TILE_NAME2 = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder2"; + + private TestLaunchAccessibilityActivityPreferenceFragment mFragment; + private PreferenceScreen mScreen; + private Context mContext = ApplicationProvider.getApplicationContext(); + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private PreferenceManager mPreferenceManager; + + @Before + public void setUpTestFragment() { + MockitoAnnotations.initMocks(this); + + mFragment = spy(new TestLaunchAccessibilityActivityPreferenceFragment()); + when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); + when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); + when(mFragment.getContext()).thenReturn(mContext); + mScreen = spy(new PreferenceScreen(mContext, /* attrs= */ null)); + when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager); + doReturn(mScreen).when(mFragment).getPreferenceScreen(); + } + + @Test + public void getTileName_noTileServiceAssigned_noMatchString() { + final CharSequence tileName = mFragment.getTileName(); + assertThat(tileName.toString()).isEqualTo(""); + } + + @Test + public void getTileName_hasOneTileService_haveMatchString() { + final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); + final ResolveInfo info = new ResolveInfo(); + info.serviceInfo = new FakeServiceInfo(); + info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; + info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME; + final ShadowPackageManager shadowPackageManager = + Shadows.shadowOf(mContext.getPackageManager()); + shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info)); + + final CharSequence tileName = mFragment.getTileName(); + assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME); + } + + @Test + public void getTileName_hasTwoTileServices_haveMatchString() { + final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); + final ResolveInfo info = new ResolveInfo(); + info.serviceInfo = new FakeServiceInfo(); + info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; + info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME; + final ResolveInfo info2 = new ResolveInfo(); + info2.serviceInfo = new FakeServiceInfo2(); + info2.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; + info2.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME2; + final ShadowPackageManager shadowPackageManager = + Shadows.shadowOf(mContext.getPackageManager()); + shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info, info2)); + + final CharSequence tileName = mFragment.getTileName(); + assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME); + } + + private static class FakeServiceInfo extends ServiceInfo { + public String loadLabel(PackageManager mgr) { + return PLACEHOLDER_TILE_NAME; + } + } + + private static class FakeServiceInfo2 extends ServiceInfo { + public String loadLabel(PackageManager mgr) { + return PLACEHOLDER_TILE_NAME2; + } + } + + private static class TestLaunchAccessibilityActivityPreferenceFragment + extends LaunchAccessibilityActivityPreferenceFragment { + + @Override + protected ComponentName getTileComponentName() { + return PLACEHOLDER_TILE_COMPONENT_NAME; + } + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java new file mode 100644 index 00000000000..db5b83c841d --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java @@ -0,0 +1,145 @@ +/* + * 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.accessibility; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.service.quicksettings.TileService; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +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.RobolectricTestRunner; +import org.robolectric.Shadows; +import org.robolectric.shadows.ShadowPackageManager; + +import java.util.Arrays; + +/** Tests for {@link ToggleAccessibilityServicePreferenceFragment} */ +@RunWith(RobolectricTestRunner.class) +public class ToggleAccessibilityServicePreferenceFragmentTest { + + private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example"; + private static final String PLACEHOLDER_TILE_CLASS_NAME = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; + private static final String PLACEHOLDER_TILE_CLASS_NAME2 = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder2"; + private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName( + PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME); + private static final String PLACEHOLDER_TILE_NAME = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; + private static final String PLACEHOLDER_TILE_NAME2 = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder2"; + + private TestToggleAccessibilityServicePreferenceFragment mFragment; + private PreferenceScreen mScreen; + private Context mContext = ApplicationProvider.getApplicationContext(); + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private PreferenceManager mPreferenceManager; + + @Before + public void setUpTestFragment() { + MockitoAnnotations.initMocks(this); + + mFragment = spy(new TestToggleAccessibilityServicePreferenceFragment()); + when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); + when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); + when(mFragment.getContext()).thenReturn(mContext); + mScreen = spy(new PreferenceScreen(mContext, /* attrs= */ null)); + when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager); + doReturn(mScreen).when(mFragment).getPreferenceScreen(); + } + + @Test + public void getTileName_noTileServiceAssigned_noMatchString() { + final CharSequence tileName = mFragment.getTileName(); + assertThat(tileName.toString()).isEqualTo(""); + } + + @Test + public void getTileName_hasOneTileService_haveMatchString() { + final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); + final ResolveInfo info = new ResolveInfo(); + info.serviceInfo = new FakeServiceInfo(); + info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; + info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME; + final ShadowPackageManager shadowPackageManager = + Shadows.shadowOf(mContext.getPackageManager()); + shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info)); + + final CharSequence tileName = mFragment.getTileName(); + assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME); + } + + @Test + public void getTileName_hasTwoTileServices_haveMatchString() { + final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); + final ResolveInfo info = new ResolveInfo(); + info.serviceInfo = new FakeServiceInfo(); + info.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; + info.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME; + final ResolveInfo info2 = new ResolveInfo(); + info2.serviceInfo = new FakeServiceInfo2(); + info2.serviceInfo.packageName = PLACEHOLDER_PACKAGE_NAME; + info2.serviceInfo.name = PLACEHOLDER_TILE_CLASS_NAME2; + final ShadowPackageManager shadowPackageManager = + Shadows.shadowOf(mContext.getPackageManager()); + shadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info, info2)); + + final CharSequence tileName = mFragment.getTileName(); + assertThat(tileName.toString()).isEqualTo(PLACEHOLDER_TILE_NAME); + } + + private static class FakeServiceInfo extends ServiceInfo { + public String loadLabel(PackageManager mgr) { + return PLACEHOLDER_TILE_NAME; + } + } + + private static class FakeServiceInfo2 extends ServiceInfo { + public String loadLabel(PackageManager mgr) { + return PLACEHOLDER_TILE_NAME2; + } + } + + private static class TestToggleAccessibilityServicePreferenceFragment + extends ToggleAccessibilityServicePreferenceFragment { + + @Override + protected ComponentName getTileComponentName() { + return PLACEHOLDER_TILE_COMPONENT_NAME; + } + } +}