1 /* 2 * Copyright (C) 2022 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.bluetooth; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.when; 22 23 import android.accessibilityservice.AccessibilityServiceInfo; 24 import android.content.ComponentName; 25 import android.content.pm.ApplicationInfo; 26 import android.content.pm.ResolveInfo; 27 import android.content.pm.ServiceInfo; 28 import android.view.accessibility.AccessibilityManager; 29 30 import androidx.preference.Preference; 31 import androidx.preference.PreferenceCategory; 32 33 import com.android.settings.testutils.FakeFeatureFactory; 34 35 import org.junit.Rule; 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 import org.mockito.junit.MockitoJUnit; 39 import org.mockito.junit.MockitoRule; 40 import org.robolectric.RobolectricTestRunner; 41 import org.robolectric.shadow.api.Shadow; 42 import org.robolectric.shadows.ShadowAccessibilityManager; 43 import org.xmlpull.v1.XmlPullParserException; 44 45 import java.io.IOException; 46 import java.util.List; 47 48 /** Tests for {@link BluetoothDetailsRelatedToolsController}. */ 49 @RunWith(RobolectricTestRunner.class) 50 public class BluetoothDetailsRelatedToolsControllerTest extends BluetoothDetailsControllerTestBase { 51 @Rule 52 public final MockitoRule mockito = MockitoJUnit.rule(); 53 54 private static final String PACKAGE_NAME = "com.android.test"; 55 private static final String PACKAGE_NAME2 = "com.android.test2"; 56 private static final String CLASS_NAME = PACKAGE_NAME + ".test_a11y_service"; 57 private static final String KEY_RELATED_TOOLS_GROUP = "bluetooth_related_tools"; 58 private static final String KEY_LIVE_CAPTION = "live_caption"; 59 60 61 private BluetoothDetailsRelatedToolsController mController; 62 private BluetoothFeatureProvider mFeatureProvider; 63 private ShadowAccessibilityManager mShadowAccessibilityManager; 64 private PreferenceCategory mPreferenceCategory; 65 66 @Override setUp()67 public void setUp() { 68 super.setUp(); 69 final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest(); 70 mFeatureProvider = fakeFeatureFactory.getBluetoothFeatureProvider(); 71 mShadowAccessibilityManager = Shadow.extract(AccessibilityManager.getInstance(mContext)); 72 final Preference preference = new Preference(mContext); 73 preference.setKey(KEY_LIVE_CAPTION); 74 mPreferenceCategory = new PreferenceCategory(mContext); 75 mPreferenceCategory.setKey(KEY_RELATED_TOOLS_GROUP); 76 mScreen.addPreference(mPreferenceCategory); 77 mScreen.addPreference(preference); 78 79 mController = new BluetoothDetailsRelatedToolsController(mContext, mFragment, mCachedDevice, 80 mLifecycle); 81 mController.init(mScreen); 82 } 83 84 @Test isAvailable_isHearingAidDevice_available()85 public void isAvailable_isHearingAidDevice_available() { 86 when(mCachedDevice.isHearingAidDevice()).thenReturn(true); 87 88 assertThat(mController.isAvailable()).isTrue(); 89 } 90 91 @Test isAvailable_isNotHearingAidDevice_notAvailable()92 public void isAvailable_isNotHearingAidDevice_notAvailable() { 93 when(mCachedDevice.isHearingAidDevice()).thenReturn(false); 94 95 assertThat(mController.isAvailable()).isFalse(); 96 } 97 98 @Test displayPreference_oneRelatedToolsMatchA11yService_showOnePreference()99 public void displayPreference_oneRelatedToolsMatchA11yService_showOnePreference() { 100 when(mCachedDevice.isHearingAidDevice()).thenReturn(true); 101 mShadowAccessibilityManager.setInstalledAccessibilityServiceList( 102 List.of(getMockAccessibilityServiceInfo(PACKAGE_NAME, CLASS_NAME))); 103 when(mFeatureProvider.getRelatedTools()).thenReturn( 104 List.of(new ComponentName(PACKAGE_NAME, CLASS_NAME))); 105 106 mController.displayPreference(mScreen); 107 108 assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(1); 109 } 110 111 @Test displayPreference_oneRelatedToolsNotMatchA11yService_showNoPreference()112 public void displayPreference_oneRelatedToolsNotMatchA11yService_showNoPreference() { 113 when(mCachedDevice.isHearingAidDevice()).thenReturn(true); 114 mShadowAccessibilityManager.setInstalledAccessibilityServiceList( 115 List.of(getMockAccessibilityServiceInfo(PACKAGE_NAME, CLASS_NAME))); 116 when(mFeatureProvider.getRelatedTools()).thenReturn( 117 List.of(new ComponentName(PACKAGE_NAME2, CLASS_NAME))); 118 119 mController.displayPreference(mScreen); 120 121 assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(0); 122 } 123 124 @Test displayPreference_noRelatedTools_showNoPreference()125 public void displayPreference_noRelatedTools_showNoPreference() { 126 when(mCachedDevice.isHearingAidDevice()).thenReturn(true); 127 mShadowAccessibilityManager.setInstalledAccessibilityServiceList( 128 List.of(getMockAccessibilityServiceInfo(PACKAGE_NAME, CLASS_NAME))); 129 when(mFeatureProvider.getRelatedTools()).thenReturn(null); 130 131 mController.displayPreference(mScreen); 132 133 assertThat(mPreferenceCategory.getPreferenceCount()).isEqualTo(0); 134 } 135 getMockAccessibilityServiceInfo(String packageName, String className)136 private AccessibilityServiceInfo getMockAccessibilityServiceInfo(String packageName, 137 String className) { 138 final ApplicationInfo applicationInfo = new ApplicationInfo(); 139 final ServiceInfo serviceInfo = new ServiceInfo(); 140 applicationInfo.packageName = packageName; 141 serviceInfo.packageName = packageName; 142 serviceInfo.name = className; 143 serviceInfo.applicationInfo = applicationInfo; 144 145 final ResolveInfo resolveInfo = new ResolveInfo(); 146 resolveInfo.serviceInfo = serviceInfo; 147 148 try { 149 final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo, 150 mContext); 151 ComponentName componentName = ComponentName.unflattenFromString( 152 packageName + "/" + className); 153 info.setComponentName(componentName); 154 return info; 155 } catch (XmlPullParserException | IOException e) { 156 // Do nothing 157 } 158 159 return null; 160 } 161 } 162