• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 #define LOG_NDEBUG 0
18 #define LOG_TAG "CAR.INPUT"
19 
20 #include <string.h>
21 #include <sys/time.h>
22 #include <linux/input.h>
23 #include <jni.h>
24 #include <JNIHelp.h>
25 #include <android/keycodes.h>
26 #include <cutils/log.h>
27 #include <utils/Errors.h>
28 
29 
30 namespace android {
31 
androidKeyCodeToLinuxKeyCode(int androidKeyCode)32 static int androidKeyCodeToLinuxKeyCode(int androidKeyCode) {
33     switch (androidKeyCode) {
34     case AKEYCODE_VOLUME_UP:
35         return KEY_VOLUMEUP;
36     case AKEYCODE_VOLUME_DOWN:
37         return KEY_VOLUMEDOWN;
38     case AKEYCODE_CALL:
39         return KEY_SEND;
40     case AKEYCODE_ENDCALL:
41         return KEY_END;
42     /* TODO add more keys like these:
43     case AKEYCODE_MEDIA_PLAY_PAUSE:
44     case AKEYCODE_MEDIA_STOP:
45     case AKEYCODE_MEDIA_NEXT:
46     case AKEYCODE_MEDIA_PREVIOUS:*/
47     case AKEYCODE_VOICE_ASSIST:
48         return KEY_MICMUTE;
49     default:
50         ALOGW("Unmapped android key code %d dropped", androidKeyCode);
51         return 0;
52     }
53 }
54 
55 /*
56  * Class:     com_android_car_CarInputService
57  * Method:    nativeInjectKeyEvent
58  * Signature: (IIZ)I
59  */
com_android_car_CarInputService_nativeInjectKeyEvent(JNIEnv * env,jobject,jint fd,jint keyCode,jboolean down)60 static jint com_android_car_CarInputService_nativeInjectKeyEvent
61   (JNIEnv *env, jobject /*object*/, jint fd, jint keyCode, jboolean down) {
62     int linuxKeyCode = androidKeyCodeToLinuxKeyCode(keyCode);
63     if (linuxKeyCode == 0) {
64         return BAD_VALUE;
65     }
66     struct input_event ev[2];
67     memset(reinterpret_cast<void*>(&ev), 0, sizeof(ev));
68     struct timeval now;
69     gettimeofday(&now, NULL);
70     // kernel driver is not using time now, but set it to be safe.
71     ev[0].time = now;
72     ev[0].type = EV_KEY;
73     ev[0].code = linuxKeyCode;
74     ev[0].value = (down ? 1 : 0);
75     // force delivery and flushing
76     ev[1].time = now;
77     ev[1].type = EV_SYN;
78     ev[1].code = SYN_REPORT;
79     ev[1].value = 0;
80     ALOGI("injectKeyEvent down %d keyCode %d, value %d", down, ev[0].code, ev[0].value);
81     int r = write(fd, reinterpret_cast<void*>(&ev), sizeof(ev));
82     if (r != sizeof(ev)) {
83         return -EIO;
84     }
85     return 0;
86 }
87 
88 static JNINativeMethod gMethods[] = {
89     { "nativeInjectKeyEvent", "(IIZ)I",
90             (void*)com_android_car_CarInputService_nativeInjectKeyEvent },
91 };
92 
register_com_android_car_CarInputService(JNIEnv * env)93 int register_com_android_car_CarInputService(JNIEnv *env) {
94     return jniRegisterNativeMethods(env, "com/android/car/CarInputService",
95             gMethods, NELEM(gMethods));
96 }
97 
98 } // namespace android
99