Merge "Add tests to ensure input settings are loaded on boot" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
6f7805292a
@@ -46,7 +46,6 @@ import android.view.InputDevice;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.input.BatteryController.UEventManager.UEventBatteryListener;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
@@ -102,8 +101,9 @@ final class BatteryController {
|
||||
@GuardedBy("mLock")
|
||||
private BluetoothBatteryManager.BluetoothBatteryListener mBluetoothBatteryListener;
|
||||
|
||||
BatteryController(Context context, NativeInputManagerService nativeService, Looper looper) {
|
||||
this(context, nativeService, looper, new UEventManager() {},
|
||||
BatteryController(Context context, NativeInputManagerService nativeService, Looper looper,
|
||||
UEventManager uEventManager) {
|
||||
this(context, nativeService, looper, uEventManager,
|
||||
new LocalBluetoothBatteryManager(context, looper));
|
||||
}
|
||||
|
||||
@@ -567,7 +567,7 @@ final class BatteryController {
|
||||
private BluetoothAdapter.OnMetadataChangedListener mBluetoothMetadataListener;
|
||||
|
||||
@Nullable
|
||||
private UEventBatteryListener mUEventBatteryListener;
|
||||
private BatteryController.UEventBatteryListener mUEventBatteryListener;
|
||||
|
||||
DeviceMonitor(int deviceId) {
|
||||
mState = new State(deviceId);
|
||||
@@ -630,7 +630,7 @@ final class BatteryController {
|
||||
return;
|
||||
}
|
||||
final int deviceId = mState.deviceId;
|
||||
mUEventBatteryListener = new UEventBatteryListener() {
|
||||
mUEventBatteryListener = new BatteryController.UEventBatteryListener() {
|
||||
@Override
|
||||
public void onBatteryUEvent(long eventTime) {
|
||||
handleUEventNotification(deviceId, eventTime);
|
||||
@@ -898,40 +898,25 @@ final class BatteryController {
|
||||
}
|
||||
}
|
||||
|
||||
// An interface used to change the API of UEventObserver to a more test-friendly format.
|
||||
@VisibleForTesting
|
||||
interface UEventManager {
|
||||
|
||||
@VisibleForTesting
|
||||
abstract class UEventBatteryListener {
|
||||
private final UEventObserver mObserver = new UEventObserver() {
|
||||
@Override
|
||||
public void onUEvent(UEvent event) {
|
||||
final long eventTime = SystemClock.uptimeMillis();
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG,
|
||||
"UEventListener: Received UEvent: "
|
||||
+ event + " eventTime: " + eventTime);
|
||||
}
|
||||
if (!"CHANGE".equalsIgnoreCase(event.get("ACTION"))
|
||||
|| !"POWER_SUPPLY".equalsIgnoreCase(event.get("SUBSYSTEM"))) {
|
||||
// Disregard any UEvents that do not correspond to battery changes.
|
||||
return;
|
||||
}
|
||||
UEventBatteryListener.this.onBatteryUEvent(eventTime);
|
||||
}
|
||||
};
|
||||
|
||||
public abstract void onBatteryUEvent(long eventTime);
|
||||
abstract static class UEventBatteryListener extends UEventManager.UEventListener {
|
||||
@Override
|
||||
public void onUEvent(UEventObserver.UEvent event) {
|
||||
final long eventTime = SystemClock.uptimeMillis();
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG,
|
||||
"UEventListener: Received UEvent: "
|
||||
+ event + " eventTime: " + eventTime);
|
||||
}
|
||||
if (!"CHANGE".equalsIgnoreCase(event.get("ACTION"))
|
||||
|| !"POWER_SUPPLY".equalsIgnoreCase(event.get("SUBSYSTEM"))) {
|
||||
// Disregard any UEvents that do not correspond to battery changes.
|
||||
return;
|
||||
}
|
||||
UEventBatteryListener.this.onBatteryUEvent(eventTime);
|
||||
}
|
||||
|
||||
default void addListener(UEventBatteryListener listener, String match) {
|
||||
listener.mObserver.startObserving(match);
|
||||
}
|
||||
|
||||
default void removeListener(UEventBatteryListener listener) {
|
||||
listener.mObserver.stopObserving();
|
||||
}
|
||||
public abstract void onBatteryUEvent(long eventTime);
|
||||
}
|
||||
|
||||
// An interface used to change the API of adding a bluetooth battery listener to a more
|
||||
|
||||
@@ -393,10 +393,12 @@ public class InputManagerService extends IInputManager.Stub
|
||||
static class Injector {
|
||||
private final Context mContext;
|
||||
private final Looper mLooper;
|
||||
private final UEventManager mUEventManager;
|
||||
|
||||
Injector(Context context, Looper looper) {
|
||||
Injector(Context context, Looper looper, UEventManager uEventManager) {
|
||||
mContext = context;
|
||||
mLooper = looper;
|
||||
mUEventManager = uEventManager;
|
||||
}
|
||||
|
||||
Context getContext() {
|
||||
@@ -407,6 +409,10 @@ public class InputManagerService extends IInputManager.Stub
|
||||
return mLooper;
|
||||
}
|
||||
|
||||
UEventManager getUEventManager() {
|
||||
return mUEventManager;
|
||||
}
|
||||
|
||||
NativeInputManagerService getNativeService(InputManagerService service) {
|
||||
return new NativeInputManagerService.NativeImpl(service, mLooper.getQueue());
|
||||
}
|
||||
@@ -417,7 +423,7 @@ public class InputManagerService extends IInputManager.Stub
|
||||
}
|
||||
|
||||
public InputManagerService(Context context) {
|
||||
this(new Injector(context, DisplayThread.get().getLooper()));
|
||||
this(new Injector(context, DisplayThread.get().getLooper(), new UEventManager() {}));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -432,10 +438,12 @@ public class InputManagerService extends IInputManager.Stub
|
||||
mSettingsObserver = new InputSettingsObserver(mContext, mHandler, this, mNative);
|
||||
mKeyboardLayoutManager = new KeyboardLayoutManager(mContext, mNative, mDataStore,
|
||||
injector.getLooper());
|
||||
mBatteryController = new BatteryController(mContext, mNative, injector.getLooper());
|
||||
mBatteryController = new BatteryController(mContext, mNative, injector.getLooper(),
|
||||
injector.getUEventManager());
|
||||
mKeyboardBacklightController = InputFeatureFlagProvider.isKeyboardBacklightControlEnabled()
|
||||
? new KeyboardBacklightController(mContext, mNative, mDataStore,
|
||||
injector.getLooper()) : new KeyboardBacklightControllerInterface() {};
|
||||
injector.getLooper(), injector.getUEventManager())
|
||||
: new KeyboardBacklightControllerInterface() {};
|
||||
mKeyRemapper = new KeyRemapper(mContext, mNative, mDataStore, injector.getLooper());
|
||||
|
||||
mUseDevInputEventForAudioJack =
|
||||
|
||||
@@ -94,6 +94,7 @@ final class KeyboardBacklightController implements
|
||||
private final PersistentDataStore mDataStore;
|
||||
private final Handler mHandler;
|
||||
private final AnimatorFactory mAnimatorFactory;
|
||||
private final UEventManager mUEventManager;
|
||||
// Always access on handler thread or need to lock this for synchronization.
|
||||
private final SparseArray<KeyboardBacklightState> mKeyboardBacklights = new SparseArray<>(1);
|
||||
// Maintains state if all backlights should be on or turned off
|
||||
@@ -123,19 +124,21 @@ final class KeyboardBacklightController implements
|
||||
}
|
||||
|
||||
KeyboardBacklightController(Context context, NativeInputManagerService nativeService,
|
||||
PersistentDataStore dataStore, Looper looper) {
|
||||
this(context, nativeService, dataStore, looper, ValueAnimator::ofInt);
|
||||
PersistentDataStore dataStore, Looper looper, UEventManager uEventManager) {
|
||||
this(context, nativeService, dataStore, looper, ValueAnimator::ofInt, uEventManager);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
KeyboardBacklightController(Context context, NativeInputManagerService nativeService,
|
||||
PersistentDataStore dataStore, Looper looper, AnimatorFactory animatorFactory) {
|
||||
PersistentDataStore dataStore, Looper looper, AnimatorFactory animatorFactory,
|
||||
UEventManager uEventManager) {
|
||||
mContext = context;
|
||||
mNative = nativeService;
|
||||
mDataStore = dataStore;
|
||||
mHandler = new Handler(looper, this::handleMessage);
|
||||
mAnimatorFactory = animatorFactory;
|
||||
mAmbientController = new AmbientKeyboardBacklightController(context, looper);
|
||||
mUEventManager = uEventManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,13 +155,12 @@ final class KeyboardBacklightController implements
|
||||
// We want to observe creation of such LED nodes since they might be created after device
|
||||
// FD created and InputDevice creation logic doesn't initialize LED nodes which leads to
|
||||
// backlight not working.
|
||||
UEventObserver observer = new UEventObserver() {
|
||||
mUEventManager.addListener(new UEventManager.UEventListener() {
|
||||
@Override
|
||||
public void onUEvent(UEvent event) {
|
||||
public void onUEvent(UEventObserver.UEvent event) {
|
||||
onKeyboardBacklightUEvent(event);
|
||||
}
|
||||
};
|
||||
observer.startObserving(UEVENT_KEYBOARD_BACKLIGHT_TAG);
|
||||
}, UEVENT_KEYBOARD_BACKLIGHT_TAG);
|
||||
|
||||
if (InputFeatureFlagProvider.isAmbientKeyboardBacklightControlEnabled()) {
|
||||
// Start ambient backlight controller
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2023 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.input;
|
||||
|
||||
import android.os.UEventObserver;
|
||||
|
||||
/** An interface used to change the API of UEventObserver to a more test-friendly format. */
|
||||
interface UEventManager {
|
||||
|
||||
abstract class UEventListener {
|
||||
private final UEventObserver mObserver = new UEventObserver() {
|
||||
@Override
|
||||
public void onUEvent(UEvent event) {
|
||||
UEventListener.this.onUEvent(event);
|
||||
}
|
||||
};
|
||||
|
||||
public abstract void onUEvent(UEventObserver.UEvent event);
|
||||
}
|
||||
|
||||
default void addListener(UEventListener listener, String match) {
|
||||
listener.mObserver.startObserving(match);
|
||||
}
|
||||
|
||||
default void removeListener(UEventListener listener) {
|
||||
listener.mObserver.stopObserving();
|
||||
}
|
||||
}
|
||||
@@ -40,8 +40,7 @@ import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.server.input.BatteryController.BluetoothBatteryManager
|
||||
import com.android.server.input.BatteryController.BluetoothBatteryManager.BluetoothBatteryListener
|
||||
import com.android.server.input.BatteryController.POLLING_PERIOD_MILLIS
|
||||
import com.android.server.input.BatteryController.UEventManager
|
||||
import com.android.server.input.BatteryController.UEventManager.UEventBatteryListener
|
||||
import com.android.server.input.BatteryController.UEventBatteryListener
|
||||
import com.android.server.input.BatteryController.USI_BATTERY_VALIDITY_DURATION_MILLIS
|
||||
import org.hamcrest.Description
|
||||
import org.hamcrest.Matcher
|
||||
|
||||
@@ -23,9 +23,12 @@ import android.hardware.display.DisplayViewport
|
||||
import android.os.IInputConstants
|
||||
import android.os.test.TestLooper
|
||||
import android.platform.test.annotations.Presubmit
|
||||
import android.provider.Settings
|
||||
import android.test.mock.MockContentResolver
|
||||
import android.view.Display
|
||||
import android.view.PointerIcon
|
||||
import androidx.test.InstrumentationRegistry
|
||||
import com.android.internal.util.test.FakeSettingsProvider
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
@@ -33,6 +36,8 @@ import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentMatchers.any
|
||||
import org.mockito.ArgumentMatchers.anyBoolean
|
||||
import org.mockito.ArgumentMatchers.anyFloat
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.ArgumentMatchers.eq
|
||||
import org.mockito.Mock
|
||||
@@ -44,7 +49,9 @@ import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.times
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.verifyNoMoreInteractions
|
||||
import org.mockito.Mockito.verifyZeroInteractions
|
||||
import org.mockito.junit.MockitoJUnit
|
||||
import org.mockito.stubbing.OngoingStubbing
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@@ -58,7 +65,10 @@ import java.util.concurrent.TimeUnit
|
||||
class InputManagerServiceTests {
|
||||
|
||||
@get:Rule
|
||||
val rule = MockitoJUnit.rule()!!
|
||||
val mockitoRule = MockitoJUnit.rule()!!
|
||||
|
||||
@get:Rule
|
||||
val fakeSettingsProviderRule = FakeSettingsProvider.rule()!!
|
||||
|
||||
@Mock
|
||||
private lateinit var native: NativeInputManagerService
|
||||
@@ -66,17 +76,25 @@ class InputManagerServiceTests {
|
||||
@Mock
|
||||
private lateinit var wmCallbacks: InputManagerService.WindowManagerCallbacks
|
||||
|
||||
@Mock
|
||||
private lateinit var uEventManager: UEventManager
|
||||
|
||||
private lateinit var service: InputManagerService
|
||||
private lateinit var localService: InputManagerInternal
|
||||
private lateinit var context: Context
|
||||
private lateinit var testLooper: TestLooper
|
||||
private lateinit var contentResolver: MockContentResolver
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
context = spy(ContextWrapper(InstrumentationRegistry.getContext()))
|
||||
contentResolver = MockContentResolver(context)
|
||||
contentResolver.addProvider(Settings.AUTHORITY, FakeSettingsProvider())
|
||||
whenever(context.contentResolver).thenReturn(contentResolver)
|
||||
testLooper = TestLooper()
|
||||
service =
|
||||
InputManagerService(object : InputManagerService.Injector(context, testLooper.looper) {
|
||||
InputManagerService(object : InputManagerService.Injector(
|
||||
context, testLooper.looper, uEventManager) {
|
||||
override fun getNativeService(
|
||||
service: InputManagerService?
|
||||
): NativeInputManagerService {
|
||||
@@ -91,10 +109,37 @@ class InputManagerServiceTests {
|
||||
service.setWindowManagerCallbacks(wmCallbacks)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStart() {
|
||||
verifyZeroInteractions(native)
|
||||
|
||||
service.start()
|
||||
verify(native).start()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInputSettingsUpdatedOnSystemRunning() {
|
||||
verifyZeroInteractions(native)
|
||||
|
||||
service.systemRunning()
|
||||
|
||||
verify(native).setPointerSpeed(anyInt())
|
||||
verify(native).setTouchpadPointerSpeed(anyInt())
|
||||
verify(native).setTouchpadNaturalScrollingEnabled(anyBoolean())
|
||||
verify(native).setTouchpadTapToClickEnabled(anyBoolean())
|
||||
verify(native).setTouchpadRightClickZoneEnabled(anyBoolean())
|
||||
verify(native).setShowTouches(anyBoolean())
|
||||
verify(native).reloadPointerIcons()
|
||||
verify(native).notifyKeyGestureTimeoutsChanged()
|
||||
verify(native).setMotionClassifierEnabled(anyBoolean())
|
||||
verify(native).setMaximumObscuringOpacityForTouch(anyFloat())
|
||||
verify(native).setStylusPointerIconEnabled(anyBoolean())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPointerDisplayUpdatesWhenDisplayViewportsChanged() {
|
||||
val displayId = 123
|
||||
`when`(wmCallbacks.pointerDisplayId).thenReturn(displayId)
|
||||
whenever(wmCallbacks.pointerDisplayId).thenReturn(displayId)
|
||||
val viewports = listOf<DisplayViewport>()
|
||||
localService.setDisplayViewports(viewports)
|
||||
verify(native).setDisplayViewports(any(Array<DisplayViewport>::class.java))
|
||||
@@ -337,3 +382,5 @@ class InputManagerServiceTests {
|
||||
thread.join(100 /*millis*/)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall)
|
||||
|
||||
@@ -105,6 +105,8 @@ class KeyboardBacklightControllerTests {
|
||||
private lateinit var iInputManager: IInputManager
|
||||
@Mock
|
||||
private lateinit var native: NativeInputManagerService
|
||||
@Mock
|
||||
private lateinit var uEventManager: UEventManager
|
||||
private lateinit var keyboardBacklightController: KeyboardBacklightController
|
||||
private lateinit var context: Context
|
||||
private lateinit var dataStore: PersistentDataStore
|
||||
@@ -130,7 +132,7 @@ class KeyboardBacklightControllerTests {
|
||||
})
|
||||
testLooper = TestLooper()
|
||||
keyboardBacklightController = KeyboardBacklightController(context, native, dataStore,
|
||||
testLooper.looper, FakeAnimatorFactory())
|
||||
testLooper.looper, FakeAnimatorFactory(), uEventManager)
|
||||
InputManagerGlobal.resetInstance(iInputManager)
|
||||
val inputManager = InputManager(context)
|
||||
`when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager)
|
||||
|
||||
Reference in New Issue
Block a user