FM-HAL: Add support for FM Core functionalities
FM-HAL Layer contains the core FM Functionality required
for carrying out various FM operations such as FM Enable,
FM Tune, FM Seek, FM Search, FM Disable etc..
FM-HAL layer interacts with the FM-HCI layer for sending
commands and receiving events to and from Controller.
Change-Id: I0ac1c9c80671e43aafa30ce2b68f5ee695c9d764
diff --git a/jni/Android.mk b/jni/Android.mk
index 5bc46d3..b554b40 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -10,7 +10,9 @@
FmIoctlsInterface.cpp \
FmPerformanceParams.cpp
+LOCAL_LDLIBS += -ldl
LOCAL_SHARED_LIBRARIES := \
+ libandroid_runtime \
libnativehelper \
libcutils
diff --git a/jni/FmConst.h b/jni/FmConst.h
index 00e6f82..8c8d6f4 100644
--- a/jni/FmConst.h
+++ b/jni/FmConst.h
@@ -145,5 +145,13 @@
V4L2_CID_PRV_IRIS_READ_DEFAULT = V4L2_CTRL_CLASS_USER + 0x928,
V4L2_CID_PRV_IRIS_WRITE_DEFAULT,
V4L2_CID_PRV_SET_CALIBRATION = V4L2_CTRL_CLASS_USER + 0x92A,
+ HCI_FM_HELIUM_SET_SPURTABLE = 0x0098092D,
+ HCI_FM_HELIUM_GET_SPUR_TBL = 0x0098092E,
+ V4L2_CID_PRV_IRIS_FREQ,
+ V4L2_CID_PRV_IRIS_SEEK,
+ V4L2_CID_PRV_IRIS_UPPER_BAND,
+ V4L2_CID_PRV_IRIS_LOWER_BAND,
+ V4L2_CID_PRV_IRIS_AUDIO_MODE,
};
+
#endif
diff --git a/jni/android_hardware_fm.cpp b/jni/android_hardware_fm.cpp
index 9eea048..8663bfe 100644
--- a/jni/android_hardware_fm.cpp
+++ b/jni/android_hardware_fm.cpp
@@ -30,20 +30,32 @@
#include "jni.h"
#include "JNIHelp.h"
-#include "android_runtime/AndroidRuntime.h"
#include "utils/Log.h"
#include "utils/misc.h"
#include "FmIoctlsInterface.h"
#include "ConfigFmThs.h"
#include <cutils/properties.h>
#include <fcntl.h>
+#include <math.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
-#include <math.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include "android_runtime/Log.h"
+#include "android_runtime/AndroidRuntime.h"
#define RADIO "/dev/radio0"
#define FM_JNI_SUCCESS 0L
#define FM_JNI_FAILURE -1L
+
+static JNIEnv *g_jEnv = NULL;
+static JavaVM *g_jVM = NULL;
+
+namespace android {
+char *FM_LIBRARY_NAME = "fm_helium.so";
+char *FM_LIBRARY_SYMBOL_NAME = "FM_HELIUM_LIB_INTERFACE";
+void *lib_handle;
+
#define SEARCH_DOWN 0
#define SEARCH_UP 1
#define HIGH_BAND 2
@@ -74,9 +86,296 @@
SCAN_UP,
SCAN_DN
};
+typedef void (*enb_result_cb)();
+typedef void (*tune_rsp_cb)(int Freq);
+typedef void (*seek_rsp_cb)(int Freq);
+typedef void (*scan_rsp_cb)();
+typedef void (*srch_list_rsp_cb)(uint16_t *scan_tbl);
+typedef void (*stereo_mode_cb)(bool status);
+typedef void (*rds_avl_sts_cb)(bool status);
+typedef void (*af_list_cb)(uint16_t *af_list);
+typedef void (*rt_cb)(char *rt);
+typedef void (*ps_cb)(char *ps);
+typedef void (*oda_cb)();
+typedef void (*rt_plus_cb)(char *rt_plus);
+typedef void (*ert_cb)(char *ert);
+typedef void (*disable_cb)();
+typedef void (*callback_thread_event)(unsigned int evt);
-using namespace android;
+static JNIEnv *mCallbackEnv = NULL;
+static jobject mCallbacksObj = NULL;
+static jfieldID sCallbacksField;
+
+jclass javaClassRef;
+static jmethodID method_psInfoCallback;
+static jmethodID method_rtCallback;
+static jmethodID method_ertCallback;
+static jmethodID method_aflistCallback;
+static jmethodID method_rtplusCallback;
+
+jmethodID method_enableCallback;
+jmethodID method_tuneCallback;
+jmethodID method_seekCmplCallback;
+jmethodID method_scanNxtCallback;
+jmethodID method_srchListCallback;
+jmethodID method_stereostsCallback;
+jmethodID method_rdsAvlStsCallback;
+jmethodID method_disableCallback;
+
+static bool checkCallbackThread() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ ALOGE("Callback env check fail: env: %p, callback: %p", env, mCallbackEnv);
+ if (mCallbackEnv != env || mCallbackEnv == NULL)
+ {
+ ALOGE("Callback env check fail: env: %p, callback: %p", env, mCallbackEnv);
+ return false;
+ }
+ return true;
+}
+
+void fm_enabled_cb() {
+ ALOGE("Entered %s", __func__);
+ if (mCallbackEnv != NULL) {
+ ALOGE("javaObjectRef creating");
+ jobject javaObjectRef = mCallbackEnv->NewObject(javaClassRef, method_enableCallback);
+ mCallbacksObj = javaObjectRef;
+ ALOGE("javaObjectRef = %p mCallbackobject =%p \n",javaObjectRef,mCallbacksObj);
+ }
+ ALOGE("exit %s", __func__);
+}
+
+void fm_tune_cb(int Freq)
+{
+ ALOGE("TUNE:Freq:%d", Freq);
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_tuneCallback, (jint) Freq);
+}
+
+void fm_seek_cmpl_cb(int Freq)
+{
+ ALOGE("SEEK_CMPL: Freq: %d", Freq);
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_seekCmplCallback, (jint) Freq);
+}
+
+void fm_scan_next_cb()
+{
+ ALOGE("SCAN_NEXT");
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_scanNxtCallback);
+}
+
+void fm_srch_list_cb(uint16_t *scan_tbl)
+{
+ ALOGE("SRCH_LIST");
+ //mCallbackEnv->CallVoidMethod(javaObjectRef, method_srchListCallback);
+}
+
+void fm_stereo_status_cb(bool stereo)
+{
+ ALOGE("STEREO: %d", stereo);
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_stereostsCallback, (jboolean) stereo);
+}
+
+void fm_rds_avail_status_cb(bool rds_avl)
+{
+ ALOGE("fm_rds_avail_status_cb: %d", rds_avl);
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_rdsAvlStsCallback, (jboolean) rds_avl);
+}
+
+void fm_af_list_update_cb(uint16_t *af_list)
+{
+ ALOGE("AF_LIST");
+ jbyteArray af_buffer = NULL;
+
+ if (!checkCallbackThread()) {
+ ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
+ return;
+ }
+
+ af_buffer = mCallbackEnv->NewByteArray(STD_BUF_SIZE);
+ if (af_buffer == NULL) {
+ ALOGE(" af list allocate failed :");
+ return;
+ }
+
+ mCallbackEnv->SetByteArrayRegion(af_buffer, 0, STD_BUF_SIZE,(jbyte *)af_list);
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_aflistCallback,af_buffer);
+ mCallbackEnv->DeleteLocalRef(af_buffer);
+}
+
+void fm_rt_update_cb(char *rt)
+{
+ ALOGE("RT_EVT: " );
+ jbyteArray rt_buff = NULL;
+ int i,len;
+
+ if (!checkCallbackThread()) {
+ ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
+ return;
+ }
+
+ len = (int)(rt[0] & 0x0F);
+ len = len+5;
+
+ ALOGE(" rt data len=%d :",len);
+ rt_buff = mCallbackEnv->NewByteArray(len);
+ if (rt_buff == NULL) {
+ ALOGE(" ps data allocate failed :");
+ return;
+ }
+
+ mCallbackEnv->SetByteArrayRegion(rt_buff, 0, len,(jbyte *)rt);
+ jbyte* bytes= mCallbackEnv->GetByteArrayElements(rt_buff,0);
+
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_rtCallback,rt_buff);
+ mCallbackEnv->DeleteLocalRef(rt_buff);
+}
+
+void fm_ps_update_cb(char *ps)
+{
+ jbyteArray ps_data = NULL;
+ int i,len;
+ int numPs;
+ if (!checkCallbackThread()) {
+ ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
+ return;
+ }
+
+ numPs = (int)(ps[0] & 0x0F);
+ len = (numPs *8)+5;
+
+ ALOGE(" ps data len=%d :",len);
+ ps_data = mCallbackEnv->NewByteArray(len);
+ if(ps_data == NULL) {
+ ALOGE(" ps data allocate failed :");
+ return;
+ }
+
+ mCallbackEnv->SetByteArrayRegion(ps_data, 0, len,(jbyte *)ps);
+ jbyte* bytes= mCallbackEnv->GetByteArrayElements(ps_data,0);
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_psInfoCallback,ps_data);
+ mCallbackEnv->DeleteLocalRef(ps_data);
+}
+
+void fm_oda_update_cb()
+{
+ ALOGE("ODA_EVT");
+}
+
+void fm_rt_plus_update_cb(char *rt_plus)
+{
+ jbyteArray RtPlus = NULL;
+ ALOGE("RT_PLUS");
+ int len;
+
+ len = (int)(rt_plus[0] & 0x0F);
+ ALOGE(" rt plus len=%d :",len);
+ RtPlus = mCallbackEnv->NewByteArray(len);
+ if (RtPlus == NULL) {
+ ALOGE(" rt plus data allocate failed :");
+ return;
+ }
+ mCallbackEnv->SetByteArrayRegion(RtPlus, 0, len,(jbyte *)rt_plus);
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_rtplusCallback,RtPlus);
+ mCallbackEnv->DeleteLocalRef(RtPlus);
+}
+
+void fm_ert_update_cb(char *ert)
+{
+ ALOGE("ERT_EVT");
+ jbyteArray ert_buff = NULL;
+ int i,len;
+
+ if (!checkCallbackThread()) {
+ ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
+ return;
+ }
+
+ len = (int)(ert[0] & 0x0F);
+ len = len+3;
+
+ ALOGE(" ert data len=%d :",len);
+ ert_buff = mCallbackEnv->NewByteArray(len);
+ if (ert_buff == NULL) {
+ ALOGE(" ps data allocate failed :");
+ return;
+ }
+
+ mCallbackEnv->SetByteArrayRegion(ert_buff, 0, len,(jbyte *)ert);
+ jbyte* bytes= mCallbackEnv->GetByteArrayElements(ert_buff,0);
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_ertCallback,ert_buff);
+ mCallbackEnv->DeleteLocalRef(ert_buff);
+}
+
+void fm_disabled_cb()
+{
+ ALOGE("DISABLE");
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_disableCallback);
+}
+
+static void fm_thread_evt_cb(unsigned int event) {
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ if (event == 0) {
+ JavaVMAttachArgs args;
+ char name[] = "FM Service Callback Thread";
+ args.version = JNI_VERSION_1_6;
+ args.name = name;
+ args.group = NULL;
+ vm->AttachCurrentThread(&mCallbackEnv, &args);
+ ALOGE("satish: Callback thread attached: %p", mCallbackEnv);
+ } else if (event == 1) {
+ if (!checkCallbackThread()) {
+ ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
+ return;
+ }
+ vm->DetachCurrentThread();
+ }
+}
+typedef struct {
+ size_t size;
+
+ enb_result_cb enabled_cb;
+ tune_rsp_cb tune_cb;
+ seek_rsp_cb seek_cmpl_cb;
+ scan_rsp_cb scan_next_cb;
+ srch_list_rsp_cb srch_list_cb;
+ stereo_mode_cb stereo_status_cb;
+ rds_avl_sts_cb rds_avail_status_cb;
+ af_list_cb af_list_update_cb;
+ rt_cb rt_update_cb;
+ ps_cb ps_update_cb;
+ oda_cb oda_update_cb;
+ rt_plus_cb rt_plus_update_cb;
+ ert_cb ert_update_cb;
+ disable_cb disabled_cb;
+ callback_thread_event thread_evt_cb;
+} fm_vendor_callbacks_t;
+
+typedef struct {
+ int (*hal_init)(fm_vendor_callbacks_t *p_cb);
+
+ int (*set_fm_ctrl)(int ioctl, int val);
+ int (*get_fm_ctrl) (int ioctl, int val);
+} fm_interface_t;
+
+fm_interface_t *vendor_interface;
+static fm_vendor_callbacks_t fm_callbacks = {
+ sizeof(fm_callbacks),
+ fm_enabled_cb,
+ fm_tune_cb,
+ fm_seek_cmpl_cb,
+ fm_scan_next_cb,
+ fm_srch_list_cb,
+ fm_stereo_status_cb,
+ fm_rds_avail_status_cb,
+ fm_af_list_update_cb,
+ fm_rt_update_cb,
+ fm_ps_update_cb,
+ fm_oda_update_cb,
+ fm_rt_plus_update_cb,
+ fm_ert_update_cb,
+ fm_disabled_cb,
+ fm_thread_evt_cb
+};
/* native interface */
static jint android_hardware_fmradio_FmReceiverJNI_acquireFdNative
@@ -178,7 +477,8 @@
int err;
long freq;
- if (fd >= 0) {
+ err = vendor_interface->get_fm_ctrl(V4L2_CID_PRV_IRIS_FREQ, freq);
+/* if (fd >= 0) {
err = FmIoctlsInterface :: get_cur_freq(fd, freq);
if(err < 0) {
err = FM_JNI_FAILURE;
@@ -190,7 +490,7 @@
ALOGE("%s: get freq failed because fd is negative, fd: %d\n",
LOG_TAG, fd);
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -200,7 +500,8 @@
{
int err;
- if ((fd >= 0) && (freq > 0)) {
+ err = vendor_interface->set_fm_ctrl(V4L2_CID_PRV_IRIS_FREQ, freq);
+/* if ((fd >= 0) && (freq > 0)) {
err = FmIoctlsInterface :: set_freq(fd, freq);
if (err < 0) {
ALOGE("%s: set freq failed, freq: %d\n", LOG_TAG, freq);
@@ -212,7 +513,7 @@
ALOGE("%s: set freq failed because either fd/freq is negative,\
fd: %d, freq: %d\n", LOG_TAG, fd, freq);
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -223,7 +524,7 @@
int err;
ALOGE("id(%x) value: %x\n", id, value);
- if ((fd >= 0) && (id >= 0)) {
+/* if ((fd >= 0) && (id >= 0)) {
err = FmIoctlsInterface :: set_control(fd, id, value);
if (err < 0) {
ALOGE("%s: set control failed, id: %d\n", LOG_TAG, id);
@@ -235,7 +536,8 @@
ALOGE("%s: set control failed because either fd/id is negavtive,\
fd: %d, id: %d\n", LOG_TAG, fd, id);
err = FM_JNI_FAILURE;
- }
+ } */
+ err = vendor_interface->set_fm_ctrl(id, value);
return err;
}
@@ -271,7 +573,14 @@
ALOGE("id(%x)\n", id);
- if ((fd >= 0) && (id >= 0)) {
+ err = vendor_interface->get_fm_ctrl(id, val);
+ if (err < 0) {
+ ALOGE("%s: get control failed, id: %d\n", LOG_TAG, id);
+ err = FM_JNI_FAILURE;
+ } else {
+ err = val;
+ }
+/* if ((fd >= 0) && (id >= 0)) {
err = FmIoctlsInterface :: get_control(fd, id, val);
if (err < 0) {
ALOGE("%s: get control failed, id: %d\n", LOG_TAG, id);
@@ -283,7 +592,7 @@
ALOGE("%s: get control failed because either fd/id is negavtive,\
fd: %d, id: %d\n", LOG_TAG, fd, id);
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -294,7 +603,14 @@
{
int err;
- if ((fd >= 0) && (dir >= 0)) {
+ err = vendor_interface->set_fm_ctrl(V4L2_CID_PRV_IRIS_SEEK, dir);
+ if (err < 0) {
+ ALOGE("%s: search failed, dir: %d\n", LOG_TAG, dir);
+ err = FM_JNI_FAILURE;
+ } else {
+ err = FM_JNI_SUCCESS;
+ }
+/* if ((fd >= 0) && (dir >= 0)) {
ALOGD("startSearchNative: Issuing the VIDIOC_S_HW_FREQ_SEEK");
err = FmIoctlsInterface :: start_search(fd, dir);
if (err < 0) {
@@ -307,7 +623,7 @@
ALOGE("%s: search failed because either fd/dir is negative,\
fd: %d, dir: %d\n", LOG_TAG, fd, dir);
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -318,7 +634,14 @@
{
int err;
- if (fd >= 0) {
+ err = vendor_interface->set_fm_ctrl(V4L2_CID_PRV_SRCHON, 0);
+ if (err < 0) {
+ ALOGE("%s: cancel search failed\n", LOG_TAG);
+ err = FM_JNI_FAILURE;
+ } else {
+ err = FM_JNI_SUCCESS;
+ }
+/* if (fd >= 0) {
err = FmIoctlsInterface :: set_control(fd, V4L2_CID_PRV_SRCHON, 0);
if (err < 0) {
ALOGE("%s: cancel search failed\n", LOG_TAG);
@@ -330,7 +653,7 @@
ALOGE("%s: cancel search failed because fd is negative, fd: %d\n",
LOG_TAG, fd);
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -365,7 +688,20 @@
{
int err;
- if ((fd >= 0) && (low >= 0) && (high >= 0)) {
+ err = vendor_interface->set_fm_ctrl(V4L2_CID_PRV_IRIS_UPPER_BAND, high);
+ if (err < 0) {
+ ALOGE("%s: set band failed, high: %d\n", LOG_TAG, high);
+ err = FM_JNI_FAILURE;
+ return err;
+ }
+ err = vendor_interface->set_fm_ctrl(V4L2_CID_PRV_IRIS_LOWER_BAND, low);
+ if (err < 0) {
+ ALOGE("%s: set band failed, low: %d\n", LOG_TAG, low);
+ err = FM_JNI_FAILURE;
+ } else {
+ err = FM_JNI_SUCCESS;
+ }
+/* if ((fd >= 0) && (low >= 0) && (high >= 0)) {
err = FmIoctlsInterface :: set_band(fd, low, high);
if (err < 0) {
ALOGE("%s: set band failed, low: %d, high: %d\n",
@@ -378,7 +714,7 @@
ALOGE("%s: set band failed because either fd/band is negative,\
fd: %d, low: %d, high: %d\n", LOG_TAG, fd, low, high);
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -390,7 +726,14 @@
int err;
ULINT freq;
- if (fd >= 0) {
+ err = vendor_interface->get_fm_ctrl(V4L2_CID_PRV_IRIS_LOWER_BAND, freq);
+ if (err < 0) {
+ ALOGE("%s: get lower band failed\n", LOG_TAG);
+ err = FM_JNI_FAILURE;
+ } else {
+ err = freq;
+ }
+/* if (fd >= 0) {
err = FmIoctlsInterface :: get_lowerband_limit(fd, freq);
if (err < 0) {
ALOGE("%s: get lower band failed\n", LOG_TAG);
@@ -402,7 +745,7 @@
ALOGE("%s: get lower band failed because fd is negative,\
fd: %d\n", LOG_TAG, fd);
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -414,7 +757,14 @@
int err;
ULINT freq;
- if (fd >= 0) {
+ err = vendor_interface->get_fm_ctrl(V4L2_CID_PRV_IRIS_UPPER_BAND, freq);
+ if (err < 0) {
+ ALOGE("%s: get upper band failed\n", LOG_TAG);
+ err = FM_JNI_FAILURE;
+ } else {
+ err = freq;
+ }
+/* if (fd >= 0) {
err = FmIoctlsInterface :: get_upperband_limit(fd, freq);
if (err < 0) {
ALOGE("%s: get lower band failed\n", LOG_TAG);
@@ -426,7 +776,7 @@
ALOGE("%s: get lower band failed because fd is negative,\
fd: %d\n", LOG_TAG, fd);
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -437,7 +787,14 @@
int err;
- if (fd >= 0) {
+ err = vendor_interface->get_fm_ctrl(V4L2_CID_PRV_IRIS_AUDIO_MODE, val);
+ if (err < 0) {
+ ALOGE("%s: set audio mode failed\n", LOG_TAG);
+ err = FM_JNI_FAILURE;
+ } else {
+ err = FM_JNI_SUCCESS;
+ }
+/* if (fd >= 0) {
err = FmIoctlsInterface :: set_audio_mode(fd, (enum AUDIO_MODE)val);
if (err < 0) {
err = FM_JNI_FAILURE;
@@ -446,7 +803,7 @@
}
} else {
err = FM_JNI_FAILURE;
- }
+ } */
return err;
}
@@ -927,11 +1284,83 @@
return FM_JNI_SUCCESS;
}
+static void classInitNative(JNIEnv* env, jclass clazz) {
+
+ ALOGE("ClassInit native called \n");
+ jclass dataClass = env->FindClass("qcom/fmradio/FmReceiverJNI");
+ javaClassRef = (jclass) env->NewGlobalRef(dataClass);
+ lib_handle = dlopen(FM_LIBRARY_NAME, RTLD_NOW);
+ if (!lib_handle) {
+ ALOGE("%s unable to open %s: %s", __func__, FM_LIBRARY_NAME, dlerror());
+ goto error;
+ }
+ ALOGE("Opened %s shared object library successfully", FM_LIBRARY_NAME);
+
+ ALOGI("Obtaining handle: '%s' to the shared object library...", FM_LIBRARY_SYMBOL_NAME);
+ vendor_interface = (fm_interface_t *)dlsym(lib_handle, FM_LIBRARY_SYMBOL_NAME);
+ if (!vendor_interface) {
+ ALOGE("%s unable to find symbol %s in %s: %s", __func__, FM_LIBRARY_SYMBOL_NAME, FM_LIBRARY_NAME, dlerror());
+ goto error;
+ }
+
+ method_psInfoCallback = env->GetMethodID(javaClassRef, "PsInfoCallback", "([B)V");
+ method_rtCallback = env->GetMethodID(javaClassRef, "RtCallback", "([B)V");
+ method_ertCallback = env->GetMethodID(javaClassRef, "ErtCallback", "([B)V");
+ method_rtplusCallback = env->GetMethodID(javaClassRef, "RtPlusCallback", "([B)V");
+ method_aflistCallback = env->GetMethodID(javaClassRef, "AflistCallback", "([B)V");
+ ALOGI("method_psInfoCallback: '%p' env =%p...", method_psInfoCallback, env);
+ method_enableCallback = env->GetMethodID(javaClassRef, "enableCallback", "()V");
+ method_tuneCallback = env->GetMethodID(javaClassRef, "tuneCallback", "(I)V");
+ method_seekCmplCallback = env->GetMethodID(javaClassRef, "seekCmplCallback", "(I)V");
+ method_scanNxtCallback = env->GetMethodID(javaClassRef, "scanNxtCallback", "()V");
+ //method_srchListCallback = env->GetMethodID(javaClassRef, "srchListCallback", "([B)V");
+ method_stereostsCallback = env->GetMethodID(javaClassRef, "stereostsCallback", "(Z)V");
+ method_rdsAvlStsCallback = env->GetMethodID(javaClassRef, "rdsAvlStsCallback", "(Z)V");
+ method_disableCallback = env->GetMethodID(javaClassRef, "disableCallback", "()V");
+
+ return;
+error:
+ vendor_interface = NULL;
+ if (lib_handle)
+ dlclose(lib_handle);
+ lib_handle = NULL;
+}
+
+static void initNative(JNIEnv *env, jobject object) {
+
+ int status;
+ ALOGE("Init native called \n");
+
+ if (vendor_interface) {
+ ALOGE("Initializing the FM HAL module & registering the JNI callback functions...");
+ status = vendor_interface->hal_init(&fm_callbacks);
+ if (status) {
+ ALOGE("%s unable to initialize vendor library: %d", __func__, status);
+ return;
+ }
+ ALOGE("***** FM HAL Initialization complete *****\n");
+ }
+ ALOGE("object =%p, env = %p\n",object,env);
+ mCallbacksObj = env->NewGlobalRef(object);
+ ALOGE("mCallbackobject =%p, \n",mCallbacksObj);
+
+
+}
+static void cleanupNative(JNIEnv *env, jobject object) {
+
+ if (mCallbacksObj != NULL) {
+ env->DeleteGlobalRef(mCallbacksObj);
+ mCallbacksObj = NULL;
+ }
+}
/*
* JNI registration.
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
+ { "classInitNative", "()V", (void*)classInitNative},
+ { "initNative", "()V", (void*)initNative},
+ {"cleanupNative", "()V", (void *) cleanupNative},
{ "acquireFdNative", "(Ljava/lang/String;)I",
(void*)android_hardware_fmradio_FmReceiverJNI_acquireFdNative},
{ "closeFdNative", "(I)I",
@@ -996,21 +1425,24 @@
{
return jniRegisterNativeMethods(env, "qcom/fmradio/FmReceiverJNI", gMethods, NELEM(gMethods));
}
+} // end namespace
+
jint JNI_OnLoad(JavaVM *jvm, void *reserved)
{
- JNIEnv *e;
- int status;
- ALOGE("FM : loading QCOMM FM-JNI\n");
-
- if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
- ALOGE("JNI version mismatch error");
- return JNI_ERR;
- }
+ JNIEnv *e;
+ int status;
+ g_jVM = jvm;
- if ((status = register_android_hardware_fm_fmradio(e)) < 0) {
- ALOGE("jni adapter service registration failure, status: %d", status);
- return JNI_ERR;
- }
- return JNI_VERSION_1_6;
+ ALOGE("FM : Loading QCOMM FM-JNI");
+ if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
+ ALOGE("JNI version mismatch error");
+ return JNI_ERR;
+ }
+
+ if ((status = android::register_android_hardware_fm_fmradio(e)) < 0) {
+ ALOGE("jni adapter service registration failure, status: %d", status);
+ return JNI_ERR;
+ }
+ return JNI_VERSION_1_6;
}