Merge "NEW_API: Rework CameraSound into MediaActionSound, and unhide it."
diff --git a/api/current.txt b/api/current.txt
index 1c4190e..4110a20 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -10780,6 +10780,17 @@
method public abstract void onJetUserIdUpdate(android.media.JetPlayer, int, int);
}
+ public class MediaActionSound {
+ ctor public MediaActionSound();
+ method public void load(int);
+ method public void play(int);
+ method public void release();
+ field public static final int FOCUS_COMPLETE = 1; // 0x1
+ field public static final int SHUTTER_CLICK = 0; // 0x0
+ field public static final int START_VIDEO_RECORDING = 2; // 0x2
+ field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
+ }
+
public class MediaMetadataRetriever {
ctor public MediaMetadataRetriever();
method public java.lang.String extractMetadata(int);
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index cca208a..573e6ea 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -36,7 +36,6 @@
import java.util.List;
import java.util.StringTokenizer;
-
/**
* The Camera class is used to set image capture settings, start/stop preview,
* snap pictures, and retrieve frames for encoding for video. This class is a
diff --git a/core/java/android/hardware/CameraSound.java b/core/java/android/hardware/CameraSound.java
deleted file mode 100644
index dc97ff09..0000000
--- a/core/java/android/hardware/CameraSound.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2011 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 android.hardware;
-
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * <p>Use this class to play an appropriate sound when implementing a custom
- * still or video recording mechanism through the preview callbacks.</p>
- *
- * <p>There is no need to play sounds when using {@link #android.hardware.Camera#takePicture}
- * or {@link android.media.MediaRecorder} for still images or video,
- * respectively, as these play their own sounds when needed.</p>
- *
- * @hide
- */
-public class CameraSound {
- private static final String TAG = "CameraSound";
- /**
- * The sound used by {@link android.hardware.Camera#takePicture} to
- * indicate still image capture.
- */
- public static final int SHUTTER_CLICK = 0;
-
- /**
- * A sound to indicate that focusing has completed. Because deciding
- * when this occurs is application-dependent, this sound is not used by
- * any methods in the Camera class.
- */
- public static final int FOCUS_COMPLETE = 1;
-
- /**
- * The sound used by {@link android.media.MediaRecorder#start} to
- * indicate the start of video recording.
- */
- public static final int START_VIDEO_RECORDING = 2;
-
- /**
- * The sound used by {@link android.media.MediaRecorder#stop} to
- * indicate the end of video recording.
- */
- public static final int STOP_VIDEO_RECORDING = 3;
-
- private static final int NUM_SOUNDS = 4;
- private CameraSoundPlayer[] mCameraSoundPlayers;
-
- public CameraSound() {
- }
-
- /**
- * <p>Play one of the predefined platform sounds for camera actions.</p>
- *
- * <p>Use this method to play a platform-specific sound for various camera
- * actions. The sound playing is done asynchronously, with the same behavior
- * and content as the sounds played by {@link #takePicture takePicture},
- * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
- * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
- *
- * <p>Using this method makes it easy to match the default device sounds
- * when recording or capturing data through the preview callbacks.</p>
- *
- * @param soundId The type of sound to play, selected from SHUTTER_CLICK,
- * FOCUS_COMPLETE, START_VIDEO_RECORDING, or STOP_VIDEO_RECORDING.
- * @see android.hardware#takePicture
- * @see android.media.MediaRecorder
- * @see #SHUTTER_CLICK
- * @see #FOCUS_COMPLETE
- * @see #START_VIDEO_RECORDING
- * @see #STOP_VIDEO_RECORDING
- */
- public void playSound(int soundId) {
- if (mCameraSoundPlayers == null) {
- mCameraSoundPlayers = new CameraSoundPlayer[NUM_SOUNDS];
- }
- if (mCameraSoundPlayers[soundId] == null) {
- mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
- }
- mCameraSoundPlayers[soundId].play();
- }
-
- public void release() {
- if (mCameraSoundPlayers != null) {
- for (CameraSoundPlayer csp: mCameraSoundPlayers) {
- if (csp != null) {
- csp.release();
- }
- }
- mCameraSoundPlayers = null;
- }
- }
-
- private static class CameraSoundPlayer implements Runnable {
- private int mSoundId;
- private MediaPlayer mPlayer;
- private Thread mThread;
- private boolean mExit;
- private int mPlayCount;
-
- private static final String mShutterSound =
- "/system/media/audio/ui/camera_click.ogg";
- private static final String mFocusSound =
- "/system/media/audio/ui/camera_focus.ogg";
- private static final String mVideoStartSound =
- "/system/media/audio/ui/VideoRecord.ogg";
- private static final String mVideoStopSound =
- "/system/media/audio/ui/VideoRecord.ogg";
-
- @Override
- public void run() {
- String soundFilePath;
- switch (mSoundId) {
- case SHUTTER_CLICK:
- soundFilePath = mShutterSound;
- break;
- case FOCUS_COMPLETE:
- soundFilePath = mFocusSound;
- break;
- case START_VIDEO_RECORDING:
- soundFilePath = mVideoStartSound;
- break;
- case STOP_VIDEO_RECORDING:
- soundFilePath = mVideoStopSound;
- break;
- default:
- Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
- return;
- }
- mPlayer = new MediaPlayer();
- try {
- mPlayer.setAudioStreamType(AudioManager.STREAM_SYSTEM_ENFORCED);
- mPlayer.setDataSource(soundFilePath);
- mPlayer.setLooping(false);
- mPlayer.prepare();
- } catch(IOException e) {
- Log.e(TAG, "Error setting up sound " + mSoundId, e);
- return;
- }
-
- while(true) {
- try {
- synchronized (this) {
- while(true) {
- if (mExit) {
- return;
- } else if (mPlayCount <= 0) {
- wait();
- } else {
- mPlayCount--;
- break;
- }
- }
- }
- mPlayer.start();
- } catch (Exception e) {
- Log.e(TAG, "Error playing sound " + mSoundId, e);
- }
- }
- }
-
- public CameraSoundPlayer(int soundId) {
- mSoundId = soundId;
- }
-
- public void play() {
- if (mThread == null) {
- mThread = new Thread(this);
- mThread.start();
- }
- synchronized (this) {
- mPlayCount++;
- notifyAll();
- }
- }
-
- public void release() {
- if (mThread != null) {
- synchronized (this) {
- mExit = true;
- notifyAll();
- }
- try {
- mThread.join();
- } catch (InterruptedException e) {
- }
- mThread = null;
- }
- if (mPlayer != null) {
- mPlayer.release();
- mPlayer = null;
- }
- }
-
- @Override
- protected void finalize() {
- release();
- }
- }
-}
\ No newline at end of file
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
new file mode 100644
index 0000000..d0e6910
--- /dev/null
+++ b/media/java/android/media/MediaActionSound.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2012 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 android.media;
+
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.util.Log;
+
+/**
+ * <p>A class for producing sounds that match those produced by various actions
+ * taken by the media and camera APIs. </p>
+ *
+ * <p>Use this class to play an appropriate camera operation sound when
+ * implementing a custom still or video recording mechanism (through the Camera
+ * preview callbacks with {@link android.hardware.Camera#setPreviewCallback
+ * Camera.setPreviewCallback}, or through GPU processing with {@link
+ * android.hardware.Camera#setPreviewTexture Camera.setPreviewTexture}, for
+ * example), or when implementing some other camera-like function in your
+ * application.</p>
+ *
+ * <p>There is no need to play sounds when using
+ * {@link android.hardware.Camera#takePicture Camera.takePicture} or
+ * {@link android.media.MediaRecorder} for still images or video, respectively,
+ * as the Android framework will play the appropriate sounds when needed for
+ * these calls.</p>
+ *
+ */
+public class MediaActionSound {
+ private static final int NUM_MEDIA_SOUND_STREAMS = 1;
+
+ private SoundPool mSoundPool;
+ private int[] mSoundIds;
+ private int mSoundIdToPlay;
+
+ private static final String[] SOUND_FILES = {
+ "/system/media/audio/ui/camera_click.ogg",
+ "/system/media/audio/ui/camera_focus.ogg",
+ "/system/media/audio/ui/VideoRecord.ogg",
+ "/system/media/audio/ui/VideoRecord.ogg"
+ };
+
+ private static final String TAG = "MediaActionSound";
+ /**
+ * The sound used by
+ * {@link android.hardware.Camera#takePicture Camera.takePicture} to
+ * indicate still image capture.
+ * @see #play
+ */
+ public static final int SHUTTER_CLICK = 0;
+
+ /**
+ * A sound to indicate that focusing has completed. Because deciding
+ * when this occurs is application-dependent, this sound is not used by
+ * any methods in the media or camera APIs.
+ * @see #play
+ */
+ public static final int FOCUS_COMPLETE = 1;
+
+ /**
+ * The sound used by
+ * {@link android.media.MediaRecorder#start MediaRecorder.start()} to
+ * indicate the start of video recording.
+ * @see #play
+ */
+ public static final int START_VIDEO_RECORDING = 2;
+
+ /**
+ * The sound used by
+ * {@link android.media.MediaRecorder#stop MediaRecorder.stop()} to
+ * indicate the end of video recording.
+ * @see #play
+ */
+ public static final int STOP_VIDEO_RECORDING = 3;
+
+ private static final int SOUND_NOT_LOADED = -1;
+
+ /**
+ * Construct a new MediaActionSound instance. Only a single instance is
+ * needed for playing any platform media action sound; you do not need a
+ * separate instance for each sound type.
+ */
+ public MediaActionSound() {
+ mSoundPool = new SoundPool(NUM_MEDIA_SOUND_STREAMS,
+ AudioManager.STREAM_SYSTEM_ENFORCED, 0);
+ mSoundPool.setOnLoadCompleteListener(mLoadCompleteListener);
+ mSoundIds = new int[SOUND_FILES.length];
+ for (int i = 0; i < mSoundIds.length; i++) {
+ mSoundIds[i] = SOUND_NOT_LOADED;
+ }
+ mSoundIdToPlay = SOUND_NOT_LOADED;
+ }
+
+ /**
+ * Preload a predefined platform sound to minimize latency when the sound is
+ * played later by {@link #play}.
+ * @param soundName The type of sound to preload, selected from
+ * SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, or
+ * STOP_VIDEO_RECORDING.
+ * @see #play
+ * @see #SHUTTER_CLICK
+ * @see #FOCUS_COMPLETE
+ * @see #START_VIDEO_RECORDING
+ * @see #STOP_VIDEO_RECORDING
+ */
+ public synchronized void load(int soundName) {
+ if (soundName < 0 || soundName >= SOUND_FILES.length) {
+ throw new RuntimeException("Unknown sound requested: " + soundName);
+ }
+ if (mSoundIds[soundName] == SOUND_NOT_LOADED) {
+ mSoundIds[soundName] =
+ mSoundPool.load(SOUND_FILES[soundName], 1);
+ }
+ }
+
+ /**
+ * <p>Play one of the predefined platform sounds for media actions.</p>
+ *
+ * <p>Use this method to play a platform-specific sound for various media
+ * actions. The sound playback is done asynchronously, with the same
+ * behavior and content as the sounds played by
+ * {@link android.hardware.Camera#takePicture Camera.takePicture},
+ * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
+ * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
+ *
+ * <p>Using this method makes it easy to match the default device sounds
+ * when recording or capturing data through the preview callbacks, or when
+ * implementing custom camera-like features in your
+ * application.</p>
+ *
+ * <p>If the sound has not been loaded by {@link #load} before calling play,
+ * play will load the sound at the cost of some additional latency before
+ * sound playback begins. </p>
+ *
+ * @param soundName The type of sound to play, selected from
+ * SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, or
+ * STOP_VIDEO_RECORDING.
+ * @see android.hardware.Camera#takePicture
+ * @see android.media.MediaRecorder
+ * @see #SHUTTER_CLICK
+ * @see #FOCUS_COMPLETE
+ * @see #START_VIDEO_RECORDING
+ * @see #STOP_VIDEO_RECORDING
+ */
+ public synchronized void play(int soundName) {
+ if (soundName < 0 || soundName >= SOUND_FILES.length) {
+ throw new RuntimeException("Unknown sound requested: " + soundName);
+ }
+ if (mSoundIds[soundName] == SOUND_NOT_LOADED) {
+ mSoundIdToPlay =
+ mSoundPool.load(SOUND_FILES[soundName], 1);
+ mSoundIds[soundName] = mSoundIdToPlay;
+ } else {
+ mSoundPool.play(mSoundIds[soundName], 1.0f, 1.0f, 0, 0, 1.0f);
+ }
+ }
+
+ private SoundPool.OnLoadCompleteListener mLoadCompleteListener =
+ new SoundPool.OnLoadCompleteListener() {
+ public void onLoadComplete(SoundPool soundPool,
+ int sampleId, int status) {
+ if (status == 0) {
+ if (mSoundIdToPlay == sampleId) {
+ soundPool.play(sampleId, 1.0f, 1.0f, 0, 0, 1.0f);
+ mSoundIdToPlay = SOUND_NOT_LOADED;
+ }
+ } else {
+ Log.e(TAG, "Unable to load sound for playback (status: " +
+ status + ")");
+ }
+ }
+ };
+
+ /**
+ * Free up all audio resources used by this MediaActionSound instance
+ */
+ public void release() {
+ mSoundPool.release();
+ mSoundPool = null;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index c4a92f7..9a76c14 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -34,7 +34,7 @@
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.PointF;
-import android.hardware.CameraSound;
+import android.media.MediaActionSound;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
@@ -256,7 +256,7 @@
private float mBgPadding;
private float mBgPaddingScale;
- private CameraSound mCameraSound;
+ private MediaActionSound mCameraSound;
/**
@@ -309,7 +309,8 @@
mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
// Setup the Camera shutter sound
- mCameraSound = new CameraSound();
+ mCameraSound = new MediaActionSound();
+ mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
}
/**
@@ -422,7 +423,7 @@
@Override
public void run() {
// Play the shutter sound to notify that we've taken a screenshot
- mCameraSound.playSound(CameraSound.SHUTTER_CLICK);
+ mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
mScreenshotView.buildLayer();