b/12068020 Make kb layouts only unique to vendor/product

Instead of storing a kb layout per device descriptor (which is expected
to be unique), store it for each vendor/product. This way we can keep
a consistent layout between identical but physically different keyboards.

There are some corner cases this is expected to fail on, namely devices
that incorrectly have the same vendor/product id. Devices that don't
define a vendor/product id will continue to use the descriptor to store
layout files.

Change-Id: Id0890d13e1c859eaf993d4831b7b1acbaf5df80f
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 4ab2086..12a1c7a 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -99,6 +99,12 @@
     jclass clazz;
 } gMotionEventClassInfo;
 
+static struct {
+    jclass clazz;
+    jmethodID constructor;
+} gInputDeviceIdentifierInfo;
+
+
 
 // --- Global functions ---
 
@@ -183,7 +189,7 @@
     virtual void getReaderConfiguration(InputReaderConfiguration* outConfig);
     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
     virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices);
-    virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const String8& inputDeviceDescriptor);
+    virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier);
     virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier);
 
     /* --- InputDispatcherPolicyInterface implementation --- */
@@ -492,13 +498,16 @@
 }
 
 sp<KeyCharacterMap> NativeInputManager::getKeyboardLayoutOverlay(
-        const String8& inputDeviceDescriptor) {
+        const InputDeviceIdentifier& identifier) {
     JNIEnv* env = jniEnv();
 
     sp<KeyCharacterMap> result;
-    ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string()));
+    ScopedLocalRef<jstring> descriptor(env, env->NewStringUTF(identifier.descriptor.string()));
+    ScopedLocalRef<jobject> identifierObj(env, env->NewObject(gInputDeviceIdentifierInfo.clazz,
+            gInputDeviceIdentifierInfo.constructor, descriptor.get(),
+            identifier.vendor, identifier.product));
     ScopedLocalRef<jobjectArray> arrayObj(env, jobjectArray(env->CallObjectMethod(mServiceObj,
-                gServiceClassInfo.getKeyboardLayoutOverlay, descriptorObj.get())));
+                gServiceClassInfo.getKeyboardLayoutOverlay, identifierObj.get())));
     if (arrayObj.get()) {
         ScopedLocalRef<jstring> filenameObj(env,
                 jstring(env->GetObjectArrayElement(arrayObj.get(), 0)));
@@ -1438,7 +1447,8 @@
             "getPointerIcon", "()Landroid/view/PointerIcon;");
 
     GET_METHOD_ID(gServiceClassInfo.getKeyboardLayoutOverlay, clazz,
-            "getKeyboardLayoutOverlay", "(Ljava/lang/String;)[Ljava/lang/String;");
+            "getKeyboardLayoutOverlay",
+            "(Landroid/hardware/input/InputDeviceIdentifier;)[Ljava/lang/String;");
 
     GET_METHOD_ID(gServiceClassInfo.getDeviceAlias, clazz,
             "getDeviceAlias", "(Ljava/lang/String;)Ljava/lang/String;");
@@ -1458,6 +1468,13 @@
     FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
     gMotionEventClassInfo.clazz = jclass(env->NewGlobalRef(gMotionEventClassInfo.clazz));
 
+    // InputDeviceIdentifier
+
+    FIND_CLASS(gInputDeviceIdentifierInfo.clazz, "android/hardware/input/InputDeviceIdentifier");
+    gInputDeviceIdentifierInfo.clazz = jclass(env->NewGlobalRef(gInputDeviceIdentifierInfo.clazz));
+    GET_METHOD_ID(gInputDeviceIdentifierInfo.constructor, gInputDeviceIdentifierInfo.clazz,
+            "<init>", "(Ljava/lang/String;II)V");
+
     return 0;
 }