blob: 7ec7d86ee647c561c4a720f2bbae157e2cda5d95
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <unistd.h> |
4 | #include <sys/types.h> |
5 | #include <sys/stat.h> |
6 | #include <fcntl.h> |
7 | #include <assert.h> |
8 | #include "jni.h" |
9 | #include "JNIHelp.h" |
10 | #include "android_runtime/AndroidRuntime.h" |
11 | #include "tv/CFbcCommunication.h" |
12 | |
13 | #define TAG "joey_jni" |
14 | #define JNI_DBG(a...) __android_log_print(ANDROID_LOG_INFO, TAG, a) |
15 | #define MAX_CNT 128 |
16 | |
17 | static JNIEnv *jni_local_env = NULL; |
18 | static jclass jni_local_clz = NULL; |
19 | static jobject jni_local_obj = NULL; |
20 | static jmethodID jni_local_mid = NULL; |
21 | static JavaVM *m_vm = NULL; |
22 | static CFbcCommunication *g_cfbc_handle = NULL; |
23 | |
24 | JNIEnv *getJNIEnv(bool *needsDetach) |
25 | { |
26 | JNIEnv *env = NULL; |
27 | jint result = -1; |
28 | if (m_vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) { |
29 | __android_log_print(ANDROID_LOG_INFO, TAG, "ERROR: GetEnv failed\n"); |
30 | |
31 | int status = m_vm->AttachCurrentThread(&env, NULL); |
32 | if (status < 0) { |
33 | __android_log_print(ANDROID_LOG_INFO, TAG, "callback_handler: failed to attach current thread"); |
34 | return NULL; |
35 | } |
36 | |
37 | *needsDetach = true; |
38 | } |
39 | |
40 | __android_log_print(ANDROID_LOG_INFO, TAG, "GetEnv Success"); |
41 | return env; |
42 | } |
43 | |
44 | void detachJNI() |
45 | { |
46 | int result = m_vm->DetachCurrentThread(); |
47 | if (result != JNI_OK) { |
48 | __android_log_print(ANDROID_LOG_INFO, TAG, "thread detach failed: %#x", result); |
49 | } |
50 | } |
51 | |
52 | //this data buf is same as cmd buf |
53 | void java_jni_callback(char *str, int cnt, int data_buf[]) |
54 | { |
55 | char temp_str[MAX_CNT]; |
56 | int idx = 0; |
57 | if (str != NULL && cnt > 0) { |
58 | memset(temp_str, 0, sizeof(temp_str)); |
59 | JNI_DBG("java jni string is:\n%s, cnt:%d.", str, cnt); |
60 | //strcpy(temp_str, "Call From C/C++!"); |
61 | memcpy(temp_str, str, strlen(str) % MAX_CNT); |
62 | |
63 | if (NULL != jni_local_obj) { |
64 | bool needsDetach = false; |
65 | jint j_cnt = data_buf[1]; |
66 | jint j_data_buf[MAX_CNT]; |
67 | for (idx = 0; idx < j_cnt; idx++) { |
68 | idx %= MAX_CNT; |
69 | j_data_buf[idx] = data_buf[idx]; |
70 | JNI_DBG("java_jni_callback the %d data is:0x%x, %d.", idx, j_data_buf[idx], data_buf[idx]); |
71 | } |
72 | |
73 | //jobject obj; |
74 | jni_local_env = getJNIEnv(&needsDetach); |
75 | //obj = (*jni_local_env)->NewGlobalRef(jni_local_env,jni_local_obj); |
76 | jni_local_clz = jni_local_env->GetObjectClass(jni_local_obj); |
77 | //this func name and parameters should be same as the callback defined in java code |
78 | jni_local_mid = jni_local_env->GetMethodID(jni_local_clz, "android_java_callback", "(Ljava/lang/String;[I)I"); |
79 | |
80 | jstring str1 = jni_local_env->NewStringUTF(temp_str); |
81 | |
82 | jintArray cc_data_arr = jni_local_env->NewIntArray(j_cnt); |
83 | jni_local_env->SetIntArrayRegion(cc_data_arr, 0, cnt, j_data_buf); |
84 | //jint *temp_data = jni_local_env->GetIntArrayElements(cc_data_arr, NULL); |
85 | |
86 | jint cnt = jni_local_env->CallIntMethod(jni_local_obj, jni_local_mid, str1, cc_data_arr); |
87 | |
88 | //jni_local_env->ReleaseIntArrayElements(cc_data_arr, temp_data, 0); |
89 | //jni_local_env->ReleaseIntArrayElements(cc_cmd_arr, temp_cmd, 0); |
90 | JNI_DBG("%s %d be called.", __FUNCTION__, __LINE__); |
91 | |
92 | if (needsDetach) { |
93 | detachJNI(); |
94 | } |
95 | } |
96 | } |
97 | } |
98 | |
99 | //here we needn't to match the java package name |
100 | static jint jni_java_exec_cmd(JNIEnv *env, jobject obj, jintArray cmdArray) |
101 | { |
102 | jint *arry = env->GetIntArrayElements(cmdArray, NULL); |
103 | jint length = env->GetArrayLength(cmdArray); |
104 | |
105 | int cmd_cnt = arry[1], idx = 0; |
106 | int cmd_array[MAX_CNT]; |
107 | memset(cmd_array, 0, sizeof(cmd_array)); |
108 | for (idx = 0; idx < cmd_cnt; idx++) |
109 | cmd_array[idx] = arry[idx]; |
110 | |
111 | JNI_DBG("%s %s %d be called.", __FILE__, __FUNCTION__, __LINE__); |
112 | |
113 | if (g_cfbc_handle == NULL) { |
114 | g_cfbc_handle = new CFbcCommunication(); |
115 | g_cfbc_handle->run("cfbc_thread", 0, 0); |
116 | } |
117 | |
118 | //g_cfbc_handle->handleCmd(COMM_DEV_CEC, cmd_array); |
119 | //c_exec_cmd(cmd_array); |
120 | |
121 | if (NULL == jni_local_obj) { |
122 | jni_local_obj = env->NewGlobalRef(obj); |
123 | } |
124 | |
125 | #if 0 |
126 | /* this is used to terminate the jni call if needed |
127 | ** and we should handle the pthread we create in c layer |
128 | */ |
129 | if (cmd_array[0] == 0x1002) { |
130 | if (NULL != jni_local_obj) |
131 | env->DeleteGlobalRef(jni_local_obj); |
132 | } |
133 | #endif |
134 | return 0; |
135 | } |
136 | |
137 | //the name of 'exec_cmd' should be same as the native func in java code |
138 | static JNINativeMethod gMethods[] = { |
139 | {"exec_cmd", "([I)I", (void *)jni_java_exec_cmd}, |
140 | }; |
141 | |
142 | static int register_android_MyFunc(JNIEnv *env) |
143 | { |
144 | JNI_DBG("%s %s %d be called.", __FILE__, __FUNCTION__, __LINE__); |
145 | //the name below should be same as the class name in which native method declared in Java layer |
146 | return android::AndroidRuntime::registerNativeMethods(env, "com/fbc/MyFunc", gMethods, NELEM(gMethods)); |
147 | } |
148 | |
149 | jint JNI_OnLoad(JavaVM *vm, void *reserved) |
150 | { |
151 | JNIEnv *env = NULL; |
152 | JNI_DBG("%s %s %d be called.", __FILE__, __FUNCTION__, __LINE__); |
153 | //c_set_callback(&java_jni_callback); |
154 | if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { |
155 | JNI_DBG("Error GetEnv\n"); |
156 | return -1; |
157 | } |
158 | |
159 | assert(env != NULL); |
160 | if (register_android_MyFunc(env) < 0) { |
161 | JNI_DBG("register_android_test_hdi error.\n"); |
162 | return -1; |
163 | } |
164 | |
165 | m_vm = vm; |
166 | return JNI_VERSION_1_4; |
167 | } |
168 |