Merge "FM: Change the status notification icon's color to black"
diff --git a/fmapp2/src/com/caf/fmradio/FMRadio.java b/fmapp2/src/com/caf/fmradio/FMRadio.java
index 0acbc63..6fa9298 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadio.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadio.java
@@ -234,6 +234,7 @@
 
    /* Current Status Indicators */
    private static boolean mRecording = false;
+   private static boolean mRtPlusSupported = false;
    private static boolean mIsScaning = false;
    private static boolean mIsSeeking = false;
    private static boolean mIsSearching = false;
@@ -648,6 +649,7 @@
       MenuItem item;
       boolean radioOn = isFmOn();
       boolean recording = isRecording();
+      boolean RtPlusSupported = isRtPlusSupported();
       boolean mSpeakerPhoneOn = isSpeakerEnabled();
       boolean searchActive = isScanActive() || isSeekActive();
 
@@ -681,6 +683,9 @@
       if (item != null) {
           item.setVisible(sleepActive && radioOn);
       }
+      item = menu.findItem(MENU_TAGS);
+      if (item != null)
+          item.setVisible(RtPlusSupported);
       return true;
    }
 
@@ -1831,6 +1836,19 @@
       return(mRecording);
    }
 
+   private boolean isRtPlusSupported() {
+      mRtPlusSupported = false;
+      if (mService != null) {
+          try {
+             mRtPlusSupported = mService.isRtPlusSupported();
+          } catch (RemoteException e) {
+             e.printStackTrace();
+         }
+      }
+      Log.d(LOGTAG, "mRtPlusSupported: " + mRtPlusSupported);
+      return(mRtPlusSupported);
+   }
+
    private boolean isSpeakerEnabled() {
       boolean speakerEnabled = false;
       if (mService != null) {
diff --git a/fmapp2/src/com/caf/fmradio/FMRadioService.java b/fmapp2/src/com/caf/fmradio/FMRadioService.java
index c463f46..c7f1682 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadioService.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadioService.java
@@ -125,6 +125,7 @@
    MediaRecorder mA2dp = null;
    private boolean mFMOn = false;
    private boolean mFmRecordingOn = false;
+   private static boolean mRtPlusSupport = false;
    private boolean mSpeakerPhoneOn = false;
    private int mCallStatus = 0;
    private BroadcastReceiver mScreenOnOffReceiver = null;
@@ -184,6 +185,7 @@
    private MediaSession mSession;
    private boolean mIsSSRInProgress = false;
    private boolean mIsSSRInProgressFromActivity = false;
+   private int mKeyActionDownCount = 0;
 
    public FMRadioService() {
    }
@@ -826,10 +828,18 @@
             Log.d(LOGTAG, "SessionCallback.onMediaButton()...  event = " +event);
             int key_action = event.getAction();
             if ((event != null) && ((event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)
-                                    || (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE))
-                                && (key_action == KeyEvent.ACTION_DOWN)) {
-                Log.d(LOGTAG, "SessionCallback: HEADSETHOOK/MEDIA_PLAY_PAUSE");
-                toggleFM();
+                                    || (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE))) {
+                if (key_action == KeyEvent.ACTION_DOWN) {
+                    mKeyActionDownCount++;
+                }
+                if ((mKeyActionDownCount == 1) && (key_action == KeyEvent.ACTION_UP)) {
+                    Log.d(LOGTAG, "SessionCallback: HEADSETHOOK/MEDIA_PLAY_PAUSE short press");
+                    mKeyActionDownCount = 0;
+                    toggleFM();
+                } else if ((mKeyActionDownCount == 2) && (key_action == KeyEvent.ACTION_DOWN)) {
+                    Log.d(LOGTAG, "SessionCallback: HEADSETHOOK/MEDIA_PLAY_PAUSE long press");
+                    mKeyActionDownCount = 0;
+                }
                 return true;
             } else if((event != null) && (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PAUSE)
                        && (key_action == KeyEvent.ACTION_DOWN)) {
@@ -1495,6 +1505,11 @@
          return(mService.get().isFmRecordingOn());
       }
 
+      public boolean isRtPlusSupported()
+      {
+         return(mService.get().isRtPlusSupported());
+      }
+
       public boolean isSpeakerEnabled()
       {
          return(mService.get().isSpeakerEnabled());
@@ -2029,6 +2044,10 @@
       return mFmRecordingOn;
    }
 
+   public boolean isRtPlusSupported() {
+      return mRtPlusSupport;
+   }
+
    public boolean isSpeakerEnabled() {
       return mSpeakerPhoneOn;
    }
@@ -2697,6 +2716,7 @@
 
    public void clearStationInfo() {
        if(mFMRxRDSData != null) {
+          mRtPlusSupport = false;
           mFMRxRDSData.setRadioText("");
           mFMRxRDSData.setPrgmId(0);
           mFMRxRDSData.setPrgmType(0);
@@ -2991,6 +3011,7 @@
       {
          int tag_nums;
          Log.d(LOGTAG, "FmRxEvRTPlusInfo");
+         mRtPlusSupport =  true;
          if (mReceiver != null) {
              mFMRxRDSData = mReceiver.getRTPlusInfo();
              tag_nums = mFMRxRDSData.getTagNums();
diff --git a/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl b/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
index 7b04d71..7a2062d 100644
--- a/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
+++ b/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
@@ -73,5 +73,6 @@
     long getRecordingStartTime();
     boolean isSleepTimerActive();
     boolean isSSRInProgress();
+    boolean isRtPlusSupported();
 }
 
diff --git a/jni/android_hardware_fm.cpp b/jni/android_hardware_fm.cpp
index 82fdb97..b97c554 100644
--- a/jni/android_hardware_fm.cpp
+++ b/jni/android_hardware_fm.cpp
@@ -38,7 +38,6 @@
 #include <cutils/properties.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
-#include <media/tavarua.h>
 #include <linux/videodev2.h>
 #include <math.h>
 
@@ -59,6 +58,16 @@
 #define WAIT_TIMEOUT 200000 /* 200*1000us */
 #define TX_RT_DELIMITER    0x0d
 #define PS_LEN    9
+#define V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_RT 0x08000017
+#define V4L2_CID_PRIVATE_TAVARUA_STOP_RDS_TX_PS_NAME 0x08000016
+#define V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE 0x08000034
+#define V4L2_CID_PRIVATE_TAVARUA_TX_SETPSREPEATCOUNT 0x08000034
+#define MASK_PI                    (0x0000FFFF)
+#define MASK_PI_MSB                (0x0000FF00)
+#define MASK_PI_LSB                (0x000000FF)
+#define MASK_PTY                   (0x0000001F)
+#define MASK_TXREPCOUNT            (0x0000000F)
+
 enum search_dir_t {
     SEEK_UP,
     SEEK_DN,