Fix stuck recording ui when recording is aborted
When the recording activity is paused and recording is canceled (e.g.
loss of audio focus), the recording UI appears frozen when the
activity resumes.
This happens due to two issues:
1. When the activity is paused it ignores the cancellation
MSG_FM_EXIT event.
2. When the activity is destroyed, it does not check the current
state of the Recorder when it resumes.
In both these cases, the activity assumes that the recording is still
ongoing but the stop button fails silently when there is no recording
to stop.
Fix these issues by querying the recording status when the activity
resumes and show the save dialog if the recording was stopped.
oResume() and onServiceConnected() have been consolidated in to
onResumeWithService() and handles checking the status of the service,
starting recording and revisiting the activity.
In FmService, the recording state returns 'INVALID' before the first
recording starts because the recorder has not yet been created.
Querying the recording state before starting the 2nd recording returns
'IDLE'. Treat the 1st and 2nd cases the same and return 'IDLE'.
FEIJ-1373
Change-Id: I8a6f85f067a4c5737c5e00e6c035ba743c373e8f
diff --git a/src/com/android/fmradio/FmRecordActivity.java b/src/com/android/fmradio/FmRecordActivity.java
index 09cbb75..7461724 100644
--- a/src/com/android/fmradio/FmRecordActivity.java
+++ b/src/com/android/fmradio/FmRecordActivity.java
@@ -75,6 +75,7 @@
private FragmentManager mFragmentManager;
private boolean mIsInBackground = false;
private int mRecordState = FmRecorder.STATE_INVALID;
+ private boolean mRecordingStarted = false;
private int mCurrentStation = FmUtils.DEFAULT_STATION;
private Notification.Builder mNotificationBuilder = null;
@@ -109,11 +110,13 @@
if (savedInstanceState != null) {
mCurrentStation = savedInstanceState.getInt(FmStation.CURRENT_STATION);
mRecordState = savedInstanceState.getInt("last_record_state");
+ mRecordingStarted = savedInstanceState.getBoolean("recording_started", false);
} else {
Intent intent = getIntent();
mCurrentStation = intent.getIntExtra(FmStation.CURRENT_STATION,
FmUtils.DEFAULT_STATION);
mRecordState = intent.getIntExtra("last_record_state", FmRecorder.STATE_INVALID);
+ mRecordingStarted = intent.getBooleanExtra("recording_started", false);
}
bindService(new Intent(this, FmService.class), mServiceConnection,
Context.BIND_AUTO_CREATE);
@@ -225,20 +228,60 @@
protected void onResume() {
super.onResume();
mIsInBackground = false;
- if (null != mService) {
- mService.setFmRecordActivityForeground(true);
+
+ onResumeWithService();
+ }
+
+ private void onResumeWithService() {
+
+ if (null == mService) {
+ // service not yet connected
+ return;
}
- // Show save dialog if record has stopped and never show it before.
- if (isStopRecording() && !isSaveDialogShown()) {
- showSaveDialog();
+
+ if (mIsInBackground) {
+ // not resumed yet
+ return;
}
- // Trigger to refreshing timer text if still in record
- if (!isStopRecording()) {
- mHandler.removeMessages(FmListener.MSGID_REFRESH);
- mHandler.sendEmptyMessage(FmListener.MSGID_REFRESH);
- }
- // Clear notification, it only need show when in background
+
+ mCurrentStation = mService.getFrequency();
+ mRecordState = mService.getRecorderState();
+
+ mService.setFmRecordActivityForeground(true);
removeNotification();
+ switch (mRecordState) {
+ case FmRecorder.STATE_IDLE:
+ if (!mRecordingStarted) {
+ // start the new recording
+ mRecordingStarted = true;
+ mService.startRecordingAsync();
+ break;
+ }
+
+ // recording was stopped while we were away
+ if (!isSaveDialogShown()) {
+ showSaveDialog();
+ break;
+ }
+
+ Log.wtf(TAG, "returned to FmRecordActivity after save dialog");
+ finish();
+ return;
+
+ case FmRecorder.STATE_RECORDING:
+ break;
+
+ case FmRecorder.STATE_INVALID:
+ default:
+ Log.wtf(TAG, "Unexpected state: " + mRecordState);
+ finish();
+ return;
+ }
+
+ mPlayIndicator.startAnimation();
+ mStopRecordButton.setEnabled(true);
+ mHandler.removeMessages(FmListener.MSGID_REFRESH);
+ mHandler.sendEmptyMessage(FmListener.MSGID_REFRESH);
}
@Override
@@ -278,6 +321,7 @@
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(FmStation.CURRENT_STATION, mCurrentStation);
outState.putInt("last_record_state", mRecordState);
+ outState.putBoolean("recording_started", mRecordingStarted);
super.onSaveInstanceState(outState);
}
@@ -332,24 +376,8 @@
public void onServiceConnected(ComponentName name, android.os.IBinder service) {
mService = ((FmService.ServiceBinder) service).getService();
mService.registerFmRadioListener(mFmListener);
- mService.setFmRecordActivityForeground(!mIsInBackground);
- // 1. If have stopped recording, we need check whether need show save dialog again.
- // Because when stop recording in background, we need show it when switch to foreground.
- if (isStopRecording()) {
- if (!isSaveDialogShown()) {
- showSaveDialog();
- }
- return;
- }
- // 2. If not start recording, start it directly, this case happen when start this
- // activity from main fm activity.
- if (!isStartRecording()) {
- mService.startRecordingAsync();
- }
- mPlayIndicator.startAnimation();
- mStopRecordButton.setEnabled(true);
- mHandler.removeMessages(FmListener.MSGID_REFRESH);
- mHandler.sendEmptyMessage(FmListener.MSGID_REFRESH);
+
+ onResumeWithService();
};
@Override
@@ -390,20 +418,23 @@
break;
case FmListener.LISTEN_RECORDSTATE_CHANGED:
- // State change from STATE_INVALID to STATE_RECORDING mean begin recording
+ // State change from STATE_IDLE to STATE_RECORDING mean begin recording
// State change from STATE_RECORDING to STATE_IDLE mean stop recording
int newState = mService.getRecorderState();
Log.d(TAG, "handleMessage, record state changed: newState = " + newState
+ ", mRecordState = " + mRecordState);
- if (mRecordState == FmRecorder.STATE_INVALID
+ if (mRecordState == FmRecorder.STATE_IDLE
&& newState == FmRecorder.STATE_RECORDING) {
- mRecordState = FmRecorder.STATE_RECORDING;
+ Log.d(TAG, "Recording started");
} else if (mRecordState == FmRecorder.STATE_RECORDING
&& newState == FmRecorder.STATE_IDLE) {
- mRecordState = FmRecorder.STATE_IDLE;
+ Log.d(TAG, "Recording stopped");
mPlayIndicator.stopAnimation();
showSaveDialog();
+ } else {
+ Log.e(TAG, "Unexpected recording state: " + newState);
}
+ mRecordState = newState;
break;
case FmListener.LISTEN_RECORDERROR:
@@ -494,6 +525,7 @@
int flag = bundle.getInt(FmListener.CALLBACK_FLAG);
if (flag == FmListener.MSGID_FM_EXIT) {
mHandler.removeCallbacksAndMessages(null);
+ mRecordState = FmRecorder.STATE_IDLE;
}
// remove tag message first, avoid too many same messages in queue.
diff --git a/src/com/android/fmradio/FmService.java b/src/com/android/fmradio/FmService.java
index 28f63d5..25ad3e9 100644
--- a/src/com/android/fmradio/FmService.java
+++ b/src/com/android/fmradio/FmService.java
@@ -1237,7 +1237,7 @@
if (null != mFmRecorder) {
return mFmRecorder.getState();
}
- return FmRecorder.STATE_INVALID;
+ return FmRecorder.STATE_IDLE;
}
/**