doubao_chat/lib/net/libduer-device/jni/lightduer_os.c

607 lines
18 KiB
C

/**
* Copyright (2017) Baidu Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define TAG "lightduer_os"
#include "lightduer_coap_defs.h"
#include "lightduer_jni.h"
#include "lightduer_jni_controlpoint.h"
#include "lightduer_jni_dcs.h"
#include "lightduer_jni_event.h"
#include "lightduer_jni_log.h"
#include "lightduer_jni_utils.h"
#include "lightduer_jni_voice.h"
#include "lightduer_memory.h"
#include "lightduer_lib.h"
#include "lightduer_voice.h"
#include "lightduer_system_info.h"
duer_system_static_info_t g_system_static_info = {
.os_version = "Android x.x.x",
.sw_version = "unknown",
.brand = "unknown",
.hardware_version = "unknown",
.equipment_type = "unknown",
.ram_size = 0,
.rom_size = 0,
};
static void lightduer_os_jni_initialize(JNIEnv *env, jclass clazz, jobject *jinfo)
{
if (jinfo) {
jclass info_clazz = NULL;
jfieldID id = NULL;
jstring jstr = NULL;
const char *str = NULL;
do {
info_clazz = (*env)->FindClass(env,
"com/baidu/lightduer/lib/jni/utils/LightduerSystemStaticInfo");
if (info_clazz == NULL) {
LOGE("Can't find LightduerSystemStaticInfo class.");
break;
}
id = (*env)->GetFieldID(env, info_clazz, "mOsVersion", "Ljava/lang/String;");
if (id == NULL) {
LOGE("Can't find mOsVersion field.");
break;
}
jstr = (jstring)(*env)->GetObjectField(env, jinfo, id);
str = (*env)->GetStringUTFChars(env, jstr, NULL);
DUER_SNPRINTF(g_system_static_info.os_version, OS_VERSION_LEN, "%s", str);
(*env)->ReleaseStringUTFChars(env, jstr, str);
(*env)->DeleteLocalRef(env, jstr);
id = (*env)->GetFieldID(env, info_clazz, "mSwVersion", "Ljava/lang/String;");
if (id == NULL) {
LOGE("Can't find mSwVersion field.");
break;
}
jstr = (jstring)(*env)->GetObjectField(env, jinfo, id);
str = (*env)->GetStringUTFChars(env, jstr, NULL);
DUER_SNPRINTF(g_system_static_info.sw_version, SW_VERSION_LEN, "%s", str);
(*env)->ReleaseStringUTFChars(env, jstr, str);
(*env)->DeleteLocalRef(env, jstr);
id = (*env)->GetFieldID(env, info_clazz, "mBrand", "Ljava/lang/String;");
if (id == NULL) {
LOGE("Can't find mBrand field.");
break;
}
jstr = (jstring)(*env)->GetObjectField(env, jinfo, id);
str = (*env)->GetStringUTFChars(env, jstr, NULL);
DUER_SNPRINTF(g_system_static_info.brand, BRAND_LEN, "%s", str);
(*env)->ReleaseStringUTFChars(env, jstr, str);
(*env)->DeleteLocalRef(env, jstr);
id = (*env)->GetFieldID(env, info_clazz, "mEquipmentType", "Ljava/lang/String;");
if (id == NULL) {
LOGE("Can't find mEquipmentType field.");
break;
}
jstr = (jstring)(*env)->GetObjectField(env, jinfo, id);
str = (*env)->GetStringUTFChars(env, jstr, NULL);
DUER_SNPRINTF(g_system_static_info.equipment_type, EQUIPMENT_TYPE_LEN, "%s", str);
(*env)->ReleaseStringUTFChars(env, jstr, str);
(*env)->DeleteLocalRef(env, jstr);
id = (*env)->GetFieldID(env, info_clazz, "mHardwareVersion", "Ljava/lang/String;");
if (id == NULL) {
LOGE("Can't find mHardwareVersion field.");
break;
}
jstr = (jstring)(*env)->GetObjectField(env, jinfo, id);
str = (*env)->GetStringUTFChars(env, jstr, NULL);
DUER_SNPRINTF(g_system_static_info.hardware_version, HARDWARE_VERSION_LEN, "%s", str);
(*env)->ReleaseStringUTFChars(env, jstr, str);
(*env)->DeleteLocalRef(env, jstr);
id = (*env)->GetFieldID(env, info_clazz, "mRamSize", "I");
if (id == NULL) {
LOGE("Can't find mRamSize field.");
break;
}
g_system_static_info.ram_size = (uint32_t)(*env)->GetIntField(env, jinfo, id);
id = (*env)->GetFieldID(env, info_clazz, "mRomSize", "I");
if (id == NULL) {
LOGE("Can't find mRomSize field.");
break;
}
g_system_static_info.rom_size = (uint32_t)(*env)->GetIntField(env, jinfo, id);
} while (0);
if (info_clazz) {
(*env)->DeleteLocalRef(env, info_clazz);
}
}
duer_initialize();
}
static void duer_event_hook(duer_event_t *event)
{
if (!event) {
LOGE("NULL event!!!\n");
return;
}
LOGD("event: %d\n", event->_event);
LOGD("event code: %d\n", event->_code);
int needDetach = 0;
JNIEnv *jenv = duer_jni_get_JNIEnv(&needDetach);
if (jenv == NULL) {
LOGE("can't get jenv\n");
return;
}
duer_jni_event_call_callback(jenv, event);
if (needDetach) {
duer_jni_detach_current_thread();
}
}
static void lightduer_os_jni_set_event_listener(JNIEnv *jenv, jclass cls, jobject obj)
{
int init_result = duer_jni_event_init(jenv, obj);
if (init_result != DUER_OK) {
LOGE("init event failed!\n");
return;
}
duer_set_event_callback(duer_event_hook);
}
static void duer_voice_result(struct baidu_json *result)
{
int needDetach = 0;
JNIEnv *jenv = duer_jni_get_JNIEnv(&needDetach);
char *str_result = baidu_json_PrintUnformatted(result);
LOGD("duer_voice_result:%s \n", str_result);
jstring jstr_result = (*jenv)->NewStringUTF(jenv, str_result);
LOGD("before call voice callback \n");
duer_jni_voice_call_callback(jenv, jstr_result);
LOGD("after call voice callback \n");
(*jenv)->DeleteLocalRef(jenv, jstr_result);
baidu_json_release(str_result);
if (needDetach) {
duer_jni_detach_current_thread();
}
}
static void lightduer_os_jni_set_voice_result_listener(JNIEnv *jenv, jclass clazz, jobject obj)
{
LOGW("@deprecated dcs3.0 does not to setVoiceResultListener");
// @deprecated dcs3.0 does not to set the callback
//
// int init_result = duer_jni_voice_init(jenv, obj);
// if (init_result != DUER_OK) {
// LOGE("voice init failed\n");
// return;
// }
// duer_voice_set_result_callback(duer_voice_result);
}
static jint lightduer_os_jni_start_server_by_profile(JNIEnv *jenv, jclass clazz, jbyteArray byteArray)
{
jbyte *data = (*jenv)->GetByteArrayElements(jenv, byteArray, 0);
jsize size = (*jenv)->GetArrayLength(jenv, byteArray);
LOGI("data:%s \n", data);
LOGI("size:%d \n", size);
int result = duer_start(data, size);
(*jenv)->ReleaseByteArrayElements(jenv, byteArray, data, 0);
return result;
}
static jint lightduer_os_jni_stop_server(JNIEnv *env, jclass clazz)
{
return duer_stop();
}
static void lightduer_os_jni_set_voice_mode(JNIEnv *env, jclass clazz, jint mode)
{
LOGI("set voice mode:%d\n", mode);
switch (mode) {
case 1:
duer_voice_set_mode(DUER_VOICE_MODE_CHINESE_TO_ENGLISH);
break;
case 2:
duer_voice_set_mode(DUER_VOICE_MODE_ENGLISH_TO_CHINESE);
break;
case 3:
duer_voice_set_mode(DUER_VOICE_MODE_WCHAT);
break;
default:
duer_voice_set_mode(DUER_VOICE_MODE_DEFAULT);
break;
}
}
static jint lightduer_os_jni_get_voice_mode(JNIEnv *env, jclass clazz)
{
return (jint)duer_voice_get_mode();
}
static jint lightduer_os_jni_start_voice(JNIEnv *env, jclass clazz, jint samplerate)
{
return duer_voice_start(samplerate);
}
static jint lightduer_os_jni_send_voice_data(JNIEnv *jenv, jclass clazz, jbyteArray voice_data)
{
jbyte *data = (*jenv)->GetByteArrayElements(jenv, voice_data, 0);
jsize size = (*jenv)->GetArrayLength(jenv, voice_data);
jint result = duer_voice_send(data, size);
(*jenv)->ReleaseByteArrayElements(jenv, voice_data, data, 0);
return result;
}
static jint lightduer_os_jni_stop_voice(JNIEnv *env, jclass clazz)
{
return duer_voice_stop();
}
static jint lightduer_os_jni_report_data(JNIEnv *jenv, jclass clazz, jstring data)
{
int result = DUER_OK;
baidu_json *json_data = NULL;
const char *c_data = (*jenv)->GetStringUTFChars(jenv, data, NULL);
do {
if (c_data == NULL) {
LOGE("get c char failed\n");
result = DUER_ERR_FAILED;
break;
}
json_data = baidu_json_Parse(c_data);
if (json_data == NULL) {
LOGE("get json failed\n");
result = DUER_ERR_FAILED;
break;
}
result = duer_data_report(json_data);
} while (0);
if (c_data) {
(*jenv)->ReleaseStringUTFChars(jenv, data, c_data);
c_data = NULL;
}
if (json_data) {
baidu_json_Delete(json_data);
json_data = NULL;
}
return result;
}
static jint lightduer_os_jni_add_resource(JNIEnv *jenv, jclass clazz, jobjectArray objArray)
{
int result = DUER_ERR_FAILED;
duer_res_t *resources = NULL;
jsize arraylength = (*jenv)->GetArrayLength(jenv, objArray);
if (arraylength <= 0) {
LOGE("no element in array");
return result;
}
do {
resources = (duer_res_t *)DUER_MALLOC(sizeof(duer_res_t) * arraylength);
if (!resources) {
LOGE("resources alloc fail!!\n");
break;
}
DUER_MEMSET(resources, 0, sizeof(duer_res_t) * arraylength);
result = duer_jni_utils_init(jenv);
if (result != DUER_OK) {
LOGE("utils init failed");
break;
}
result = duer_jni_get_native_duer_resources(jenv, objArray, resources, arraylength);
if (result == DUER_OK) {
result = duer_add_resources(resources, arraylength);
}
} while (0);
// release the memory allocate in duer_jni_get_native_duer_resources
// more info see duer_jni_get_native_duer_resources
if (resources) {
for (int i = 0; i < arraylength; ++i) {
if (resources[i].path) {
DUER_FREE(resources[i].path);
resources[i].path = NULL;
}
if (resources[i].mode == DUER_RES_MODE_STATIC) {
if (resources[i].res.s_res.data) {
DUER_FREE(resources[i].res.s_res.data);
resources[i].res.s_res.data = NULL;
}
}
}
DUER_FREE(resources);
resources = NULL;
}
return result;
}
static jint lightduer_os_jni_send_response(JNIEnv *jenv, jclass clazz, jobject message, jshort msgCode, jbyteArray payload_)
{
duer_msg_t duer_message;
DUER_MEMSET(&duer_message, 0, sizeof(duer_msg_t));
int result = duer_jni_get_native_duer_message(jenv, message, &duer_message);
do {
if (result != DUER_OK) {
LOGE("create native duer_message fail\n");
break;
}
LOGI("msgCode: %d\n", msgCode);
if (payload_) {
jbyte *payload = (*jenv)->GetByteArrayElements(jenv, payload_, NULL);
jsize payload_len = (*jenv)->GetArrayLength(jenv, payload_);
LOGD("payload_len: %d\n", payload_len);
duer_response(&duer_message, msgCode, payload, payload_len);
(*jenv)->ReleaseByteArrayElements(jenv, payload_, payload, 0);
} else {
duer_response(&duer_message, msgCode, NULL, 0);
}
} while (0);
// release the buffer allocate in duer_jni_get_native_duer_message
// see duer_jni_get_native_duer_message for more info
if (duer_message.path) {
DUER_FREE(duer_message.path);
duer_message.path = NULL;
}
if (duer_message.query) {
DUER_FREE(duer_message.query);
duer_message.query = NULL;
}
if (duer_message.token) {
DUER_FREE(duer_message.token);
duer_message.token = NULL;
}
if (duer_message.payload) {
DUER_FREE(duer_message.payload);
duer_message.payload = NULL;
}
return result;
}
static JNINativeMethod g_lightduer_os_methods[] = {
/* name, signature, funcPtr */
{
"initialize", "(Lcom/baidu/lightduer/lib/jni/utils/LightduerSystemStaticInfo;)V",
(void *) lightduer_os_jni_initialize
},
{
"setEventListener", "(Lcom/baidu/lightduer/lib/jni/event/LightduerEventListener;)V",
(void *) lightduer_os_jni_set_event_listener
},
{
"setVoiceResultListener",
"(Lcom/baidu/lightduer/lib/jni/voice/LightduerVoiceResultListener;)V",
(void *) lightduer_os_jni_set_voice_result_listener
},
{
"startServerByProfile", "([B)I",
(void *) lightduer_os_jni_start_server_by_profile
},
{
"stopServer", "()I",
(void *) lightduer_os_jni_stop_server
},
{
"setVoiceMode", "(I)V",
(void *) lightduer_os_jni_set_voice_mode
},
{
"getVoiceMode", "()I",
(void *) lightduer_os_jni_get_voice_mode
},
{
"startVoice", "(I)I",
(void *) lightduer_os_jni_start_voice
},
{
"sendVoiceData", "([B)I",
(void *) lightduer_os_jni_send_voice_data
},
{
"stopVoice", "()I",
(void *) lightduer_os_jni_stop_voice
},
{
"reportData", "(Ljava/lang/String;)I",
(void *) lightduer_os_jni_report_data
},
{
"addResource", "([Lcom/baidu/lightduer/lib/jni/controlpoint/LightduerResource;)I",
(void *) lightduer_os_jni_add_resource
},
{
"sendResponse", "(Lcom/baidu/lightduer/lib/jni/utils/LightduerMessage;S[B)I",
(void *) lightduer_os_jni_send_response
},
{
"initFramework", "()I",
(void *) lightduer_os_jni_init_framework
},
{
"initVoiceInput", "(Lcom/baidu/lightduer/lib/jni/dcs/VoiceInputListener;)I",
(void *) lightduer_os_jni_init_voice_input
},
{
"onListenStarted", "()I",
(void *) lightduer_os_jni_on_listen_started
},
{
"onListenStopped", "()I",
(void *) lightduer_os_jni_on_listen_stopped
},
{
"initVoiceOutput", "(Lcom/baidu/lightduer/lib/jni/dcs/VoiceOutputListener;)I",
(void *) lightduer_os_jni_init_voice_output
},
{
"onSpeakFinished", "()I",
(void *) lightduer_os_jni_on_speak_finished
},
{
"initSpeakerControl", "(Lcom/baidu/lightduer/lib/jni/dcs/SpeakerControlListener;)I",
(void *) lightduer_os_jni_init_speaker_control
},
{
"onVolumeChange", "()I",
(void *) lightduer_os_jni_on_volume_change
},
{
"onMute", "()I",
(void *) lightduer_os_jni_on_mute
},
{
"initAudioPlayer", "(Lcom/baidu/lightduer/lib/jni/dcs/AudioPlayerListener;)I",
(void *) lightduer_os_jni_init_audio_player
},
{
"sendPlayControlCommand", "(I)I",
(void *) lightduer_os_jni_send_play_control_command
},
{
"onAudioFinished", "()I",
(void *) lightduer_os_jni_on_audio_finished
},
{
"audioPlayFailed", "(ILjava/lang/String;)I",
(void *) lightduer_os_jni_audio_play_failed
},
{
"audioReportMetadata", "(Ljava/lang/String;)I",
(void *) lightduer_os_jni_audio_report_metadata
},
{
"onAudioStuttered", "(Z)I",
(void *) lightduer_os_jni_on_audio_stuttered
},
{
"syncState", "()I",
(void *) lightduer_os_jni_sync_state
},
{
"closeMultiDialog", "()I",
(void *) lightduer_os_jni_close_multi_dialog
},
{
"initScreenDisplay", "(Lcom/baidu/lightduer/lib/jni/dcs/ScreenDisplayListener;)I",
(void *) lightduer_os_jni_init_screen_display
},
{
"initDeviceControl", "(Lcom/baidu/lightduer/lib/jni/dcs/DeviceControlListener;)I",
(void *) lightduer_os_jni_init_device_control
},
{
"nativeAddDcsDirective", "([Lcom/baidu/lightduer/lib/jni/dcs/DcsDirective;"
"Lcom/baidu/lightduer/lib/jni/dcs/DcsDirective$IDirectiveHandler;Ljava/lang/String;)I",
(void *) lightduer_os_jni_add_dcs_directive
},
{
"registerClientContextProvider",
"(Lcom/baidu/lightduer/lib/jni/dcs/DcsClientContextProvider;)I",
(void *) lightduer_os_jni_register_client_context_provider
},
{
"createDcsEvent", "(Ljava/lang/String;Ljava/lang/String;Z)Ljava/lang/String;",
(void *) lightduer_os_jni_create_dcs_event
},
{
"dcsDialogCancel", "()I",
(void *) lightduer_os_jni_dcs_dialog_cancel
},
{
"dcsOnLinkClicked", "(Ljava/lang/String;)I",
(void *) lightduer_os_jni_dcs_on_link_clicked
},
{
"initDcsAlert", "(Lcom/baidu/lightduer/lib/jni/dcs/DcsAlertListener;)I",
(void *) lightduer_os_jni_init_dcs_alert
},
{
"reportDcsAlertEvent", "(Ljava/lang/String;I)I",
(void *) lightduer_os_jni_report_dcs_alert_event
},
};
static int jniRegisterNativeMethods(JNIEnv *env, const char *className,
const JNINativeMethod *gMethods, int numMethods)
{
LOGI("Registering %s's %d native methods...", className, numMethods);
jclass c = (*env)->FindClass(env, className);
if (c == NULL) {
char *msg;
asprintf(&msg, "Native registration unable to find class '%s'; aborting...", className);
(*env)->FatalError(env, msg);
}
if ((*env)->RegisterNatives(env, c, gMethods, numMethods) < 0) {
char *msg;
asprintf(&msg, "RegisterNatives failed for '%s'; aborting...", className);
(*env)->FatalError(env, msg);
}
return 0;
}
int register_java_com_baidu_lightduer_lib_jni_LightduerOsJni(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/baidu/lightduer/lib/jni/LightduerOsJni",
g_lightduer_os_methods,
(int) sizeof(g_lightduer_os_methods) / sizeof(g_lightduer_os_methods[0]));
}