Correct FM sequence in turn on and audio focus loss/gain cases for wcn3990
The FM sequence is different for wcn3990 compared to older targets ->
When enabling FM ->
1. Enable Cherokee SB slave block.
2. From FM audio driver configure SB master and port.
3. Enable FM radio on Cherokee.
When audio focus changes from FM to A2DP ->
1. FM audio driver disable/resets SB port.
2. Cherokee FM radio is shutdown (SB slave port is left enabled).
When turning off FM ->
1. FM audio driver disables/shuts down SB port.
2. Cherokee FM shuts down both FM radio and SB slave block.
Change-Id: Ib6e7efd94d82f7e4249f5b1676a7e591c339058b
diff --git a/fmapp2/src/com/caf/fmradio/FMRadioService.java b/fmapp2/src/com/caf/fmradio/FMRadioService.java
index 41022be..5213c8c 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadioService.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadioService.java
@@ -221,7 +221,9 @@
private static final int FM_OFF_FROM_APPLICATION = 1;
private static final int FM_OFF_FROM_ANTENNA = 2;
private static final int RADIO_TIMEOUT = 1500;
- private static final int RESET_SLIMBUS_DATA_PORT = 1;
+ private static final int DISABLE_SLIMBUS_DATA_PORT = 0;
+ private static final int ENABLE_SLIMBUS_DATA_PORT = 1;
+ private static final int ENABLE_SLIMBUS_CLOCK_DATA = 2;
private static Object mNotchFilterLock = new Object();
@@ -877,6 +879,7 @@
@Override
public void onRebind(Intent intent) {
+ Log.d(LOGTAG, "onRebind");
mDelayedStopHandler.removeCallbacksAndMessages(null);
cancelAlarmDealyedServiceStop();
mServiceInUse = true;
@@ -884,8 +887,9 @@
if (isFmOn()) {
setLowPowerMode(false);
startFM();
+ if (mReceiver.isCherokeeChip())
+ mReceiver.EnableSlimbus(ENABLE_SLIMBUS_DATA_PORT);
}
- Log.d(LOGTAG, "onRebind");
}
@Override
@@ -1596,15 +1600,16 @@
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
if (mReceiver != null)
- mReceiver.EnableSlimbus(RESET_SLIMBUS_DATA_PORT);
+ mReceiver.EnableSlimbus(ENABLE_SLIMBUS_DATA_PORT);
if (true == mPlaybackInProgress) {
stopFM();
}
+ mReceiver.EnableSlimbus(DISABLE_SLIMBUS_DATA_PORT);
mStoppedOnFocusLoss = true;
break;
case AudioManager.AUDIOFOCUS_LOSS:
Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_LOSS");
- //intentional fall through.
+
if (mSpeakerPhoneOn) {
mSpeakerDisableHandler.removeCallbacks(mSpeakerDisableTask);
mSpeakerDisableHandler.postDelayed(mSpeakerDisableTask, 0);
@@ -1612,6 +1617,10 @@
if (true == mPlaybackInProgress) {
stopFM();
}
+
+ //intentional fall through.
+ mReceiver.EnableSlimbus(DISABLE_SLIMBUS_DATA_PORT);
+
if (true == isFmRecordingOn())
stopRecording();
@@ -1630,8 +1639,11 @@
resumeAfterCall();
break;
}
+
if(false == mPlaybackInProgress)
startFM();
+
+ mReceiver.EnableSlimbus(ENABLE_SLIMBUS_DATA_PORT);
mSession.setActive(true);
break;
default:
@@ -2173,60 +2185,27 @@
return status;
}
- /*
- * Turn ON FM: Powers up FM hardware, and initializes the FM module
- * .
- * @return true if fm Enable api was invoked successfully, false if the api failed.
- */
- private boolean fmOn() {
- boolean bStatus=false;
- mWakeLock.acquire(10*1000);
- if ( TelephonyManager.CALL_STATE_IDLE != getCallState() ) {
- return bStatus;
- }
+ private boolean fmTurnOnSequence () {
+ boolean bStatus = false;
+ // This sets up the FM radio device
+ FmConfig config = FmSharedPreferences.getFMConfiguration();
- if(mReceiver == null)
- {
- try {
- mReceiver = new FmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);
- }
- catch (InstantiationException e)
- {
- throw new RuntimeException("FmReceiver service not available!");
- }
- }
+ Log.d(LOGTAG, "fmOn: RadioBand :"+ config.getRadioBand());
+ Log.d(LOGTAG, "fmOn: Emphasis :"+ config.getEmphasis());
+ Log.d(LOGTAG, "fmOn: ChSpacing :"+ config.getChSpacing());
+ Log.d(LOGTAG, "fmOn: RdsStd :"+ config.getRdsStd());
+ Log.d(LOGTAG, "fmOn: LowerLimit :"+ config.getLowerLimit());
+ Log.d(LOGTAG, "fmOn: UpperLimit :"+ config.getUpperLimit());
- if (mReceiver != null)
- {
- if (isFmOn())
- {
- /* FM Is already on,*/
- bStatus = true;
- Log.d(LOGTAG, "mReceiver.already enabled");
- }
- else
- {
- // This sets up the FM radio device
- FmConfig config = FmSharedPreferences.getFMConfiguration();
- Log.d(LOGTAG, "fmOn: RadioBand :"+ config.getRadioBand());
- Log.d(LOGTAG, "fmOn: Emphasis :"+ config.getEmphasis());
- Log.d(LOGTAG, "fmOn: ChSpacing :"+ config.getChSpacing());
- Log.d(LOGTAG, "fmOn: RdsStd :"+ config.getRdsStd());
- Log.d(LOGTAG, "fmOn: LowerLimit :"+ config.getLowerLimit());
- Log.d(LOGTAG, "fmOn: UpperLimit :"+ config.getUpperLimit());
- mEventReceived = false;
- bStatus = mReceiver.enable(FmSharedPreferences.getFMConfiguration(), this);
+ mEventReceived = false;
+ bStatus = mReceiver.enable(FmSharedPreferences.getFMConfiguration(), this);
- if (mReceiver.isCherokeeChip()) {
- bStatus = waitForEvent();
- }
- if (isSpeakerEnabled()) {
- setAudioPath(false);
- } else {
- setAudioPath(true);
- }
- Log.d(LOGTAG, "mReceiver.enable done, Status :" + bStatus);
- }
+ if (isSpeakerEnabled()) {
+ setAudioPath(false);
+ } else {
+ setAudioPath(true);
+ }
+ Log.d(LOGTAG, "mReceiver.enable done, Status :" + bStatus);
if (bStatus == true)
{
@@ -2281,8 +2260,141 @@
stop();
}
- /* reset SSR flag */
- mIsSSRInProgressFromActivity = false;
+ return bStatus;
+ }
+
+ /*
+ * Turn ON FM: Powers up FM hardware, and initializes the FM module
+ * .
+ * @return true if fm Enable api was invoked successfully, false if the api failed.
+ */
+ private boolean fmTurnOnSequenceCherokee () {
+ boolean bStatus = false;
+
+ // Send command to power up SB slave block
+ mEventReceived = false;
+ mReceiver.EnableSlimbus(ENABLE_SLIMBUS_CLOCK_DATA);
+ bStatus = waitForEvent();
+
+ // Send command to enable FM core
+ mEventReceived = false;
+ mReceiver.EnableSlimbus(ENABLE_SLIMBUS_DATA_PORT);
+ bStatus = waitForEvent();
+
+ AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ if ((audioManager != null) & (false == mPlaybackInProgress)) {
+ Log.d(LOGTAG, "mAudioManager.setFmRadioOn = true \n" );
+ int state = getCallState();
+ if (TelephonyManager.CALL_STATE_IDLE != getCallState())
+ {
+ fmActionOnCallState(state);
+ } else {
+ startFM(); // enable FM Audio only when Call is IDLE
+ }
+ Log.d(LOGTAG, "mAudioManager.setFmRadioOn done \n" );
+ }
+
+ // This sets up the FM radio device
+ FmConfig config = FmSharedPreferences.getFMConfiguration();
+ Log.d(LOGTAG, "fmOn: RadioBand :"+ config.getRadioBand());
+ Log.d(LOGTAG, "fmOn: Emphasis :"+ config.getEmphasis());
+ Log.d(LOGTAG, "fmOn: ChSpacing :"+ config.getChSpacing());
+ Log.d(LOGTAG, "fmOn: RdsStd :"+ config.getRdsStd());
+ Log.d(LOGTAG, "fmOn: LowerLimit :"+ config.getLowerLimit());
+ Log.d(LOGTAG, "fmOn: UpperLimit :"+ config.getUpperLimit());
+
+ // Enable FM receiver
+ mEventReceived = false;
+ bStatus = mReceiver.enable(FmSharedPreferences.getFMConfiguration(), this);
+ bStatus = waitForEvent();
+
+ if (isSpeakerEnabled()) {
+ setAudioPath(false);
+ } else {
+ setAudioPath(true);
+ }
+ Log.d(LOGTAG, "mReceiver.enable done, Status :" + bStatus);
+
+ if (bStatus == true) {
+ /* Put the hardware into normal mode */
+ bStatus = setLowPowerMode(false);
+ Log.d(LOGTAG, "setLowPowerMode done, Status :" + bStatus);
+
+ if (mReceiver != null) {
+ bStatus = mReceiver.registerRdsGroupProcessing(FmReceiver.FM_RX_RDS_GRP_RT_EBL|
+ FmReceiver.FM_RX_RDS_GRP_PS_EBL|
+ FmReceiver.FM_RX_RDS_GRP_AF_EBL|
+ FmReceiver.FM_RX_RDS_GRP_PS_SIMPLE_EBL|
+ FmReceiver.FM_RX_RDS_GRP_ECC_EBL|
+ FmReceiver.FM_RX_RDS_GRP_PTYN_EBL|
+ FmReceiver.FM_RX_RDS_GRP_RT_PLUS_EBL);
+ Log.d(LOGTAG, "registerRdsGroupProcessing done, Status :" + bStatus);
+ }
+ bStatus = enableAutoAF(FmSharedPreferences.getAutoAFSwitch());
+ Log.d(LOGTAG, "enableAutoAF done, Status :" + bStatus);
+
+ /* There is no internal Antenna*/
+ bStatus = mReceiver.setInternalAntenna(false);
+ Log.d(LOGTAG, "setInternalAntenna done, Status :" + bStatus);
+
+ /* Read back to verify the internal Antenna mode*/
+ readInternalAntennaAvailable();
+
+ startNotification();
+ bStatus = true;
+ } else {
+ mReceiver = null; // as enable failed no need to disable
+ // failure of enable can be because handle
+ // already open which gets effected if
+ // we disable
+ stop();
+ }
+
+ return bStatus;
+ }
+
+ /*
+ * Turn ON FM: Powers up FM hardware, and initializes the FM module
+ * .
+ * @return true if fm Enable api was invoked successfully, false if the api failed.
+ */
+ private boolean fmOn () {
+ boolean bStatus = false;
+ mWakeLock.acquire(10*1000);
+
+ if (TelephonyManager.CALL_STATE_IDLE != getCallState()) {
+ return bStatus;
+ }
+
+ if (mReceiver == null)
+ {
+ try {
+ mReceiver = new FmReceiver(FMRADIO_DEVICE_FD_STRING, fmCallbacks);
+ }
+ catch (InstantiationException e)
+ {
+ throw new RuntimeException("FmReceiver service not available!");
+ }
+ }
+
+ if (mReceiver != null)
+ {
+ if (isFmOn())
+ {
+ /* FM Is already on,*/
+ bStatus = true;
+ Log.d(LOGTAG, "mReceiver.already enabled");
+ }
+ else
+ {
+ if (mReceiver.isCherokeeChip()) {
+ bStatus = fmTurnOnSequenceCherokee();
+ } else {
+ bStatus = fmTurnOnSequence();
+ }
+ /* reset SSR flag */
+ mIsSSRInProgressFromActivity = false;
+ }
}
return(bStatus);
}
@@ -3155,7 +3267,8 @@
/* Receiver callbacks back from the FM Stack */
FmRxEvCallbacksAdaptor fmCallbacks = new FmRxEvCallbacksAdaptor()
{
- public void FmRxEvEnableReceiver() {
+ public void FmRxEvEnableReceiver()
+ {
Log.d(LOGTAG, "FmRxEvEnableReceiver");
mReceiver.setRawRdsGrpMask();
if (mReceiver != null && mReceiver.isCherokeeChip()) {
@@ -3610,6 +3723,16 @@
{
Log.d(LOGTAG, "FmRxEvRdsPiMatchRegDone");
}
+ public void FmRxEvEnableSlimbus(int status)
+ {
+ Log.e(LOGTAG, "FmRxEvEnableSlimbus status = " + status);
+ if (mReceiver != null && mReceiver.isCherokeeChip()) {
+ synchronized(mEventWaitLock) {
+ mEventReceived = true;
+ mEventWaitLock.notify();
+ }
+ }
+ }
};
@@ -3870,7 +3993,8 @@
else
cancelAlarmRecordTimeout();
}
- private void requestFocus() {
+
+ private void requestFocusImpl() {
if( (false == mPlaybackInProgress) &&
(true == mStoppedOnFocusLoss) && isFmOn()) {
// adding code for audio focus gain.
@@ -3881,6 +4005,33 @@
mStoppedOnFocusLoss = false;
}
}
+
+ private void requestFocusImplCherokee() {
+ Log.d(LOGTAG, "++requestFocusImplCherokee mPlaybackInProgress: " +
+ mPlaybackInProgress + " mStoppedOnFocusLoss: " +
+ mStoppedOnFocusLoss + " isFmOn: " + isFmOn());
+ if( (false == mPlaybackInProgress) &&
+ (true == mStoppedOnFocusLoss) && isFmOn()) {
+ // adding code for audio focus gain.
+ AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
+ audioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ startFM();
+ mReceiver.EnableSlimbus(ENABLE_SLIMBUS_DATA_PORT);
+ mStoppedOnFocusLoss = false;
+ }
+ }
+
+ private void requestFocus() {
+ Log.d(LOGTAG, "++requestFocus");
+ if (mReceiver.isCherokeeChip()) {
+ requestFocusImplCherokee();
+ } else {
+ requestFocusImpl();
+ }
+ Log.d(LOGTAG, "--requestFocus");
+ }
+
private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
mDelayedStopHandler.obtainMessage(FOCUSCHANGE, focusChange, 0).sendToTarget();
diff --git a/fmapp2/src/com/caf/fmradio/FMTransmitterService.java b/fmapp2/src/com/caf/fmradio/FMTransmitterService.java
index e3cf3d6..1d964c4 100644
--- a/fmapp2/src/com/caf/fmradio/FMTransmitterService.java
+++ b/fmapp2/src/com/caf/fmradio/FMTransmitterService.java
@@ -1018,6 +1018,11 @@
e.printStackTrace();
}
}
+
+ public void FmRxEvEnableSlimbus(int status)
+ {
+ Log.d(LOGTAG, "FmRxEvEnableReceiver status = " + status);
+ }
};
diff --git a/helium/radio-helium.h b/helium/radio-helium.h
index 200e006..79f61bd 100644
--- a/helium/radio-helium.h
+++ b/helium/radio-helium.h
@@ -171,6 +171,7 @@
typedef void (*fm_set_blnd_cb) (int status);
typedef void (*fm_get_stn_prm_cb) (int val, int status);
typedef void (*fm_get_stn_dbg_prm_cb) (int val, int status);
+typedef void (*fm_enable_slimbus_cb) (int status);
typedef struct {
size_t size;
@@ -206,6 +207,7 @@
fm_set_blnd_cb fm_set_blend_cb;
fm_get_stn_prm_cb fm_get_station_param_cb;
fm_get_stn_dbg_prm_cb fm_get_station_debug_param_cb;
+ fm_enable_slimbus_cb enable_slimbus_cb;
} fm_hal_callbacks_t;
/* Opcode OCF */
diff --git a/helium/radio_helium_hal.c b/helium/radio_helium_hal.c
index 1109ca3..a25d888 100644
--- a/helium/radio_helium_hal.c
+++ b/helium/radio_helium_hal.c
@@ -79,7 +79,6 @@
return;
}
rsp = (struct hci_fm_conf_rsp *)ev_rsp;
- hal->jni_cb->thread_evt_cb(0);
radio_hci_req_complete(rsp->status);
hal->jni_cb->enabled_cb();
if (rsp->status == FM_HC_STATUS_SUCCESS)
@@ -394,6 +393,13 @@
clear_all_bit(station_dbg_param_mask_flag);
}
+static void hci_cc_enable_slimbus_rsp(char *ev_buff)
+{
+ ALOGV("%s status %d", __func__, ev_buff[0]);
+ hal->jni_cb->thread_evt_cb(0);
+ hal->jni_cb->enable_slimbus_cb(ev_buff[0]);
+}
+
static inline void hci_cmd_complete_event(char *buff)
{
uint16_t opcode;
@@ -491,6 +497,10 @@
hci_cc_dbg_param_rsp(pbuf);
break;
+ case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_ENABLE_SLIMBUS):
+ hci_cc_enable_slimbus_rsp(pbuf);
+ break;
+
/* case hci_common_cmd_op_pack(HCI_OCF_FM_GET_SPUR_TABLE):
hci_cc_get_spur_tbl(buff);
break;
diff --git a/jni/android_hardware_fm.cpp b/jni/android_hardware_fm.cpp
index 516e0e4..06d03ce 100644
--- a/jni/android_hardware_fm.cpp
+++ b/jni/android_hardware_fm.cpp
@@ -120,9 +120,11 @@
typedef void (*fm_set_blnd_cb) (int status);
typedef void (*fm_get_stn_prm_cb) (int val, int status);
typedef void (*fm_get_stn_dbg_prm_cb) (int val, int status);
+typedef void (*fm_enable_sb_cb) (int status);
static JNIEnv *mCallbackEnv = NULL;
static jobject mCallbacksObj = NULL;
+static bool mCallbacksObjCreated = false;
static jfieldID sCallbacksField;
jclass javaClassRef;
@@ -150,6 +152,7 @@
jmethodID method_setBlendCallback;
jmethodID method_getStnParamCallback;
jmethodID method_getStnDbgParamCallback;
+jmethodID method_enableSlimbusCallback;
static bool checkCallbackThread() {
JNIEnv* env = AndroidRuntime::getJNIEnv();
@@ -163,12 +166,11 @@
void fm_enabled_cb() {
ALOGD("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);
- }
+
+ if (!checkCallbackThread())
+ return;
+
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_enableCallback);
ALOGD("exit %s", __func__);
}
@@ -396,6 +398,7 @@
return;
mCallbackEnv->CallVoidMethod(mCallbacksObj, method_disableCallback);
+ mCallbacksObjCreated = false;
}
void fm_peek_rsp_cb(char *peek_rsp) {
@@ -523,6 +526,24 @@
mCallbackEnv->CallVoidMethod(mCallbacksObj, method_getStnDbgParamCallback, val, status);
}
+static void fm_enable_slimbus_cb(int status)
+{
+ ALOGD("++fm_enable_slimbus_cb mCallbacksObjCreated: %d", mCallbacksObjCreated);
+
+ if (mCallbacksObjCreated == false) {
+ jobject javaObjectRef = mCallbackEnv->NewObject(javaClassRef, method_enableSlimbusCallback);
+ mCallbacksObj = javaObjectRef;
+ mCallbacksObjCreated = true;
+ return;
+ }
+
+ if (!checkCallbackThread())
+ return;
+
+ mCallbackEnv->CallVoidMethod(mCallbacksObj, method_enableSlimbusCallback, status);
+ ALOGV("--fm_enable_slimbus_cb");
+}
+
typedef struct {
size_t size;
@@ -557,6 +578,7 @@
fm_set_blnd_cb fm_set_blend_cb;
fm_get_stn_prm_cb fm_get_station_param_cb;
fm_get_stn_dbg_prm_cb fm_get_station_debug_param_cb;
+ fm_enable_sb_cb fm_enable_slimbus_cb;
} fm_vendor_callbacks_t;
typedef struct {
@@ -598,7 +620,8 @@
fm_def_data_write_cb,
fm_set_blend_cb,
fm_get_station_param_cb,
- fm_get_station_debug_param_cb
+ fm_get_station_debug_param_cb,
+ fm_enable_slimbus_cb
};
#endif
/* native interface */
@@ -1593,6 +1616,7 @@
method_setBlendCallback = env->GetMethodID(javaClassRef, "setBlendCallback", "(I)V");
method_getStnParamCallback = env->GetMethodID(javaClassRef, "getStnParamCallback", "(II)V");
method_getStnDbgParamCallback = env->GetMethodID(javaClassRef, "getStnDbgParamCallback", "(II)V");
+ method_enableSlimbusCallback = env->GetMethodID(javaClassRef, "enableSlimbusCallback", "(I)V");
return;
error:
@@ -1621,6 +1645,7 @@
mCallbacksObj = env->NewGlobalRef(object);
#endif
}
+
static void cleanupNative(JNIEnv *env, jobject object) {
#ifdef FM_SOC_TYPE_CHEROKEE
diff --git a/qcom/fmradio/FmReceiverJNI.java b/qcom/fmradio/FmReceiverJNI.java
index d9fa79a..1487b7c 100644
--- a/qcom/fmradio/FmReceiverJNI.java
+++ b/qcom/fmradio/FmReceiverJNI.java
@@ -127,6 +127,13 @@
FmReceiver.mCallback.FmRxGetStationDbgParam(val, status);
}
+ public void enableSlimbusCallback(int status)
+ {
+ Log.d(TAG, "++enableSlimbusCallback" );
+ FmReceiver.mCallback.FmRxEvEnableSlimbus(status);
+ Log.d(TAG, "--enableSlimbusCallback" );
+ }
+
public void RtPlusCallback(byte[] rtplus) {
Log.d(TAG, "RtPlusCallback enter " );
if (rtplus == null) {
diff --git a/qcom/fmradio/FmRxEvCallbacks.java b/qcom/fmradio/FmRxEvCallbacks.java
index 267d73d..31a8312 100644
--- a/qcom/fmradio/FmRxEvCallbacks.java
+++ b/qcom/fmradio/FmRxEvCallbacks.java
@@ -47,4 +47,5 @@
public void FmRxEvRTPlus();
public void FmRxEvERTInfo();
public void FmRxEvECCInfo();
+ public void FmRxEvEnableSlimbus(int status);
}
diff --git a/qcom/fmradio/FmRxEvCallbacksAdaptor.java b/qcom/fmradio/FmRxEvCallbacksAdaptor.java
index 59953e8..213cf43 100644
--- a/qcom/fmradio/FmRxEvCallbacksAdaptor.java
+++ b/qcom/fmradio/FmRxEvCallbacksAdaptor.java
@@ -61,4 +61,5 @@
public void FmRxEvSetBlend(int status) {};
public void FmRxGetStationParam(int val, int status) {};
public void FmRxGetStationDbgParam(int val, int status) {};
+ public void FmRxEvEnableSlimbus(int status) {};
}