1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.accessibility; 18 19 import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_BUTTON_COMPONENT_NAME; 20 import static com.android.internal.accessibility.AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME; 21 import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import android.accessibilityservice.AccessibilityServiceInfo; 26 import android.app.Activity; 27 import android.app.admin.DevicePolicyManager; 28 import android.app.settings.SettingsEnums; 29 import android.content.ComponentName; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.pm.ApplicationInfo; 33 import android.content.pm.ResolveInfo; 34 import android.content.pm.ServiceInfo; 35 import android.view.accessibility.AccessibilityManager; 36 37 import androidx.test.core.app.ApplicationProvider; 38 39 import com.android.settings.SettingsActivity; 40 import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; 41 import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal; 42 43 import com.google.common.collect.ImmutableList; 44 45 import org.junit.Before; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 import org.robolectric.RobolectricTestRunner; 49 import org.robolectric.Shadows; 50 import org.robolectric.annotation.Config; 51 import org.robolectric.shadow.api.Shadow; 52 import org.robolectric.shadows.ShadowAccessibilityManager; 53 import org.robolectric.shadows.androidx.fragment.FragmentController; 54 import org.xmlpull.v1.XmlPullParserException; 55 56 import java.io.IOException; 57 import java.util.ArrayList; 58 import java.util.List; 59 60 /** Tests for {@link AccessibilityDetailsSettingsFragment}. */ 61 @Config(shadows = { 62 ShadowDevicePolicyManager.class, 63 ShadowRestrictedLockUtilsInternal.class 64 }) 65 @RunWith(RobolectricTestRunner.class) 66 public class AccessibilityDetailsSettingsFragmentTest { 67 private static final String PACKAGE_NAME = "com.foo.bar"; 68 private static final String CLASS_NAME = PACKAGE_NAME + ".fake_a11y_service"; 69 private static final String COMPONENT_NAME = PACKAGE_NAME + "/" + CLASS_NAME; 70 71 private Context mContext; 72 73 private FragmentController<AccessibilityDetailsSettingsFragment> mFragmentController; 74 75 @Before setUp()76 public void setUp() { 77 mContext = ApplicationProvider.getApplicationContext(); 78 ShadowAccessibilityManager shadowAccessibilityManager = Shadow.extract( 79 AccessibilityManager.getInstance(mContext)); 80 shadowAccessibilityManager.setInstalledAccessibilityServiceList(getMockServiceList()); 81 } 82 83 @Test onCreate_afterSuccessfullyLaunch_shouldBeFinished()84 public void onCreate_afterSuccessfullyLaunch_shouldBeFinished() { 85 final Intent intent = new Intent(); 86 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME); 87 88 AccessibilityDetailsSettingsFragment fragment = startFragment(intent); 89 90 assertThat(fragment.getActivity().isFinishing()).isTrue(); 91 } 92 93 @Test onCreate_hasValidExtraComponentName_launchExpectedFragment()94 public void onCreate_hasValidExtraComponentName_launchExpectedFragment() { 95 Intent intent = new Intent(); 96 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME); 97 98 AccessibilityDetailsSettingsFragment fragment = startFragment(intent); 99 100 assertStartActivityWithExpectedFragment(fragment.getActivity(), 101 ToggleAccessibilityServicePreferenceFragment.class.getName()); 102 } 103 104 @Test onCreate_hasInvalidExtraComponentName_launchAccessibilitySettings()105 public void onCreate_hasInvalidExtraComponentName_launchAccessibilitySettings() { 106 Intent intent = new Intent(); 107 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, PACKAGE_NAME + "/.service"); 108 109 AccessibilityDetailsSettingsFragment fragment = startFragment(intent); 110 111 assertStartActivityWithExpectedFragment(fragment.getActivity(), 112 AccessibilitySettings.class.getName()); 113 } 114 115 @Test onCreate_hasNoExtraComponentName_launchAccessibilitySettings()116 public void onCreate_hasNoExtraComponentName_launchAccessibilitySettings() { 117 AccessibilityDetailsSettingsFragment fragment = startFragment(/* intent= */ null); 118 119 assertStartActivityWithExpectedFragment(fragment.getActivity(), 120 AccessibilitySettings.class.getName()); 121 } 122 123 @Test onCreate_extraComponentNameIsDisallowed_launchAccessibilitySettings()124 public void onCreate_extraComponentNameIsDisallowed_launchAccessibilitySettings() { 125 Intent intent = new Intent(); 126 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME); 127 DevicePolicyManager dpm = mContext.getSystemService( 128 DevicePolicyManager.class); 129 ((ShadowDevicePolicyManager) Shadows.shadowOf(dpm)).setPermittedAccessibilityServices( 130 ImmutableList.of()); 131 132 AccessibilityDetailsSettingsFragment fragment = startFragment(intent); 133 134 assertStartActivityWithExpectedFragment(fragment.getActivity(), 135 AccessibilitySettings.class.getName()); 136 } 137 138 @Test onCreate_magnificationComponentName_launchMagnificationFragment()139 public void onCreate_magnificationComponentName_launchMagnificationFragment() { 140 Intent intent = new Intent(); 141 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, 142 MAGNIFICATION_COMPONENT_NAME.flattenToString()); 143 144 AccessibilityDetailsSettingsFragment fragment = startFragment(intent); 145 146 assertStartActivityWithExpectedFragment(fragment.getActivity(), 147 ToggleScreenMagnificationPreferenceFragment.class.getName()); 148 } 149 150 @Test onCreate_accessibilityButton_launchAccessibilityButtonFragment()151 public void onCreate_accessibilityButton_launchAccessibilityButtonFragment() { 152 Intent intent = new Intent(); 153 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, 154 ACCESSIBILITY_BUTTON_COMPONENT_NAME.flattenToString()); 155 156 AccessibilityDetailsSettingsFragment fragment = startFragment(intent); 157 158 assertStartActivityWithExpectedFragment(fragment.getActivity(), 159 AccessibilityButtonFragment.class.getName()); 160 } 161 162 @Test onCreate_hearingAidsComponentName_launchAccessibilityHearingAidsFragment()163 public void onCreate_hearingAidsComponentName_launchAccessibilityHearingAidsFragment() { 164 Intent intent = new Intent(); 165 intent.putExtra(Intent.EXTRA_COMPONENT_NAME, 166 ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString()); 167 168 AccessibilityDetailsSettingsFragment fragment = startFragment(intent); 169 170 assertStartActivityWithExpectedFragment(fragment.getActivity(), 171 AccessibilityHearingAidsFragment.class.getName()); 172 } 173 174 @Test getMetricsCategory_returnsCorrectCategory()175 public void getMetricsCategory_returnsCorrectCategory() { 176 177 AccessibilityDetailsSettingsFragment fragment = startFragment(/* intent= */ null); 178 179 assertThat(fragment.getMetricsCategory()).isEqualTo( 180 SettingsEnums.ACCESSIBILITY_DETAILS_SETTINGS); 181 } 182 startFragment(Intent intent)183 private AccessibilityDetailsSettingsFragment startFragment(Intent intent) { 184 mFragmentController = FragmentController.of( 185 new AccessibilityDetailsSettingsFragment(), intent) 186 .create() 187 .visible(); 188 189 return mFragmentController.get(); 190 } 191 getMockAccessibilityServiceInfo()192 private AccessibilityServiceInfo getMockAccessibilityServiceInfo() { 193 final ApplicationInfo applicationInfo = new ApplicationInfo(); 194 final ServiceInfo serviceInfo = new ServiceInfo(); 195 applicationInfo.packageName = PACKAGE_NAME; 196 serviceInfo.packageName = PACKAGE_NAME; 197 serviceInfo.name = CLASS_NAME; 198 serviceInfo.applicationInfo = applicationInfo; 199 200 final ResolveInfo resolveInfo = new ResolveInfo(); 201 resolveInfo.serviceInfo = serviceInfo; 202 203 try { 204 final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo, 205 mContext); 206 ComponentName componentName = ComponentName.unflattenFromString(COMPONENT_NAME); 207 info.setComponentName(componentName); 208 return info; 209 } catch (XmlPullParserException | IOException e) { 210 // Do nothing 211 } 212 213 return null; 214 } 215 getMockServiceList()216 private List<AccessibilityServiceInfo> getMockServiceList() { 217 final List<AccessibilityServiceInfo> infoList = new ArrayList<>(); 218 infoList.add(getMockAccessibilityServiceInfo()); 219 return infoList; 220 } 221 assertStartActivityWithExpectedFragment(Activity activity, String fragmentName)222 private void assertStartActivityWithExpectedFragment(Activity activity, String fragmentName) { 223 Intent intent = Shadows.shadowOf(activity).getNextStartedActivity(); 224 assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo( 225 fragmentName); 226 } 227 } 228