Merge "Set the orientation of a panorama image." into ics-mr1
diff --git a/res/raw/camera_focus.ogg b/res/raw/camera_focus.ogg
deleted file mode 100644
index 0db2683..0000000
--- a/res/raw/camera_focus.ogg
+++ /dev/null
Binary files differ
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index 0da0095..f0c1f30 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -380,7 +380,6 @@
         boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT);
         mFocusManager.initialize(mFocusAreaIndicator, mPreviewFrame, mFaceView, this,
                 mirror, mDisplayOrientation);
-        mFocusManager.initializeSoundPlayer(getResources().openRawResourceFd(R.raw.camera_focus));
         mImageSaver = new ImageSaver();
         Util.initializeScreenBrightness(getWindow(), getContentResolver());
         installIntentFilter();
@@ -440,7 +439,6 @@
         mLocationManager.recordLocation(recordLocation);
 
         installIntentFilter();
-        mFocusManager.initializeSoundPlayer(getResources().openRawResourceFd(R.raw.camera_focus));
         mImageSaver = new ImageSaver();
         initializeZoom();
         keepMediaProviderInstance();
@@ -1058,6 +1056,11 @@
         setCameraParameters(UPDATE_PARAM_PREFERENCE);
     }
 
+    @Override
+    public void playSound(int soundId) {
+        mCameraDevice.playSound(soundId);
+    }
+
     private boolean saveDataToFile(String filePath, byte[] data) {
         FileOutputStream f = null;
         try {
@@ -1588,8 +1591,6 @@
         if (mLocationManager != null) mLocationManager.recordLocation(false);
         updateExposureOnScreenIndicator(0);
 
-        mFocusManager.releaseSoundPlayer();
-
         if (mStorageHint != null) {
             mStorageHint.cancel();
             mStorageHint = null;
diff --git a/src/com/android/camera/EffectsRecorder.java b/src/com/android/camera/EffectsRecorder.java
index 737e828..390efa6 100644
--- a/src/com/android/camera/EffectsRecorder.java
+++ b/src/com/android/camera/EffectsRecorder.java
@@ -34,11 +34,9 @@
 import android.hardware.Camera;
 import android.media.MediaRecorder;
 import android.media.CamcorderProfile;
-import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
-import android.os.SystemProperties;
 import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceHolder;
@@ -73,6 +71,7 @@
     public static final int  EFFECT_MSG_SWITCHING_EFFECT = 2;
     public static final int  EFFECT_MSG_EFFECTS_STOPPED  = 3;
     public static final int  EFFECT_MSG_RECORDING_DONE   = 4;
+    public static final int  EFFECT_MSG_PREVIEW_RUNNING  = 5;
 
     private Context mContext;
     private Handler mHandler;
@@ -108,9 +107,6 @@
 
     private SurfaceTexture mTextureSource;
 
-    private static final String mVideoRecordSound = "/system/media/audio/ui/VideoRecord.ogg";
-    private SoundPlayer mRecordSound;
-
     private static final int STATE_CONFIGURE              = 0;
     private static final int STATE_WAITING_FOR_SURFACE    = 1;
     private static final int STATE_STARTING_PREVIEW       = 2;
@@ -140,28 +136,6 @@
         if (mLogVerbose) Log.v(TAG, "EffectsRecorder created (" + this + ")");
         mContext = context;
         mHandler = new Handler(Looper.getMainLooper());
-
-        // Construct sound player; use enforced sound output if necessary
-        File recordSoundFile = new File(mVideoRecordSound);
-        try {
-            ParcelFileDescriptor recordSoundParcel =
-                    ParcelFileDescriptor.open(recordSoundFile,
-                            ParcelFileDescriptor.MODE_READ_ONLY);
-            AssetFileDescriptor recordSoundAsset =
-                    new AssetFileDescriptor(recordSoundParcel, 0,
-                                            AssetFileDescriptor.UNKNOWN_LENGTH);
-            if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
-                if (mLogVerbose) Log.v(TAG, "Standard recording sound");
-                mRecordSound = new SoundPlayer(recordSoundAsset, false);
-            } else {
-                if (mLogVerbose) Log.v(TAG, "Forced recording sound");
-                mRecordSound = new SoundPlayer(recordSoundAsset, true);
-            }
-        } catch (java.io.FileNotFoundException e) {
-            Log.e(TAG, "System video record sound not found");
-            mRecordSound = null;
-        }
-
     }
 
     public void setCamera(Camera cameraDevice) {
@@ -634,6 +608,9 @@
                 mState = STATE_PREVIEW;
 
                 if (mLogVerbose) Log.v(TAG, "Start preview/effect switch complete");
+
+                // Sending a message to listener that preview is complete
+                sendMessage(mCurrentEffect, EFFECT_MSG_PREVIEW_RUNNING);
             }
         }
     };
@@ -713,7 +690,7 @@
         recorder.setInputValue("maxFileSize", mMaxFileSize);
         recorder.setInputValue("maxDurationMs", mMaxDurationMs);
         recorder.setInputValue("recording", true);
-        if (mRecordSound != null) mRecordSound.play();
+        mCameraDevice.playSound(Camera.Sound.START_VIDEO_RECORDING);
         mState = STATE_RECORD;
     }
 
@@ -733,7 +710,7 @@
         }
         Filter recorder = mRunner.getGraph().getFilter("recorder");
         recorder.setInputValue("recording", false);
-        if (mRecordSound != null) mRecordSound.play();
+        mCameraDevice.playSound(Camera.Sound.STOP_VIDEO_RECORDING);
         mState = STATE_PREVIEW;
     }
 
@@ -865,7 +842,6 @@
                 stopPreview();
                 // Fall-through
             default:
-                mRecordSound.release();
                 mState = STATE_RELEASED;
                 break;
         }
diff --git a/src/com/android/camera/FocusManager.java b/src/com/android/camera/FocusManager.java
index 76a8737..8c3f14d 100644
--- a/src/com/android/camera/FocusManager.java
+++ b/src/com/android/camera/FocusManager.java
@@ -26,6 +26,7 @@
 import android.graphics.RectF;
 import android.hardware.Camera.Area;
 import android.hardware.Camera.Parameters;
+import android.hardware.Camera.Sound;
 import android.os.Handler;
 import android.os.Message;
 import android.util.Log;
@@ -59,7 +60,6 @@
     private boolean mLockAeAwbNeeded;
     private boolean mAeAwbLock;
     private Matrix mMatrix;
-    private SoundPlayer mSoundPlayer;
     private View mFocusIndicatorRotateLayout;
     private FocusIndicatorView mFocusIndicator;
     private View mPreviewFrame;
@@ -81,6 +81,7 @@
         public void startFaceDetection();
         public void stopFaceDetection();
         public void setFocusParameters();
+        public void playSound(int soundId);
     }
 
     private class MainHandler extends Handler {
@@ -221,9 +222,9 @@
                 // Do not play the sound in continuous autofocus mode. It does
                 // not do a full scan. The focus callback arrives before doSnap
                 // so the state is always STATE_FOCUSING.
-                if (!Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)
-                        && mSoundPlayer != null) {
-                    mSoundPlayer.play();
+                if (!Parameters.FOCUS_MODE_CONTINUOUS_PICTURE.
+                        equals(mFocusMode)) {
+                    mListener.playSound(Sound.FOCUS_COMPLETE);
                 }
             } else {
                 mState = STATE_FAIL;
@@ -346,18 +347,6 @@
         }
     }
 
-    public void initializeSoundPlayer(AssetFileDescriptor fd) {
-        mSoundPlayer = new SoundPlayer(fd);
-    }
-
-    public void releaseSoundPlayer() {
-        if (mSoundPlayer != null) {
-            mSoundPlayer.release();
-            mSoundPlayer = null;
-        }
-    }
-
-
     // This can only be called after mParameters is initialized.
     public String getFocusMode() {
         if (mOverrideFocusMode != null) return mOverrideFocusMode;
diff --git a/src/com/android/camera/SoundPlayer.java b/src/com/android/camera/SoundPlayer.java
deleted file mode 100644
index a3acb44..0000000
--- a/src/com/android/camera/SoundPlayer.java
+++ /dev/null
@@ -1,122 +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 com.android.camera;
-
-import android.content.res.AssetFileDescriptor;
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * Plays an AssetFileDescriptor, but does all the hard work on another thread so
- * that any slowness with preparing or loading doesn't block the calling thread.
- */
-public class SoundPlayer implements Runnable {
-    private static final String TAG = "SoundPlayer";
-    private Thread mThread;
-    private MediaPlayer mPlayer;
-    private int mPlayCount = 0;
-    private boolean mExit;
-    private AssetFileDescriptor mAfd;
-    private int mAudioStreamType;
-
-    @Override
-    public void run() {
-        while(true) {
-            try {
-                if (mPlayer == null) {
-                    MediaPlayer player = new MediaPlayer();
-                    player.setAudioStreamType(mAudioStreamType);
-                    player.setDataSource(mAfd.getFileDescriptor(), mAfd.getStartOffset(),
-                            mAfd.getLength());
-                    player.setLooping(false);
-                    player.prepare();
-                    mPlayer = player;
-                    mAfd.close();
-                    mAfd = null;
-                }
-                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", e);
-            }
-        }
-    }
-
-    public SoundPlayer(AssetFileDescriptor afd) {
-        mAfd = afd;
-        mAudioStreamType = AudioManager.STREAM_MUSIC;
-    }
-
-    public SoundPlayer(AssetFileDescriptor afd, boolean enforceAudible) {
-        mAfd = afd;
-        if (enforceAudible) {
-            mAudioStreamType = 7; // AudioManager.STREAM_SYSTEM_ENFORCED; currently hidden API.
-        } else {
-            mAudioStreamType = AudioManager.STREAM_MUSIC;
-        }
-    }
-
-    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 (mAfd != null) {
-            try {
-                mAfd.close();
-            } catch(IOException e) {
-            }
-            mAfd = null;
-        }
-        if (mPlayer != null) {
-            mPlayer.release();
-            mPlayer = null;
-        }
-    }
-}
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index f725f43..1e90544 100755
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -432,6 +432,16 @@
         mShutterButton.setOnShutterButtonListener(this);
         mShutterButton.requestFocus();
 
+        // Disable the shutter button if effects are ON since it might take
+        // a little more time for the effects preview to be ready. We do not
+        // want to allow recording before that happens. The shutter button
+        // will be enabled when we get the message from effectsrecorder that
+        // the preview is running. This becomes critical when the camera is
+        // swapped.
+        if (effectsActive()) {
+            mShutterButton.setEnabled(false);
+        }
+
         mRecordingTimeView = (TextView) findViewById(R.id.recording_time);
         mRecordingTimeRect = (RotateLayout) findViewById(R.id.recording_time_rect);
         mOrientationListener = new MyOrientationEventListener(this);
@@ -641,6 +651,7 @@
     @Override
     public void onShutterButtonClick() {
         if (collapseCameraControls()) return;
+
         boolean stop = mMediaRecorderRecording;
 
         if (stop) {
@@ -1386,6 +1397,11 @@
         mCurrentVideoValues.put(Video.Media.RESOLUTION,
                 Integer.toString(mProfile.videoFrameWidth) + "x" +
                 Integer.toString(mProfile.videoFrameHeight));
+        Location loc = mLocationManager.getCurrentLocation();
+        if (loc != null) {
+            mCurrentVideoValues.put(Video.Media.LATITUDE, loc.getLatitude());
+            mCurrentVideoValues.put(Video.Media.LONGITUDE, loc.getLongitude());
+        }
         Log.v(TAG, "New video filename: " + mVideoFilename);
     }
 
@@ -1992,6 +2008,9 @@
                 }
             }
             mEffectsDisplayResult = false;
+        } else if (effectMsg == EffectsRecorder.EFFECT_MSG_PREVIEW_RUNNING) {
+            // Enable the shutter button once the preview is complete.
+            mShutterButton.setEnabled(true);
         } else if (effectId == EffectsRecorder.EFFECT_BACKDROPPER) {
             switch (effectMsg) {
                 case EffectsRecorder.EFFECT_MSG_STARTED_LEARNING:
diff --git a/src/com/android/camera/panorama/PanoramaActivity.java b/src/com/android/camera/panorama/PanoramaActivity.java
index 331c849..6978477 100755
--- a/src/com/android/camera/panorama/PanoramaActivity.java
+++ b/src/com/android/camera/panorama/PanoramaActivity.java
@@ -27,7 +27,6 @@
 import com.android.camera.R;
 import com.android.camera.RotateDialogController;
 import com.android.camera.ShutterButton;
-import com.android.camera.SoundPlayer;
 import com.android.camera.Storage;
 import com.android.camera.Thumbnail;
 import com.android.camera.Util;
@@ -50,6 +49,7 @@
 import android.graphics.YuvImage;
 import android.hardware.Camera.Parameters;
 import android.hardware.Camera.Size;
+import android.hardware.Camera.Sound;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
 import android.media.ExifInterface;
@@ -58,7 +58,6 @@
 import android.os.Handler;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
-import android.os.SystemProperties;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.Menu;
@@ -106,8 +105,6 @@
     // Ratio of nanosecond to second
     private static final float NS2S = 1.0f / 1000000000.0f;
 
-    private static final String VIDEO_RECORD_SOUND = "/system/media/audio/ui/VideoRecord.ogg";
-
     private boolean mPausing;
 
     private View mPanoLayout;
@@ -169,8 +166,6 @@
     private float[] mTransformMatrix;
     private float mHorizontalViewAngle;
 
-    private SoundPlayer mRecordSound;
-
     // Prefer FOCUS_MODE_INFINITY to FOCUS_MODE_CONTINUOUS_VIDEO because of
     // getting a better image quality by the former.
     private String mTargetFocusMode = Parameters.FOCUS_MODE_INFINITY;
@@ -737,11 +732,11 @@
         // right now.
         switch (mCaptureState) {
             case CAPTURE_STATE_VIEWFINDER:
-                if (mRecordSound != null) mRecordSound.play();
+                mCameraDevice.playSound(Sound.START_VIDEO_RECORDING);
                 startCapture();
                 break;
             case CAPTURE_STATE_MOSAIC:
-                if (mRecordSound != null) mRecordSound.play();
+                mCameraDevice.playSound(Sound.STOP_VIDEO_RECORDING);
                 stopCapture(false);
         }
     }
@@ -958,34 +953,6 @@
         mMosaicFrameProcessor.initialize();
     }
 
-    private void initSoundRecorder() {
-        // Construct sound player; use enforced sound output if necessary
-        File recordSoundFile = new File(VIDEO_RECORD_SOUND);
-        try {
-            ParcelFileDescriptor recordSoundParcel =
-                    ParcelFileDescriptor.open(recordSoundFile,
-                            ParcelFileDescriptor.MODE_READ_ONLY);
-            AssetFileDescriptor recordSoundAsset =
-                    new AssetFileDescriptor(recordSoundParcel, 0,
-                                            AssetFileDescriptor.UNKNOWN_LENGTH);
-            if (SystemProperties.get("ro.camera.sound.forced", "0").equals("0")) {
-                mRecordSound = new SoundPlayer(recordSoundAsset, false);
-            } else {
-                mRecordSound = new SoundPlayer(recordSoundAsset, true);
-            }
-        } catch (java.io.FileNotFoundException e) {
-            Log.e(TAG, "System video record sound not found");
-            mRecordSound = null;
-        }
-    }
-
-    private void releaseSoundRecorder() {
-        if (mRecordSound != null) {
-            mRecordSound.release();
-            mRecordSound = null;
-        }
-    }
-
     @Override
     protected void onPause() {
         super.onPause();
@@ -1004,7 +971,6 @@
         }
 
         releaseCamera();
-        releaseSoundRecorder();
         mMosaicView.onPause();
         clearMosaicFrameProcessorIfNeeded();
         mOrientationEventListener.disable();
@@ -1020,8 +986,6 @@
         mCaptureState = CAPTURE_STATE_VIEWFINDER;
         setupCamera();
 
-        initSoundRecorder();
-
         // Camera must be initialized before MosaicFrameProcessor is initialized. The preview size
         // has to be decided by camera device.
         initMosaicFrameProcessorIfNeeded();