author | yongguang.hong <yongguang.hong@amlogic.com> | 2018-03-16 01:25:25 (GMT) |
---|---|---|
committer | jie.yuan <jie.yuan@amlogic.com> | 2018-03-27 09:01:03 (GMT) |
commit | fc311a56bb7e7f2cc86e01a8aa389fb7e3f56343 (patch) | |
tree | 70ef9fa8c539bebe02e45f7717a5fb6008fee119 | |
parent | e818c085daa1f937529c3c0196e8131f85bffe0f (diff) | |
download | ampere-fc311a56bb7e7f2cc86e01a8aa389fb7e3f56343.zip ampere-fc311a56bb7e7f2cc86e01a8aa389fb7e3f56343.tar.gz ampere-fc311a56bb7e7f2cc86e01a8aa389fb7e3f56343.tar.bz2 |
wifi/bt: use short key for RC voice control [1/3]
PD#157669
Change-Id: I178a4442e355de41fcaafdb763f8ef59fb44c955
-rw-r--r-- | frameworks/core/jni/Android.mk | 34 | ||||
-rw-r--r-- | frameworks/core/jni/droid_logic_RemoteControl.cpp | 256 | ||||
-rw-r--r-- | frameworks/core/res/Android.mk | 6 | ||||
-rw-r--r-- | frameworks/core/res/src/com/droidlogic/DialogBluetoothService.java | 60 |
4 files changed, 333 insertions, 23 deletions
diff --git a/frameworks/core/jni/Android.mk b/frameworks/core/jni/Android.mk index 1d64600..e1b8ac2 100644 --- a/frameworks/core/jni/Android.mk +++ b/frameworks/core/jni/Android.mk @@ -1,5 +1,6 @@ LOCAL_PATH:= $(call my-dir) +ifeq ($(SUPPORT_HDMIIN),true) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ @@ -18,8 +19,8 @@ LOCAL_C_INCLUDES += \ external/skia/include/core \ libcore/include \ libcore/include/libsuspend \ - $(call include-path-for, libhardware)/hardware \ - $(call include-path-for, libhardware_legacy)/hardware_legacy + $(call include-path-for, libhardware)/hardware \ + $(call include-path-for, libhardware_legacy)/hardware_legacy ifeq ($(strip $(BOARD_ALSA_AUDIO)),tiny) LOCAL_C_INCLUDES += external/tinyalsa/include @@ -61,10 +62,12 @@ endif include $(BUILD_SHARED_LIBRARY) +endif + include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - droid_logic_DisplaySetting.cpp + droid_logic_DisplaySetting.cpp LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) @@ -113,4 +116,29 @@ endif include $(BUILD_SHARED_LIBRARY) + +########### build libremotecontrol + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + droid_logic_RemoteControl.cpp + +LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) + +LOCAL_MODULE := libremotecontrol_jni + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libcutils \ + libgui \ + libnativehelper \ + libandroid_runtime + +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26 && echo OK),OK) +LOCAL_PROPRIETARY_MODULE := true +endif + +include $(BUILD_SHARED_LIBRARY) + include $(LOCAL_PATH)/hdmi_cec/Android.mk diff --git a/frameworks/core/jni/droid_logic_RemoteControl.cpp b/frameworks/core/jni/droid_logic_RemoteControl.cpp new file mode 100644 index 0000000..4cd5e22 --- a/dev/null +++ b/frameworks/core/jni/droid_logic_RemoteControl.cpp @@ -0,0 +1,256 @@ +//#define LOG_NDEBUG 0 +#define LOG_TAG "remotecontrol_jni" + +#include <jni.h> +#include <JNIHelp.h> + +#include <errno.h> +#include <netinet/in.h> +#include <sys/types.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <pthread.h> + +#include <unistd.h> +#include <utils/Log.h> +#include "utils/misc.h" +#include "android_runtime/AndroidRuntime.h" + + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +static JNIEnv* callbackEnv = NULL;// jni env +static jobject sJniObj = NULL; +static jmethodID method_onSearchStateChanged; + + +#define REMOTE_CONTROL_SOCKET_PATH "/data/misc/bluedroid/.rc_ctrl" + +typedef struct { + pthread_t tid; //main thread id + int server_fd; + int client_fd; + int max_fd; + int signal_fds[2]; + fd_set active_set; +}tMain_IPC; + +tMain_IPC g_mainIPC; +static int uipc_init(void); +static void uipc_deinit(void); + +namespace android +{ + static void classInitNative(JNIEnv* env, jclass clazz) { + ALOGI("%s", __func__); + + //jclass jniCallbackClass = env->FindClass("com/droidlogic/DialogBluetoothService"); + method_onSearchStateChanged = env->GetMethodID(clazz, "searchStateChanged", "(I)V"); + } + + static bool initNative(JNIEnv* env, jobject obj) { + ALOGI("%s", __func__); + sJniObj = env->NewGlobalRef(obj); + + uipc_init(); + + return JNI_TRUE; + } + + static void setMicEnableCallback(int flag) { + ALOGI("%s: flag is: %d", __func__, flag); + callbackEnv->CallVoidMethod(sJniObj, method_onSearchStateChanged, (jint)flag); + } + + static bool cleanupNative(JNIEnv *env, jobject obj) { + env->DeleteGlobalRef(sJniObj); + uipc_deinit(); + return JNI_TRUE; + } + + static JNINativeMethod sMethods[] = { + {"classInitNative", "()V", (void *) classInitNative}, + {"initNative", "()Z", (void *) initNative}, + {"cleanupNative", "()Z", (void*) cleanupNative}, + }; + + + int register_android_RemoteControl(JNIEnv* env) { + ALOGI("%s: ++", __func__); + return jniRegisterNativeMethods(env, "com/droidlogic/DialogBluetoothService", + sMethods, NELEM(sMethods)); + } +} // end namespace android + +using namespace android; + +static void *listen_task(void *arg) { + int ret; + fd_set read_fds; + char sig_recv = 0; + ssize_t readlen = 0; + + ALOGI("%s:main thread run...", __func__); + + //attach java + JavaVM* vm = AndroidRuntime::getJavaVM(); + JavaVMAttachArgs args; + char name[] = "Remote control service Callback Thread"; + args.version = JNI_VERSION_1_4; + args.name = name; + args.group = NULL; + vm->AttachCurrentThread(&callbackEnv, &args); + + while (1) { + read_fds = g_mainIPC.active_set; + ret = select(g_mainIPC.max_fd + 1, &read_fds, NULL, NULL, NULL); + ALOGI("%s:interrupt done, err=%d", __func__, errno); + if (ret == -1 && errno == EINTR) continue; + if (FD_ISSET(g_mainIPC.signal_fds[0], &read_fds)) { + //wakeup interrupt + readlen = recv(g_mainIPC.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL); + if (ret == -1 && errno == EINTR) continue; + if (sig_recv == 0) break; + } + else if (FD_ISSET(g_mainIPC.server_fd, &read_fds)) { + //client connect + struct sockaddr_un remote; + socklen_t len = sizeof(struct sockaddr_un); + g_mainIPC.client_fd = accept(g_mainIPC.server_fd, (struct sockaddr *)&remote, &len); + if (g_mainIPC.client_fd > 0) { + FD_SET(g_mainIPC.client_fd, &g_mainIPC.active_set); + g_mainIPC.max_fd = MAX(g_mainIPC.max_fd, g_mainIPC.client_fd); + } + + } + else if (FD_ISSET(g_mainIPC.client_fd, &read_fds)) { + //read data + readlen = recv(g_mainIPC.client_fd, &sig_recv, sizeof(sig_recv), MSG_WAITALL); + ALOGI("%s:rx readlen=%d, err=%d", __func__, readlen, errno); + if (readlen == 1 && errno == 0) { + setMicEnableCallback((int)sig_recv); + } + else if (errno != EINTR) { + FD_CLR(g_mainIPC.client_fd, &g_mainIPC.active_set); + } + } + + } + + //detach java + vm->DetachCurrentThread(); + + //cleanup + close(g_mainIPC.signal_fds[0]); + close(g_mainIPC.signal_fds[1]); + close(g_mainIPC.client_fd); + close(g_mainIPC.server_fd); + FD_ZERO(&g_mainIPC.active_set); + + return NULL; +} + + +static int create_server_socket(const char *name) { + struct sockaddr_un addr; + socklen_t alen; + int err, n = 1; + size_t namelen; + int s = socket(AF_LOCAL, SOCK_STREAM, 0); + if (s < 0) return -1; + + memset(&addr, 0, sizeof(addr)); + namelen = strlen(name); + if ((namelen + 1) > sizeof(addr.sun_path)) + return -1; + + /* + * Note: The path in this case is *not* supposed to be + * '\0'-terminated. ("man 7 unix" for the gory details.) + */ + addr.sun_path[0] = 0; + memcpy(addr.sun_path + 1, name, namelen); + addr.sun_family = AF_LOCAL; + alen = namelen + offsetof(struct sockaddr_un, sun_path) + 1; + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)); + + if (bind(s, (struct sockaddr *)&addr, alen) < 0) { + ALOGE("bind failed:%d", errno); + return -1; + } + + if (listen(s, 5) < 0) { + ALOGE("listen failed:%d", errno); + return -1; + } + + ALOGI("%s: socket=%d", __func__, s); + + return s; +} + +pthread_t create_listen_thread() { + pthread_t tid; + + if (pthread_create(&tid, (const pthread_attr_t *) NULL, listen_task, NULL) < 0) + { + ALOGE("create_listen_thread pthread_create failed:%d", errno); + return -1; + } + + return tid; +} + +static int uipc_init(void) { + ALOGI("%s: ++", __func__); + + memset(&g_mainIPC, 0, sizeof(g_mainIPC)); + + FD_ZERO(&g_mainIPC.active_set); + + /* setup interrupt socket pair */ + if (socketpair(AF_UNIX, SOCK_STREAM, 0, g_mainIPC.signal_fds) < 0) { + return -1; + } + FD_SET(g_mainIPC.signal_fds[0], &g_mainIPC.active_set); + g_mainIPC.max_fd = MAX(g_mainIPC.max_fd, g_mainIPC.signal_fds[0]); + + //create server socket + g_mainIPC.server_fd = create_server_socket(REMOTE_CONTROL_SOCKET_PATH); + FD_SET(g_mainIPC.server_fd, &g_mainIPC.active_set); + g_mainIPC.max_fd = MAX(g_mainIPC.max_fd, g_mainIPC.server_fd); + + g_mainIPC.tid = create_listen_thread(); + + return 0; +} + +static void uipc_deinit(void) { + //exit thread + if (g_mainIPC.signal_fds[1] > 0) { + char sig_off = 0; + send(g_mainIPC.signal_fds[1], &sig_off, sizeof(sig_off), MSG_NOSIGNAL); + } + if (g_mainIPC.tid) pthread_join(g_mainIPC.tid, NULL); +} + +extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) +{ + JNIEnv* env = NULL; + jint result = -1; + + ALOGI("%s: ++", __func__); + + if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { + ALOGE("GetEnv failed!"); + return result; + } + + register_android_RemoteControl(env); + + return JNI_VERSION_1_4; +} + diff --git a/frameworks/core/res/Android.mk b/frameworks/core/res/Android.mk index ff4caa1..96959ce 100644 --- a/frameworks/core/res/Android.mk +++ b/frameworks/core/res/Android.mk @@ -4,10 +4,10 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-subdir-java-files) LOCAL_JAVA_LIBRARIES := droidlogic \ - android.hidl.manager-V1.0-java - + android.hidl.manager-V1.0-java +LOCAL_JNI_SHARED_LIBRARIES := libremotecontrol_jni LOCAL_STATIC_JAVA_LIBRARIES := android.hidl.base-V1.0-java-static \ - vendor.amlogic.hardware.droidvold-V1.0-java + vendor.amlogic.hardware.droidvold-V1.0-java #LOCAL_SDK_VERSION := current diff --git a/frameworks/core/res/src/com/droidlogic/DialogBluetoothService.java b/frameworks/core/res/src/com/droidlogic/DialogBluetoothService.java index 3a46da6..d49d436 100644 --- a/frameworks/core/res/src/com/droidlogic/DialogBluetoothService.java +++ b/frameworks/core/res/src/com/droidlogic/DialogBluetoothService.java @@ -75,6 +75,8 @@ public class DialogBluetoothService extends Service { "DA14582 IR&M&VRemote", "DA1458x RCU", "RemoteB008", + "Amlogic_RC16", + "Amlogic_RC18" }; // Time to wait before connecting to bonded devices @@ -113,13 +115,13 @@ public class DialogBluetoothService extends Service { private static final UUID CLIENT_CONFIG_DESCRIPTOR = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); // Ble Remote HID Report Characteristic instance IDs (Audio) - private static final int HID_STREAM_ENABLE_WRITE_INSTANCE = 59; - private static final int HID_STREAM_ENABLE_READ_INSTANCE = 62; - private static final int HID_STREAM_DATA_MIN_INSTANCE = 66; - private static final int HID_STREAM_DATA_MAX_INSTANCE = 74; - private static final int HID_STREAM_DATA_REP5_INSTANCE = 66; - private static final int HID_STREAM_DATA_REP6_INSTANCE = 70; - private static final int HID_STREAM_DATA_REP7_INSTANCE = 74; + private static final int HID_STREAM_ENABLE_WRITE_INSTANCE = 65;//59; hugo modify for huitong rc; + private static final int HID_STREAM_ENABLE_READ_INSTANCE = 61;//62; + private static final int HID_STREAM_DATA_MIN_INSTANCE = 41;//66; + private static final int HID_STREAM_DATA_MAX_INSTANCE = 45;//74; + private static final int HID_STREAM_DATA_REP5_INSTANCE = 53;//66; + private static final int HID_STREAM_DATA_REP6_INSTANCE = 57;//70; + private static final int HID_STREAM_DATA_REP7_INSTANCE = 49;//74; // Data private BluetoothManager mBluetoothManager; @@ -137,6 +139,11 @@ public class DialogBluetoothService extends Service { private AudioManager mAudioManager; private int connectedState = 0; + static { + System.loadLibrary("remotecontrol_jni"); + classInitNative(); + } + /** * Used in order for the service to be notified about HID devices connection and bond state. */ @@ -294,6 +301,8 @@ public class DialogBluetoothService extends Service { filter.addAction(BluetoothInputDevice.ACTION_CONNECTION_STATE_CHANGED); registerReceiver(receiver, filter); + initNative(); + // On service start, check for supported devices connectToBondedDevices(); } @@ -304,6 +313,7 @@ public class DialogBluetoothService extends Service { mHandler.removeCallbacksAndMessages(null); unregisterReceiver(receiver); close(); + cleanupNative(); } @Override @@ -403,11 +413,14 @@ public class DialogBluetoothService extends Service { */ public void close() { Log.w(TAG, "Close called!"); - if (mBluetoothGatt == null) { - return; + if (mBluetoothGatt != null) { + mBluetoothGatt.close(); } - mBluetoothGatt.close(); mBluetoothGatt = null; + enableCharacteristic = null; + rep5Characteristic = null; + rep6Characteristic = null; + rep7Characteristic = null; } @@ -420,16 +433,17 @@ public class DialogBluetoothService extends Service { return; Log.i(TAG,"Write Enable: " + flag); + /* masked by hugo if (flag != 0) { showToast(AUDIO_STREAM_TEXT_ON); broadcastUpdate(ACTION_AUDIO_TRANSFER, AUDIO_STREAM_TEXT_ON); } else { showToast(AUDIO_STREAM_TEXT_OFF); broadcastUpdate(ACTION_AUDIO_TRANSFER, AUDIO_STREAM_TEXT_OFF); - } + }*/ prevInstance = 0; - byte packet[] = new byte[20]; + byte packet[] = new byte[1]; packet[0] = (byte) flag; enableCharacteristic.setValue(packet); mBluetoothGatt.writeCharacteristic(enableCharacteristic); @@ -515,11 +529,14 @@ public class DialogBluetoothService extends Service { // Possible audio button report else if ((HID_REPORT_CHAR.compareTo(characteristic.getUuid()) == 0) && (instance == HID_STREAM_ENABLE_READ_INSTANCE)) { byte[] value = characteristic.getValue(); - Log.i(TAG,"Enable char "+String.format("%x %x", value[0]&0xff, value[1]&0xff)); - int type = value[1]; - if (type == 0) { - // got enable/disable - sendEnable(value[0] != 0 ? 1 : 0); + Log.i(TAG,"rx key: "+ String.format("%x %x", value[0], value[1])); + if (value[0] == 0x21 && value[1] == 0x02) { + Log.i(TAG,"enable RC MIC "); + //sendEnable(0x01); + } + else if (value[0] == 0x42 && value[1] == 0x00) { + Log.i(TAG,"disable RC MIC "); + //sendEnable(0x00); } } } @@ -633,6 +650,12 @@ public class DialogBluetoothService extends Service { }; + void searchStateChanged(int status) { + Log.i(TAG,"state=" + status); + sendEnable(status == 0 ? 0 : 1); + } + + /***** * broadcastUpdate functions to send data back to BleActivity */ @@ -663,4 +686,7 @@ public class DialogBluetoothService extends Service { }); } + private native static void classInitNative(); + private native boolean initNative(); + private native boolean cleanupNative(); } |