FM: New mechanism to handle FM recording
- FM Radio is running with system process.
- System process does not have permission to access SDCard.
- Handle the FM recording in another application.
Change-Id: Ie321143b4a2601f2c669292154510eef8cbf7940
CRs-Fixed: 515621
diff --git a/Android.mk b/Android.mk
index 7ba73d6..a08bbc1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,4 +17,6 @@
include $(LOCAL_PATH)/fmapp/Android.mk
LOCAL_PATH := $(LOCAL_DIR_PATH)
include $(LOCAL_PATH)/fmapp2/Android.mk
+LOCAL_PATH := $(LOCAL_DIR_PATH)
+include $(LOCAL_PATH)/FMRecord/Android.mk
endif # is-vendor-board-platform
diff --git a/FMRecord/Android.mk b/FMRecord/Android.mk
new file mode 100644
index 0000000..00837f0
--- /dev/null
+++ b/FMRecord/Android.mk
@@ -0,0 +1,14 @@
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src/com/codeaurora/fmrecording/)
+
+LOCAL_PACKAGE_NAME := FMRecord
+LOCAL_CERTIFICATE := platform
+LOCAL_PROGUARD_ENABLED := disabled
+include $(BUILD_PACKAGE)
+
+endif
diff --git a/FMRecord/AndroidManifest.xml b/FMRecord/AndroidManifest.xml
new file mode 100644
index 0000000..beb0cf7
--- /dev/null
+++ b/FMRecord/AndroidManifest.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.codeaurora.fmrecording" >
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+
+<application>
+
+<receiver android:name="FMRecordingReceiver">
+ <intent-filter>
+ <action android:name="codeaurora.intent.action.FM" />
+ </intent-filter>
+</receiver>
+
+<service android:name="com.codeaurora.fmrecording.FMRecordingService"></service>
+</application>
+</manifest>
diff --git a/FMRecord/res/values/strings.xml b/FMRecord/res/values/strings.xml
new file mode 100644
index 0000000..59f14ad
--- /dev/null
+++ b/FMRecord/res/values/strings.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- alert to the user that USB storage must be available before using FM recording [CHAR LIMIT=NONE] -->
+ <string name="no_storage">Mount SD card before start recording.</string>
+ <!-- alert to the user that the USB storage is being disk-checked [CHAR LIMIT=30] -->
+ <string name="preparing_sd">Preparing SD card</string>
+ <!-- alert to the user that the FM fails to read or write the USB storage. [CHAR LIMIT=NONE] -->
+ <string name="access_sd_fail">Couldn\'t access SD card.</string>
+ <!-- Low-memory dialog message [CHAR LIMT=NONE] -->
+ <string name="spaceIsLow_content">Your SD card storage is running out of space. Change the quality setting or delete some images or other files.</string>
+ <!-- The messsage shown when FM record reaches size limit. -->
+ <string name="FMRecording_reach_size_limit">Size limit reached.</string>
+ <!-- the name under which recordings will be visible in the media database is formatted like this -->
+ <string name="audio_db_title_format"><xliff:g id="format">yyyy-MM-dd HH:mm:ss</xliff:g></string>
+ <!-- all recordings will show up in the media database with this 'artist' name -->
+ <string name="audio_db_artist_name">My FM recordings</string>
+ <!-- all recordings will show up in the media database with this 'album' name -->
+ <string name="audio_db_album_name">FM recordings</string>
+ <!-- all recordings will show up in the media database in a playlist with this name -->
+ <string name="audio_db_playlist_name">FM recordings</string>
+ <string name="save_record_file">FM Recorded file saved to "<xliff:g id="record_file">%1$s</xliff:g>"</string>
+</resources>
diff --git a/FMRecord/src/com/codeaurora/fmrecording/FMRecordingReceiver.java b/FMRecord/src/com/codeaurora/fmrecording/FMRecordingReceiver.java
new file mode 100644
index 0000000..9389f10
--- /dev/null
+++ b/FMRecord/src/com/codeaurora/fmrecording/FMRecordingReceiver.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.codeaurora.fmrecording;
+
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+import android.content.pm.PackageManager;
+import android.content.Context;
+import android.content.ComponentName;
+import android.util.Log;
+import java.lang.String;
+
+
+public class FMRecordingReceiver extends BroadcastReceiver {
+
+ private static final String TAG = "FMRecordingReceiver";
+ public static final String ACTION_FM =
+ "codeaurora.intent.action.FM";
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ Log.d(TAG, "Received intent: " + action);
+ if((action != null) && action.equals(ACTION_FM)) {
+ Log.d(TAG, "FM intent received");
+ Intent in = new Intent();
+ in.putExtras(intent);
+ in.setClass(context, FMRecordingService.class);
+ int state = intent.getIntExtra("state", 0);
+ boolean startService = true;
+
+ if (state == 1) {
+ Log.d(TAG, "FM ON intent received");
+ startService = true;
+ context.startService(in);
+ } else if(state == 0){
+ Log.d(TAG, "FM OFF intent received");
+ startService = false;
+ context.stopService(in);
+ }
+ }
+ }
+}
diff --git a/FMRecord/src/com/codeaurora/fmrecording/FMRecordingService.java b/FMRecord/src/com/codeaurora/fmrecording/FMRecordingService.java
new file mode 100644
index 0000000..2b0d00a
--- /dev/null
+++ b/FMRecord/src/com/codeaurora/fmrecording/FMRecordingService.java
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of The Linux Foundation nor
+ * the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.codeaurora.fmrecording;
+
+import java.util.*;
+import android.app.Service;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.BroadcastReceiver;
+import android.media.AudioManager;
+import android.media.AudioManager.OnAudioFocusChangeListener;
+import android.media.AudioSystem;
+import android.media.MediaRecorder;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.Log;
+import java.util.Date;
+import java.text.SimpleDateFormat;
+import android.provider.MediaStore;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.database.Cursor;
+import java.io.File;
+import android.widget.Toast;
+import android.os.UserHandle;
+import android.net.Uri;
+import android.content.res.Resources;
+import android.os.StatFs;
+
+public class FMRecordingService extends Service {
+ private static final String TAG = "FMRecordingService";
+ private BroadcastReceiver mFmRecordingReceiver = null;
+ private BroadcastReceiver mSdcardUnmountReceiver = null;
+ public static final long UNAVAILABLE = -1L;
+ public static final long PREPARING = -2L;
+ public static final long UNKNOWN_SIZE = -3L;
+ public static final long LOW_STORAGE_THRESHOLD = 50000000;
+ private long mStorageSpace;
+ private boolean mFmRecordingOn = false;
+ public static final String ACTION_FM_RECORDING =
+ "codeaurora.intent.action.FM_Recording";
+ public static final String ACTION_FM_RECORDING_STATUS =
+ "codeaurora.intent.action.FM.Recording.Status";
+
+ private File mSampleFile = null;
+ private MediaRecorder mRecorder = null;
+ long mSampleStart = 0;
+ static final int START = 1;
+ static final int STOP = 0;
+
+ public void onCreate() {
+
+ super.onCreate();
+ Log.d(TAG, "FMRecording Service onCreate");
+ registerRecordingListner();
+ registerExternalStorageListener();
+ }
+
+ public int onStartCommand(Intent intent, int flags, int startId) {
+
+ Log.d(TAG, "FMRecording Service onCreate");
+ return START_NOT_STICKY;
+ }
+
+ public void onDestroy() {
+ Log.d(TAG, "FMRecording Service onDestroy");
+ if (mFmRecordingOn == true) {
+ Log.d(TAG, "Still recording on progress, Stoping it");
+ stopRecord();
+ }
+ unregisterBroadCastReceiver(mFmRecordingReceiver);
+ unregisterBroadCastReceiver(mSdcardUnmountReceiver);
+ super.onDestroy();
+ }
+
+ public IBinder onBind(Intent intent) {
+ Log.v(TAG, "FMRecording Service onBind");
+ return null;
+ }
+
+ private void unregisterBroadCastReceiver(BroadcastReceiver myreceiver) {
+
+ if (myreceiver != null) {
+ unregisterReceiver(myreceiver);
+ myreceiver = null;
+ }
+ }
+ /**
+ * Registers an intent to listen for ACTION_MEDIA_UNMOUNTED notifications.
+ * The intent will call closeExternalStorageFiles() if the external media
+ * is going to be ejected, so applications can clean up.
+ */
+ private void registerExternalStorageListener() {
+ if (mSdcardUnmountReceiver == null) {
+ mSdcardUnmountReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if ((action.equals(Intent.ACTION_MEDIA_UNMOUNTED))
+ || (action.equals(Intent.ACTION_MEDIA_EJECT))) {
+
+ Log.d(TAG, "ACTION_MEDIA_UNMOUNTED Intent received");
+ if (mFmRecordingOn == true) {
+ try {
+ stopRecord();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ };
+ IntentFilter iFilter = new IntentFilter();
+ iFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
+ iFilter.addAction(Intent.ACTION_MEDIA_EJECT);
+ iFilter.addDataScheme("file");
+ registerReceiver(mSdcardUnmountReceiver, iFilter);
+ }
+ }
+
+ private static long getAvailableSpace() {
+ String state = Environment.getExternalStorageState();
+ Log.d(TAG, "External storage state=" + state);
+ if (Environment.MEDIA_CHECKING.equals(state)) {
+ return PREPARING;
+ }
+ if (!Environment.MEDIA_MOUNTED.equals(state)) {
+ return UNAVAILABLE;
+ }
+
+ try {
+ File sampleDir = Environment.getExternalStorageDirectory();
+ StatFs stat = new StatFs(sampleDir.getAbsolutePath());
+ return stat.getAvailableBlocks() * (long) stat.getBlockSize();
+ } catch (Exception e) {
+ Log.i(TAG, "Fail to access external storage", e);
+ }
+ return UNKNOWN_SIZE;
+ }
+
+ private boolean updateAndShowStorageHint() {
+ mStorageSpace = getAvailableSpace();
+ return showStorageHint();
+ }
+
+ private boolean showStorageHint() {
+ String errorMessage = null;
+ if (mStorageSpace == UNAVAILABLE) {
+ errorMessage = getString(R.string.no_storage);
+ } else if (mStorageSpace == PREPARING) {
+ errorMessage = getString(R.string.preparing_sd);
+ } else if (mStorageSpace == UNKNOWN_SIZE) {
+ errorMessage = getString(R.string.access_sd_fail);
+ } else if (mStorageSpace < LOW_STORAGE_THRESHOLD) {
+ errorMessage = getString(R.string.spaceIsLow_content);
+ }
+
+ if (errorMessage != null) {
+ Toast.makeText(this, errorMessage,
+ Toast.LENGTH_LONG).show();
+ return false;
+ }
+ return true;
+ }
+
+ private void sendRecordingStatusIntent(int status) {
+ Intent intent = new Intent(ACTION_FM_RECORDING_STATUS);
+ intent.putExtra("state", status);
+ Log.d(TAG, "posting intent for FM Recording status as = " +status);
+ getApplicationContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
+ private boolean startRecord() {
+
+ Log.d(TAG, "Enter startRecord");
+ if (mRecorder != null) { /* Stop existing recording if any */
+ Log.d(TAG, "Stopping existing record");
+ try {
+ mRecorder.stop();
+ mRecorder.reset();
+ mRecorder.release();
+ mRecorder = null;
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ if (!updateAndShowStorageHint())
+ return false;
+ long maxFileSize = mStorageSpace - LOW_STORAGE_THRESHOLD;
+ mRecorder = new MediaRecorder();
+ try {
+ mRecorder.setMaxFileSize(maxFileSize);
+ } catch (RuntimeException exception) {
+
+ }
+ mSampleFile = null;
+ File sampleDir = Environment.getExternalStorageDirectory();
+
+ try {
+ mSampleFile = File.createTempFile("FMRecording", ".3gpp", sampleDir);
+ } catch (IOException e) {
+ Log.e(TAG, "Not able to access SD Card");
+ Toast.makeText(this, "Not able to access SD Card", Toast.LENGTH_SHORT).show();
+ }
+ try {
+ Log.d(TAG, "AudioSource.FM_RX" +MediaRecorder.AudioSource.FM_RX);
+ mRecorder.setAudioSource(MediaRecorder.AudioSource.FM_RX);
+ mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
+ } catch (RuntimeException exception) {
+ Log.d(TAG, "RuntimeException while settings");
+ mRecorder.reset();
+ mRecorder.release();
+ mRecorder = null;
+ return false;
+ }
+ Log.d(TAG, "setOutputFile");
+ mRecorder.setOutputFile(mSampleFile.getAbsolutePath());
+ try {
+ mRecorder.prepare();
+ Log.d(TAG, "start");
+ mRecorder.start();
+ } catch (IOException e) {
+ Log.d(TAG, "IOException while start");
+ mRecorder.reset();
+ mRecorder.release();
+ mRecorder = null;
+ return false;
+ } catch (RuntimeException e) {
+ Log.d(TAG, "RuntimeException while start");
+ mRecorder.reset();
+ mRecorder.release();
+ mRecorder = null;
+ return false;
+ }
+ mFmRecordingOn = true;
+ Log.d(TAG, "mSampleFile.getAbsolutePath() " +mSampleFile.getAbsolutePath());
+ mRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
+ public void onInfo(MediaRecorder mr, int what, int extra) {
+ if ((what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) ||
+ (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED)) {
+ if (mFmRecordingOn) {
+ Log.d(TAG, "Maximum file size/duration reached, stopping the recording");
+ stopRecord();
+ }
+ // Show the toast.
+ Toast.makeText(FMRecordingService.this, R.string.FMRecording_reach_size_limit,
+ Toast.LENGTH_LONG).show();
+ }
+ }
+ // from MediaRecorder.OnErrorListener
+ public void onError(MediaRecorder mr, int what, int extra) {
+ Log.e(TAG, "MediaRecorder error. what=" + what + ". extra=" + extra);
+ if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
+ // We may have run out of space on the sdcard.
+ if (mFmRecordingOn) {
+ stopRecord();
+ }
+ updateAndShowStorageHint();
+ }
+ }
+ });
+ mSampleStart = System.currentTimeMillis();
+ sendRecordingStatusIntent(START);
+ return true;
+ }
+
+ private void stopRecord() {
+ Log.d(TAG, "Enter stopRecord");
+ mFmRecordingOn = false;
+ if (mRecorder == null)
+ return;
+ try {
+ mRecorder.stop();
+ mRecorder.reset();
+ mRecorder.release();
+ mRecorder = null;
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ sendRecordingStatusIntent(STOP);
+ saveFile();
+ }
+
+ private void saveFile() {
+ int sampleLength = (int)((System.currentTimeMillis() - mSampleStart)/1000 );
+ Log.d(TAG, "Enter saveFile");
+ if (sampleLength == 0)
+ return;
+ String state = Environment.getExternalStorageState();
+ Log.d(TAG, "storage state is " + state);
+
+ if (Environment.MEDIA_MOUNTED.equals(state)) {
+ try {
+ this.addToMediaDB(mSampleFile);
+ Toast.makeText(this,getString(R.string.save_record_file,
+ mSampleFile.getAbsolutePath( )),
+ Toast.LENGTH_LONG).show();
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ Log.e(TAG, "SD card must have removed during recording. ");
+ Toast.makeText(this, "Recording aborted", Toast.LENGTH_SHORT).show();
+ }
+ return;
+ }
+
+ /*
+ * Adds file and returns content uri.
+ */
+ private Uri addToMediaDB(File file) {
+ Log.d(TAG, "In addToMediaDB");
+ Resources res = getResources();
+ ContentValues cv = new ContentValues();
+ long current = System.currentTimeMillis();
+ long modDate = file.lastModified();
+ Date date = new Date(current);
+ SimpleDateFormat formatter = new SimpleDateFormat(
+ res.getString(R.string.audio_db_title_format));
+ String title = formatter.format(date);
+
+ // Lets label the recorded audio file as NON-MUSIC so that the file
+ // won't be displayed automatically, except for in the playlist.
+ cv.put(MediaStore.Audio.Media.IS_MUSIC, "1");
+ cv.put(MediaStore.Audio.Media.TITLE, title);
+ cv.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath());
+ cv.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
+ cv.put(MediaStore.Audio.Media.DATE_MODIFIED, (int) (modDate / 1000));
+ cv.put(MediaStore.Audio.Media.MIME_TYPE, "AUDIO_AAC_MP4");
+ cv.put(MediaStore.Audio.Media.ARTIST,
+ res.getString(R.string.audio_db_artist_name));
+ cv.put(MediaStore.Audio.Media.ALBUM,
+ res.getString(R.string.audio_db_album_name));
+ Log.d(TAG, "Inserting audio record: " + cv.toString());
+ ContentResolver resolver = getContentResolver();
+ Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+ Log.d(TAG, "ContentURI: " + base);
+ Uri result = resolver.insert(base, cv);
+ if (result == null) {
+ Toast.makeText(this, "Unable to save recorded audio", Toast.LENGTH_SHORT).show();
+ return null;
+ }
+ if (getPlaylistId(res) == -1) {
+ createPlaylist(res, resolver);
+ }
+ int audioId = Integer.valueOf(result.getLastPathSegment());
+ addToPlaylist(resolver, audioId, getPlaylistId(res));
+
+ // Notify those applications such as Music listening to the
+ // scanner events that a recorded audio file just created.
+ sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
+ return result;
+ }
+
+ private int getPlaylistId(Resources res) {
+ Uri uri = MediaStore.Audio.Playlists.getContentUri("external");
+ final String[] ids = new String[] { MediaStore.Audio.Playlists._ID };
+ final String where = MediaStore.Audio.Playlists.NAME + "=?";
+ final String[] args = new String[] { res.getString(R.string.audio_db_playlist_name) };
+ Cursor cursor = query(uri, ids, where, args, null);
+ if (cursor == null) {
+ Log.v(TAG, "query returns null");
+ }
+ int id = -1;
+ if (cursor != null) {
+ cursor.moveToFirst();
+ if (!cursor.isAfterLast()) {
+ id = cursor.getInt(0);
+ }
+ cursor.close();
+ }
+ return id;
+ }
+
+ private Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
+ try {
+ ContentResolver resolver = getContentResolver();
+ if (resolver == null) {
+ return null;
+ }
+ return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
+ } catch (UnsupportedOperationException ex) {
+ return null;
+ }
+ }
+
+ private Uri createPlaylist(Resources res, ContentResolver resolver) {
+ ContentValues cv = new ContentValues();
+ cv.put(MediaStore.Audio.Playlists.NAME, res.getString(R.string.audio_db_playlist_name));
+ Uri uri = resolver.insert(MediaStore.Audio.Playlists.getContentUri("external"), cv);
+ if (uri == null) {
+ Toast.makeText(this, "Unable to save recorded audio", Toast.LENGTH_SHORT).show();
+ }
+ return uri;
+ }
+
+ private void addToPlaylist(ContentResolver resolver, int audioId, long playlistId) {
+ String[] cols = new String[] {
+ "count(*)"
+ };
+ Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
+ Cursor cur = resolver.query(uri, cols, null, null, null);
+ final int base;
+ if (cur != null) {
+ cur.moveToFirst();
+ base = cur.getInt(0);
+ cur.close();
+ } else {
+ base = 0;
+ }
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + audioId));
+ values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audioId);
+ resolver.insert(uri, values);
+ }
+
+ private void registerRecordingListner() {
+ if (mFmRecordingReceiver == null) {
+ mFmRecordingReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "Received intent " +intent);
+ String action = intent.getAction();
+ Log.d(TAG, " action = " +action);
+ if (action.equals(ACTION_FM_RECORDING)) {
+ int state = intent.getIntExtra("state", STOP);
+ Log.d(TAG, "ACTION_FM_RECORDING Intent received" +state);
+ if (state == START) {
+ Log.d(TAG, "Recording start");
+ startRecord();
+ } else if (state == STOP) {
+ Log.d(TAG, "Stop recording");
+ stopRecord();
+ }
+ }
+ }
+ };
+ IntentFilter iFilter = new IntentFilter();
+ iFilter.addAction(ACTION_FM_RECORDING);
+ registerReceiver(mFmRecordingReceiver, iFilter);
+ }
+ }
+
+}
diff --git a/fmapp/AndroidManifest.xml b/fmapp/AndroidManifest.xml
index d0232bc..6c0f4f8 100644
--- a/fmapp/AndroidManifest.xml
+++ b/fmapp/AndroidManifest.xml
@@ -41,6 +41,8 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<application
android:icon="@drawable/ic_launcher_fmradio"
diff --git a/fmapp/src/com/codeaurora/fmradio/FMRadio.java b/fmapp/src/com/codeaurora/fmradio/FMRadio.java
index d592bc2..408cf04 100644
--- a/fmapp/src/com/codeaurora/fmradio/FMRadio.java
+++ b/fmapp/src/com/codeaurora/fmradio/FMRadio.java
@@ -2139,20 +2139,20 @@
{
try
{
- mRecording = mService.startRecording();
+ mService.startRecording();
} catch (RemoteException e)
{
e.printStackTrace();
}
- //Initiate record timer thread here
- if( mRecording == true ) {
- int durationInMins = FmSharedPreferences.getRecordDuration();
- Log.e(LOGTAG, " Fected duration:" + durationInMins );
- initiateRecordDurationTimer( durationInMins );
- }
}
}
+ private void startRecordingTimer() {
+ mRecording = true;
+ int durationInMins = FmSharedPreferences.getRecordDuration();
+ Log.e(LOGTAG, " Fected duration:" + durationInMins );
+ initiateRecordDurationTimer( durationInMins );
+ }
private void stopRecording() {
mRecording = false;
DebugToasts("Stopped Recording", Toast.LENGTH_SHORT);
@@ -3591,5 +3591,10 @@
Log.d(LOGTAG, "mServiceCallbacks.onRecordingStopped:");
stopRecording();
}
+ public void onRecordingStarted()
+ {
+ Log.d(LOGTAG, "mServiceCallbacks.onRecordingStarted:");
+ startRecordingTimer();
+ }
};
}
diff --git a/fmapp/src/com/codeaurora/fmradio/FMRadioService.java b/fmapp/src/com/codeaurora/fmradio/FMRadioService.java
index d467162..e15117d 100644
--- a/fmapp/src/com/codeaurora/fmradio/FMRadioService.java
+++ b/fmapp/src/com/codeaurora/fmradio/FMRadioService.java
@@ -78,6 +78,10 @@
import android.content.ComponentName;
import android.os.StatFs;
import android.os.SystemClock;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.app.IntentService;
+import android.os.UserHandle;
/**
* Provides "background" FM Radio (that uses the hardware) capabilities,
@@ -160,6 +164,16 @@
private static final String SLEEP_EXPIRED_ACTION = "com.codeaurora.fmradio.SLEEP_EXPIRED";
private static final String RECORD_EXPIRED_ACTION = "com.codeaurora.fmradio.RECORD_TIMEOUT";
private static final String SERVICE_DELAYED_STOP_ACTION = "com.codeaurora.fmradio.SERVICE_STOP";
+ public static final String ACTION_FM =
+ "codeaurora.intent.action.FM";
+ public static final String ACTION_FM_RECORDING =
+ "codeaurora.intent.action.FM_Recording";
+ public static final String ACTION_FM_RECORDING_STATUS =
+ "codeaurora.intent.action.FM.Recording.Status";
+ private String mFilePath = "";
+ private BroadcastReceiver mFmRecordingStatus = null;
+ static final int RECORD_START = 1;
+ static final int RECORD_STOP = 0;
public FMRadioService() {
}
@@ -184,7 +198,7 @@
registerSleepExpired();
registerRecordTimeout();
registerDelayedServiceStop();
- registerExternalStorageListener();
+ registerFMRecordingStatus();
// registering media button receiver seperately as we need to set
// different priority for receiving media events
registerFmMediaButtonReceiver();
@@ -233,10 +247,6 @@
unregisterReceiver(mHeadsetReceiver);
mHeadsetReceiver = null;
}
- if( mSdcardUnmountReceiver != null ) {
- unregisterReceiver(mSdcardUnmountReceiver);
- mSdcardUnmountReceiver = null;
- }
if( mMusicCommandListener != null ) {
unregisterReceiver(mMusicCommandListener);
mMusicCommandListener = null;
@@ -257,6 +267,10 @@
unregisterReceiver(mDelayedServiceStopListener);
mDelayedServiceStopListener = null;
}
+ if (mFmRecordingStatus != null ) {
+ unregisterReceiver(mFmRecordingStatus);
+ mFmRecordingStatus = null;
+ }
/* Since the service is closing, disable the receiver */
fmOff();
@@ -270,38 +284,46 @@
super.onDestroy();
}
-/**
- * Registers an intent to listen for ACTION_MEDIA_UNMOUNTED notifications.
- * The intent will call closeExternalStorageFiles() if the external media
- * is going to be ejected, so applications can clean up.
- */
- public void registerExternalStorageListener() {
- if (mSdcardUnmountReceiver == null) {
- mSdcardUnmountReceiver = new BroadcastReceiver() {
+ public void registerFMRecordingStatus() {
+ if (mFmRecordingStatus == null) {
+ mFmRecordingStatus = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ Log.d(LOGTAG, "received intent " +intent);
String action = intent.getAction();
- if ((action.equals(Intent.ACTION_MEDIA_UNMOUNTED))
- || (action.equals(Intent.ACTION_MEDIA_EJECT))) {
- Log.d(LOGTAG, "ACTION_MEDIA_UNMOUNTED Intent received");
- if (mFmRecordingOn == true) {
+ if (action.equals(ACTION_FM_RECORDING_STATUS)) {
+ Log.d(LOGTAG, "ACTION_FM_RECORDING_STATUS Intent received");
+ int state = intent.getIntExtra("state", 0);
+ if (state == RECORD_START) {
+ Log.d(LOGTAG, "FM Recording started");
+ mFmRecordingOn = true;
try {
- stopRecording();
- } catch (Exception e) {
+ if ((mServiceInUse) && (mCallbacks != null) ) {
+ Log.d(LOGTAG, "start recording thread");
+ mCallbacks.onRecordingStarted();
+ }
+ } catch (RemoteException e) {
e.printStackTrace();
}
- }
+ } else if (state == RECORD_STOP) {
+ Log.d(LOGTAG, "FM Recording stopped");
+ mFmRecordingOn = false;
+ try {
+ if ((mServiceInUse) && (mCallbacks != null) ) {
+ mCallbacks.onRecordingStopped();
+ }
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
}
}
};
IntentFilter iFilter = new IntentFilter();
- iFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
- iFilter.addAction(Intent.ACTION_MEDIA_EJECT);
- iFilter.addDataScheme("file");
- registerReceiver(mSdcardUnmountReceiver, iFilter);
+ iFilter.addAction(ACTION_FM_RECORDING_STATUS);
+ registerReceiver(mFmRecordingStatus , iFilter);
}
- }
-
+ }
/**
* Registers an intent to listen for ACTION_HEADSET_PLUG
@@ -666,6 +688,20 @@
return true;
}
+ private void sendRecordIntent(int action) {
+ Intent intent = new Intent(ACTION_FM_RECORDING);
+ intent.putExtra("state", action);
+ Log.d(LOGTAG, "Sending Recording intent for = " +action);
+ getApplicationContext().sendBroadcast(intent);
+ }
+
+ private void sendRecordServiceIntent(int action) {
+ Intent intent = new Intent(ACTION_FM);
+ intent.putExtra("state", action);
+ Log.d(LOGTAG, "Sending Recording intent for = " +action);
+ getApplicationContext().sendBroadcast(intent);
+ }
+
private void startFM(){
Log.d(LOGTAG, "In startFM");
if(true == mAppShutdown) { // not to send intent to AudioManager in Shutdown
@@ -703,6 +739,7 @@
}
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
AudioSystem.DEVICE_STATE_AVAILABLE, "");
+ sendRecordServiceIntent(RECORD_START);
}
mPlaybackInProgress = true;
}
@@ -716,6 +753,7 @@
Log.d(LOGTAG, "FMRadio: Requesting to stop FM");
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
+ sendRecordServiceIntent(RECORD_STOP);
}
mPlaybackInProgress = false;
}
@@ -729,105 +767,23 @@
Log.d(LOGTAG, "FMRadio: Requesting to stop FM");
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
+ sendRecordServiceIntent(RECORD_STOP);
}
mPlaybackInProgress = false;
}
- public boolean startRecording() {
- Log.d(LOGTAG, "In startRecording of Recorder");
- if( (true == mSingleRecordingInstanceSupported) &&
- (true == mOverA2DP )) {
- Toast.makeText( this,
- "playback on BT in progress,can't record now",
- Toast.LENGTH_SHORT).show();
- return false;
+ public void startRecording() {
+
+ Log.d(LOGTAG, "In startRecording of Recorder");
+ if ((true == mSingleRecordingInstanceSupported) &&
+ (true == mOverA2DP )) {
+ Toast.makeText( this,
+ "playback on BT in progress,can't record now",
+ Toast.LENGTH_SHORT).show();
+ return;
}
- stopRecording();
-
- if (!updateAndShowStorageHint())
- return false;
- long maxFileSize = mStorageSpace - LOW_STORAGE_THRESHOLD;
- mRecorder = new MediaRecorder();
- try {
- mRecorder.setMaxFileSize(maxFileSize);
- } catch (RuntimeException exception) {
-
- }
-
- mSampleFile = null;
- File sampleDir = Environment.getExternalStorageDirectory();
- if (!sampleDir.canWrite()) // Workaround for broken sdcard support on
- // the device.
- sampleDir = new File("/sdcard/sdcard");
- try {
- mSampleFile = File
- .createTempFile("FMRecording", ".3gpp", sampleDir);
- } catch (IOException e) {
- Log.e(LOGTAG, "Not able to access SD Card");
- Toast.makeText(this, "Not able to access SD Card", Toast.LENGTH_SHORT).show();
- return false;
- }
- if (mRecorder == null) {
- Toast.makeText(this,"MediaRecorder failed to create an instance",
- Toast.LENGTH_SHORT).show();
- return false;
- }
-
- try {
- mRecorder.setAudioSource(MediaRecorder.AudioSource.FM_RX);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- } catch (RuntimeException exception) {
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- return false;
- }
- mRecorder.setOutputFile(mSampleFile.getAbsolutePath());
- try {
- mRecorder.prepare();
- mRecorder.start();
- } catch (IOException e) {
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- return false;
- } catch (RuntimeException e) {
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- return false;
- }
- mFmRecordingOn = true;
- mRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
- public void onInfo(MediaRecorder mr, int what, int extra) {
- if ((what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) ||
- (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED)) {
- if (mFmRecordingOn) {
- Log.d(LOGTAG, "Maximum file size/duration reached, stopping the recording");
- stopRecording();
- }
- // Show the toast.
- Toast.makeText(FMRadioService.this, R.string.FMRecording_reach_size_limit,
- Toast.LENGTH_LONG).show();
- }
- }
- // from MediaRecorder.OnErrorListener
- public void onError(MediaRecorder mr, int what, int extra) {
- Log.e(LOGTAG, "MediaRecorder error. what=" + what + ". extra=" + extra);
- if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
- // We may have run out of space on the sdcard.
- if (mFmRecordingOn) {
- stopRecording();
- }
- updateAndShowStorageHint();
- }
- }
- });
-
- mSampleStart = System.currentTimeMillis();
- return true;
- }
+ sendRecordIntent(RECORD_START);
+ }
public boolean startA2dpPlayback() {
Log.d(LOGTAG, "In startA2dpPlayback");
@@ -925,197 +881,13 @@
return;
}
- private void resetRecording() {
-
- Log.v(LOGTAG, "resetRecording()");
-
- mFmRecordingOn = false;
- if (mRecorder == null)
- return;
-
- // Send Intent for IOBUSY VOTE, because MediaRecorder.stop
- // gets Activity context which might not be always available
- // and would thus fail to send the intent.
- Intent ioBusyUnVoteIntent = new Intent(IOBUSY_UNVOTE);
- // Remove vote for io_is_busy to be turned off.
- ioBusyUnVoteIntent.putExtra("com.android.server.CpuGovernorService.voteType", 0);
- sendBroadcast(ioBusyUnVoteIntent);
-
- mRecorder.stop();
-
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- int sampleLength = (int)((System.currentTimeMillis() - mSampleStart)/1000 );
- if (sampleLength == 0)
- return;
- String state = Environment.getExternalStorageState();
- Log.d(LOGTAG, "storage state is " + state);
-
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- this.addToMediaDB(mSampleFile);
- }
- else{
- Log.e(LOGTAG, "SD card must have removed during recording. ");
- Toast.makeText(this, "Recording aborted", Toast.LENGTH_SHORT).show();
- }
- return;
- }
-
public void stopRecording() {
- mFmRecordingOn = false;
- if (mRecorder == null)
+ if (!mFmRecordingOn)
return;
- try {
- mRecorder.stop();
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- } catch(Exception e) {
- e.printStackTrace();
- }
- int sampleLength = (int)((System.currentTimeMillis() - mSampleStart)/1000 );
- if (sampleLength == 0)
- return;
- String state = Environment.getExternalStorageState();
- Log.d(LOGTAG, "storage state is " + state);
-
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- try {
- this.addToMediaDB(mSampleFile);
- Toast.makeText(this,getString(R.string.save_record_file, mSampleFile.getAbsolutePath()),
- Toast.LENGTH_LONG).show();
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- }
- else{
- Log.e(LOGTAG, "SD card must have removed during recording. ");
- Toast.makeText(this, "Recording aborted", Toast.LENGTH_SHORT).show();
- }
- try
- {
- if((mServiceInUse) && (mCallbacks != null) ) {
- mCallbacks.onRecordingStopped();
- }
- } catch (RemoteException e)
- {
- e.printStackTrace();
- }
+ sendRecordIntent(RECORD_STOP);
return;
}
- /*
- * Adds file and returns content uri.
- */
- private Uri addToMediaDB(File file) {
- Log.d(LOGTAG, "In addToMediaDB");
- Resources res = getResources();
- ContentValues cv = new ContentValues();
- long current = System.currentTimeMillis();
- long modDate = file.lastModified();
- Date date = new Date(current);
- SimpleDateFormat formatter = new SimpleDateFormat(
- res.getString(R.string.audio_db_title_format));
- String title = formatter.format(date);
-
- // Lets label the recorded audio file as NON-MUSIC so that the file
- // won't be displayed automatically, except for in the playlist.
- cv.put(MediaStore.Audio.Media.IS_MUSIC, "1");
-
- cv.put(MediaStore.Audio.Media.TITLE, title);
- cv.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath());
- cv.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
- cv.put(MediaStore.Audio.Media.DATE_MODIFIED, (int) (modDate / 1000));
- cv.put(MediaStore.Audio.Media.MIME_TYPE, "AUDIO_AAC_MP4");
- cv.put(MediaStore.Audio.Media.ARTIST,
- res.getString(R.string.audio_db_artist_name));
- cv.put(MediaStore.Audio.Media.ALBUM,
- res.getString(R.string.audio_db_album_name));
- Log.d(LOGTAG, "Inserting audio record: " + cv.toString());
- ContentResolver resolver = getContentResolver();
- Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
- Log.d(LOGTAG, "ContentURI: " + base);
- Uri result = resolver.insert(base, cv);
- if (result == null) {
- Toast.makeText(this, "Unable to save recorded audio", Toast.LENGTH_SHORT).show();
- return null;
- }
- if (getPlaylistId(res) == -1) {
- createPlaylist(res, resolver);
- }
- int audioId = Integer.valueOf(result.getLastPathSegment());
- addToPlaylist(resolver, audioId, getPlaylistId(res));
-
- // Notify those applications such as Music listening to the
- // scanner events that a recorded audio file just created.
- sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
- return result;
- }
-
- private int getPlaylistId(Resources res) {
- Uri uri = MediaStore.Audio.Playlists.getContentUri("external");
- final String[] ids = new String[] { MediaStore.Audio.Playlists._ID };
- final String where = MediaStore.Audio.Playlists.NAME + "=?";
- final String[] args = new String[] { res.getString(R.string.audio_db_playlist_name) };
- Cursor cursor = query(uri, ids, where, args, null);
- if (cursor == null) {
- Log.v(LOGTAG, "query returns null");
- }
- int id = -1;
- if (cursor != null) {
- cursor.moveToFirst();
- if (!cursor.isAfterLast()) {
- id = cursor.getInt(0);
- }
- cursor.close();
- }
- return id;
- }
-
- private Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
- try {
- ContentResolver resolver = getContentResolver();
- if (resolver == null) {
- return null;
- }
- return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
- } catch (UnsupportedOperationException ex) {
- return null;
- }
- }
-
- private Uri createPlaylist(Resources res, ContentResolver resolver) {
- ContentValues cv = new ContentValues();
- cv.put(MediaStore.Audio.Playlists.NAME, res.getString(R.string.audio_db_playlist_name));
- Uri uri = resolver.insert(MediaStore.Audio.Playlists.getContentUri("external"), cv);
- if (uri == null) {
- Toast.makeText(this, "Unable to save recorded audio", Toast.LENGTH_SHORT).show();
- }
- return uri;
- }
-
- private void addToPlaylist(ContentResolver resolver, int audioId, long playlistId) {
- String[] cols = new String[] {
- "count(*)"
- };
- Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
- Cursor cur = resolver.query(uri, cols, null, null, null);
- final int base;
- if (cur != null) {
- cur.moveToFirst();
- base = cur.getInt(0);
- cur.close();
- }
- else {
- base = 0;
- }
- ContentValues values = new ContentValues();
- values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + audioId));
- values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audioId);
- resolver.insert(uri, values);
- }
private void fmActionOnCallState( int state ) {
//if Call Status is non IDLE we need to Mute FM as well stop recording if
//any. Similarly once call is ended FM should be unmuted.
@@ -1480,9 +1252,9 @@
return(mService.get().isMuted());
}
- public boolean startRecording()
+ public void startRecording()
{
- return(mService.get().startRecording());
+ mService.get().startRecording();
}
public void stopRecording()
@@ -1870,7 +1642,7 @@
if (isFmRecordingOn())
{
- resetRecording();
+ stopRecording();
}
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
diff --git a/fmapp/src/com/codeaurora/fmradio/FMStats.java b/fmapp/src/com/codeaurora/fmradio/FMStats.java
index 2306907..a68ccc4 100644
--- a/fmapp/src/com/codeaurora/fmradio/FMStats.java
+++ b/fmapp/src/com/codeaurora/fmradio/FMStats.java
@@ -2062,6 +2062,10 @@
{
Log.d(LOGTAG, "mServiceCallbacks.onFinishActivity:");
}
+ public void onRecordingStarted()
+ {
+ Log.d(LOGTAG, "mServiceCallbacks.onRecordingStarted:");
+ }
};
/* Radio Vars */
final Handler mHandler = new Handler();
diff --git a/fmapp/src/com/codeaurora/fmradio/IFMRadioService.aidl b/fmapp/src/com/codeaurora/fmradio/IFMRadioService.aidl
index 79d83f7..d80c320 100644
--- a/fmapp/src/com/codeaurora/fmradio/IFMRadioService.aidl
+++ b/fmapp/src/com/codeaurora/fmradio/IFMRadioService.aidl
@@ -46,7 +46,7 @@
boolean routeAudio(int device);
boolean unMute();
boolean isMuted();
- boolean startRecording();
+ void startRecording();
void stopRecording();
boolean tune(int frequency);
boolean seek(boolean up);
diff --git a/fmapp/src/com/codeaurora/fmradio/IFMRadioServiceCallbacks.aidl b/fmapp/src/com/codeaurora/fmradio/IFMRadioServiceCallbacks.aidl
index eb782e8..4d116ec 100644
--- a/fmapp/src/com/codeaurora/fmradio/IFMRadioServiceCallbacks.aidl
+++ b/fmapp/src/com/codeaurora/fmradio/IFMRadioServiceCallbacks.aidl
@@ -45,4 +45,5 @@
void onStationRDSSupported(boolean bRDSSupported);
void onRecordingStopped();
void onExtenRadioTextChanged();
+ void onRecordingStarted();
}
diff --git a/fmapp2/AndroidManifest.xml b/fmapp2/AndroidManifest.xml
index 4cef8c0..b377b9d 100644
--- a/fmapp2/AndroidManifest.xml
+++ b/fmapp2/AndroidManifest.xml
@@ -42,6 +42,8 @@
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<application
android:icon="@drawable/ic_launcher_fmradio"
diff --git a/fmapp2/src/com/caf/fmradio/FMRadio.java b/fmapp2/src/com/caf/fmradio/FMRadio.java
index caa9bb2..631ab40 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadio.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadio.java
@@ -1768,21 +1768,20 @@
private void startRecording() {
if(mService != null) {
try {
- mRecording = mService.startRecording();
- }catch (RemoteException e) {
- e.printStackTrace();
- }
- //Initiate record timer thread here
- if(mRecording == true) {
- mRecordingMsgTV.setCompoundDrawablesWithIntrinsicBounds
- (R.drawable.recorder_stop, 0, 0, 0);
- int durationInMins = FmSharedPreferences.getRecordDuration();
- Log.e(LOGTAG, "Fected duration: " + durationInMins);
- initiateRecordDurationTimer( durationInMins );
+ mService.startRecording();
+ } catch (RemoteException e) {
+ e.printStackTrace();
}
}
}
+ private void startRecordingTimer() {
+ mRecording = true;
+ int durationInMins = FmSharedPreferences.getRecordDuration();
+ Log.e(LOGTAG, " Fected duration:" + durationInMins );
+ initiateRecordDurationTimer( durationInMins );
+ }
+
private void stopRecording() {
mRecording = false;
DebugToasts("Stopped Recording", Toast.LENGTH_SHORT);
@@ -3033,5 +3032,10 @@
Log.d(LOGTAG, "mServiceCallbacks.onRecordingStopped:");
stopRecording();
}
+ public void onRecordingStarted()
+ {
+ Log.d(LOGTAG, "mServiceCallbacks.onRecordingStarted:");
+ startRecordingTimer();
+ }
};
}
diff --git a/fmapp2/src/com/caf/fmradio/FMRadioService.java b/fmapp2/src/com/caf/fmradio/FMRadioService.java
index 5d971cf..54b9aed 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadioService.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadioService.java
@@ -41,6 +41,8 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.app.IntentService;
+import android.os.UserHandle;
import android.content.BroadcastReceiver;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
@@ -160,6 +162,15 @@
private static final String SLEEP_EXPIRED_ACTION = "com.caf.fmradio.SLEEP_EXPIRED";
private static final String RECORD_EXPIRED_ACTION = "com.caf.fmradio.RECORD_TIMEOUT";
private static final String SERVICE_DELAYED_STOP_ACTION = "com.caf.fmradio.SERVICE_STOP";
+ public static final String ACTION_FM =
+ "codeaurora.intent.action.FM";
+ public static final String ACTION_FM_RECORDING =
+ "codeaurora.intent.action.FM_Recording";
+ public static final String ACTION_FM_RECORDING_STATUS =
+ "codeaurora.intent.action.FM.Recording.Status";
+ private BroadcastReceiver mFmRecordingStatus = null;
+ static final int RECORD_START = 1;
+ static final int RECORD_STOP = 0;
public FMRadioService() {
}
@@ -184,7 +195,7 @@
registerSleepExpired();
registerRecordTimeout();
registerDelayedServiceStop();
- registerExternalStorageListener();
+ registerFMRecordingStatus();
// registering media button receiver seperately as we need to set
// different priority for receiving media events
registerFmMediaButtonReceiver();
@@ -233,10 +244,6 @@
unregisterReceiver(mHeadsetReceiver);
mHeadsetReceiver = null;
}
- if( mSdcardUnmountReceiver != null ) {
- unregisterReceiver(mSdcardUnmountReceiver);
- mSdcardUnmountReceiver = null;
- }
if( mMusicCommandListener != null ) {
unregisterReceiver(mMusicCommandListener);
mMusicCommandListener = null;
@@ -257,6 +264,10 @@
unregisterReceiver(mDelayedServiceStopListener);
mDelayedServiceStopListener = null;
}
+ if (mFmRecordingStatus != null ) {
+ unregisterReceiver(mFmRecordingStatus);
+ mFmRecordingStatus = null;
+ }
/* Since the service is closing, disable the receiver */
fmOff();
@@ -270,38 +281,46 @@
super.onDestroy();
}
-/**
- * Registers an intent to listen for ACTION_MEDIA_UNMOUNTED notifications.
- * The intent will call closeExternalStorageFiles() if the external media
- * is going to be ejected, so applications can clean up.
- */
- public void registerExternalStorageListener() {
- if (mSdcardUnmountReceiver == null) {
- mSdcardUnmountReceiver = new BroadcastReceiver() {
+ public void registerFMRecordingStatus() {
+ if (mFmRecordingStatus == null) {
+ mFmRecordingStatus = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
+ Log.d(LOGTAG, "received intent " +intent);
String action = intent.getAction();
- if ((action.equals(Intent.ACTION_MEDIA_UNMOUNTED))
- || (action.equals(Intent.ACTION_MEDIA_EJECT))) {
- Log.d(LOGTAG, "ACTION_MEDIA_UNMOUNTED Intent received");
- if (mFmRecordingOn == true) {
+ if (action.equals(ACTION_FM_RECORDING_STATUS)) {
+ Log.d(LOGTAG, "ACTION_FM_RECORDING_STATUS Intent received");
+ int state = intent.getIntExtra("state", 0);
+ if (state == RECORD_START) {
+ Log.d(LOGTAG, "FM Recording started");
+ mFmRecordingOn = true;
try {
- stopRecording();
- } catch (Exception e) {
+ if ((mServiceInUse) && (mCallbacks != null) ) {
+ Log.d(LOGTAG, "start recording thread");
+ mCallbacks.onRecordingStarted();
+ }
+ } catch (RemoteException e) {
e.printStackTrace();
}
- }
+ } else if (state == RECORD_STOP) {
+ Log.d(LOGTAG, "FM Recording stopped");
+ mFmRecordingOn = false;
+ try {
+ if ((mServiceInUse) && (mCallbacks != null) ) {
+ mCallbacks.onRecordingStopped();
+ }
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
}
}
};
IntentFilter iFilter = new IntentFilter();
- iFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
- iFilter.addAction(Intent.ACTION_MEDIA_EJECT);
- iFilter.addDataScheme("file");
- registerReceiver(mSdcardUnmountReceiver, iFilter);
+ iFilter.addAction(ACTION_FM_RECORDING_STATUS);
+ registerReceiver(mFmRecordingStatus , iFilter);
}
- }
-
+ }
/**
* Registers an intent to listen for ACTION_HEADSET_PLUG
@@ -666,6 +685,20 @@
return true;
}
+ private void sendRecordIntent(int action) {
+ Intent intent = new Intent(ACTION_FM_RECORDING);
+ intent.putExtra("state", action);
+ Log.d(LOGTAG, "Sending Recording intent for = " +action);
+ getApplicationContext().sendBroadcast(intent);
+ }
+
+ private void sendRecordServiceIntent(int action) {
+ Intent intent = new Intent(ACTION_FM);
+ intent.putExtra("state", action);
+ Log.d(LOGTAG, "Sending Recording intent for = " +action);
+ getApplicationContext().sendBroadcast(intent);
+ }
+
private void startFM(){
Log.d(LOGTAG, "In startFM");
if(true == mAppShutdown) { // not to send intent to AudioManager in Shutdown
@@ -703,6 +736,7 @@
}
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
AudioSystem.DEVICE_STATE_AVAILABLE, "");
+ sendRecordServiceIntent(RECORD_START);
}
mPlaybackInProgress = true;
}
@@ -716,6 +750,7 @@
Log.d(LOGTAG, "FMRadio: Requesting to stop FM");
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
+ sendRecordServiceIntent(RECORD_STOP);
}
mPlaybackInProgress = false;
}
@@ -729,105 +764,23 @@
Log.d(LOGTAG, "FMRadio: Requesting to stop FM");
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,
AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
+ sendRecordServiceIntent(RECORD_STOP);
}
mPlaybackInProgress = false;
}
- public boolean startRecording() {
- Log.d(LOGTAG, "In startRecording of Recorder");
- if( (true == mSingleRecordingInstanceSupported) &&
- (true == mOverA2DP )) {
- Toast.makeText( this,
- "playback on BT in progress,can't record now",
- Toast.LENGTH_SHORT).show();
- return false;
+ public void startRecording() {
+
+ Log.d(LOGTAG, "In startRecording of Recorder");
+ if ((true == mSingleRecordingInstanceSupported) &&
+ (true == mOverA2DP )) {
+ Toast.makeText( this,
+ "playback on BT in progress,can't record now",
+ Toast.LENGTH_SHORT).show();
+ return;
}
- stopRecording();
-
- if (!updateAndShowStorageHint())
- return false;
- long maxFileSize = mStorageSpace - LOW_STORAGE_THRESHOLD;
- mRecorder = new MediaRecorder();
- try {
- mRecorder.setMaxFileSize(maxFileSize);
- } catch (RuntimeException exception) {
-
- }
-
- mSampleFile = null;
- File sampleDir = Environment.getExternalStorageDirectory();
- if (!sampleDir.canWrite()) // Workaround for broken sdcard support on
- // the device.
- sampleDir = new File("/sdcard/sdcard");
- try {
- mSampleFile = File
- .createTempFile("FMRecording", ".3gpp", sampleDir);
- } catch (IOException e) {
- Log.e(LOGTAG, "Not able to access SD Card");
- Toast.makeText(this, "Not able to access SD Card", Toast.LENGTH_SHORT).show();
- return false;
- }
- if (mRecorder == null) {
- Toast.makeText(this,"MediaRecorder failed to create an instance",
- Toast.LENGTH_SHORT).show();
- return false;
- }
-
- try {
- mRecorder.setAudioSource(MediaRecorder.AudioSource.FM_RX);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
- mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
- } catch (RuntimeException exception) {
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- return false;
- }
- mRecorder.setOutputFile(mSampleFile.getAbsolutePath());
- try {
- mRecorder.prepare();
- mRecorder.start();
- } catch (IOException e) {
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- return false;
- } catch (RuntimeException e) {
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- return false;
- }
- mFmRecordingOn = true;
- mRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
- public void onInfo(MediaRecorder mr, int what, int extra) {
- if ((what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) ||
- (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED)) {
- if (mFmRecordingOn) {
- Log.d(LOGTAG, "Maximum file size/duration reached, stopping the recording");
- stopRecording();
- }
- // Show the toast.
- Toast.makeText(FMRadioService.this, R.string.FMRecording_reach_size_limit,
- Toast.LENGTH_LONG).show();
- }
- }
- // from MediaRecorder.OnErrorListener
- public void onError(MediaRecorder mr, int what, int extra) {
- Log.e(LOGTAG, "MediaRecorder error. what=" + what + ". extra=" + extra);
- if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) {
- // We may have run out of space on the sdcard.
- if (mFmRecordingOn) {
- stopRecording();
- }
- updateAndShowStorageHint();
- }
- }
- });
-
- mSampleStart = System.currentTimeMillis();
- return true;
- }
+ sendRecordIntent(RECORD_START);
+ }
public boolean startA2dpPlayback() {
Log.d(LOGTAG, "In startA2dpPlayback");
@@ -925,195 +878,13 @@
return;
}
- private void resetRecording() {
-
- Log.v(LOGTAG, "resetRecording()");
-
- mFmRecordingOn = false;
- if (mRecorder == null)
- return;
-
- // Send Intent for IOBUSY VOTE, because MediaRecorder.stop
- // gets Activity context which might not be always available
- // and would thus fail to send the intent.
- Intent ioBusyUnVoteIntent = new Intent(IOBUSY_UNVOTE);
- // Remove vote for io_is_busy to be turned off.
- ioBusyUnVoteIntent.putExtra("com.android.server.CpuGovernorService.voteType", 0);
- sendBroadcast(ioBusyUnVoteIntent);
-
- mRecorder.stop();
-
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- int sampleLength = (int)((System.currentTimeMillis() - mSampleStart)/1000 );
- if (sampleLength == 0)
- return;
- String state = Environment.getExternalStorageState();
- Log.d(LOGTAG, "storage state is " + state);
-
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- this.addToMediaDB(mSampleFile);
- }
- else{
- Log.e(LOGTAG, "SD card must have removed during recording. ");
- Toast.makeText(this, "Recording aborted", Toast.LENGTH_SHORT).show();
- }
- return;
- }
-
public void stopRecording() {
- mFmRecordingOn = false;
- if (mRecorder == null)
+ if (!mFmRecordingOn)
return;
- try {
- mRecorder.stop();
- mRecorder.reset();
- mRecorder.release();
- mRecorder = null;
- } catch(Exception e) {
- e.printStackTrace();
- }
- int sampleLength = (int)((System.currentTimeMillis() - mSampleStart)/1000 );
- if (sampleLength == 0)
- return;
- String state = Environment.getExternalStorageState();
- Log.d(LOGTAG, "storage state is " + state);
-
- if (Environment.MEDIA_MOUNTED.equals(state)) {
- try {
- this.addToMediaDB(mSampleFile);
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- }
- else{
- Log.e(LOGTAG, "SD card must have removed during recording. ");
- Toast.makeText(this, "Recording aborted", Toast.LENGTH_SHORT).show();
- }
- try
- {
- if((mServiceInUse) && (mCallbacks != null) ) {
- mCallbacks.onRecordingStopped();
- }
- } catch (RemoteException e)
- {
- e.printStackTrace();
- }
+ sendRecordIntent(RECORD_STOP);
return;
}
- /*
- * Adds file and returns content uri.
- */
- private Uri addToMediaDB(File file) {
- Log.d(LOGTAG, "In addToMediaDB");
- Resources res = getResources();
- ContentValues cv = new ContentValues();
- long current = System.currentTimeMillis();
- long modDate = file.lastModified();
- Date date = new Date(current);
- SimpleDateFormat formatter = new SimpleDateFormat(
- res.getString(R.string.audio_db_title_format));
- String title = formatter.format(date);
-
- // Lets label the recorded audio file as NON-MUSIC so that the file
- // won't be displayed automatically, except for in the playlist.
- cv.put(MediaStore.Audio.Media.IS_MUSIC, "1");
-
- cv.put(MediaStore.Audio.Media.TITLE, title);
- cv.put(MediaStore.Audio.Media.DATA, file.getAbsolutePath());
- cv.put(MediaStore.Audio.Media.DATE_ADDED, (int) (current / 1000));
- cv.put(MediaStore.Audio.Media.DATE_MODIFIED, (int) (modDate / 1000));
- cv.put(MediaStore.Audio.Media.MIME_TYPE, "AUDIO_AAC_MP4");
- cv.put(MediaStore.Audio.Media.ARTIST,
- res.getString(R.string.audio_db_artist_name));
- cv.put(MediaStore.Audio.Media.ALBUM,
- res.getString(R.string.audio_db_album_name));
- Log.d(LOGTAG, "Inserting audio record: " + cv.toString());
- ContentResolver resolver = getContentResolver();
- Uri base = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
- Log.d(LOGTAG, "ContentURI: " + base);
- Uri result = resolver.insert(base, cv);
- if (result == null) {
- Toast.makeText(this, "Unable to save recorded audio", Toast.LENGTH_SHORT).show();
- return null;
- }
- if (getPlaylistId(res) == -1) {
- createPlaylist(res, resolver);
- }
- int audioId = Integer.valueOf(result.getLastPathSegment());
- addToPlaylist(resolver, audioId, getPlaylistId(res));
-
- // Notify those applications such as Music listening to the
- // scanner events that a recorded audio file just created.
- sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
- return result;
- }
-
- private int getPlaylistId(Resources res) {
- Uri uri = MediaStore.Audio.Playlists.getContentUri("external");
- final String[] ids = new String[] { MediaStore.Audio.Playlists._ID };
- final String where = MediaStore.Audio.Playlists.NAME + "=?";
- final String[] args = new String[] { res.getString(R.string.audio_db_playlist_name) };
- Cursor cursor = query(uri, ids, where, args, null);
- if (cursor == null) {
- Log.v(LOGTAG, "query returns null");
- }
- int id = -1;
- if (cursor != null) {
- cursor.moveToFirst();
- if (!cursor.isAfterLast()) {
- id = cursor.getInt(0);
- }
- cursor.close();
- }
- return id;
- }
-
- private Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
- try {
- ContentResolver resolver = getContentResolver();
- if (resolver == null) {
- return null;
- }
- return resolver.query(uri, projection, selection, selectionArgs, sortOrder);
- } catch (UnsupportedOperationException ex) {
- return null;
- }
- }
-
- private Uri createPlaylist(Resources res, ContentResolver resolver) {
- ContentValues cv = new ContentValues();
- cv.put(MediaStore.Audio.Playlists.NAME, res.getString(R.string.audio_db_playlist_name));
- Uri uri = resolver.insert(MediaStore.Audio.Playlists.getContentUri("external"), cv);
- if (uri == null) {
- Toast.makeText(this, "Unable to save recorded audio", Toast.LENGTH_SHORT).show();
- }
- return uri;
- }
-
- private void addToPlaylist(ContentResolver resolver, int audioId, long playlistId) {
- String[] cols = new String[] {
- "count(*)"
- };
- Uri uri = MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId);
- Cursor cur = resolver.query(uri, cols, null, null, null);
- final int base;
- if (cur != null) {
- cur.moveToFirst();
- base = cur.getInt(0);
- cur.close();
- }
- else {
- base = 0;
- }
- ContentValues values = new ContentValues();
- values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(base + audioId));
- values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, audioId);
- resolver.insert(uri, values);
- }
private void fmActionOnCallState( int state ) {
//if Call Status is non IDLE we need to Mute FM as well stop recording if
//any. Similarly once call is ended FM should be unmuted.
@@ -1468,9 +1239,9 @@
return(mService.get().isMuted());
}
- public boolean startRecording()
+ public void startRecording()
{
- return(mService.get().startRecording());
+ mService.get().startRecording();
}
public void stopRecording()
@@ -1790,7 +1561,7 @@
if (isFmRecordingOn())
{
- resetRecording();
+ stopRecording();
}
AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
diff --git a/fmapp2/src/com/caf/fmradio/FMStats.java b/fmapp2/src/com/caf/fmradio/FMStats.java
index 2afb301..feb6aab 100644
--- a/fmapp2/src/com/caf/fmradio/FMStats.java
+++ b/fmapp2/src/com/caf/fmradio/FMStats.java
@@ -1290,6 +1290,10 @@
{
Log.d(LOGTAG, "mServiceCallbacks.onFinishActivity:");
}
+ public void onRecordingStarted()
+ {
+ Log.d(LOGTAG, "mServiceCallbacks.onRecordingStarted:");
+ }
};
/* Radio Vars */
final Handler mHandler = new Handler();
diff --git a/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl b/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
index 7358149..8e2fe99 100644
--- a/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
+++ b/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
@@ -18,7 +18,7 @@
boolean routeAudio(int device);
boolean unMute();
boolean isMuted();
- boolean startRecording();
+ void startRecording();
void stopRecording();
boolean tune(int frequency);
boolean seek(boolean up);
diff --git a/fmapp2/src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl b/fmapp2/src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl
index 1926f24..4b9d2f0 100644
--- a/fmapp2/src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl
+++ b/fmapp2/src/com/caf/fmradio/IFMRadioServiceCallbacks.aidl
@@ -45,4 +45,5 @@
void onStationRDSSupported(boolean bRDSSupported);
void onRecordingStopped();
void onExtenRadioTextChanged();
+ void onRecordingStarted();
}