Add coretest for android.view.InputDevice.
Add coretest cases for android.view.InputDevice, for parcel/unparcel
input device object.
Bug: 173326051
Test: atest InputDeviceTest
Change-Id: I5dea2783b11a195dc2eb8337aad77368b98cf068
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 02a9788..aa1acc1 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.input.InputManager;
import android.os.Build;
@@ -25,6 +26,8 @@
import android.util.AndroidRuntimeException;
import android.util.SparseIntArray;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.text.Normalizer;
/**
@@ -297,6 +300,8 @@
private static native char nativeGetDisplayLabel(long ptr, int keyCode);
private static native int nativeGetKeyboardType(long ptr);
private static native KeyEvent[] nativeGetEvents(long ptr, char[] chars);
+ private static native KeyCharacterMap nativeObtainEmptyKeyCharacterMap(int deviceId);
+ private static native boolean nativeEquals(long ptr1, long ptr2);
private KeyCharacterMap(Parcel in) {
if (in == null) {
@@ -323,6 +328,18 @@
}
/**
+ * Obtain empty key character map
+ * @param deviceId The input device ID
+ * @return The KeyCharacterMap object
+ * @hide
+ */
+ @VisibleForTesting
+ @Nullable
+ public static KeyCharacterMap obtainEmptyMap(int deviceId) {
+ return nativeObtainEmptyKeyCharacterMap(deviceId);
+ }
+
+ /**
* Loads the key character maps for the keyboard with the specified device id.
*
* @param deviceId The device id of the keyboard.
@@ -729,6 +746,18 @@
return 0;
}
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof KeyCharacterMap)) {
+ return false;
+ }
+ KeyCharacterMap peer = (KeyCharacterMap) obj;
+ if (mPtr == 0 || peer.mPtr == 0) {
+ return mPtr == peer.mPtr;
+ }
+ return nativeEquals(mPtr, peer.mPtr);
+ }
+
/**
* Thrown by {@link KeyCharacterMap#load} when a key character map could not be loaded.
*/
diff --git a/core/jni/android_view_KeyCharacterMap.cpp b/core/jni/android_view_KeyCharacterMap.cpp
index ebc507a..469e577 100644
--- a/core/jni/android_view_KeyCharacterMap.cpp
+++ b/core/jni/android_view_KeyCharacterMap.cpp
@@ -16,9 +16,10 @@
#include <android_runtime/AndroidRuntime.h>
-#include <input/KeyCharacterMap.h>
-#include <input/Input.h>
#include <binder/Parcel.h>
+#include <input/Input.h>
+#include <input/InputDevice.h>
+#include <input/KeyCharacterMap.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
@@ -75,6 +76,10 @@
reinterpret_cast<jlong>(nativeMap));
}
+static jobject nativeObtainEmptyKeyCharacterMap(JNIEnv* env, jobject /* clazz */, jint deviceId) {
+ return android_view_KeyCharacterMap_create(env, deviceId, nullptr);
+}
+
static jlong nativeReadFromParcel(JNIEnv *env, jobject clazz, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
if (!parcel) {
@@ -224,33 +229,37 @@
return result;
}
+static jboolean nativeEquals(JNIEnv* env, jobject clazz, jlong ptr1, jlong ptr2) {
+ const std::shared_ptr<KeyCharacterMap>& map1 =
+ (reinterpret_cast<NativeKeyCharacterMap*>(ptr1))->getMap();
+ const std::shared_ptr<KeyCharacterMap>& map2 =
+ (reinterpret_cast<NativeKeyCharacterMap*>(ptr2))->getMap();
+ if (map1 == nullptr || map2 == nullptr) {
+ return map1 == map2;
+ }
+ return static_cast<jboolean>(*map1 == *map2);
+}
/*
* JNI registration.
*/
static const JNINativeMethod g_methods[] = {
- /* name, signature, funcPtr */
- { "nativeReadFromParcel", "(Landroid/os/Parcel;)J",
- (void*)nativeReadFromParcel },
- { "nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
- (void*)nativeWriteToParcel },
- { "nativeDispose", "(J)V",
- (void*)nativeDispose },
- { "nativeGetCharacter", "(JII)C",
- (void*)nativeGetCharacter },
- { "nativeGetFallbackAction", "(JIILandroid/view/KeyCharacterMap$FallbackAction;)Z",
- (void*)nativeGetFallbackAction },
- { "nativeGetNumber", "(JI)C",
- (void*)nativeGetNumber },
- { "nativeGetMatch", "(JI[CI)C",
- (void*)nativeGetMatch },
- { "nativeGetDisplayLabel", "(JI)C",
- (void*)nativeGetDisplayLabel },
- { "nativeGetKeyboardType", "(J)I",
- (void*)nativeGetKeyboardType },
- { "nativeGetEvents", "(J[C)[Landroid/view/KeyEvent;",
- (void*)nativeGetEvents },
+ /* name, signature, funcPtr */
+ {"nativeReadFromParcel", "(Landroid/os/Parcel;)J", (void*)nativeReadFromParcel},
+ {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V", (void*)nativeWriteToParcel},
+ {"nativeDispose", "(J)V", (void*)nativeDispose},
+ {"nativeGetCharacter", "(JII)C", (void*)nativeGetCharacter},
+ {"nativeGetFallbackAction", "(JIILandroid/view/KeyCharacterMap$FallbackAction;)Z",
+ (void*)nativeGetFallbackAction},
+ {"nativeGetNumber", "(JI)C", (void*)nativeGetNumber},
+ {"nativeGetMatch", "(JI[CI)C", (void*)nativeGetMatch},
+ {"nativeGetDisplayLabel", "(JI)C", (void*)nativeGetDisplayLabel},
+ {"nativeGetKeyboardType", "(J)I", (void*)nativeGetKeyboardType},
+ {"nativeGetEvents", "(J[C)[Landroid/view/KeyEvent;", (void*)nativeGetEvents},
+ {"nativeObtainEmptyKeyCharacterMap", "(I)Landroid/view/KeyCharacterMap;",
+ (void*)nativeObtainEmptyKeyCharacterMap},
+ {"nativeEquals", "(JJ)Z", (void*)nativeEquals},
};
int register_android_view_KeyCharacterMap(JNIEnv* env)
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 335c8d0..eacf5b2 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -9,14 +9,17 @@
android_test {
name: "InputTests",
- srcs: ["src/**/*.kt"],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
platform_apis: true,
certificate: "platform",
static_libs: [
- "androidx.test.ext.junit",
- "androidx.test.rules",
- "truth-prebuilt",
- "ub-uiautomator",
- ],
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "truth-prebuilt",
+ "ub-uiautomator",
+ ],
test_suites: ["device-tests"],
}
diff --git a/tests/Input/src/com/android/test/input/InputDeviceTest.java b/tests/Input/src/com/android/test/input/InputDeviceTest.java
new file mode 100644
index 0000000..6350077
--- /dev/null
+++ b/tests/Input/src/com/android/test/input/InputDeviceTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 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 android.view;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class InputDeviceTest {
+ private static final float DELTA = 0.01f;
+ private static final int DEVICE_ID = 1000;
+
+ private void assertMotionRangeEquals(InputDevice.MotionRange range,
+ InputDevice.MotionRange outRange) {
+ assertEquals(range.getAxis(), outRange.getAxis());
+ assertEquals(range.getSource(), outRange.getSource());
+ assertEquals(range.getMin(), outRange.getMin(), DELTA);
+ assertEquals(range.getMax(), outRange.getMax(), DELTA);
+ assertEquals(range.getFlat(), outRange.getFlat(), DELTA);
+ assertEquals(range.getFuzz(), outRange.getFuzz(), DELTA);
+ assertEquals(range.getResolution(), outRange.getResolution(), DELTA);
+ }
+
+ private void assertDeviceEquals(InputDevice device, InputDevice outDevice) {
+ assertEquals(device.getId(), outDevice.getId());
+ assertEquals(device.getGeneration(), outDevice.getGeneration());
+ assertEquals(device.getControllerNumber(), outDevice.getControllerNumber());
+ assertEquals(device.getName(), outDevice.getName());
+ assertEquals(device.getVendorId(), outDevice.getVendorId());
+ assertEquals(device.getProductId(), outDevice.getProductId());
+ assertEquals(device.getDescriptor(), outDevice.getDescriptor());
+ assertEquals(device.isExternal(), outDevice.isExternal());
+ assertEquals(device.getSources(), outDevice.getSources());
+ assertEquals(device.getKeyboardType(), outDevice.getKeyboardType());
+ assertEquals(device.getMotionRanges().size(), outDevice.getMotionRanges().size());
+
+ KeyCharacterMap keyCharacterMap = device.getKeyCharacterMap();
+ KeyCharacterMap outKeyCharacterMap = outDevice.getKeyCharacterMap();
+ assertTrue("keyCharacterMap not equal", keyCharacterMap.equals(outKeyCharacterMap));
+
+ for (int j = 0; j < device.getMotionRanges().size(); j++) {
+ assertMotionRangeEquals(device.getMotionRanges().get(j),
+ outDevice.getMotionRanges().get(j));
+ }
+ }
+
+ private void assertInputDeviceParcelUnparcel(KeyCharacterMap keyCharacterMap) {
+ final InputDevice device =
+ new InputDevice(DEVICE_ID, 0 /* generation */, 0 /* controllerNumber */, "name",
+ 0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
+ 0 /* sources */, 0 /* keyboardType */, keyCharacterMap,
+ false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
+ true /* hasSensor */, false /* hasBattery */);
+
+ Parcel parcel = Parcel.obtain();
+ device.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ InputDevice outDevice = InputDevice.CREATOR.createFromParcel(parcel);
+ assertDeviceEquals(device, outDevice);
+ }
+
+ @Test
+ public void testParcelUnparcelInputDevice_VirtualCharacterMap() {
+ final KeyCharacterMap keyCharacterMap =
+ KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
+ assertInputDeviceParcelUnparcel(keyCharacterMap);
+ }
+
+ @Test
+ public void testParcelUnparcelInputDevice_EmptyCharacterMap() {
+ final KeyCharacterMap keyCharacterMap = KeyCharacterMap.obtainEmptyMap(DEVICE_ID);
+ assertInputDeviceParcelUnparcel(keyCharacterMap);
+ }
+}