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