Merge changes from topic "inputdevice-supportsusi"
* changes: BatteryController: Only listen to UEvents from power_supply changes BatteryController: Remove the /sys prefix when adding UEvent listener Determine whether an input device supports USI using IDC files
This commit is contained in:
committed by
Android (Google) Code Review
commit
fdf025854e
@@ -80,6 +80,7 @@ public final class InputDevice implements Parcelable {
|
||||
private final boolean mHasButtonUnderPad;
|
||||
private final boolean mHasSensor;
|
||||
private final boolean mHasBattery;
|
||||
private final boolean mSupportsUsi;
|
||||
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
|
||||
|
||||
@GuardedBy("mMotionRanges")
|
||||
@@ -462,7 +463,7 @@ public final class InputDevice implements Parcelable {
|
||||
int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
|
||||
KeyCharacterMap keyCharacterMap, @InputDeviceCountryCode int countryCode,
|
||||
boolean hasVibrator, boolean hasMicrophone, boolean hasButtonUnderPad,
|
||||
boolean hasSensor, boolean hasBattery) {
|
||||
boolean hasSensor, boolean hasBattery, boolean supportsUsi) {
|
||||
mId = id;
|
||||
mGeneration = generation;
|
||||
mControllerNumber = controllerNumber;
|
||||
@@ -481,6 +482,7 @@ public final class InputDevice implements Parcelable {
|
||||
mHasSensor = hasSensor;
|
||||
mHasBattery = hasBattery;
|
||||
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
|
||||
mSupportsUsi = supportsUsi;
|
||||
}
|
||||
|
||||
private InputDevice(Parcel in) {
|
||||
@@ -501,6 +503,7 @@ public final class InputDevice implements Parcelable {
|
||||
mHasButtonUnderPad = in.readInt() != 0;
|
||||
mHasSensor = in.readInt() != 0;
|
||||
mHasBattery = in.readInt() != 0;
|
||||
mSupportsUsi = in.readInt() != 0;
|
||||
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
|
||||
|
||||
int numRanges = in.readInt();
|
||||
@@ -538,6 +541,7 @@ public final class InputDevice implements Parcelable {
|
||||
private boolean mHasBattery = false;
|
||||
@InputDeviceCountryCode
|
||||
private int mCountryCode = InputDeviceCountryCode.INVALID;
|
||||
private boolean mSupportsUsi = false;
|
||||
|
||||
/** @see InputDevice#getId() */
|
||||
public Builder setId(int id) {
|
||||
@@ -641,12 +645,18 @@ public final class InputDevice implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @see InputDevice#supportsUsi() () */
|
||||
public Builder setSupportsUsi(boolean supportsUsi) {
|
||||
mSupportsUsi = supportsUsi;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Build {@link InputDevice}. */
|
||||
public InputDevice build() {
|
||||
return new InputDevice(mId, mGeneration, mControllerNumber, mName, mVendorId,
|
||||
mProductId, mDescriptor, mIsExternal, mSources, mKeyboardType, mKeyCharacterMap,
|
||||
mCountryCode, mHasVibrator, mHasMicrophone, mHasButtonUnderPad, mHasSensor,
|
||||
mHasBattery);
|
||||
mHasBattery, mSupportsUsi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1178,6 +1188,15 @@ public final class InputDevice implements Parcelable {
|
||||
return mHasBattery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports whether the device supports the Universal Stylus Initiative (USI) protocol for
|
||||
* styluses.
|
||||
* @hide
|
||||
*/
|
||||
public boolean supportsUsi() {
|
||||
return mSupportsUsi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides information about the range of values for a particular {@link MotionEvent} axis.
|
||||
*
|
||||
@@ -1308,6 +1327,7 @@ public final class InputDevice implements Parcelable {
|
||||
out.writeInt(mHasButtonUnderPad ? 1 : 0);
|
||||
out.writeInt(mHasSensor ? 1 : 0);
|
||||
out.writeInt(mHasBattery ? 1 : 0);
|
||||
out.writeInt(mSupportsUsi ? 1 : 0);
|
||||
|
||||
final int numRanges = mMotionRanges.size();
|
||||
out.writeInt(numRanges);
|
||||
@@ -1361,6 +1381,8 @@ public final class InputDevice implements Parcelable {
|
||||
|
||||
description.append(" Has mic: ").append(mHasMicrophone).append("\n");
|
||||
|
||||
description.append(" Supports USI: ").append(mSupportsUsi).append("\n");
|
||||
|
||||
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
|
||||
appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
|
||||
appendSourceDescriptionIfApplicable(description, SOURCE_DPAD, "dpad");
|
||||
|
||||
@@ -57,9 +57,6 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
|
||||
|
||||
const InputDeviceIdentifier& ident = deviceInfo.getIdentifier();
|
||||
|
||||
// Not sure why, but JNI is complaining when I pass this through directly.
|
||||
jboolean hasMic = deviceInfo.hasMic() ? JNI_TRUE : JNI_FALSE;
|
||||
|
||||
ScopedLocalRef<jobject>
|
||||
inputDeviceObj(env,
|
||||
env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor,
|
||||
@@ -70,8 +67,9 @@ jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& devi
|
||||
deviceInfo.isExternal(), deviceInfo.getSources(),
|
||||
deviceInfo.getKeyboardType(), kcmObj.get(),
|
||||
deviceInfo.getCountryCode(), deviceInfo.hasVibrator(),
|
||||
hasMic, deviceInfo.hasButtonUnderPad(),
|
||||
deviceInfo.hasSensor(), deviceInfo.hasBattery()));
|
||||
deviceInfo.hasMic(), deviceInfo.hasButtonUnderPad(),
|
||||
deviceInfo.hasSensor(), deviceInfo.hasBattery(),
|
||||
deviceInfo.supportsUsi()));
|
||||
|
||||
const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
|
||||
for (const InputDeviceInfo::MotionRange& range: ranges) {
|
||||
@@ -94,7 +92,7 @@ int register_android_view_InputDevice(JNIEnv* env)
|
||||
gInputDeviceClassInfo.ctor =
|
||||
GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
|
||||
"(IIILjava/lang/String;IILjava/lang/"
|
||||
"String;ZIILandroid/view/KeyCharacterMap;IZZZZZ)V");
|
||||
"String;ZIILandroid/view/KeyCharacterMap;IZZZZZZ)V");
|
||||
|
||||
gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz,
|
||||
"addMotionRange", "(IIFFFFF)V");
|
||||
|
||||
@@ -38,7 +38,7 @@ import android.view.InputDevice;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.input.BatteryController.UEventManager.UEventListener;
|
||||
import com.android.server.input.BatteryController.UEventManager.UEventBatteryListener;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
@@ -438,7 +438,7 @@ final class BatteryController {
|
||||
private State mState;
|
||||
|
||||
@Nullable
|
||||
private UEventListener mUEventListener;
|
||||
private UEventBatteryListener mUEventBatteryListener;
|
||||
|
||||
DeviceMonitor(int deviceId) {
|
||||
mState = new State(deviceId);
|
||||
@@ -473,20 +473,26 @@ final class BatteryController {
|
||||
return;
|
||||
}
|
||||
final int deviceId = mState.deviceId;
|
||||
mUEventListener = new UEventListener() {
|
||||
mUEventBatteryListener = new UEventBatteryListener() {
|
||||
@Override
|
||||
public void onUEvent(long eventTime) {
|
||||
public void onBatteryUEvent(long eventTime) {
|
||||
handleUEventNotification(deviceId, eventTime);
|
||||
}
|
||||
};
|
||||
mUEventManager.addListener(mUEventListener, "DEVPATH=" + batteryPath);
|
||||
mUEventManager.addListener(
|
||||
mUEventBatteryListener, "DEVPATH=" + formatDevPath(batteryPath));
|
||||
}
|
||||
|
||||
private String formatDevPath(String path) {
|
||||
// Remove the "/sys" prefix if it has one.
|
||||
return path.startsWith("/sys") ? path.substring(4) : path;
|
||||
}
|
||||
|
||||
// This must be called when the device is no longer being monitored.
|
||||
public void stopMonitoring() {
|
||||
if (mUEventListener != null) {
|
||||
mUEventManager.removeListener(mUEventListener);
|
||||
mUEventListener = null;
|
||||
if (mUEventBatteryListener != null) {
|
||||
mUEventManager.removeListener(mUEventBatteryListener);
|
||||
mUEventBatteryListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,7 +504,7 @@ final class BatteryController {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "state=" + mState
|
||||
+ ", uEventListener=" + (mUEventListener != null ? "added" : "none");
|
||||
+ ", uEventListener=" + (mUEventBatteryListener != null ? "added" : "none");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,7 +513,7 @@ final class BatteryController {
|
||||
interface UEventManager {
|
||||
|
||||
@VisibleForTesting
|
||||
abstract class UEventListener {
|
||||
abstract class UEventBatteryListener {
|
||||
private final UEventObserver mObserver = new UEventObserver() {
|
||||
@Override
|
||||
public void onUEvent(UEvent event) {
|
||||
@@ -517,18 +523,23 @@ final class BatteryController {
|
||||
"UEventListener: Received UEvent: "
|
||||
+ event + " eventTime: " + eventTime);
|
||||
}
|
||||
UEventListener.this.onUEvent(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 onUEvent(long eventTime);
|
||||
public abstract void onBatteryUEvent(long eventTime);
|
||||
}
|
||||
|
||||
default void addListener(UEventListener listener, String match) {
|
||||
default void addListener(UEventBatteryListener listener, String match) {
|
||||
listener.mObserver.startObserving(match);
|
||||
}
|
||||
|
||||
default void removeListener(UEventListener listener) {
|
||||
default void removeListener(UEventBatteryListener listener) {
|
||||
listener.mObserver.stopObserving();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.platform.test.annotations.Presubmit
|
||||
import android.view.InputDevice
|
||||
import androidx.test.InstrumentationRegistry
|
||||
import com.android.server.input.BatteryController.UEventManager
|
||||
import com.android.server.input.BatteryController.UEventManager.UEventBatteryListener
|
||||
import org.hamcrest.Description
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
@@ -260,25 +261,28 @@ class BatteryControllerTests {
|
||||
|
||||
@Test
|
||||
fun testListenersNotifiedOnUEventNotification() {
|
||||
`when`(native.getBatteryDevicePath(DEVICE_ID)).thenReturn("/test/device1")
|
||||
`when`(native.getBatteryDevicePath(DEVICE_ID)).thenReturn("/sys/dev/test/device1")
|
||||
`when`(native.getBatteryStatus(DEVICE_ID)).thenReturn(STATUS_CHARGING)
|
||||
`when`(native.getBatteryCapacity(DEVICE_ID)).thenReturn(78)
|
||||
val listener = createMockListener()
|
||||
val uEventListener = ArgumentCaptor.forClass(UEventManager.UEventListener::class.java)
|
||||
val uEventListener = ArgumentCaptor.forClass(UEventBatteryListener::class.java)
|
||||
batteryController.registerBatteryListener(DEVICE_ID, listener, PID)
|
||||
verify(uEventManager).addListener(uEventListener.capture(), eq("DEVPATH=/test/device1"))
|
||||
// The device paths for UEvent notifications do not include the "/sys" prefix, so verify
|
||||
// that the added listener is configured to match the path without that prefix.
|
||||
verify(uEventManager)
|
||||
.addListener(uEventListener.capture(), eq("DEVPATH=/dev/test/device1"))
|
||||
listener.verifyNotified(DEVICE_ID, status = STATUS_CHARGING, capacity = 0.78f)
|
||||
|
||||
// If the battery state has changed when an UEvent is sent, the listeners are notified.
|
||||
`when`(native.getBatteryCapacity(DEVICE_ID)).thenReturn(80)
|
||||
uEventListener.value!!.onUEvent(TIMESTAMP)
|
||||
uEventListener.value!!.onBatteryUEvent(TIMESTAMP)
|
||||
listener.verifyNotified(DEVICE_ID, status = STATUS_CHARGING, capacity = 0.80f,
|
||||
eventTime = TIMESTAMP)
|
||||
|
||||
// If the battery state has not changed when an UEvent is sent, the listeners are not
|
||||
// notified.
|
||||
clearInvocations(listener)
|
||||
uEventListener.value!!.onUEvent(TIMESTAMP + 1)
|
||||
uEventListener.value!!.onBatteryUEvent(TIMESTAMP + 1)
|
||||
verifyNoMoreInteractions(listener)
|
||||
|
||||
batteryController.unregisterBatteryListener(DEVICE_ID, listener, PID)
|
||||
@@ -293,7 +297,7 @@ class BatteryControllerTests {
|
||||
`when`(native.getBatteryStatus(DEVICE_ID)).thenReturn(STATUS_CHARGING)
|
||||
`when`(native.getBatteryCapacity(DEVICE_ID)).thenReturn(78)
|
||||
val listener = createMockListener()
|
||||
val uEventListener = ArgumentCaptor.forClass(UEventManager.UEventListener::class.java)
|
||||
val uEventListener = ArgumentCaptor.forClass(UEventBatteryListener::class.java)
|
||||
batteryController.registerBatteryListener(DEVICE_ID, listener, PID)
|
||||
verify(uEventManager).addListener(uEventListener.capture(), eq("DEVPATH=/test/device1"))
|
||||
listener.verifyNotified(DEVICE_ID, status = STATUS_CHARGING, capacity = 0.78f)
|
||||
|
||||
@@ -87,6 +87,7 @@ public class InputDeviceTest {
|
||||
.setHasSensor(true)
|
||||
.setHasBattery(true)
|
||||
.setCountryCode(InputDeviceCountryCode.INTERNATIONAL)
|
||||
.setSupportsUsi(true)
|
||||
.build();
|
||||
|
||||
Parcel parcel = Parcel.obtain();
|
||||
|
||||
Reference in New Issue
Block a user