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 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 */ 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 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