1 /* 2 * Copyright (C) 2018 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.inputmethod; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyString; 23 import static org.mockito.Mockito.never; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.when; 26 27 import android.content.Context; 28 import android.hardware.input.InputDeviceIdentifier; 29 import android.hardware.input.InputManager; 30 import android.hardware.input.KeyboardLayout; 31 import android.view.InputDevice; 32 33 import androidx.fragment.app.Fragment; 34 import androidx.fragment.app.FragmentActivity; 35 import androidx.preference.PreferenceManager; 36 import androidx.preference.PreferenceScreen; 37 38 import com.android.settings.core.BasePreferenceController; 39 import com.android.settings.testutils.shadow.ShadowInputDevice; 40 41 import org.junit.Before; 42 import org.junit.Ignore; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.Mock; 46 import org.mockito.MockitoAnnotations; 47 import org.robolectric.Robolectric; 48 import org.robolectric.RobolectricTestRunner; 49 import org.robolectric.RuntimeEnvironment; 50 import org.robolectric.annotation.Config; 51 import org.robolectric.shadows.ShadowApplication; 52 53 @Ignore 54 @RunWith(RobolectricTestRunner.class) 55 public class KeyboardLayoutPickerControllerTest { 56 57 @Mock 58 private Fragment mFragment; 59 @Mock 60 private InputManager mInputManager; 61 62 private Context mContext; 63 private InputDeviceIdentifier mInputDeviceIdentifier; 64 private KeyboardLayoutPickerController mController; 65 66 @Before setUp()67 public void setUp() { 68 MockitoAnnotations.initMocks(this); 69 final ShadowApplication shadowContext = ShadowApplication.getInstance(); 70 shadowContext.setSystemService(Context.INPUT_SERVICE, mInputManager); 71 72 mContext = RuntimeEnvironment.application; 73 mInputDeviceIdentifier = new InputDeviceIdentifier("descriptor", 1, 1); 74 mController = new KeyboardLayoutPickerController(mContext, "pref_key"); 75 76 initializeOneLayout(); 77 } 78 79 @Test isAlwaysAvailable()80 public void isAlwaysAvailable() { 81 assertThat(mController.getAvailabilityStatus()) 82 .isEqualTo(BasePreferenceController.AVAILABLE); 83 } 84 85 @Test testLifecycle_onStart_shouldRegisterInputManager()86 public void testLifecycle_onStart_shouldRegisterInputManager() { 87 final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class); 88 when(mFragment.getActivity()).thenReturn(activity); 89 90 mController.onStart(); 91 92 // Register is called, but unregister should not be called. 93 verify(mInputManager).registerInputDeviceListener(mController, null); 94 verify(mInputManager, never()).unregisterInputDeviceListener(mController); 95 } 96 97 @Test testLifecycle_onStart_NoInputDevice_shouldReturn()98 public void testLifecycle_onStart_NoInputDevice_shouldReturn() { 99 final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class); 100 when(mInputManager.getInputDeviceByDescriptor(anyString())).thenReturn(null); 101 when(mFragment.getActivity()).thenReturn(activity); 102 103 mController.onStart(); 104 verify(mInputManager, never()).getEnabledKeyboardLayoutsForInputDevice(any()); 105 } 106 107 @Test testLifecycle_onStop_shouldCancelRegisterInputManager()108 public void testLifecycle_onStop_shouldCancelRegisterInputManager() { 109 mController.onStop(); 110 111 // Unregister is called, but register should not be called. 112 verify(mInputManager).unregisterInputDeviceListener(mController); 113 verify(mInputManager, never()).registerInputDeviceListener(mController, null); 114 } 115 116 @Test test_createPreferenceHierarchy_shouldAddOnePreference()117 public void test_createPreferenceHierarchy_shouldAddOnePreference() { 118 final PreferenceManager preferenceManager = new PreferenceManager(mContext); 119 final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); 120 121 mController.displayPreference(screen); 122 123 // We create a keyboard layouts in initializeOneLayout() 124 assertThat(screen.getPreferenceCount()).isEqualTo(1); 125 } 126 127 @Test test_createPreferenceHierarchy_shouldAddTwoPreference()128 public void test_createPreferenceHierarchy_shouldAddTwoPreference() { 129 initializeTwoLayouts(); 130 final PreferenceManager preferenceManager = new PreferenceManager(mContext); 131 final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); 132 133 mController.displayPreference(screen); 134 135 // We create two keyboard layouts in initializeOneLayout() 136 assertThat(screen.getPreferenceCount()).isEqualTo(2); 137 } 138 139 @Test 140 @Config(shadows = ShadowInputDevice.class) testOnDeviceRemove_getSameDevice_shouldFinish()141 public void testOnDeviceRemove_getSameDevice_shouldFinish() { 142 final int TARGET_DEVICE_ID = 1; 143 final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class); 144 final String[] enableKeyboardLayouts = {"layout1"}; 145 final InputDevice device = ShadowInputDevice.makeInputDevicebyId(TARGET_DEVICE_ID); 146 147 when(mFragment.getActivity()).thenReturn(activity); 148 when(mInputManager.getInputDeviceByDescriptor(anyString())).thenReturn(device); 149 when(mInputManager.getEnabledKeyboardLayoutsForInputDevice( 150 any(InputDeviceIdentifier.class))).thenReturn(enableKeyboardLayouts); 151 152 mController.onStart(); 153 mController.onInputDeviceRemoved(TARGET_DEVICE_ID); 154 155 assertThat(activity.isFinishing()).isTrue(); 156 } 157 158 @Test 159 @Config(shadows = ShadowInputDevice.class) testOnDeviceRemove_getDifferentDevice_shouldNotFinish()160 public void testOnDeviceRemove_getDifferentDevice_shouldNotFinish() { 161 final int TARGET_DEVICE_ID = 1; 162 final int ANOTHER_DEVICE_ID = 2; 163 final FragmentActivity activity = Robolectric.setupActivity(FragmentActivity.class); 164 final String[] enableKeyboardLayouts = {"layout1"}; 165 final InputDevice device = ShadowInputDevice.makeInputDevicebyId(TARGET_DEVICE_ID); 166 167 when(mFragment.getActivity()).thenReturn(activity); 168 when(mInputManager.getInputDeviceByDescriptor(anyString())).thenReturn(device); 169 when(mInputManager.getEnabledKeyboardLayoutsForInputDevice( 170 any(InputDeviceIdentifier.class))).thenReturn(enableKeyboardLayouts); 171 172 mController.onStart(); 173 mController.onInputDeviceRemoved(ANOTHER_DEVICE_ID); 174 175 assertThat(activity.isFinishing()).isFalse(); 176 } 177 initializeOneLayout()178 private void initializeOneLayout() { 179 final KeyboardLayout[] keyboardLayouts = {new KeyboardLayout("", "", "", 1, null, 0, 1, 1)}; 180 when(mInputManager.getKeyboardLayoutsForInputDevice( 181 any(InputDeviceIdentifier.class))).thenReturn( 182 keyboardLayouts); 183 184 mController.initialize(mFragment, mInputDeviceIdentifier); 185 } 186 initializeTwoLayouts()187 private void initializeTwoLayouts() { 188 final KeyboardLayout[] keyboardLayouts = {new KeyboardLayout("", "", "", 1, null, 0, 1, 1), 189 new KeyboardLayout("", "", "", 2, null, 0, 2, 2)}; 190 when(mInputManager.getKeyboardLayoutsForInputDevice(any(InputDeviceIdentifier.class))). 191 thenReturn(keyboardLayouts); 192 193 mController.initialize(mFragment, mInputDeviceIdentifier); 194 } 195 } 196