summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java')
-rw-r--r--src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java223
1 files changed, 0 insertions, 223 deletions
diff --git a/src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java b/src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java
deleted file mode 100644
index 06730a3..0000000
--- a/src/com/android/messaging/ui/mediapicker/LevelTrackingMediaRecorder.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2015 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.messaging.ui.mediapicker;
-
-import android.media.MediaRecorder;
-import android.net.Uri;
-import android.os.ParcelFileDescriptor;
-
-import com.android.messaging.Factory;
-import com.android.messaging.R;
-import com.android.messaging.datamodel.MediaScratchFileProvider;
-import com.android.messaging.util.Assert;
-import com.android.messaging.util.ContentType;
-import com.android.messaging.util.LogUtil;
-import com.android.messaging.util.SafeAsyncTask;
-import com.android.messaging.util.UiUtils;
-
-import java.io.IOException;
-
-/**
- * Wraps around the functionalities of MediaRecorder, performs routine setup for audio recording
- * and updates the audio level to be displayed in UI.
- *
- * During the start and end of a recording session, we kick off a thread that polls for audio
- * levels, and updates the thread-safe AudioLevelSource instance. Consumers may bind to the
- * sound level by either polling from the level source, or register for a level change callback
- * on the level source object. In Bugle, the UI element (SoundLevels) polls for the sound level
- * on the UI thread by using animation ticks and invalidating itself.
- *
- * Aside from tracking sound levels, this also encapsulates the functionality to save the file
- * to the scratch space. The saved file is returned by calling stopRecording().
- */
-public class LevelTrackingMediaRecorder {
- // We refresh sound level every 100ms during a recording session.
- private static final int REFRESH_INTERVAL_MILLIS = 100;
-
- // The native amplitude returned from MediaRecorder ranges from 0~32768 (unfortunately, this
- // is not a constant that's defined anywhere, but the framework's Recorder app is using the
- // same hard-coded number). Therefore, a constant is needed in order to make it 0~100.
- private static final int MAX_AMPLITUDE_FACTOR = 32768 / 100;
-
- // We want to limit the max audio file size by the max message size allowed by MmsConfig,
- // plus multiplied by this fudge ratio to guarantee that we don't go over limit.
- private static final float MAX_SIZE_RATIO = 0.8f;
-
- // Default recorder settings for Bugle.
- // TODO: Do we want these to be tweakable?
- private static final int MEDIA_RECORDER_AUDIO_SOURCE = MediaRecorder.AudioSource.MIC;
- private static final int MEDIA_RECORDER_OUTPUT_FORMAT = MediaRecorder.OutputFormat.THREE_GPP;
- private static final int MEDIA_RECORDER_AUDIO_ENCODER = MediaRecorder.AudioEncoder.AMR_NB;
-
- private final AudioLevelSource mLevelSource;
- private Thread mRefreshLevelThread;
- private MediaRecorder mRecorder;
- private Uri mOutputUri;
- private ParcelFileDescriptor mOutputFD;
-
- public LevelTrackingMediaRecorder() {
- mLevelSource = new AudioLevelSource();
- }
-
- public AudioLevelSource getLevelSource() {
- return mLevelSource;
- }
-
- /**
- * @return if we are currently in a recording session.
- */
- public boolean isRecording() {
- return mRecorder != null;
- }
-
- /**
- * Start a new recording session.
- * @return true if a session is successfully started; false if something went wrong or if
- * we are already recording.
- */
- public boolean startRecording(final MediaRecorder.OnErrorListener errorListener,
- final MediaRecorder.OnInfoListener infoListener, int maxSize) {
- synchronized (LevelTrackingMediaRecorder.class) {
- if (mRecorder == null) {
- mOutputUri = MediaScratchFileProvider.buildMediaScratchSpaceUri(
- ContentType.THREE_GPP_EXTENSION);
- mRecorder = new MediaRecorder();
- try {
- // The scratch space file is a Uri, however MediaRecorder
- // API only accepts absolute FD's. Therefore, get the
- // FileDescriptor from the content resolver to ensure the
- // directory is created and get the file path to output the
- // audio to.
- maxSize *= MAX_SIZE_RATIO;
- mOutputFD = Factory.get().getApplicationContext()
- .getContentResolver().openFileDescriptor(mOutputUri, "w");
- mRecorder.setAudioSource(MEDIA_RECORDER_AUDIO_SOURCE);
- mRecorder.setOutputFormat(MEDIA_RECORDER_OUTPUT_FORMAT);
- mRecorder.setAudioEncoder(MEDIA_RECORDER_AUDIO_ENCODER);
- mRecorder.setOutputFile(mOutputFD.getFileDescriptor());
- mRecorder.setMaxFileSize(maxSize);
- mRecorder.setOnErrorListener(errorListener);
- mRecorder.setOnInfoListener(infoListener);
- mRecorder.prepare();
- mRecorder.start();
- startTrackingSoundLevel();
- return true;
- } catch (final Exception e) {
- // There may be a device failure or I/O failure, record the error but
- // don't fail.
- LogUtil.e(LogUtil.BUGLE_TAG, "Something went wrong when starting " +
- "media recorder. " + e);
- UiUtils.showToastAtBottom(R.string.audio_recording_start_failed);
- stopRecording();
- }
- } else {
- Assert.fail("Trying to start a new recording session while already recording!");
- }
- return false;
- }
- }
-
- /**
- * Stop the current recording session.
- * @return the Uri of the output file, or null if not currently recording.
- */
- public Uri stopRecording() {
- synchronized (LevelTrackingMediaRecorder.class) {
- if (mRecorder != null) {
- try {
- mRecorder.stop();
- } catch (final RuntimeException ex) {
- // This may happen when the recording is too short, so just drop the recording
- // in this case.
- LogUtil.w(LogUtil.BUGLE_TAG, "Something went wrong when stopping " +
- "media recorder. " + ex);
- if (mOutputUri != null) {
- final Uri outputUri = mOutputUri;
- SafeAsyncTask.executeOnThreadPool(new Runnable() {
- @Override
- public void run() {
- Factory.get().getApplicationContext().getContentResolver().delete(
- outputUri, null, null);
- }
- });
- mOutputUri = null;
- }
- } finally {
- mRecorder.release();
- mRecorder = null;
- }
- } else {
- Assert.fail("Not currently recording!");
- return null;
- }
- }
-
- if (mOutputFD != null) {
- try {
- mOutputFD.close();
- } catch (final IOException e) {
- // Nothing to do
- }
- mOutputFD = null;
- }
-
- stopTrackingSoundLevel();
- return mOutputUri;
- }
-
- private int getAmplitude() {
- synchronized (LevelTrackingMediaRecorder.class) {
- if (mRecorder != null) {
- final int maxAmplitude = mRecorder.getMaxAmplitude() / MAX_AMPLITUDE_FACTOR;
- return Math.min(maxAmplitude, 100);
- } else {
- return 0;
- }
- }
- }
-
- private void startTrackingSoundLevel() {
- stopTrackingSoundLevel();
- mRefreshLevelThread = new Thread() {
- @Override
- public void run() {
- try {
- while (true) {
- synchronized (LevelTrackingMediaRecorder.class) {
- if (mRecorder != null) {
- mLevelSource.setSpeechLevel(getAmplitude());
- } else {
- // The recording session is over, finish the thread.
- return;
- }
- }
- Thread.sleep(REFRESH_INTERVAL_MILLIS);
- }
- } catch (final InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- };
- mRefreshLevelThread.start();
- }
-
- private void stopTrackingSoundLevel() {
- if (mRefreshLevelThread != null && mRefreshLevelThread.isAlive()) {
- mRefreshLevelThread.interrupt();
- mRefreshLevelThread = null;
- }
- }
-}