• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 #include <android/input.h>
19 #include <jni.h>
20 #include <nativehelper/ScopedLocalFrame.h>
21 #include <nativehelper/ScopedLocalRef.h>
22 #include <nativehelper/ScopedUtfChars.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include <map>
29 #include <sstream>
30 #include <unordered_map>
31 #include <vector>
32 
33 #define LOG_TAG "InputDeviceKeyLayoutMapTest"
34 
35 namespace android {
36 
37 // Loads Generic.kl file and returns it as a std::map from scancode to key code.
loadGenericKl(std::string genericKl)38 std::map<int, std::string> loadGenericKl(std::string genericKl) {
39     std::map<int, std::string> result;
40     std::istringstream ssFile(genericKl);
41 
42     for (std::string line; std::getline(ssFile, line);) {
43         if (line.empty() || line[0] == '#') {
44             // Skip the comment lines
45             continue;
46         }
47 
48         std::string type, code, label, flags;
49         std::istringstream ssLine(line);
50         ssLine >> type >> code >> label >> flags;
51 
52         // Skip non-key mappings.
53         if (type != "key") {
54             continue;
55         }
56 
57         // Skip HID usage keys.
58         if (code == "usage") {
59             continue;
60         }
61 
62         // Skip keys with flags like "FUNCTION"
63         if (!flags.empty()) {
64             continue;
65         }
66 
67         result.emplace(std::stoi(code), label);
68     }
69 
70     return result;
71 }
72 
android_view_cts_nativeLoadKeyLayout(JNIEnv * env,jclass,jstring genericKl)73 static jobject android_view_cts_nativeLoadKeyLayout(JNIEnv* env, jclass, jstring genericKl) {
74     ScopedUtfChars keyLayout(env, genericKl);
75     if (keyLayout.c_str() == nullptr) {
76         return nullptr;
77     }
78     std::map<int, std::string> map = loadGenericKl(keyLayout.c_str());
79 
80     ScopedLocalRef<jclass> hashMapClazz(env, env->FindClass("java/util/HashMap"));
81 
82     jmethodID hashMapConstructID = env->GetMethodID(hashMapClazz.get(), "<init>", "()V");
83 
84     jmethodID hashMapPutID =
85             env->GetMethodID(hashMapClazz.get(), "put",
86                              "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
87 
88     ScopedLocalRef<jclass> integerClazz(env, env->FindClass("java/lang/Integer"));
89 
90     jmethodID integerConstructID = env->GetMethodID(integerClazz.get(), "<init>", "(I)V");
91 
92     jobject keyLayoutMap = env->NewObject(hashMapClazz.get(), hashMapConstructID);
93 
94     {
95         ScopedLocalFrame localFrame(env);
96         for (const auto& [key, label] : map) {
97             env->CallObjectMethod(keyLayoutMap, hashMapPutID, env->NewStringUTF(label.c_str()),
98                                   env->NewObject(integerClazz.get(), integerConstructID, key));
99         }
100     }
101     return keyLayoutMap;
102 }
103 
104 } // namespace android
105 
106 static JNINativeMethod gMethods[] = {
107         {"nativeLoadKeyLayout", "(Ljava/lang/String;)Ljava/util/Map;",
108          (void*)android::android_view_cts_nativeLoadKeyLayout},
109 };
110 
register_android_view_cts_InputDeviceKeyLayoutMapTest(JNIEnv * env)111 int register_android_view_cts_InputDeviceKeyLayoutMapTest(JNIEnv* env) {
112     jclass clazz = env->FindClass("android/view/cts/input/InputDeviceKeyLayoutMapTest");
113     return env->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(JNINativeMethod));
114 }
115