Add Support to enable ECC events and update in UI

This does enable ECC bit during RDS group processing and add
logic to receive ECC events from SOC and sent the ECC code to
application.

Change-Id: I61687ea6fe041d2dc4aed16700632be5cdd781d8
diff --git a/fmapp2/src/com/caf/fmradio/FMRadio.java b/fmapp2/src/com/caf/fmradio/FMRadio.java
index 909a14c..ee8ef3d 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadio.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadio.java
@@ -218,6 +218,7 @@
    /* Bottom row in the station info layout */
    private TextView mRadioTextTV;
    private TextView mERadioTextTV;
+   private TextView mEContryCodeTV;
 
    /* Sleep and Recording Messages */
    private TextView mSleepMsgTV;
@@ -2805,6 +2806,26 @@
       }
    };
 
+   Runnable mUpdateExtenCountryCode = new Runnable() {
+      public void run() {
+         String str = "";
+         int value;
+         if ((mService != null) && isFmOn()) {
+            try {
+               /* Get Extended Radio Text and update the display */
+               value = mService.getExtenCountryCode();
+               str = Integer.toString(value);
+               Log.d(LOGTAG, "mUpdateExtenCountryCode: Updatable string: [" + str + "]");
+               mERadioTextTV.setText(str);
+               mERadioTextScroller.mOriginalString = str;
+               mERadioTextScroller.startScroll();
+            }catch (RemoteException e) {
+               e.printStackTrace();
+            }
+         }
+      }
+   };
+
    /* Create runnable for posting */
    Runnable mUpdateProgramService = new Runnable() {
       public void run() {
@@ -3124,6 +3145,9 @@
       public void onExtenRadioTextChanged() {
          mHandler.post(mUpdateExtenRadioText);
       }
+      public void onExtenCountryCodeChanged() {
+         mHandler.post(mUpdateExtenCountryCode);
+      }
       public void onAlternateFrequencyChanged() {
          Log.d(LOGTAG, "mServiceCallbacks.onAlternateFrequencyChanged :");
       }
diff --git a/fmapp2/src/com/caf/fmradio/FMRadioService.java b/fmapp2/src/com/caf/fmradio/FMRadioService.java
index 65f33cb..f4b24fb 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadioService.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadioService.java
@@ -2043,6 +2043,10 @@
          return(mService.get().isA2DPConnected());
       }
 
+      public int getExtenCountryCode()
+      {
+         return(mService.get().getExtenCountryCode());
+      }
    }
    private final IBinder mBinder = new ServiceStub(this);
 
@@ -2741,6 +2745,16 @@
       Log.d(LOGTAG, "eRadio Text:[" + str +"]");
       return str;
    }
+   public int  getExtenCountryCode() {
+      int val = 0;
+      if (mFMRxRDSData != null)
+      {
+         val = mFMRxRDSData.getECountryCode();
+      }
+      Log.d(LOGTAG, "eCountry Code :[" + val +"]");
+      return val;
+   }
+
    /* Retrieves the RDS Program Type (PTY) code.
     *
     * @return int - RDS PTY code.
@@ -3295,6 +3309,19 @@
              e.printStackTrace();
          }
       }
+      public void FmRxEvECCInfo()
+      {
+         Log.d(LOGTAG, "FmRxEvECCInfo");
+         try {
+             if (mReceiver != null) {
+                mFMRxRDSData = mReceiver.getECCInfo();
+                if(mCallbacks != null)
+                   mCallbacks.onExtenCountryCodeChanged();
+             }
+         } catch (RemoteException e) {
+             e.printStackTrace();
+         }
+      }
       public void FmRxEvRdsPiMatchAvailable()
       {
          Log.d(LOGTAG, "FmRxEvRdsPiMatchAvailable");
diff --git a/fmapp2/src/com/caf/fmradio/FMStats.java b/fmapp2/src/com/caf/fmradio/FMStats.java
index c035475..75ba4c6 100644
--- a/fmapp2/src/com/caf/fmradio/FMStats.java
+++ b/fmapp2/src/com/caf/fmradio/FMStats.java
@@ -2657,6 +2657,10 @@
           {
              Log.d(LOGTAG, "Extended Radio Text changed:");
           }
+          public void onExtenCountryCodeChanged()
+          {
+             Log.d(LOGTAG, "Extended ountry Code  changed:");
+          }
           public void onAlternateFrequencyChanged()
           {
              Log.d(LOGTAG, "mServiceCallbacks.onAlternateFrequencyChanged :");
diff --git a/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl b/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
index a02c593..766961a 100644
--- a/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
+++ b/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
@@ -53,6 +53,7 @@
     boolean setIntfDetLowTh(int intfLowTh);
     boolean setIntfDetHighTh(int intfHighTh);
     String getExtenRadioText();
+    int getExtenCountryCode();
     int getSinrSamplesCnt();
     int getSinrTh();
     int getSearchAlgoType();
diff --git a/fmapp2/src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl b/fmapp2/src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl
index 24aaa70..826b5f3 100644
--- a/fmapp2/src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl
+++ b/fmapp2/src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl
@@ -50,4 +50,5 @@
   void onA2DPConnectionstateChanged(boolean state);
   void onFmAudioPathStarted();
   void onFmAudioPathStopped();
+  void onExtenCountryCodeChanged();
 }
diff --git a/helium/radio-helium.h b/helium/radio-helium.h
index 5c21bdd..98452d8 100644
--- a/helium/radio-helium.h
+++ b/helium/radio-helium.h
@@ -163,6 +163,7 @@
 typedef void (*fm_peek_cb)(char *peek_rsp);
 typedef void (*fm_ssbi_peek_cb)(char *ssbi_peek_rsp);
 typedef void (*fm_ch_det_th_cb)(char *ch_det_rsp);
+typedef void (*fm_ecc_evt_cb)(char *ecc_rsp);
 
 typedef struct {
     size_t  size;
@@ -185,6 +186,7 @@
     fm_peek_cb fm_peek_rsp_cb;
     fm_ssbi_peek_cb fm_ssbi_peek_rsp_cb;
     fm_ch_det_th_cb fm_ch_det_th_rsp_cb;
+    fm_ecc_evt_cb	ext_country_code_cb;
     callback_thread_event thread_evt_cb;
 } fm_vendor_callbacks_t;
 
@@ -501,6 +503,8 @@
 #define HCI_EV_SEARCH_COMPLETE          0x12
 #define HCI_EV_SEARCH_RDS_COMPLETE      0x13
 #define HCI_EV_SEARCH_LIST_COMPLETE     0x14
+
+#define HCI_EV_EXT_COUNTRY_CODE         0x17
 #define HCI_EV_RADIO_TEXT_PLUS_ID       0x18
 #define HCI_EV_RADIO_TEXT_PLUS_TAG      0x19
 #define HCI_EV_HW_ERR_EVENT             0x1A
diff --git a/helium/radio_helium_hal.c b/helium/radio_helium_hal.c
index fd673ab..561c92a 100644
--- a/helium/radio_helium_hal.c
+++ b/helium/radio_helium_hal.c
@@ -558,6 +558,28 @@
      }
 }
 
+static void  hci_ev_ext_country_code(char *buff)
+{
+    char *data = NULL;
+    int len = 15;
+    ALOGD("%s:%s: start", LOG_TAG, __func__);
+    data = malloc(len);
+    if (data != NULL) {
+        data[0] = len;
+        ALOGI("%s:%s: data length=%d\n", LOG_TAG, __func__,data[0]);
+        data[1] = buff[RDS_PTYPE];
+        data[2] = buff[RDS_PID_LOWER];
+        data[3] = buff[RDS_PID_HIGHER];
+        data[4] = buff[3];
+        memcpy(&data[RDS_OFFSET], &buff[4], len-RDS_OFFSET);
+        // data[len] = 0x00;
+        jni_cb->ext_country_code_cb(data);
+        free(data);
+    } else {
+        ALOGE("%s:memory allocation failed\n", LOG_TAG);
+    }
+}
+
 static void hci_ev_ert()
 {
     char *data = NULL;
@@ -770,9 +792,12 @@
     case HCI_EV_RADIO_TEXT_PLUS_TAG:
         hci_ev_rt_plus_tag(((FM_EVT_HDR *)evt_buf)->cmd_params);
         break;
+    case HCI_EV_EXT_COUNTRY_CODE:
+        hci_ev_ext_country_code(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        break;
     case HCI_EV_HW_ERR_EVENT:
-	    hci_ev_hw_error(((FM_EVT_HDR *)evt_buf)->cmd_params);
-	    break;
+        hci_ev_hw_error(((FM_EVT_HDR *)evt_buf)->cmd_params);
+        break;
     default:
         break;
     }
diff --git a/jni/android_hardware_fm.cpp b/jni/android_hardware_fm.cpp
index 53e757a..21528bb 100644
--- a/jni/android_hardware_fm.cpp
+++ b/jni/android_hardware_fm.cpp
@@ -78,7 +78,6 @@
     SCAN_DN
 };
 
-
 static JNIEnv *g_jEnv = NULL;
 static JavaVM *g_jVM = NULL;
 
@@ -89,7 +88,6 @@
 char *FM_LIBRARY_SYMBOL_NAME = "FM_HELIUM_LIB_INTERFACE";
 void *lib_handle;
 
-
 typedef void (*enb_result_cb)();
 typedef void (*tune_rsp_cb)(int Freq);
 typedef void (*seek_rsp_cb)(int Freq);
@@ -109,6 +107,7 @@
 typedef void (*fm_peek_cb)(char *peek_rsp);
 typedef void (*fm_ssbi_peek_cb)(char *ssbi_peek_rsp);
 typedef void (*fm_ch_det_th_cb)(char *ch_det_rsp);
+typedef void (*fm_ecc_evt_cb)(char *ecc);
 
 static JNIEnv *mCallbackEnv = NULL;
 static jobject mCallbacksObj = NULL;
@@ -120,6 +119,7 @@
 static jmethodID method_ertCallback;
 static jmethodID method_aflistCallback;
 static jmethodID method_rtplusCallback;
+static jmethodID method_eccCallback;
 
 jmethodID method_enableCallback;
 jmethodID method_tuneCallback;
@@ -289,7 +289,7 @@
 
 void fm_ert_update_cb(char *ert)
 {
-    ALOGE("ERT_EVT");
+    ALOGI("ERT_EVT");
     jbyteArray ert_buff = NULL;
     int i,len;
 
@@ -301,19 +301,44 @@
     len = (int)(ert[0] & 0xFF);
     len = len+3;
 
-    ALOGE(" ert data len=%d :",len);
+    ALOGI(" ert data len=%d :",len);
     ert_buff = mCallbackEnv->NewByteArray(len);
     if (ert_buff == NULL) {
-        ALOGE(" ps data allocate failed :");
+        ALOGE(" ert data allocate failed :");
         return;
     }
 
     mCallbackEnv->SetByteArrayRegion(ert_buff, 0, len,(jbyte *)ert);
-    jbyte* bytes= mCallbackEnv->GetByteArrayElements(ert_buff,0);
+   // jbyte* bytes= mCallbackEnv->GetByteArrayElements(ert_buff,0);
     mCallbackEnv->CallVoidMethod(mCallbacksObj, method_ertCallback,ert_buff);
     mCallbackEnv->DeleteLocalRef(ert_buff);
 }
 
+void fm_ext_country_code_cb(char *ecc)
+{
+    ALOGI("Extended Contry code ");
+    jbyteArray ecc_buff = NULL;
+    int i,len;
+
+    if (!checkCallbackThread()) {
+        ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);
+        return;
+    }
+
+    len = (int)(ecc[0] & 0xFF);
+
+    ALOGI(" ecc data len=%d :",len);
+    ecc_buff = mCallbackEnv->NewByteArray(len);
+    if (ecc_buff == NULL) {
+        ALOGE(" ecc data allocate failed :");
+        return;
+    }
+    mCallbackEnv->SetByteArrayRegion(ecc_buff, 0, len,(jbyte *)ecc);
+    mCallbackEnv->CallVoidMethod(mCallbacksObj, method_eccCallback,ecc_buff);
+    mCallbackEnv->DeleteLocalRef(ecc_buff);
+}
+
+
 void rds_grp_cntrs_rsp_cb(char * evt_buffer)
 {
    ALOGE("rds_grp_cntrs_rsp_cb");
@@ -376,6 +401,7 @@
    fm_peek_cb fm_peek_rsp_cb;
    fm_ssbi_peek_cb fm_ssbi_peek_rsp_cb;
    fm_ch_det_th_cb fm_ch_det_th_rsp_cb;
+   fm_ecc_evt_cb   ext_country_code_cb;
    callback_thread_event thread_evt_cb;
 } fm_vendor_callbacks_t;
 
@@ -407,6 +433,7 @@
     fm_peek_rsp_cb,
     fm_ssbi_peek_rsp_cb,
     fm_ch_det_th_rsp_cb,
+    fm_ext_country_code_cb,
     fm_thread_evt_cb
 };
 #endif
@@ -1336,7 +1363,6 @@
 
     ALOGI("ClassInit native called \n");
 #ifdef FM_SOC_TYPE_CHEROKEE
-
     jclass dataClass = env->FindClass("qcom/fmradio/FmReceiverJNI");
     javaClassRef = (jclass) env->NewGlobalRef(dataClass);
     lib_handle = dlopen(FM_LIBRARY_NAME, RTLD_NOW);
@@ -1344,7 +1370,7 @@
         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("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);
@@ -1356,9 +1382,9 @@
     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_eccCallback = env->GetMethodID(javaClassRef, "EccCallback", "([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");
@@ -1390,9 +1416,8 @@
             ALOGE("%s unable to initialize vendor library: %d", __func__, status);
             return;
         }
-        ALOGE("***** FM HAL Initialization complete *****\n");
+        ALOGI("***** FM HAL Initialization complete *****\n");
     }
-    ALOGE("object =%p, env = %p\n",object,env);
     mCallbacksObj = env->NewGlobalRef(object);
 #endif
 }
@@ -1485,7 +1510,7 @@
     int status;
     g_jVM = jvm;
 
-    ALOGE("FM : Loading QCOMM FM-JNI");
+    ALOGI("FM : Loading QCOMM FM-JNI");
     if (jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
         ALOGE("JNI version mismatch error");
         return JNI_ERR;
diff --git a/qcom/fmradio/FmReceiver.java b/qcom/fmradio/FmReceiver.java
index 95a8c5e..8e681e7 100644
--- a/qcom/fmradio/FmReceiver.java
+++ b/qcom/fmradio/FmReceiver.java
@@ -1600,6 +1600,21 @@
       return mRdsData;
    }
 
+   public FmRxRdsData getECCInfo() {
+      byte [] raw_ecc = new byte[STD_BUF_SIZE];
+      int ecc_code =0;
+      int bytes_read;
+
+      raw_ecc = FmReceiverJNI.getPsBuffer(raw_ecc);
+      bytes_read = raw_ecc[0];
+      Log.d (TAG, "bytes_read = " + bytes_read);
+      if (bytes_read > 0) {
+          ecc_code =  raw_ecc[9] & 0xFF;
+          mRdsData.setECountryCode(ecc_code);
+          Log.d(TAG, "ECC code: " + ecc_code );
+      }
+      return mRdsData;
+   }
    /*==============================================================
    FUNCTION:  getAFInfo
    ==============================================================*/
diff --git a/qcom/fmradio/FmReceiverJNI.java b/qcom/fmradio/FmReceiverJNI.java
index 1cafe37..d085476 100644
--- a/qcom/fmradio/FmReceiverJNI.java
+++ b/qcom/fmradio/FmReceiverJNI.java
@@ -113,6 +113,17 @@
         Log.d(TAG, "RtCallback exit " );
     }
 
+    public void EccCallback(byte[] ecc) {
+        Log.i(TAG, "EccCallback enter " );
+        if (ecc == null) {
+            Log.e(TAG, "ECC null return  ");
+            return;
+        }
+        mRdsBuffer = Arrays.copyOf(ecc, ecc.length);
+        FmReceiver.mCallback.FmRxEvECCInfo();
+        Log.i(TAG, "EccCallback exit " );
+    }
+
     public void PsInfoCallback(byte[] psInfo) {
         Log.d(TAG, "PsInfoCallback enter " );
         if (psInfo == null) {
diff --git a/qcom/fmradio/FmRxEvCallbacks.java b/qcom/fmradio/FmRxEvCallbacks.java
index 50d2fb2..267d73d 100644
--- a/qcom/fmradio/FmRxEvCallbacks.java
+++ b/qcom/fmradio/FmRxEvCallbacks.java
@@ -46,4 +46,5 @@
     public void FmRxEvRdsAfInfo();
     public void FmRxEvRTPlus();
     public void FmRxEvERTInfo();
+    public void FmRxEvECCInfo();
 }
diff --git a/qcom/fmradio/FmRxEvCallbacksAdaptor.java b/qcom/fmradio/FmRxEvCallbacksAdaptor.java
index 458ff59..753d506 100644
--- a/qcom/fmradio/FmRxEvCallbacksAdaptor.java
+++ b/qcom/fmradio/FmRxEvCallbacksAdaptor.java
@@ -51,5 +51,6 @@
     public void FmRxEvRdsAfInfo() {};
     public void FmRxEvRTPlus() {};
     public void FmRxEvERTInfo() {};
+    public void FmRxEvECCInfo() {};
 }
 
diff --git a/qcom/fmradio/FmRxRdsData.java b/qcom/fmradio/FmRxRdsData.java
index f0e5b9e..1f722f1 100644
--- a/qcom/fmradio/FmRxRdsData.java
+++ b/qcom/fmradio/FmRxRdsData.java
@@ -50,6 +50,7 @@
     private int mPrgmId;
     private int mPrgmType;
     private int mFd;
+    private int mECountryCode;
 
     /* V4L2 controls */
     private static final int V4L2_CID_PRIVATE_BASE = 0x8000000;
@@ -216,6 +217,12 @@
     public void setERadioText (String x) {
          mERadioText = x;
     }
+    public void setECountryCode(int x) {
+         mECountryCode = x;
+    }
+    public int getECountryCode() {
+         return mECountryCode;
+    }
     public boolean getFormatDir() {
          return formatting_dir;
     }