blob: b642aa4500b76703ab828ef43fac5814ca0022ee [file] [log] [blame]
/*
* Copyright (C) 2019 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.server.accessibility;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD;
import static android.view.accessibility.AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
import static android.view.accessibility.AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
import static android.view.accessibility.AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.testing.DexmakerShareClassLoaderRule;
import com.android.internal.util.test.FakeSettingsProvider;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
/** Tests for AccessibilityUserState */
public class AccessibilityUserStateTest {
private static final ComponentName COMPONENT_NAME =
new ComponentName("com.android.server.accessibility", "AccessibilityUserStateTest");
// Values of setting key SHOW_IME_WITH_HARD_KEYBOARD
private static final int STATE_HIDE_IME = 0;
private static final int STATE_SHOW_IME = 1;
private static final int USER_ID = 42;
// Mock package-private class AccessibilityServiceConnection
@Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
new DexmakerShareClassLoaderRule();
@Mock private AccessibilityServiceInfo mMockServiceInfo;
@Mock private AccessibilityServiceConnection mMockConnection;
@Mock private AccessibilityUserState.ServiceInfoChangeListener mMockListener;
@Mock private Context mContext;
private MockContentResolver mMockResolver;
private AccessibilityUserState mUserState;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
FakeSettingsProvider.clearSettingsProvider();
mMockResolver = new MockContentResolver();
mMockResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
when(mContext.getContentResolver()).thenReturn(mMockResolver);
when(mMockServiceInfo.getComponentName()).thenReturn(COMPONENT_NAME);
when(mMockConnection.getServiceInfo()).thenReturn(mMockServiceInfo);
mUserState = new AccessibilityUserState(USER_ID, mContext, mMockListener);
}
@After
public void tearDown() {
FakeSettingsProvider.clearSettingsProvider();
}
@Test
public void onSwitchToAnotherUser_userStateClearedNonDefaultValues() {
mUserState.getBoundServicesLocked().add(mMockConnection);
mUserState.getBindingServicesLocked().add(COMPONENT_NAME);
mUserState.setLastSentClientStateLocked(
STATE_FLAG_ACCESSIBILITY_ENABLED
| STATE_FLAG_TOUCH_EXPLORATION_ENABLED
| STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED);
mUserState.setNonInteractiveUiTimeoutLocked(30);
mUserState.setInteractiveUiTimeoutLocked(30);
mUserState.mEnabledServices.add(COMPONENT_NAME);
mUserState.mTouchExplorationGrantedServices.add(COMPONENT_NAME);
mUserState.setTouchExplorationEnabledLocked(true);
mUserState.setDisplayMagnificationEnabledLocked(true);
mUserState.setNavBarMagnificationEnabledLocked(true);
mUserState.setServiceAssignedToAccessibilityButtonLocked(COMPONENT_NAME);
mUserState.setNavBarMagnificationAssignedToAccessibilityButtonLocked(true);
mUserState.setAutoclickEnabledLocked(true);
mUserState.setUserNonInteractiveUiTimeoutLocked(30);
mUserState.setUserInteractiveUiTimeoutLocked(30);
mUserState.onSwitchToAnotherUserLocked();
verify(mMockConnection).unbindLocked();
assertTrue(mUserState.getBoundServicesLocked().isEmpty());
assertTrue(mUserState.getBindingServicesLocked().isEmpty());
assertEquals(-1, mUserState.getLastSentClientStateLocked());
assertEquals(0, mUserState.getNonInteractiveUiTimeoutLocked());
assertEquals(0, mUserState.getInteractiveUiTimeoutLocked());
assertTrue(mUserState.mEnabledServices.isEmpty());
assertTrue(mUserState.mTouchExplorationGrantedServices.isEmpty());
assertFalse(mUserState.isTouchExplorationEnabledLocked());
assertFalse(mUserState.isDisplayMagnificationEnabledLocked());
assertFalse(mUserState.isNavBarMagnificationEnabledLocked());
assertNull(mUserState.getServiceAssignedToAccessibilityButtonLocked());
assertFalse(mUserState.isNavBarMagnificationAssignedToAccessibilityButtonLocked());
assertFalse(mUserState.isAutoclickEnabledLocked());
assertEquals(0, mUserState.getUserNonInteractiveUiTimeoutLocked());
assertEquals(0, mUserState.getUserInteractiveUiTimeoutLocked());
}
@Test
public void addService_connectionAlreadyAdded_notAddAgain() {
mUserState.getBoundServicesLocked().add(mMockConnection);
mUserState.addServiceLocked(mMockConnection);
verify(mMockConnection, never()).onAdded();
}
@Test
public void addService_connectionNotYetAddedToBoundService_addAndNotifyServices() {
when(mMockConnection.getComponentName()).thenReturn(COMPONENT_NAME);
mUserState.addServiceLocked(mMockConnection);
verify(mMockConnection).onAdded();
assertTrue(mUserState.getBoundServicesLocked().contains(mMockConnection));
assertEquals(mMockConnection, mUserState.mComponentNameToServiceMap.get(COMPONENT_NAME));
verify(mMockListener).onServiceInfoChangedLocked(eq(mUserState));
}
@Test
public void reconcileSoftKeyboardMode_whenStateNotMatchSettings_setBothDefault() {
// When soft kb show mode is hidden in settings and is auto in state.
putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
SHOW_MODE_HIDDEN, USER_ID);
mUserState.reconcileSoftKeyboardModeWithSettingsLocked();
assertEquals(SHOW_MODE_AUTO, mUserState.getSoftKeyboardShowModeLocked());
assertEquals(SHOW_MODE_AUTO,
getSecureInt(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE));
assertNull(mUserState.getServiceChangingSoftKeyboardModeLocked());
}
@Test
public void
reconcileSoftKeyboardMode_stateIgnoreHardKb_settingsShowImeHardKb_setAutoOverride() {
// When show mode is ignore hard kb without original hard kb value
// and show ime with hard kb is hide
putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
SHOW_MODE_IGNORE_HARD_KEYBOARD, USER_ID);
mUserState.setSoftKeyboardModeLocked(SHOW_MODE_IGNORE_HARD_KEYBOARD, COMPONENT_NAME);
putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD,
STATE_HIDE_IME, USER_ID);
mUserState.reconcileSoftKeyboardModeWithSettingsLocked();
assertEquals(SHOW_MODE_AUTO | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN,
getSecureInt(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE));
assertNull(mUserState.getServiceChangingSoftKeyboardModeLocked());
}
@Test
public void removeService_serviceChangingSoftKeyboardMode_removeAndSetSoftKbModeAuto() {
mUserState.setServiceChangingSoftKeyboardModeLocked(COMPONENT_NAME);
mUserState.mComponentNameToServiceMap.put(COMPONENT_NAME, mMockConnection);
mUserState.setSoftKeyboardModeLocked(SHOW_MODE_HIDDEN, COMPONENT_NAME);
mUserState.removeServiceLocked(mMockConnection);
assertFalse(mUserState.getBoundServicesLocked().contains(mMockConnection));
verify(mMockConnection).onRemoved();
assertEquals(SHOW_MODE_AUTO, mUserState.getSoftKeyboardShowModeLocked());
assertNull(mUserState.mComponentNameToServiceMap.get(COMPONENT_NAME));
verify(mMockListener).onServiceInfoChangedLocked(eq(mUserState));
}
@Test
public void serviceDisconnected_removeServiceAndAddToBinding() {
when(mMockConnection.getComponentName()).thenReturn(COMPONENT_NAME);
mUserState.addServiceLocked(mMockConnection);
mUserState.serviceDisconnectedLocked(mMockConnection);
assertFalse(mUserState.getBoundServicesLocked().contains(mMockConnection));
assertTrue(mUserState.getBindingServicesLocked().contains(COMPONENT_NAME));
}
@Test
public void setSoftKeyboardMode_withInvalidShowMode_shouldKeepDefaultAuto() {
final int invalidShowMode = SHOW_MODE_HIDDEN | SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE;
assertFalse(mUserState.setSoftKeyboardModeLocked(invalidShowMode, null));
assertEquals(SHOW_MODE_AUTO, mUserState.getSoftKeyboardShowModeLocked());
}
@Test
public void setSoftKeyboardMode_newModeSameWithCurrentState_returnTrue() {
when(mMockConnection.getComponentName()).thenReturn(COMPONENT_NAME);
mUserState.addServiceLocked(mMockConnection);
assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null));
}
@Test
public void setSoftKeyboardMode_withIgnoreHardKb_whenHardKbOverridden_returnFalseAdNoChange() {
putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
SHOW_MODE_AUTO | SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN, USER_ID);
assertFalse(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_IGNORE_HARD_KEYBOARD, null));
assertEquals(SHOW_MODE_AUTO, mUserState.getSoftKeyboardShowModeLocked());
}
@Test
public void
setSoftKeyboardMode_withIgnoreHardKb_whenShowImeWithHardKb_setOriginalHardKbValue() {
putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, STATE_SHOW_IME, USER_ID);
assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_IGNORE_HARD_KEYBOARD, null));
assertEquals(SHOW_MODE_IGNORE_HARD_KEYBOARD | SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE,
getSecureInt(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE));
}
@Test
public void setSoftKeyboardMode_whenCurrentIgnoreHardKb_shouldSetShowImeWithHardKbValue() {
mUserState.setSoftKeyboardModeLocked(SHOW_MODE_IGNORE_HARD_KEYBOARD, COMPONENT_NAME);
putSecureIntForUser(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, STATE_HIDE_IME, USER_ID);
putSecureIntForUser(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
SHOW_MODE_IGNORE_HARD_KEYBOARD | SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE, USER_ID);
assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_AUTO, null));
assertEquals(STATE_SHOW_IME, getSecureInt(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD));
}
@Test
public void setSoftKeyboardMode_withRequester_shouldUpdateInternalStateAndSettingsAsIs() {
assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_HIDDEN, COMPONENT_NAME));
assertEquals(SHOW_MODE_HIDDEN, mUserState.getSoftKeyboardShowModeLocked());
assertEquals(SHOW_MODE_HIDDEN,
getSecureInt(Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE));
assertEquals(COMPONENT_NAME, mUserState.getServiceChangingSoftKeyboardModeLocked());
}
@Test
public void setSoftKeyboardMode_shouldNotifyBoundService() {
mUserState.addServiceLocked(mMockConnection);
assertTrue(mUserState.setSoftKeyboardModeLocked(SHOW_MODE_HIDDEN, COMPONENT_NAME));
verify(mMockConnection).notifySoftKeyboardShowModeChangedLocked(eq(SHOW_MODE_HIDDEN));
}
private int getSecureInt(String key) {
return Settings.Secure.getInt(mMockResolver, key, -1);
}
private void putSecureIntForUser(String key, int value, int userId) {
Settings.Secure.putIntForUser(mMockResolver, key, value, userId);
}
}