Created
October 4, 2016 16:28
-
-
Save ngoquang2708/aa36df33685db82277647ad3a785fba8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/Android.mk b/Android.mk | |
index 1fc1a34..f6bd934 100644 | |
--- a/Android.mk | |
+++ b/Android.mk | |
@@ -28,7 +28,11 @@ LOCAL_CERTIFICATE := platform | |
LOCAL_SRC_FILES := $(call all-java-files-under, src) | |
LOCAL_PACKAGE_NAME := FMRadio | |
+ifeq ($(strip $(BOARD_HAVE_FMRADIO_BCM)),true) | |
+LOCAL_STATIC_JAVA_LIBRARIES += com.broadcom.fm | |
+else | |
LOCAL_JNI_SHARED_LIBRARIES := libfmjni | |
+endif | |
LOCAL_PROGUARD_ENABLED := disabled | |
LOCAL_PRIVILEGED_MODULE := true | |
@@ -40,4 +44,6 @@ LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages android.support.v7.cardv | |
include $(BUILD_PACKAGE) | |
+ifneq ($(strip $(BOARD_HAVE_FMRADIO_BCM)),true) | |
include $(call all-makefiles-under,$(LOCAL_PATH)) | |
+endif | |
diff --git a/src/com/android/fmradio/FmListener.java b/src/com/android/fmradio/FmListener.java | |
index e060c52..fad83b4 100644 | |
--- a/src/com/android/fmradio/FmListener.java | |
+++ b/src/com/android/fmradio/FmListener.java | |
@@ -84,6 +84,7 @@ | |
int MSGID_SET_CHANNEL_FINISHED = 6; | |
int MSGID_SET_MUTE_FINISHED = 7; | |
// Fm main | |
+ int MSGID_OPENDEVICE_FINISHED = 8; | |
int MSGID_POWERUP_FINISHED = 9; | |
int MSGID_POWERDOWN_FINISHED = 10; | |
int MSGID_FM_EXIT = 11; | |
diff --git a/src/com/android/fmradio/FmNative.java b/src/com/android/fmradio/FmNative.java | |
index da8cbce..8304ee5 100644 | |
--- a/src/com/android/fmradio/FmNative.java | |
+++ b/src/com/android/fmradio/FmNative.java | |
@@ -16,27 +16,33 @@ | |
package com.android.fmradio; | |
+import android.content.Context; | |
+ | |
/** | |
* This class define FM native interface, will description FM native interface | |
*/ | |
-public class FmNative { | |
- static { | |
- System.loadLibrary("fmjni"); | |
- } | |
+public abstract class FmNative { | |
+ private static FmNative mInstance = null; | |
+ | |
+ public static synchronized FmNative getInstance() { | |
+ if (mInstance == null) | |
+ mInstance = new FmNativeBroadcom(); | |
+ return mInstance; | |
+ } | |
/** | |
* Open FM device, call before power up | |
* | |
* @return (true,success; false, failed) | |
*/ | |
- static native boolean openDev(); | |
+ public abstract boolean openDev(Context ctx); | |
/** | |
* Close FM device, call after power down | |
* | |
* @return (true, success; false, failed) | |
*/ | |
- static native boolean closeDev(); | |
+ public abstract boolean closeDev(); | |
/** | |
* power up FM with frequency use long antenna | |
@@ -45,7 +51,7 @@ | |
* | |
* @return (true, success; false, failed) | |
*/ | |
- static native boolean powerUp(float frequency); | |
+ public abstract boolean powerUp(float frequency); | |
/** | |
* Power down FM | |
@@ -54,7 +60,7 @@ | |
* | |
* @return (true, success; false, failed) | |
*/ | |
- static native boolean powerDown(int type); | |
+ public abstract boolean powerDown(int type); | |
/** | |
* tune to frequency | |
@@ -63,7 +69,7 @@ | |
* | |
* @return (true, success; false, failed) | |
*/ | |
- static native boolean tune(float frequency); | |
+ public abstract boolean tune(float frequency); | |
/** | |
* seek with frequency in direction | |
@@ -73,14 +79,14 @@ | |
* | |
* @return frequency(float) | |
*/ | |
- static native float seek(float frequency, boolean isUp); | |
+ public abstract float seek(float frequency, boolean isUp); | |
/** | |
* Auto scan(from 87.50-108.00) | |
* | |
* @return The scan station array(short) | |
*/ | |
- static native short[] autoScan(); | |
+ public abstract short[] autoScan(); | |
/** | |
* Stop scan, also can stop seek, other native when scan should call stop | |
@@ -88,7 +94,7 @@ | |
* | |
* @return (true, can stop scan process; false, can't stop scan process) | |
*/ | |
- static native boolean stopScan(); | |
+ public abstract boolean stopScan(); | |
/** | |
* Open or close rds fuction | |
@@ -97,35 +103,35 @@ | |
* | |
* @return rdsset | |
*/ | |
- static native int setRds(boolean rdson); | |
+ public abstract int setRds(boolean rdson); | |
/** | |
* Read rds events | |
* | |
* @return rds event type | |
*/ | |
- static native short readRds(); | |
+ public abstract short readRds(); | |
/** | |
* Get program service(program name) | |
* | |
* @return The program name | |
*/ | |
- static native byte[] getPs(); | |
+ public abstract byte[] getPs(); | |
/** | |
* Get radio text, RDS standard does not support Chinese character | |
* | |
* @return The LRT (Last Radio Text) bytes | |
*/ | |
- static native byte[] getLrText(); | |
+ public abstract byte[] getLrText(); | |
/** | |
* Active alternative frequencies | |
* | |
* @return The frequency(float) | |
*/ | |
- static native short activeAf(); | |
+ public abstract short activeAf(); | |
/** | |
* Mute or unmute FM voice | |
@@ -134,14 +140,14 @@ | |
* | |
* @return (true, success; false, failed) | |
*/ | |
- static native int setMute(boolean mute); | |
+ public abstract int setMute(boolean mute); | |
/** | |
* Inquiry if RDS is support in driver | |
* | |
* @return (1, support; 0, NOT support; -1, error) | |
*/ | |
- static native int isRdsSupport(); | |
+ public abstract int isRdsSupport(); | |
/** | |
* Switch antenna | |
@@ -150,5 +156,5 @@ | |
* | |
* @return (0, success; 1 failed; 2 not support) | |
*/ | |
- static native int switchAntenna(int antenna); | |
+ public abstract int switchAntenna(int antenna); | |
} | |
diff --git a/src/com/android/fmradio/FmNativeBroadcom.java b/src/com/android/fmradio/FmNativeBroadcom.java | |
new file mode 100644 | |
index 0000000..60036d6 | |
--- /dev/null | |
+++ b/src/com/android/fmradio/FmNativeBroadcom.java | |
@@ -0,0 +1,439 @@ | |
+/* | |
+ * Copyright (C) 2014 The Android Open Source Project | |
+ * | |
+ * 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. | |
+ */ | |
+ | |
+package com.android.fmradio; | |
+ | |
+import android.content.Context; | |
+ | |
+import com.broadcom.fm.fmreceiver.FmProxy; | |
+import com.broadcom.fm.fmreceiver.IFmReceiverEventHandler; | |
+import com.broadcom.fm.fmreceiver.IFmProxyCallback; | |
+ | |
+import java.util.ArrayList; | |
+ | |
+/** | |
+ * This class define FM native interface, will description FM native interface | |
+ */ | |
+public class FmNativeBroadcom extends FmNative implements IFmProxyCallback, IFmReceiverEventHandler { | |
+ private static final int TIMEOUT = 5000; | |
+ | |
+ private static final int RDS_ID_PTY_EVT = 2; | |
+ private static final int RDS_ID_PS_EVT = 7; | |
+ private static final int RDS_ID_PTYN_EVT = 8; | |
+ private static final int RDS_ID_RT_EVT = 9; | |
+ | |
+ private static final int RDS_EVT_PS = 1; | |
+ private static final int RDS_EVT_RT = 2; | |
+ | |
+ private FmProxy mFmReceiver = null; | |
+ | |
+ private float mfrequency = 0.0f; | |
+ private boolean mRdsOn = false; | |
+ private int mRdsEvent = 0; | |
+ private String mRdsProgramService; | |
+ private String mRdsRadioText; | |
+ | |
+ public boolean openDev(Context ctx) { | |
+ synchronized(this) { | |
+ if (mFmReceiver == null) { | |
+ if (!FmProxy.getProxy(ctx, this)) { | |
+ return false; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return false; | |
+ } | |
+ return (mFmReceiver != null); | |
+ } | |
+ return true; | |
+ } | |
+ } | |
+ | |
+ public boolean closeDev() { | |
+ synchronized(this) { | |
+ if (mFmReceiver != null) { | |
+ try { | |
+ mFmReceiver.unregisterEventHandler(); | |
+ mFmReceiver.finish(); | |
+ } catch (IllegalArgumentException ei) { | |
+ ; | |
+ } catch (Exception e) { | |
+ // Fatal Exception to closeDev | |
+ } finally { | |
+ mFmReceiver = null; | |
+ } | |
+ } | |
+ return true; | |
+ } | |
+ } | |
+ | |
+ public boolean powerUp(float frequency) { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return false; | |
+ } | |
+ if (mFmReceiver.turnOnRadio(FmProxy.FUNC_REGION_NA | FmProxy.FUNC_RBDS | FmProxy.FUNC_AF | FmProxy.FUNC_SOFTMUTE) != FmProxy.STATUS_OK) { | |
+ return false; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return false; | |
+ } | |
+ if (mFmReceiver.tuneRadio((int)(frequency * 100)) != FmProxy.STATUS_OK) { | |
+ return false; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return false; | |
+ } | |
+ if (mFmReceiver.setAudioPath(FmProxy.AUDIO_PATH_DIGITAL) != FmProxy.STATUS_OK) { | |
+ return false; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return false; | |
+ } | |
+ if (mFmReceiver.setFMVolume(255) != FmProxy.STATUS_OK) { | |
+ return false; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return false; | |
+ } | |
+ return true; | |
+ } | |
+ } | |
+ | |
+ public boolean powerDown(int type) { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return false; | |
+ } | |
+ if (mFmReceiver.turnOffRadio() != FmProxy.STATUS_OK) { | |
+ return false; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return false; | |
+ } | |
+ return true; | |
+ } | |
+ } | |
+ | |
+ public boolean tune(float frequency) { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return false; | |
+ } | |
+ if (mFmReceiver.tuneRadio((int)(frequency * 100)) != FmProxy.STATUS_OK) { | |
+ return false; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return false; | |
+ } | |
+ return mfrequency == frequency; | |
+ } | |
+ } | |
+ | |
+ public float seek(float frequency, boolean isUp) { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return 0f; | |
+ } | |
+ if (mFmReceiver.tuneRadio((int)(frequency * 100)) != FmProxy.STATUS_OK) { | |
+ return 0f; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return 0f; | |
+ } | |
+ if (mfrequency != frequency) { | |
+ return 0f; | |
+ } | |
+ if (mFmReceiver.seekStation(isUp ? FmProxy.SCAN_MODE_UP : FmProxy.SCAN_MODE_DOWN) != FmProxy.STATUS_OK) { | |
+ return 0f; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return 0f; | |
+ } | |
+ return mfrequency == frequency ? 0f : mfrequency; | |
+ } | |
+ } | |
+ | |
+ public short[] autoScan() { | |
+ synchronized (this) { | |
+ ArrayList<Short> freqList = new ArrayList<Short>(); | |
+ float frequency = FmUtils.computeFrequency(FmUtils.getLowestStation()); | |
+ | |
+ if (mFmReceiver == null) { | |
+ return null; | |
+ } | |
+ if (mFmReceiver.tuneRadio((int)(frequency * 100)) != FmProxy.STATUS_OK) { | |
+ return null; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return null; | |
+ } | |
+ while (true) { | |
+ if (mFmReceiver.seekStation(FmProxy.SCAN_MODE_UP) != FmProxy.STATUS_OK) { | |
+ return null; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return null; | |
+ } | |
+ if ((mfrequency <= frequency) || (mfrequency >= FmUtils.computeFrequency(FmUtils.getHighestStation()))) { | |
+ break; | |
+ } | |
+ freqList.add((short)FmUtils.computeStation(mfrequency)); | |
+ frequency = mfrequency; | |
+ } | |
+ if (freqList.size() == 0) { | |
+ return null; | |
+ } | |
+ short[] freqArray = new short[freqList.size()]; | |
+ for (int i = 0; i < freqList.size(); i++) { | |
+ freqArray[i] = freqList.get(i); | |
+ } | |
+ return freqArray; | |
+ } | |
+ } | |
+ | |
+ public boolean stopScan() { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return false; | |
+ } | |
+ if (mFmReceiver.seekStationAbort() != FmProxy.STATUS_OK) { | |
+ return false; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return false; | |
+ } | |
+ return true; | |
+ } | |
+ } | |
+ | |
+ public int setRds(boolean rdson) { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return 0; | |
+ } | |
+ if (mFmReceiver.setRdsMode(rdson ? FmProxy.RDS_MODE_DEFAULT_ON : FmProxy.RDS_MODE_OFF, | |
+ FmProxy.RDS_FEATURE_PS | FmProxy.RDS_FEATURE_RT, | |
+ FmProxy.AF_MODE_OFF, FmProxy.MIN_SIGNAL_STRENGTH_DEFAULT) != FmProxy.STATUS_OK) { | |
+ return 0; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return 0; | |
+ } | |
+ return 1; | |
+ } | |
+ } | |
+ | |
+ public short readRds() { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return 0; | |
+ } | |
+ if (mRdsOn) { | |
+ if ((mRdsEvent & RDS_EVT_PS) != 0) { | |
+ mRdsEvent &= ~RDS_EVT_PS; | |
+ return 0x0008; | |
+ } | |
+ if ((mRdsEvent & RDS_EVT_RT) != 0) { | |
+ mRdsEvent &= ~RDS_EVT_RT; | |
+ return 0x0040; | |
+ } | |
+ } | |
+ return 0; | |
+ } | |
+ } | |
+ | |
+ public byte[] getPs() { | |
+ synchronized (this) { | |
+ if ((mFmReceiver == null) || !mRdsOn) { | |
+ return null; | |
+ } | |
+ try { | |
+ return mRdsProgramService.getBytes("UTF8"); | |
+ } catch (Exception e) { | |
+ return null; | |
+ } | |
+ } | |
+ } | |
+ | |
+ public byte[] getLrText() { | |
+ synchronized (this) { | |
+ if ((mFmReceiver == null) || !mRdsOn || (mRdsRadioText == null)) { | |
+ return null; | |
+ } | |
+ try { | |
+ return mRdsRadioText.getBytes("UTF8"); | |
+ } catch (Exception e) { | |
+ return null; | |
+ } | |
+ } | |
+ } | |
+ | |
+ public short activeAf() { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return 0; | |
+ } | |
+ if (mFmReceiver.setRdsMode(FmProxy.RDS_MODE_DEFAULT_ON, | |
+ FmProxy.RDS_FEATURE_PS | FmProxy.RDS_FEATURE_RT | FmProxy.RDS_FEATURE_TP | FmProxy.RDS_FEATURE_PTY | FmProxy.RDS_FEATURE_PTYN, | |
+ FmProxy.AF_MODE_ON, FmProxy.MIN_SIGNAL_STRENGTH_DEFAULT) != FmProxy.STATUS_OK) { | |
+ return 0; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return 0; | |
+ } | |
+ return (short)FmUtils.computeStation(mfrequency); | |
+ } | |
+ } | |
+ | |
+ public int setMute(boolean mute) { | |
+ synchronized (this) { | |
+ if (mFmReceiver == null) { | |
+ return 0; | |
+ } | |
+ if (mFmReceiver.muteAudio(mute) != FmProxy.STATUS_OK) { | |
+ return 0; | |
+ } | |
+ try { | |
+ this.wait(TIMEOUT); | |
+ } catch (Exception e) { | |
+ return 0; | |
+ } | |
+ return 1; | |
+ } | |
+ } | |
+ | |
+ public int isRdsSupport() { | |
+ return 1; | |
+ } | |
+ | |
+ public int switchAntenna(int antenna) { | |
+ return 2; | |
+ } | |
+ | |
+ | |
+ public void onProxyAvailable(Object ProxyObject) { | |
+ synchronized (this) { | |
+ mFmReceiver = (FmProxy)ProxyObject; | |
+ mFmReceiver.registerEventHandler(this); | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ public void onAudioModeEvent(int audioMode) { | |
+ synchronized (this) { | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ | |
+ public void onAudioPathEvent(int audioPath) { | |
+ synchronized (this) { | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ public void onEstimateNoiseFloorLevelEvent(int nfl) { | |
+ synchronized (this) { | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ public void onLiveAudioQualityEvent(int rssi, int snr) { | |
+ synchronized (this) { | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ public void onRdsDataEvent(int rdsDataType, int rdsIndex, | |
+ String rdsText) { | |
+ synchronized (this) { | |
+ if (mRdsOn) { | |
+ if (rdsDataType == RDS_ID_PS_EVT) { | |
+ mRdsEvent |= RDS_EVT_PS; | |
+ mRdsProgramService = rdsText; | |
+ } else if (rdsDataType == RDS_ID_RT_EVT) { | |
+ mRdsEvent |= RDS_EVT_RT; | |
+ mRdsRadioText = rdsText; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ public void onRdsModeEvent(int rdsMode, int alternateFreqHopEnabled) { | |
+ synchronized (this) { | |
+ mRdsOn = rdsMode != FmProxy.RDS_MODE_OFF; | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ public void onSeekCompleteEvent(int freq, int rssi, | |
+ int snr, boolean seeksuccess) { | |
+ synchronized (this) { | |
+ if (seeksuccess) | |
+ mfrequency = freq / 100f; | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ public void onStatusEvent(int freq, int rssi, int snr, boolean radioIsOn, | |
+ int rdsProgramType, String rdsProgramService, | |
+ String rdsRadioText, String rdsProgramTypeName, boolean isMute) { | |
+ synchronized (this) { | |
+ mfrequency = freq / 100f; | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ public void onWorldRegionEvent(int worldRegion) { | |
+ synchronized (this) { | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+ | |
+ public void onVolumeEvent(int status, int volume) { | |
+ synchronized (this) { | |
+ this.notifyAll(); | |
+ } | |
+ } | |
+} | |
diff --git a/src/com/android/fmradio/FmRecorder.java b/src/com/android/fmradio/FmRecorder.java | |
index 389fbc2..d45cae3 100644 | |
--- a/src/com/android/fmradio/FmRecorder.java | |
+++ b/src/com/android/fmradio/FmRecorder.java | |
@@ -46,10 +46,10 @@ | |
// file prefix | |
public static final String RECORDING_FILE_PREFIX = "FM"; | |
// file extension | |
- public static final String RECORDING_FILE_EXTENSION = ".3gpp"; | |
+ public static final String RECORDING_FILE_EXTENSION = ".m4a"; | |
// recording file folder | |
public static final String FM_RECORD_FOLDER = "FM Recording"; | |
- private static final String RECORDING_FILE_TYPE = "audio/3gpp"; | |
+ private static final String RECORDING_FILE_TYPE = "audio/mp4"; | |
private static final String RECORDING_FILE_SOURCE = "FM Recordings"; | |
// error type no sdcard | |
public static final int ERROR_SDCARD_NOT_PRESENT = 0; | |
diff --git a/src/com/android/fmradio/FmService.java b/src/com/android/fmradio/FmService.java | |
index f6e98c3..f2582e6 100644 | |
--- a/src/com/android/fmradio/FmService.java | |
+++ b/src/com/android/fmradio/FmService.java | |
@@ -106,6 +106,10 @@ | |
// Set audio policy for FM | |
// should check AUDIO_POLICY_FORCE_FOR_MEDIA in audio_policy.h | |
private static final int FOR_PROPRIETARY = 1; | |
+ | |
+ // use audio patch api | |
+ private static final boolean USE_AUDIO_PATCH = false; | |
+ | |
// Forced Use value | |
private int mForcedUseForMedia; | |
@@ -134,7 +138,7 @@ | |
// RT String | |
private String mRtTextString = ""; | |
// Notification target class name | |
- private String mTargetClassName = "com.android.fmradio.FmMainActivity"; | |
+ private String mTargetClassName = FmMainActivity.class.getName(); | |
// RDS thread use to receive the information send by station | |
private Thread mRdsThread = null; | |
// record whether RDS thread exit | |
@@ -217,6 +221,8 @@ | |
private Notification.Builder mNotificationBuilder = null; | |
private BigTextStyle mNotificationStyle = null; | |
+ private FmNative mFmNative = null; | |
+ | |
@Override | |
public IBinder onBind(Intent intent) { | |
return mBinder; | |
@@ -401,12 +407,14 @@ private synchronized void startRender() { | |
// need to create new audio record and audio play back track, | |
// because input/output device may be changed. | |
if (mAudioRecord != null) { | |
- mAudioRecord.stop(); | |
+ if (mAudioRecord.getState() != AudioRecord.STATE_UNINITIALIZED) | |
+ mAudioRecord.stop(); | |
mAudioRecord.release(); | |
mAudioRecord = null; | |
} | |
if (mAudioTrack != null) { | |
- mAudioTrack.stop(); | |
+ if (mAudioTrack.getState() != AudioTrack.STATE_UNINITIALIZED) | |
+ mAudioTrack.stop(); | |
mAudioTrack.release(); | |
mAudioTrack = null; | |
} | |
@@ -567,9 +575,15 @@ private boolean isSpeakerPhoneOn() { | |
* | |
* @return true if FM device open, false FM device not open | |
*/ | |
+ public void openDeviceAsync() { | |
+ mFmServiceHandler.removeMessages(FmListener.MSGID_OPENDEVICE_FINISHED); | |
+ Message msg = mFmServiceHandler.obtainMessage(FmListener.MSGID_OPENDEVICE_FINISHED); | |
+ mFmServiceHandler.sendMessage(msg); | |
+ } | |
+ | |
private boolean openDevice() { | |
if (!mIsDeviceOpen) { | |
- mIsDeviceOpen = FmNative.openDev(); | |
+ mIsDeviceOpen = mFmNative.openDev(this); | |
} | |
return mIsDeviceOpen; | |
} | |
@@ -582,7 +596,7 @@ private boolean openDevice() { | |
private boolean closeDevice() { | |
boolean isDeviceClose = false; | |
if (mIsDeviceOpen) { | |
- isDeviceClose = FmNative.closeDev(); | |
+ isDeviceClose = mFmNative.closeDev(); | |
mIsDeviceOpen = !isDeviceClose; | |
} | |
// quit looper | |
@@ -636,7 +650,7 @@ private boolean powerUp(float frequency) { | |
openDevice(); | |
} | |
- if (!FmNative.powerUp(frequency)) { | |
+ if (!mFmNative.powerUp(frequency)) { | |
mPowerStatus = POWER_DOWN; | |
return false; | |
} | |
@@ -644,6 +658,15 @@ private boolean powerUp(float frequency) { | |
// need mute after power up | |
setMute(true); | |
+ if (mPowerStatus == POWER_UP) { | |
+ if (AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_FM_TUNER, | |
+ AudioSystem.DEVICE_STATE_AVAILABLE, "", "") != AudioSystem.SUCCESS) { | |
+ Log.e(TAG, "powerUp() set AudioSystem.DEVICE_STATE_AVAILABLE for AudioSystem.DEVICE_IN_FM_TUNER failed!"); | |
+ AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_FM_TUNER, | |
+ AudioSystem.DEVICE_STATE_UNAVAILABLE, "", ""); | |
+ } | |
+ } | |
+ | |
return (mPowerStatus == POWER_UP); | |
} | |
@@ -695,6 +718,10 @@ public void powerDownAsync() { | |
* @return true if power down success | |
*/ | |
private boolean powerDown() { | |
+ // Disable DEVICE_IN_FM_TUNER | |
+ AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_IN_FM_TUNER, | |
+ AudioSystem.DEVICE_STATE_UNAVAILABLE, "", ""); | |
+ | |
if (mPowerStatus == POWER_DOWN) { | |
return true; | |
} | |
@@ -707,7 +734,7 @@ private boolean powerDown() { | |
setRds(false); | |
enableFmAudio(false); | |
- if (!FmNative.powerDown(0)) { | |
+ if (!mFmNative.powerDown(0)) { | |
if (isRdsSupported()) { | |
stopRdsThread(); | |
@@ -760,7 +787,7 @@ public void tuneStationAsync(float frequency) { | |
private boolean tuneStation(float frequency) { | |
if (mPowerStatus == POWER_UP) { | |
setRds(false); | |
- boolean bRet = FmNative.tune(frequency); | |
+ boolean bRet = mFmNative.tune(frequency); | |
if (bRet) { | |
setRds(true); | |
mCurrentStation = FmUtils.computeStation(frequency); | |
@@ -812,7 +839,7 @@ private float seekStation(float frequency, boolean isUp) { | |
setRds(false); | |
mIsNativeSeeking = true; | |
- float fRet = FmNative.seek(frequency, isUp); | |
+ float fRet = mFmNative.seek(frequency, isUp); | |
mIsNativeSeeking = false; | |
// make mIsStopScanCalled false, avoid stop scan make this true, | |
// when start scan, it will return null. | |
@@ -836,7 +863,7 @@ public void startScanAsync() { | |
short[] stationsInShort = null; | |
if (!mIsStopScanCalled) { | |
mIsNativeScanning = true; | |
- stationsInShort = FmNative.autoScan(); | |
+ stationsInShort = mFmNative.autoScan(); | |
mIsNativeScanning = false; | |
} | |
@@ -885,7 +912,7 @@ public boolean stopScan() { | |
mFmServiceHandler.removeMessages(FmListener.MSGID_SEEK_FINISHED); | |
if (mIsNativeScanning || mIsNativeSeeking) { | |
mIsStopScanCalled = true; | |
- bRet = FmNative.stopScan(); | |
+ bRet = mFmNative.stopScan(); | |
} | |
return bRet; | |
} | |
@@ -920,7 +947,7 @@ private int setRds(boolean on) { | |
} | |
int ret = -1; | |
if (isRdsSupported()) { | |
- ret = FmNative.setRds(on); | |
+ ret = mFmNative.setRds(on); | |
} | |
return ret; | |
} | |
@@ -959,7 +986,7 @@ private int activeAf() { | |
return -1; | |
} | |
- int frequency = FmNative.activeAf(); | |
+ int frequency = mFmNative.activeAf(); | |
return frequency; | |
} | |
@@ -992,7 +1019,7 @@ public int setMute(boolean mute) { | |
Log.w(TAG, "setMute, FM is not powered up"); | |
return -1; | |
} | |
- int iRet = FmNative.setMute(mute); | |
+ int iRet = mFmNative.setMute(mute); | |
mIsMuted = mute; | |
return iRet; | |
} | |
@@ -1012,7 +1039,7 @@ public boolean isMuted() { | |
* @return (true, support; false, not support) | |
*/ | |
public boolean isRdsSupported() { | |
- boolean isRdsSupported = (FmNative.isRdsSupport() == 1); | |
+ boolean isRdsSupported = (mFmNative.isRdsSupport() == 1); | |
return isRdsSupported; | |
} | |
@@ -1104,7 +1131,7 @@ public void switchAntennaAsync(int antenna) { | |
*/ | |
private int switchAntenna(int antenna) { | |
// if fm not powerup, switchAntenna will flag whether has earphone | |
- int ret = FmNative.switchAntenna(antenna); | |
+ int ret = mFmNative.switchAntenna(antenna); | |
return ret; | |
} | |
@@ -1275,6 +1302,7 @@ public String getRecordingName() { | |
@Override | |
public void onCreate() { | |
super.onCreate(); | |
+ mFmNative = FmNative.getInstance(); | |
mContext = getApplicationContext(); | |
mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); | |
mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); | |
@@ -1291,7 +1319,7 @@ public void onCreate() { | |
handlerThread.start(); | |
mFmServiceHandler = new FmRadioServiceHandler(handlerThread.getLooper()); | |
- openDevice(); | |
+ openDeviceAsync(); | |
// set speaker to default status, avoid setting->clear data. | |
setForceUse(mIsSpeakerUsed); | |
@@ -1409,7 +1437,7 @@ public void onAudioPatchListUpdate(AudioPatch[] patchList) { | |
} else if (mIsRender) { | |
ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>(); | |
mAudioManager.listAudioPatches(patches); | |
- if (isPatchMixerToEarphone(patches)) { | |
+ if (USE_AUDIO_PATCH && isPatchMixerToEarphone(patches)) { | |
int status; | |
stopAudioTrack(); | |
stopRender(); | |
@@ -1547,13 +1575,13 @@ public void run() { | |
break; | |
} | |
- int iRdsEvents = FmNative.readRds(); | |
+ int iRdsEvents = mFmNative.readRds(); | |
if (iRdsEvents != 0) { | |
Log.d(TAG, "startRdsThread, is rds events: " + iRdsEvents); | |
} | |
if (RDS_EVENT_PROGRAMNAME == (RDS_EVENT_PROGRAMNAME & iRdsEvents)) { | |
- byte[] bytePS = FmNative.getPs(); | |
+ byte[] bytePS = mFmNative.getPs(); | |
if (null != bytePS) { | |
String ps = new String(bytePS).trim(); | |
if (!mPsString.equals(ps)) { | |
@@ -1575,7 +1603,7 @@ public void run() { | |
} | |
if (RDS_EVENT_LAST_RADIOTEXT == (RDS_EVENT_LAST_RADIOTEXT & iRdsEvents)) { | |
- byte[] byteLRText = FmNative.getLrText(); | |
+ byte[] byteLRText = mFmNative.getLrText(); | |
if (null != byteLRText) { | |
String rds = new String(byteLRText).trim(); | |
if (!mRtTextString.equals(rds)) { | |
@@ -1605,7 +1633,7 @@ public void run() { | |
} else if (mPowerStatus == POWER_DOWN) { | |
Log.d(TAG, "startRdsThread, fm is power down, do nothing."); | |
} else { | |
- int iFreq = FmNative.activeAf(); | |
+ int iFreq = mFmNative.activeAf(); | |
if (FmUtils.isValidStation(iFreq)) { | |
// if the new frequency is not equal to current | |
// frequency. | |
@@ -1699,7 +1727,7 @@ private void startPatchOrRender() { | |
ArrayList<AudioPatch> patches = new ArrayList<AudioPatch>(); | |
mAudioManager.listAudioPatches(patches); | |
if (mAudioPatch == null) { | |
- if (isPatchMixerToEarphone(patches)) { | |
+ if (USE_AUDIO_PATCH && isPatchMixerToEarphone(patches)) { | |
int status; | |
stopAudioTrack(); | |
stopRender(); | |
@@ -2406,6 +2434,11 @@ public void handleMessage(Message msg) { | |
switch (msg.what) { | |
+ // Open Device | |
+ case FmListener.MSGID_OPENDEVICE_FINISHED: | |
+ openDevice(); | |
+ break; | |
+ | |
// power up | |
case FmListener.MSGID_POWERUP_FINISHED: | |
bundle = msg.getData(); | |
@@ -2736,10 +2769,10 @@ private boolean firstPlaying(float frequency) { | |
return false; | |
} | |
boolean isSeekTune = false; | |
- float seekStation = FmNative.seek(frequency, false); | |
+ float seekStation = mFmNative.seek(frequency, false); | |
int station = FmUtils.computeStation(seekStation); | |
if (FmUtils.isValidStation(station)) { | |
- isSeekTune = FmNative.tune(seekStation); | |
+ isSeekTune = mFmNative.tune(seekStation); | |
if (isSeekTune) { | |
playFrequency(seekStation); | |
} | |
diff --git a/src/com/android/fmradio/FmUtils.java b/src/com/android/fmradio/FmUtils.java | |
index b6219fd..b081f5f 100644 | |
--- a/src/com/android/fmradio/FmUtils.java | |
+++ b/src/com/android/fmradio/FmUtils.java | |
@@ -66,6 +66,14 @@ | |
// StorageManager For FM record | |
private static StorageManager sStorageManager = null; | |
+ public static int getHighestStation() { | |
+ return HIGHEST_STATION; | |
+ } | |
+ | |
+ public static int getLowestStation() { | |
+ return LOWEST_STATION; | |
+ } | |
+ | |
/** | |
* Whether the frequency is valid. | |
* |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment