diff options
author | Owen Lin <owenlin@google.com> | 2009-11-04 00:40:41 -0800 |
---|---|---|
committer | Owen Lin <owenlin@google.com> | 2009-11-04 02:15:57 -0800 |
commit | 7d2d5ec1e9d6c19278e41c103eacd8090be24406 (patch) | |
tree | 0ffae3b4688e2b21fa01b9de81ec4e1863903bde /src/com/android/camera | |
parent | 31e592d59f8c4038493f0b4ca2fba9bba97e04cd (diff) | |
download | Gallery-7d2d5ec1e9d6c19278e41c103eacd8090be24406.tar.gz |
Remove unused code in Gallery
Change-Id: I971d85a54149be074f9545c5a43319bda7f470ed
Diffstat (limited to 'src/com/android/camera')
24 files changed, 1 insertions, 6772 deletions
diff --git a/src/com/android/camera/BooleanListPreference.java b/src/com/android/camera/BooleanListPreference.java deleted file mode 100644 index e04709f..0000000 --- a/src/com/android/camera/BooleanListPreference.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2009 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.Context; -import android.preference.ListPreference; -import android.util.AttributeSet; - -/** {@code BooleanListPreference} is used for those {@code SharedPreference} - * which stores value in the type of {@code Boolean} but would like to be shown - * as two radio buttons instead of a checkbox. - */ -public class BooleanListPreference extends ListPreference { - - public BooleanListPreference(Context context, AttributeSet attrs) { - super(context, attrs); - CharSequence values[] = getEntryValues(); - if (values.length == 2) { - boolean x = Boolean.valueOf(values[0].toString()); - boolean y = Boolean.valueOf(values[1].toString()); - if (x != y) return; - } - throw new IllegalStateException( - "EntryValues should be boolean strings"); - } - - @Override - protected boolean persistString(String value) { - return persistBoolean(Boolean.valueOf(value)); - } - - @Override - protected String getPersistedString(String defaultValue) { - return Boolean.toString( - getPersistedBoolean(Boolean.valueOf(defaultValue))); - } -} diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java deleted file mode 100644 index a2d916d..0000000 --- a/src/com/android/camera/Camera.java +++ /dev/null @@ -1,2077 +0,0 @@ -/* - * Copyright (C) 2007 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 com.android.gallery.R; - -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.PictureCallback; -import android.hardware.Camera.Size; -import android.location.Location; -import android.location.LocationManager; -import android.location.LocationProvider; -import android.media.AudioManager; -import android.media.ToneGenerator; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Debug; -import android.os.Environment; -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.preference.PreferenceManager; -import android.provider.MediaStore; -import android.text.format.DateFormat; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Display; -import android.view.GestureDetector; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.OrientationEventListener; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.view.MenuItem.OnMenuItemClickListener; -import android.widget.ImageView; -import android.widget.ZoomButtonsController; - -import com.android.camera.gallery.IImage; -import com.android.camera.gallery.IImageList; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Activity of the Camera which used to see preview and take pictures. - */ -public class Camera extends NoSearchActivity implements View.OnClickListener, - ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback, - Switcher.OnSwitchListener, OnScreenSettings.OnVisibilityChangedListener, - OnSharedPreferenceChangeListener { - - private static final String TAG = "camera"; - - // This value must be as same as the item value of the string array - // "flash_mode" in file "res/values/arrays.xml". - private static final String NO_FLASH_MODE = "no_flash"; - private static final int CROP_MSG = 1; - private static final int FIRST_TIME_INIT = 2; - private static final int RESTART_PREVIEW = 3; - private static final int CLEAR_SCREEN_DELAY = 4; - - private static final String GPS_MODE_ON = "on"; - private static final String GPS_MODE_OFF = "off"; - - private static final int SCREEN_DELAY = 2 * 60 * 1000; - private static final int FOCUS_BEEP_VOLUME = 100; - - private static final String SCENE_MODE_ON = "on"; - private static final String SCENE_MODE_OFF = "off"; - - private double mZoomValue; // The current zoom value. - private double mZoomStep; - private double mZoomMax; - public static final double ZOOM_STEP_MIN = 0.25; - public static final String ZOOM_STOP = "stop"; - public static final String ZOOM_IMMEDIATE = "zoom-immediate"; - public static final String ZOOM_CONTINUOUS = "zoom-continuous"; - public static final double ZOOM_MIN = 1.0; - public static final String ZOOM_SPEED = "99"; - - private Parameters mParameters; - private Parameters mInitialParams; - - // The non-standard parameter strings to communicate with camera driver. - // This will be removed in the future. - public static final String PARM_ZOOM_STATE = "mot-zoom-state"; - public static final String PARM_ZOOM_STEP = "mot-zoom-step"; - public static final String PARM_ZOOM_TO_LEVEL = "mot-zoom-to-level"; - public static final String PARM_ZOOM_SPEED = "mot-zoom-speed"; - public static final String PARM_ZOOM_MAX = "mot-max-picture-continuous-zoom"; - - private OrientationEventListener mOrientationListener; - private int mLastOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; - private SharedPreferences mPreferences; - - private static final int IDLE = 1; - private static final int SNAPSHOT_IN_PROGRESS = 2; - - private static final boolean SWITCH_CAMERA = true; - private static final boolean SWITCH_VIDEO = false; - - private int mStatus = IDLE; - private static final String sTempCropFilename = "crop-temp"; - - private android.hardware.Camera mCameraDevice; - private SurfaceView mSurfaceView; - private SurfaceHolder mSurfaceHolder = null; - private ShutterButton mShutterButton; - private FocusRectangle mFocusRectangle; - private IconIndicator mGpsIndicator; - private IconIndicator mFlashIndicator; - private IconIndicator mFocusIndicator; - private IconIndicator mWhitebalanceIndicator; - private IconIndicator mSceneModeIndicator; - private ToneGenerator mFocusToneGenerator; - private ZoomButtonsController mZoomButtons; - private GestureDetector mGestureDetector; - private Switcher mSwitcher; - private boolean mStartPreviewFail = false; - - // mPostCaptureAlert, mLastPictureButton, mThumbController - // are non-null only if isImageCaptureIntent() is true. - private ImageView mLastPictureButton; - private ThumbnailController mThumbController; - - // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true. - private String mCropValue; - private Uri mSaveUri; - - private ImageCapture mImageCapture = null; - - private boolean mPreviewing; - private boolean mPausing; - private boolean mFirstTimeInitialized; - private boolean mIsImageCaptureIntent; - private boolean mRecordLocation; - - private static final int FOCUS_NOT_STARTED = 0; - private static final int FOCUSING = 1; - private static final int FOCUSING_SNAP_ON_FINISH = 2; - private static final int FOCUS_SUCCESS = 3; - private static final int FOCUS_FAIL = 4; - private int mFocusState = FOCUS_NOT_STARTED; - - private ContentResolver mContentResolver; - private boolean mDidRegister = false; - - private final ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>(); - - private LocationManager mLocationManager = null; - - // Use OneShotPreviewCallback to measure the time between - // JpegPictureCallback and preview. - private final OneShotPreviewCallback mOneShotPreviewCallback = - new OneShotPreviewCallback(); - private final ShutterCallback mShutterCallback = new ShutterCallback(); - private final RawPictureCallback mRawPictureCallback = - new RawPictureCallback(); - private final AutoFocusCallback mAutoFocusCallback = - new AutoFocusCallback(); - private final ZoomCallback mZoomCallback = new ZoomCallback(); - // Use the ErrorCallback to capture the crash count - // on the mediaserver - private final ErrorCallback mErrorCallback = new ErrorCallback(); - - private long mFocusStartTime; - private long mFocusCallbackTime; - private long mCaptureStartTime; - private long mShutterCallbackTime; - private long mRawPictureCallbackTime; - private long mJpegPictureCallbackTime; - private int mPicturesRemaining; - - // These latency time are for the CameraLatency test. - public long mAutoFocusTime; - public long mShutterLag; - public long mShutterAndRawPictureCallbackTime; - public long mJpegPictureCallbackTimeLag; - public long mRawPictureAndJpegPictureCallbackTime; - - // Add the media server tag - public static boolean mMediaServerDied = false; - // Focus mode. Options are pref_camera_focusmode_entryvalues. - private String mFocusMode; - - private final Handler mHandler = new MainHandler(); - private OnScreenSettings mSettings; - - /** - * This Handler is used to post message back onto the main thread of the - * application - */ - private class MainHandler extends Handler { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case RESTART_PREVIEW: { - restartPreview(); - break; - } - - case CLEAR_SCREEN_DELAY: { - getWindow().clearFlags( - WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - break; - } - - case FIRST_TIME_INIT: { - initializeFirstTime(); - break; - } - } - } - } - - // Snapshots can only be taken after this is called. It should be called - // once only. We could have done these things in onCreate() but we want to - // make preview screen appear as soon as possible. - private void initializeFirstTime() { - if (mFirstTimeInitialized) return; - - // Create orientation listenter. This should be done first because it - // takes some time to get first orientation. - mOrientationListener = - new OrientationEventListener(Camera.this) { - @Override - public void onOrientationChanged(int orientation) { - // We keep the last known orientation. So if the user - // first orient the camera then point the camera to - // floor/sky, we still have the correct orientation. - if (orientation != ORIENTATION_UNKNOWN) { - mLastOrientation = orientation; - } - } - }; - mOrientationListener.enable(); - - // Initialize location sevice. - mLocationManager = (LocationManager) - getSystemService(Context.LOCATION_SERVICE); - readPreference(); - if (mRecordLocation) startReceivingLocationUpdates(); - - checkStorage(); - - // Initialize last picture button. - mContentResolver = getContentResolver(); - if (!mIsImageCaptureIntent) { - findViewById(R.id.camera_switch).setOnClickListener(this); - mLastPictureButton = - (ImageView) findViewById(R.id.review_thumbnail); - mLastPictureButton.setOnClickListener(this); - mThumbController = new ThumbnailController( - getResources(), mLastPictureButton, mContentResolver); - mThumbController.loadData(ImageManager.getLastImageThumbPath()); - // Update last image thumbnail. - updateThumbnailButton(); - } - - // Initialize shutter button. - mShutterButton = (ShutterButton) findViewById(R.id.shutter_button); - mShutterButton.setOnShutterButtonListener(this); - mShutterButton.setVisibility(View.VISIBLE); - - mFocusRectangle = (FocusRectangle) findViewById(R.id.focus_rectangle); - updateFocusIndicator(); - - // Initialize GPS indicator. - mGpsIndicator = (IconIndicator) findViewById(R.id.gps_icon); - - ImageManager.ensureOSXCompatibleFolder(); - - installIntentFilter(); - - initializeFocusTone(); - - initializeZoom(); - - mFirstTimeInitialized = true; - } - - private void updateThumbnailButton() { - // Update last image if URI is invalid and the storage is ready. - if (!mThumbController.isUriValid() && mPicturesRemaining >= 0) { - updateLastImage(); - } - mThumbController.updateDisplayIfNeeded(); - } - - // If the activity is paused and resumed, this method will be called in - // onResume. - private void initializeSecondTime() { - // Start orientation listener as soon as possible because it takes - // some time to get first orientation. - mOrientationListener.enable(); - - // Start location update if needed. - readPreference(); - if (mRecordLocation) startReceivingLocationUpdates(); - - installIntentFilter(); - - initializeFocusTone(); - - checkStorage(); - - if (mZoomButtons != null) { - mZoomValue = Double.parseDouble( - mParameters.get(PARM_ZOOM_TO_LEVEL)); - mCameraDevice.setZoomCallback(mZoomCallback); - } - - if (!mIsImageCaptureIntent) { - updateThumbnailButton(); - } - } - - private void initializeZoom() { - // Check if the phone has zoom capability. - String zoomState = mParameters.get(PARM_ZOOM_STATE); - if (zoomState == null) return; - - mZoomValue = Double.parseDouble(mParameters.get(PARM_ZOOM_TO_LEVEL)); - mZoomMax = Double.parseDouble(mParameters.get(PARM_ZOOM_MAX)); - mZoomStep = Double.parseDouble(mParameters.get(PARM_ZOOM_STEP)); - mParameters.set(PARM_ZOOM_SPEED, ZOOM_SPEED); - mCameraDevice.setParameters(mParameters); - - mGestureDetector = new GestureDetector(this, new ZoomGestureListener()); - mCameraDevice.setZoomCallback(mZoomCallback); - mZoomButtons = new ZoomButtonsController(mSurfaceView); - mZoomButtons.setAutoDismissed(true); - mZoomButtons.setZoomSpeed(100); - mZoomButtons.setOnZoomListener( - new ZoomButtonsController.OnZoomListener() { - public void onVisibilityChanged(boolean visible) { - if (visible) { - updateZoomButtonsEnabled(); - } - } - - public void onZoom(boolean zoomIn) { - if (isZooming()) return; - - if (zoomIn) { - if (mZoomValue < mZoomMax) { - zoomToLevel(ZOOM_CONTINUOUS, mZoomValue + mZoomStep); - } - } else { - if (mZoomValue > ZOOM_MIN) { - zoomToLevel(ZOOM_CONTINUOUS, mZoomValue - mZoomStep); - } - } - } - }); - } - - public void onVisibilityChanged(boolean visible) { - // When the on-screen setting is not displayed, we show the gripper. - // When the on-screen setting is displayed, we hide the gripper. - int reverseVisibility = visible ? View.INVISIBLE : View.VISIBLE; - findViewById(R.id.btn_gripper).setVisibility(reverseVisibility); - findViewById(R.id.indicator_bar).setVisibility(reverseVisibility); - - if (visible) { - mPreferences.registerOnSharedPreferenceChangeListener(this); - } else { - mPreferences.unregisterOnSharedPreferenceChangeListener(this); - } - } - - private boolean isZooming() { - mParameters = mCameraDevice.getParameters(); - return "continuous".equals(mParameters.get(PARM_ZOOM_STATE)); - } - - private void zoomToLevel(String type, double zoomValue) { - if (zoomValue > mZoomMax) zoomValue = mZoomMax; - if (zoomValue < ZOOM_MIN) zoomValue = ZOOM_MIN; - - // If the application sets a unchanged zoom value, the driver will stuck - // at the zoom state. This is a work-around to ensure the state is at - // "stop". - mParameters.set(PARM_ZOOM_STATE, ZOOM_STOP); - mCameraDevice.setParameters(mParameters); - - mParameters.set(PARM_ZOOM_TO_LEVEL, Double.toString(zoomValue)); - mParameters.set(PARM_ZOOM_STATE, type); - mCameraDevice.setParameters(mParameters); - - if (ZOOM_IMMEDIATE.equals(type)) mZoomValue = zoomValue; - } - - private void updateZoomButtonsEnabled() { - mZoomButtons.setZoomInEnabled(mZoomValue < mZoomMax); - mZoomButtons.setZoomOutEnabled(mZoomValue > ZOOM_MIN); - } - - private class ZoomGestureListener extends - GestureDetector.SimpleOnGestureListener { - @Override - public boolean onDown(MotionEvent e) { - // Show zoom buttons only when preview is started and snapshot - // is not in progress. mZoomButtons may be null if it is not - // initialized. - if (!mPausing && isCameraIdle() && mPreviewing - && mZoomButtons != null) { - mZoomButtons.setVisible(true); - } - return true; - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - // Perform zoom only when preview is started and snapshot is not in - // progress. - if (mPausing || !isCameraIdle() || !mPreviewing - || mZoomButtons == null || isZooming()) { - return false; - } - - if (mZoomValue < mZoomMax) { - // Zoom in to the maximum. - while (mZoomValue < mZoomMax) { - zoomToLevel(ZOOM_IMMEDIATE, mZoomValue + ZOOM_STEP_MIN); - // Wait for a while so we are not changing zoom too fast. - try { - Thread.sleep(5); - } catch (InterruptedException ex) { - } - } - } else { - // Zoom out to the minimum. - while (mZoomValue > ZOOM_MIN) { - zoomToLevel(ZOOM_IMMEDIATE, mZoomValue - ZOOM_STEP_MIN); - // Wait for a while so we are not changing zoom too fast. - try { - Thread.sleep(5); - } catch (InterruptedException ex) { - } - } - } - updateZoomButtonsEnabled(); - return true; - } - } - - @Override - public boolean dispatchTouchEvent(MotionEvent m) { - if (!super.dispatchTouchEvent(m) && mGestureDetector != null) { - return mGestureDetector.onTouchEvent(m); - } - return true; - } - - LocationListener [] mLocationListeners = new LocationListener[] { - new LocationListener(LocationManager.GPS_PROVIDER), - new LocationListener(LocationManager.NETWORK_PROVIDER) - }; - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(Intent.ACTION_MEDIA_MOUNTED) - || action.equals(Intent.ACTION_MEDIA_UNMOUNTED) - || action.equals(Intent.ACTION_MEDIA_CHECKING) - || action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) { - checkStorage(); - } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) { - checkStorage(); - if (!mIsImageCaptureIntent) { - updateThumbnailButton(); - } - } - } - }; - - private class LocationListener - implements android.location.LocationListener { - Location mLastLocation; - boolean mValid = false; - String mProvider; - - public LocationListener(String provider) { - mProvider = provider; - mLastLocation = new Location(mProvider); - } - - public void onLocationChanged(Location newLocation) { - if (newLocation.getLatitude() == 0.0 - && newLocation.getLongitude() == 0.0) { - // Hack to filter out 0.0,0.0 locations - return; - } - // If GPS is available before start camera, we won't get status - // update so update GPS indicator when we receive data. - if (mRecordLocation - && LocationManager.GPS_PROVIDER.equals(mProvider)) { - mGpsIndicator.setMode(GPS_MODE_ON); - } - mLastLocation.set(newLocation); - mValid = true; - } - - public void onProviderEnabled(String provider) { - } - - public void onProviderDisabled(String provider) { - mValid = false; - } - - public void onStatusChanged( - String provider, int status, Bundle extras) { - switch(status) { - case LocationProvider.OUT_OF_SERVICE: - case LocationProvider.TEMPORARILY_UNAVAILABLE: { - mValid = false; - if (mRecordLocation && - LocationManager.GPS_PROVIDER.equals(provider)) { - mGpsIndicator.setMode(GPS_MODE_OFF); - } - break; - } - } - } - - public Location current() { - return mValid ? mLastLocation : null; - } - } - - private final class OneShotPreviewCallback - implements android.hardware.Camera.PreviewCallback { - public void onPreviewFrame(byte[] data, - android.hardware.Camera camera) { - long now = System.currentTimeMillis(); - if (mJpegPictureCallbackTime != 0) { - mJpegPictureCallbackTimeLag = now - mJpegPictureCallbackTime; - Log.v(TAG, "mJpegPictureCallbackTimeLag = " - + mJpegPictureCallbackTimeLag + "ms"); - mJpegPictureCallbackTime = 0; - } else { - Log.v(TAG, "Got first frame"); - } - } - } - - private final class ShutterCallback - implements android.hardware.Camera.ShutterCallback { - public void onShutter() { - mShutterCallbackTime = System.currentTimeMillis(); - mShutterLag = mShutterCallbackTime - mCaptureStartTime; - Log.v(TAG, "mShutterLag = " + mShutterLag + "ms"); - clearFocusState(); - } - } - - private final class RawPictureCallback implements PictureCallback { - public void onPictureTaken( - byte [] rawData, android.hardware.Camera camera) { - mRawPictureCallbackTime = System.currentTimeMillis(); - mShutterAndRawPictureCallbackTime = - mRawPictureCallbackTime - mShutterCallbackTime; - Log.v(TAG, "mShutterAndRawPictureCallbackTime = " - + mShutterAndRawPictureCallbackTime + "ms"); - } - } - - private final class JpegPictureCallback implements PictureCallback { - Location mLocation; - - public JpegPictureCallback(Location loc) { - mLocation = loc; - } - - public void onPictureTaken( - final byte [] jpegData, final android.hardware.Camera camera) { - if (mPausing) { - return; - } - - mJpegPictureCallbackTime = System.currentTimeMillis(); - mRawPictureAndJpegPictureCallbackTime = - mJpegPictureCallbackTime - mRawPictureCallbackTime; - Log.v(TAG, "mRawPictureAndJpegPictureCallbackTime = " - + mRawPictureAndJpegPictureCallbackTime + "ms"); - mImageCapture.storeImage(jpegData, camera, mLocation); - - if (!mIsImageCaptureIntent) { - long delay = 1200 - ( - System.currentTimeMillis() - mRawPictureCallbackTime); - mHandler.sendEmptyMessageDelayed( - RESTART_PREVIEW, Math.max(delay, 0)); - } - } - } - - private final class AutoFocusCallback - implements android.hardware.Camera.AutoFocusCallback { - public void onAutoFocus( - boolean focused, android.hardware.Camera camera) { - mFocusCallbackTime = System.currentTimeMillis(); - mAutoFocusTime = mFocusCallbackTime - mFocusStartTime; - Log.v(TAG, "mAutoFocusTime = " + mAutoFocusTime + "ms"); - if (mFocusState == FOCUSING_SNAP_ON_FINISH) { - // Take the picture no matter focus succeeds or fails. No need - // to play the AF sound if we're about to play the shutter - // sound. - if (focused) { - mFocusState = FOCUS_SUCCESS; - } else { - mFocusState = FOCUS_FAIL; - } - mImageCapture.onSnap(); - } else if (mFocusState == FOCUSING) { - // User is half-pressing the focus key. Play the focus tone. - // Do not take the picture now. - ToneGenerator tg = mFocusToneGenerator; - if (tg != null) { - tg.startTone(ToneGenerator.TONE_PROP_BEEP2); - } - if (focused) { - mFocusState = FOCUS_SUCCESS; - } else { - mFocusState = FOCUS_FAIL; - } - } else if (mFocusState == FOCUS_NOT_STARTED) { - // User has released the focus key before focus completes. - // Do nothing. - } - updateFocusIndicator(); - } - } - - private final class ErrorCallback - implements android.hardware.Camera.ErrorCallback { - public void onError(int error, android.hardware.Camera camera) { - if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) { - mMediaServerDied = true; - Log.v(TAG, "media server died"); - } - } - } - - private final class ZoomCallback - implements android.hardware.Camera.ZoomCallback { - public void onZoomUpdate(int zoomLevel, boolean stopped, - android.hardware.Camera camera) { - mZoomValue = (double) zoomLevel / 1000; - Log.v(TAG, "ZoomCallback: zoom level=" + zoomLevel + ".stopped=" - + stopped); - updateZoomButtonsEnabled(); - } - } - - private class ImageCapture { - - private boolean mCancel = false; - - private Uri mLastContentUri; - - byte[] mCaptureOnlyData; - - // Returns the rotation degree in the jpeg header. - private int storeImage(byte[] data, Location loc) { - try { - long dateTaken = System.currentTimeMillis(); - String name = createName(dateTaken) + ".jpg"; - int[] degree = new int[1]; - mLastContentUri = ImageManager.addImage( - mContentResolver, - name, - dateTaken, - loc, // location from gps/network - ImageManager.CAMERA_IMAGE_BUCKET_NAME, name, - null, data, - degree); - if (mLastContentUri == null) { - // this means we got an error - mCancel = true; - } - if (!mCancel) { - ImageManager.setImageSize(mContentResolver, mLastContentUri, - new File(ImageManager.CAMERA_IMAGE_BUCKET_NAME, - name).length()); - } - return degree[0]; - } catch (Exception ex) { - Log.e(TAG, "Exception while compressing image.", ex); - return 0; - } - } - - public void storeImage(final byte[] data, - android.hardware.Camera camera, Location loc) { - if (!mIsImageCaptureIntent) { - int degree = storeImage(data, loc); - sendBroadcast(new Intent( - "com.android.camera.NEW_PICTURE", mLastContentUri)); - setLastPictureThumb(data, degree, - mImageCapture.getLastCaptureUri()); - mThumbController.updateDisplayIfNeeded(); - } else { - mCaptureOnlyData = data; - showPostCaptureAlert(); - } - } - - /** - * Initiate the capture of an image. - */ - public void initiate() { - if (mCameraDevice == null) { - return; - } - - mCancel = false; - - capture(); - } - - public Uri getLastCaptureUri() { - return mLastContentUri; - } - - public byte[] getLastCaptureData() { - return mCaptureOnlyData; - } - - private void capture() { - mCaptureOnlyData = null; - - // Set rotation. - int orientation = mLastOrientation; - if (orientation != OrientationEventListener.ORIENTATION_UNKNOWN) { - orientation += 90; - } - orientation = ImageManager.roundOrientation(orientation); - Log.v(TAG, "mLastOrientation = " + mLastOrientation - + ", orientation = " + orientation); - mParameters.setRotation(orientation); - - // Clear previous GPS location from the parameters. - mParameters.removeGpsData(); - - // Set GPS location. - Location loc = mRecordLocation ? getCurrentLocation() : null; - if (loc != null) { - double lat = loc.getLatitude(); - double lon = loc.getLongitude(); - boolean hasLatLon = (lat != 0.0d) || (lon != 0.0d); - - if (hasLatLon) { - mParameters.setGpsLatitude(lat); - mParameters.setGpsLongitude(lon); - if (loc.hasAltitude()) { - mParameters.setGpsAltitude(loc.getAltitude()); - } else { - // for NETWORK_PROVIDER location provider, we may have - // no altitude information, but the driver needs it, so - // we fake one. - mParameters.setGpsAltitude(0); - } - if (loc.getTime() != 0) { - // Location.getTime() is UTC in milliseconds. - // gps-timestamp is UTC in seconds. - long utcTimeSeconds = loc.getTime() / 1000; - mParameters.setGpsTimestamp(utcTimeSeconds); - } - } else { - loc = null; - } - } - - mCameraDevice.setParameters(mParameters); - - mCameraDevice.takePicture(mShutterCallback, mRawPictureCallback, - new JpegPictureCallback(loc)); - mPreviewing = false; - } - - public void onSnap() { - // If we are already in the middle of taking a snapshot then ignore. - if (mPausing || mStatus == SNAPSHOT_IN_PROGRESS) { - return; - } - mCaptureStartTime = System.currentTimeMillis(); - - // Don't check the filesystem here, we can't afford the latency. - // Instead, check the cached value which was calculated when the - // preview was restarted. - if (mPicturesRemaining < 1) { - updateStorageHint(mPicturesRemaining); - return; - } - - mStatus = SNAPSHOT_IN_PROGRESS; - - mImageCapture.initiate(); - } - - private void clearLastData() { - mCaptureOnlyData = null; - } - } - - public boolean saveDataToFile(String filePath, byte[] data) { - FileOutputStream f = null; - try { - f = new FileOutputStream(filePath); - f.write(data); - } catch (IOException e) { - return false; - } finally { - MenuHelper.closeSilently(f); - } - return true; - } - - private void setLastPictureThumb(byte[] data, int degree, Uri uri) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = 16; - Bitmap lastPictureThumb = - BitmapFactory.decodeByteArray(data, 0, data.length, options); - lastPictureThumb = Util.rotate(lastPictureThumb, degree); - mThumbController.setData(uri, lastPictureThumb); - } - - private static String createName(long dateTaken) { - return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString(); - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - Window win = getWindow(); - win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - setContentView(R.layout.camera); - mSurfaceView = (SurfaceView) findViewById(R.id.camera_preview); - - mPreferences = PreferenceManager.getDefaultSharedPreferences(this); - - /* - * To reduce startup time, we start the preview in another thread. - * We make sure the preview is started at the end of onCreate. - */ - Thread startPreviewThread = new Thread(new Runnable() { - public void run() { - try { - mStartPreviewFail = false; - startPreview(); - } catch (CameraHardwareException e) { - // In eng build, we throw the exception so that test tool - // can detect it and report it - if ("eng".equals(Build.TYPE)) { - throw new RuntimeException(e); - } - mStartPreviewFail = true; - } - } - }); - startPreviewThread.start(); - - // don't set mSurfaceHolder here. We have it set ONLY within - // surfaceChanged / surfaceDestroyed, other parts of the code - // assume that when it is set, the surface is also set. - SurfaceHolder holder = mSurfaceView.getHolder(); - holder.addCallback(this); - holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); - - mIsImageCaptureIntent = isImageCaptureIntent(); - if (mIsImageCaptureIntent) { - setupCaptureParams(); - } - - LayoutInflater inflater = getLayoutInflater(); - - ViewGroup rootView = (ViewGroup) findViewById(R.id.camera); - if (mIsImageCaptureIntent) { - View controlBar = inflater.inflate( - R.layout.attach_camera_control, rootView); - controlBar.findViewById(R.id.btn_cancel).setOnClickListener(this); - controlBar.findViewById(R.id.btn_retake).setOnClickListener(this); - controlBar.findViewById(R.id.btn_done).setOnClickListener(this); - } else { - inflater.inflate(R.layout.camera_control, rootView); - mSwitcher = ((Switcher) findViewById(R.id.camera_switch)); - mSwitcher.setOnSwitchListener(this); - mSwitcher.addTouchView(findViewById(R.id.camera_switch_set)); - } - findViewById(R.id.btn_gripper) - .setOnTouchListener(new GripperTouchListener()); - - mFlashIndicator = (IconIndicator) findViewById(R.id.flash_icon); - mFocusIndicator = (IconIndicator) findViewById(R.id.focus_icon); - mSceneModeIndicator = (IconIndicator) findViewById(R.id.scenemode_icon); - mWhitebalanceIndicator = - (IconIndicator) findViewById(R.id.whitebalance_icon); - - // Make sure preview is started. - try { - startPreviewThread.join(); - if (mStartPreviewFail) { - showCameraErrorAndFinish(); - return; - } - } catch (InterruptedException ex) { - // ignore - } - } - - private class GripperTouchListener implements View.OnTouchListener { - public boolean onTouch(View view, MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - return true; - case MotionEvent.ACTION_UP: - showOnScreenSettings(); - return true; - } - return false; - } - } - - @Override - public void onStart() { - super.onStart(); - if (!mIsImageCaptureIntent) { - mSwitcher.setSwitch(SWITCH_CAMERA); - } - } - - private void checkStorage() { - if (ImageManager.isMediaScannerScanning(getContentResolver())) { - mPicturesRemaining = MenuHelper.NO_STORAGE_ERROR; - } else { - calculatePicturesRemaining(); - } - updateStorageHint(mPicturesRemaining); - } - - - private void showOnScreenSettings() { - if (mSettings == null) { - mSettings = new OnScreenSettings( - findViewById(R.id.camera_preview)); - CameraSettings helper = - new CameraSettings(this, mInitialParams); - mSettings.setPreferenceScreen(helper - .getPreferenceScreen(R.xml.camera_preferences)); - mSettings.setOnVisibilityChangedListener(this); - - String sceneMode = mParameters.getSceneMode(); - if (sceneMode == null - || Parameters.SCENE_MODE_AUTO.equals(sceneMode)) { - // If scene mode is auto, cancel override in settings - mSettings.overrideSettings(CameraSettings.KEY_FLASH_MODE, null); - mSettings.overrideSettings(CameraSettings.KEY_FOCUS_MODE, null); - mSettings.overrideSettings( - CameraSettings.KEY_WHITE_BALANCE, null); - } else { - // If scene mode is not auto, override the value in settings - mSettings.overrideSettings(CameraSettings.KEY_FLASH_MODE, - mParameters.getFlashMode()); - mSettings.overrideSettings(CameraSettings.KEY_FOCUS_MODE, - mParameters.getFocusMode()); - mSettings.overrideSettings(CameraSettings.KEY_WHITE_BALANCE, - mParameters.getWhiteBalance()); - } - } - - mSettings.setVisible(true); - } - - public void onClick(View v) { - switch (v.getId()) { - case R.id.btn_retake: - hidePostCaptureAlert(); - restartPreview(); - break; - case R.id.review_thumbnail: - if (isCameraIdle()) { - viewLastImage(); - } - break; - case R.id.btn_done: - doAttach(); - break; - case R.id.btn_cancel: - doCancel(); - } - } - - private Bitmap createCaptureBitmap(byte[] data) { - // This is really stupid...we just want to read the orientation in - // the jpeg header. - String filepath = ImageManager.getTempJpegPath(); - int degree = 0; - if (saveDataToFile(filepath, data)) { - degree = ImageManager.getExifOrientation(filepath); - new File(filepath).delete(); - } - - // Limit to 50k pixels so we can return it in the intent. - Bitmap bitmap = Util.makeBitmap(data, 50*1024); - bitmap = Util.rotate(bitmap, degree); - return bitmap; - } - - private void doAttach() { - if (mPausing) { - return; - } - - byte[] data = mImageCapture.getLastCaptureData(); - - if (mCropValue == null) { - // First handle the no crop case -- just return the value. If the - // caller specifies a "save uri" then write the data to it's - // stream. Otherwise, pass back a scaled down version of the bitmap - // directly in the extras. - if (mSaveUri != null) { - OutputStream outputStream = null; - try { - outputStream = mContentResolver.openOutputStream(mSaveUri); - outputStream.write(data); - outputStream.close(); - - setResult(RESULT_OK); - finish(); - } catch (IOException ex) { - // ignore exception - } finally { - Util.closeSilently(outputStream); - } - } else { - Bitmap bitmap = createCaptureBitmap(data); - setResult(RESULT_OK, - new Intent("inline-data").putExtra("data", bitmap)); - finish(); - } - } else { - // Save the image to a temp file and invoke the cropper - Uri tempUri = null; - FileOutputStream tempStream = null; - try { - File path = getFileStreamPath(sTempCropFilename); - path.delete(); - tempStream = openFileOutput(sTempCropFilename, 0); - tempStream.write(data); - tempStream.close(); - tempUri = Uri.fromFile(path); - } catch (FileNotFoundException ex) { - setResult(Activity.RESULT_CANCELED); - finish(); - return; - } catch (IOException ex) { - setResult(Activity.RESULT_CANCELED); - finish(); - return; - } finally { - Util.closeSilently(tempStream); - } - - Bundle newExtras = new Bundle(); - if (mCropValue.equals("circle")) { - newExtras.putString("circleCrop", "true"); - } - if (mSaveUri != null) { - newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri); - } else { - newExtras.putBoolean("return-data", true); - } - - Intent cropIntent = new Intent("com.android.camera.action.CROP"); - - cropIntent.setData(tempUri); - cropIntent.putExtras(newExtras); - - startActivityForResult(cropIntent, CROP_MSG); - } - } - - private void doCancel() { - setResult(RESULT_CANCELED, new Intent()); - finish(); - } - - public void onShutterButtonFocus(ShutterButton button, boolean pressed) { - if (mPausing) { - return; - } - switch (button.getId()) { - case R.id.shutter_button: - doFocus(pressed); - break; - } - } - - public void onShutterButtonClick(ShutterButton button) { - if (mPausing) { - return; - } - switch (button.getId()) { - case R.id.shutter_button: - doSnap(); - break; - } - } - - private OnScreenHint mStorageHint; - - private void updateStorageHint(int remaining) { - String noStorageText = null; - - if (remaining == MenuHelper.NO_STORAGE_ERROR) { - String state = Environment.getExternalStorageState(); - if (state == Environment.MEDIA_CHECKING || - ImageManager.isMediaScannerScanning(getContentResolver())) { - noStorageText = getString(R.string.preparing_sd); - } else { - noStorageText = getString(R.string.no_storage); - } - } else if (remaining < 1) { - noStorageText = getString(R.string.not_enough_space); - } - - if (noStorageText != null) { - if (mStorageHint == null) { - mStorageHint = OnScreenHint.makeText(this, noStorageText); - } else { - mStorageHint.setText(noStorageText); - } - mStorageHint.show(); - } else if (mStorageHint != null) { - mStorageHint.cancel(); - mStorageHint = null; - } - } - - private void installIntentFilter() { - // install an intent filter to receive SD card related events. - IntentFilter intentFilter = - new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); - intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); - intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); - intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); - intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING); - intentFilter.addDataScheme("file"); - registerReceiver(mReceiver, intentFilter); - mDidRegister = true; - } - - private void initializeFocusTone() { - // Initialize focus tone generator. - try { - mFocusToneGenerator = new ToneGenerator( - AudioManager.STREAM_SYSTEM, FOCUS_BEEP_VOLUME); - } catch (Throwable ex) { - Log.w(TAG, "Exception caught while creating tone generator: ", ex); - mFocusToneGenerator = null; - } - } - - private void readPreference() { - mRecordLocation = mPreferences.getBoolean( - "pref_camera_recordlocation_key", false); - mFocusMode = mPreferences.getString( - CameraSettings.KEY_FOCUS_MODE, - getString(R.string.pref_camera_focusmode_default)); - } - - @Override - public void onResume() { - super.onResume(); - - mPausing = false; - mJpegPictureCallbackTime = 0; - mImageCapture = new ImageCapture(); - - // Start the preview if it is not started. - if (!mPreviewing && !mStartPreviewFail) { - try { - startPreview(); - } catch (CameraHardwareException e) { - showCameraErrorAndFinish(); - return; - } - } - - if (mSurfaceHolder != null) { - // If first time initialization is not finished, put it in the - // message queue. - if (!mFirstTimeInitialized) { - mHandler.sendEmptyMessage(FIRST_TIME_INIT); - } else { - initializeSecondTime(); - } - } - keepScreenOnAwhile(); - } - - private static ImageManager.DataLocation dataLocation() { - return ImageManager.DataLocation.EXTERNAL; - } - - @Override - protected void onPause() { - mPausing = true; - stopPreview(); - // Close the camera now because other activities may need to use it. - closeCamera(); - resetScreenOn(); - - if (mSettings != null && mSettings.isVisible()) { - mSettings.setVisible(false); - } - - if (mFirstTimeInitialized) { - mOrientationListener.disable(); - mGpsIndicator.setMode(GPS_MODE_OFF); - if (!mIsImageCaptureIntent) { - mThumbController.storeData( - ImageManager.getLastImageThumbPath()); - } - hidePostCaptureAlert(); - } - - if (mDidRegister) { - unregisterReceiver(mReceiver); - mDidRegister = false; - } - stopReceivingLocationUpdates(); - - if (mFocusToneGenerator != null) { - mFocusToneGenerator.release(); - mFocusToneGenerator = null; - } - - if (mStorageHint != null) { - mStorageHint.cancel(); - mStorageHint = null; - } - - // If we are in an image capture intent and has taken - // a picture, we just clear it in onPause. - mImageCapture.clearLastData(); - mImageCapture = null; - - // This is necessary to make the ZoomButtonsController unregister - // its configuration change receiver. - if (mZoomButtons != null) { - mZoomButtons.setVisible(false); - } - - // Remove the messages in the event queue. - mHandler.removeMessages(RESTART_PREVIEW); - mHandler.removeMessages(FIRST_TIME_INIT); - - super.onPause(); - } - - @Override - protected void onActivityResult( - int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case CROP_MSG: { - Intent intent = new Intent(); - if (data != null) { - Bundle extras = data.getExtras(); - if (extras != null) { - intent.putExtras(extras); - } - } - setResult(resultCode, intent); - finish(); - - File path = getFileStreamPath(sTempCropFilename); - path.delete(); - - break; - } - } - } - - private boolean canTakePicture() { - return isCameraIdle() && mPreviewing && (mPicturesRemaining > 0); - } - - private void autoFocus() { - // Initiate autofocus only when preview is started and snapshot is not - // in progress. - if (canTakePicture()) { - Log.v(TAG, "Start autofocus."); - if (mZoomButtons != null) mZoomButtons.setVisible(false); - mFocusStartTime = System.currentTimeMillis(); - mFocusState = FOCUSING; - updateFocusIndicator(); - mCameraDevice.autoFocus(mAutoFocusCallback); - } - } - - private void cancelAutoFocus() { - // User releases half-pressed focus key. - if (mFocusState == FOCUSING || mFocusState == FOCUS_SUCCESS - || mFocusState == FOCUS_FAIL) { - Log.v(TAG, "Cancel autofocus."); - mCameraDevice.cancelAutoFocus(); - } - if (mFocusState != FOCUSING_SNAP_ON_FINISH) { - clearFocusState(); - } - } - - private void clearFocusState() { - mFocusState = FOCUS_NOT_STARTED; - updateFocusIndicator(); - } - - private void updateFocusIndicator() { - if (mFocusRectangle == null) return; - - if (mFocusState == FOCUSING || mFocusState == FOCUSING_SNAP_ON_FINISH) { - mFocusRectangle.showStart(); - } else if (mFocusState == FOCUS_SUCCESS) { - mFocusRectangle.showSuccess(); - } else if (mFocusState == FOCUS_FAIL) { - mFocusRectangle.showFail(); - } else { - mFocusRectangle.clear(); - } - } - - @Override - public void onBackPressed() { - if (!isCameraIdle()) { - // ignore backs while we're taking a picture - return; - } - super.onBackPressed(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_FOCUS: - if (mFirstTimeInitialized && event.getRepeatCount() == 0) { - doFocus(true); - } - return true; - case KeyEvent.KEYCODE_CAMERA: - if (mFirstTimeInitialized && event.getRepeatCount() == 0) { - doSnap(); - } - return true; - case KeyEvent.KEYCODE_DPAD_CENTER: - // If we get a dpad center event without any focused view, move - // the focus to the shutter button and press it. - if (mFirstTimeInitialized && event.getRepeatCount() == 0) { - // Start auto-focus immediately to reduce shutter lag. After - // the shutter button gets the focus, doFocus() will be - // called again but it is fine. - doFocus(true); - if (mShutterButton.isInTouchMode()) { - mShutterButton.requestFocusFromTouch(); - } else { - mShutterButton.requestFocus(); - } - mShutterButton.setPressed(true); - } - return true; - } - - return super.onKeyDown(keyCode, event); - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_FOCUS: - if (mFirstTimeInitialized) { - doFocus(false); - } - return true; - case KeyEvent.KEYCODE_MENU: - if (mIsImageCaptureIntent) { - showOnScreenSettings(); - return true; - } - break; - } - return super.onKeyUp(keyCode, event); - } - - private void doSnap() { - Log.v(TAG, "doSnap: mFocusState=" + mFocusState); - // If the user has half-pressed the shutter and focus is completed, we - // can take the photo right away. If the focus mode is infinity, we can - // also take the photo. - if (mFocusMode.equals(Parameters.FOCUS_MODE_INFINITY) - || (mFocusState == FOCUS_SUCCESS - || mFocusState == FOCUS_FAIL)) { - if (mZoomButtons != null) mZoomButtons.setVisible(false); - mImageCapture.onSnap(); - } else if (mFocusState == FOCUSING) { - // Half pressing the shutter (i.e. the focus button event) will - // already have requested AF for us, so just request capture on - // focus here. - mFocusState = FOCUSING_SNAP_ON_FINISH; - } else if (mFocusState == FOCUS_NOT_STARTED) { - // Focus key down event is dropped for some reasons. Just ignore. - } - } - - private void doFocus(boolean pressed) { - // Do the focus if the mode is not infinity. - if (!mFocusMode.equals(Parameters.FOCUS_MODE_INFINITY)) { - if (pressed) { // Focus key down. - autoFocus(); - } else { // Focus key up. - cancelAutoFocus(); - } - } - } - - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - // Make sure we have a surface in the holder before proceeding. - if (holder.getSurface() == null) { - Log.d(TAG, "holder.getSurface() == null"); - return; - } - - // The mCameraDevice will be null if it fails to connect to the camera - // hardware. In this case we will show a dialog and then finish the - // activity, so it's OK to ignore it. - if (mCameraDevice == null) return; - - mSurfaceHolder = holder; - - // Sometimes surfaceChanged is called after onPause. Ignore it. - if (mPausing || isFinishing()) return; - - // Set preview display if the surface is being created. Preview was - // already started. - if (holder.isCreating()) { - setPreviewDisplay(holder); - } - - // If first time initialization is not finished, send a message to do - // it later. We want to finish surfaceChanged as soon as possible to let - // user see preview first. - if (!mFirstTimeInitialized) { - mHandler.sendEmptyMessage(FIRST_TIME_INIT); - } else { - initializeSecondTime(); - } - } - - public void surfaceCreated(SurfaceHolder holder) { - } - - public void surfaceDestroyed(SurfaceHolder holder) { - stopPreview(); - mSurfaceHolder = null; - } - - private void closeCamera() { - if (mCameraDevice != null) { - CameraHolder.instance().release(); - mCameraDevice = null; - mPreviewing = false; - } - } - - private void ensureCameraDevice() throws CameraHardwareException { - if (mCameraDevice == null) { - mCameraDevice = CameraHolder.instance().open(); - mInitialParams = mCameraDevice.getParameters(); - } - } - - private void updateLastImage() { - IImageList list = ImageManager.makeImageList( - mContentResolver, - dataLocation(), - ImageManager.INCLUDE_IMAGES, - ImageManager.SORT_ASCENDING, - ImageManager.CAMERA_IMAGE_BUCKET_ID); - int count = list.getCount(); - if (count > 0) { - IImage image = list.getImageAt(count - 1); - Uri uri = image.fullSizeImageUri(); - mThumbController.setData(uri, image.miniThumbBitmap()); - } else { - mThumbController.setData(null, null); - } - list.close(); - } - - private void showCameraErrorAndFinish() { - Resources ress = getResources(); - Util.showFatalErrorAndFinish(Camera.this, - ress.getString(R.string.camera_error_title), - ress.getString(R.string.cannot_connect_camera)); - } - - private void restartPreview() { - // make sure the surfaceview fills the whole screen when previewing - try { - startPreview(); - } catch (CameraHardwareException e) { - showCameraErrorAndFinish(); - return; - } - - // Calculate this in advance of each shot so we don't add to shutter - // latency. It's true that someone else could write to the SD card in - // the mean time and fill it, but that could have happened between the - // shutter press and saving the JPEG too. - calculatePicturesRemaining(); - } - - private void setPreviewDisplay(SurfaceHolder holder) { - try { - mCameraDevice.setPreviewDisplay(holder); - } catch (Throwable ex) { - closeCamera(); - throw new RuntimeException("setPreviewDisplay failed", ex); - } - } - - private void startPreview() throws CameraHardwareException { - if (mPausing || isFinishing()) return; - - ensureCameraDevice(); - - // If we're previewing already, stop the preview first (this will blank - // the screen). - if (mPreviewing) stopPreview(); - - setPreviewDisplay(mSurfaceHolder); - setCameraParameters(); - - final long wallTimeStart = SystemClock.elapsedRealtime(); - final long threadTimeStart = Debug.threadCpuTimeNanos(); - - // Set one shot preview callback for latency measurement. - mCameraDevice.setOneShotPreviewCallback(mOneShotPreviewCallback); - mCameraDevice.setErrorCallback(mErrorCallback); - - try { - Log.v(TAG, "startPreview"); - mCameraDevice.startPreview(); - } catch (Throwable ex) { - closeCamera(); - throw new RuntimeException("startPreview failed", ex); - } - mPreviewing = true; - mStatus = IDLE; - - long threadTimeEnd = Debug.threadCpuTimeNanos(); - long wallTimeEnd = SystemClock.elapsedRealtime(); - if ((wallTimeEnd - wallTimeStart) > 3000) { - Log.w(TAG, "startPreview() to " + (wallTimeEnd - wallTimeStart) - + " ms. Thread time was" - + (threadTimeEnd - threadTimeStart) / 1000000 + " ms."); - } - } - - private void stopPreview() { - if (mCameraDevice != null && mPreviewing) { - Log.v(TAG, "stopPreview"); - mCameraDevice.stopPreview(); - } - mPreviewing = false; - // If auto focus was in progress, it would have been canceled. - clearFocusState(); - } - - private Size getOptimalPreviewSize(List<Size> sizes, double targetRatio) { - final double ASPECT_TOLERANCE = 0.05; - if (sizes == null) return null; - - Size optimalSize = null; - double minDiff = Double.MAX_VALUE; - - // Because of bugs of overlay and layout, we sometimes will try to - // layout the viewfinder in the portrait orientation and thus get the - // wrong size of mSurfaceView. When we change the preview size, the - // new overlay will be created before the old one closed, which causes - // an exception. For now, just get the screen size - - Display display = getWindowManager().getDefaultDisplay(); - int targetHeight = Math.min(display.getHeight(), display.getWidth()); - - if (targetHeight <= 0) { - // We don't know the size of SurefaceView, use screen height - WindowManager windowManager = (WindowManager) - getSystemService(Context.WINDOW_SERVICE); - targetHeight = windowManager.getDefaultDisplay().getHeight(); - } - - // Try to find an size match aspect ratio and size - for (Size size : sizes) { - double ratio = (double) size.width / size.height; - if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; - if (Math.abs(size.height - targetHeight) < minDiff) { - optimalSize = size; - minDiff = Math.abs(size.height - targetHeight); - } - } - - // Cannot find the one match the aspect ratio, ignore the requirement - if (optimalSize == null) { - Log.v(TAG, "No preview size match the aspect ratio"); - minDiff = Double.MAX_VALUE; - for (Size size : sizes) { - if (Math.abs(size.height - targetHeight) < minDiff) { - optimalSize = size; - minDiff = Math.abs(size.height - targetHeight); - } - } - } - Log.v(TAG, String.format( - "Optimal preview size is %sx%s", - optimalSize.width, optimalSize.height)); - return optimalSize; - } - - private static boolean isSupported(String value, List<String> supported) { - return supported == null ? false : supported.indexOf(value) >= 0; - } - - private void setCameraParameters() { - mParameters = mCameraDevice.getParameters(); - - // Since change scene mode may change supported values, - // Set scene mode first, - String sceneMode = mPreferences.getString( - CameraSettings.KEY_SCENE_MODE, - getString(R.string.pref_camera_scenemode_default)); - if (isSupported(sceneMode, mParameters.getSupportedSceneModes())) { - if (!mParameters.getSceneMode().equals(sceneMode)) { - mParameters.setSceneMode(sceneMode); - mCameraDevice.setParameters(mParameters); - - // Setting scene mode will change the settings of flash mode, white - // balance, and focus mode. So read back here, so that we know - // what're the settings - mParameters = mCameraDevice.getParameters(); - } - } else { - sceneMode = mParameters.getSceneMode(); - if (sceneMode == null) { - sceneMode = Parameters.SCENE_MODE_AUTO; - } - } - - // Reset preview frame rate to the maximum because it may be lowered by - // video camera application. - List<Integer> frameRates = mParameters.getSupportedPreviewFrameRates(); - if (frameRates != null) { - Integer max = Collections.max(frameRates); - mParameters.setPreviewFrameRate(max); - } - - // Set picture size. - String pictureSize = mPreferences.getString( - CameraSettings.KEY_PICTURE_SIZE, null); - if (pictureSize == null) { - CameraSettings.initialCameraPictureSize(this, mParameters); - } else { - List<Size> supported = mParameters.getSupportedPictureSizes(); - CameraSettings.setCameraPictureSize( - pictureSize, supported, mParameters); - } - - // Set the preview frame aspect ratio according to the picture size. - Size size = mParameters.getPictureSize(); - PreviewFrameLayout frameLayout = - (PreviewFrameLayout) findViewById(R.id.frame_layout); - frameLayout.setAspectRatio((double) size.width / size.height); - - // Set a preview size that is closest to the viewfinder height and has - // the right aspect ratio. - List<Size> sizes = mParameters.getSupportedPreviewSizes(); - Size optimalSize = getOptimalPreviewSize( - sizes, (double) size.width / size.height); - if (optimalSize != null) { - mParameters.setPreviewSize(optimalSize.width, optimalSize.height); - } - - // Set JPEG quality. - String jpegQuality = mPreferences.getString( - CameraSettings.KEY_JPEG_QUALITY, - getString(R.string.pref_camera_jpegquality_default)); - mParameters.setJpegQuality(Integer.parseInt(jpegQuality)); - - // For the following settings, we need to check if the settings are - // still supported by latest driver, if not, ignore the settings. - - // Set color effect parameter. - String colorEffect = mPreferences.getString( - CameraSettings.KEY_COLOR_EFFECT, - getString(R.string.pref_camera_coloreffect_default)); - if (isSupported(colorEffect, mParameters.getSupportedColorEffects())) { - mParameters.setColorEffect(colorEffect); - } - - // If scene mode is set, we cannot set flash mode, white balance, and - // focus mode, instead, we read it from driver - String flashMode; - String whiteBalance; - if (!Parameters.SCENE_MODE_AUTO.equals(sceneMode)) { - flashMode = mParameters.getFlashMode(); - whiteBalance = mParameters.getWhiteBalance(); - mFocusMode = mParameters.getFocusMode(); - if (mSettings != null) { - mSettings.overrideSettings( - CameraSettings.KEY_FLASH_MODE, flashMode); - mSettings.overrideSettings( - CameraSettings.KEY_WHITE_BALANCE, whiteBalance); - mSettings.overrideSettings( - CameraSettings.KEY_FOCUS_MODE, mFocusMode); - } - } else { - if (mSettings != null) { - mSettings.overrideSettings(CameraSettings.KEY_FLASH_MODE, null); - mSettings.overrideSettings(CameraSettings.KEY_FOCUS_MODE, null); - mSettings.overrideSettings( - CameraSettings.KEY_WHITE_BALANCE, null); - } - - // Set flash mode. - flashMode = mPreferences.getString( - CameraSettings.KEY_FLASH_MODE, - getString(R.string.pref_camera_flashmode_default)); - List<String> supportedFlash = mParameters.getSupportedFlashModes(); - if (isSupported(flashMode, supportedFlash)) { - mParameters.setFlashMode(flashMode); - } else { - flashMode = mParameters.getFlashMode(); - if (flashMode == null) { - flashMode = NO_FLASH_MODE; - } - } - - // Set white balance parameter. - whiteBalance = mPreferences.getString( - CameraSettings.KEY_WHITE_BALANCE, - getString(R.string.pref_camera_whitebalance_default)); - if (isSupported(whiteBalance, - mParameters.getSupportedWhiteBalance())) { - mParameters.setWhiteBalance(whiteBalance); - } else { - whiteBalance = mParameters.getWhiteBalance(); - if (whiteBalance == null) { - whiteBalance = Parameters.WHITE_BALANCE_AUTO; - } - } - - // Set focus mode. - mFocusMode = mPreferences.getString( - CameraSettings.KEY_FOCUS_MODE, - getString(R.string.pref_camera_focusmode_default)); - if (isSupported(mFocusMode, mParameters.getSupportedFocusModes())) { - mParameters.setFocusMode(mFocusMode); - } else { - mFocusMode = mParameters.getFocusMode(); - if (mFocusMode == null) { - mFocusMode = Parameters.FOCUS_MODE_AUTO; - } - } - - mCameraDevice.setParameters(mParameters); - } - - // We post the runner because this function can be called from - // non-UI thread (i.e., startPreviewThread). - final String finalWhiteBalance = whiteBalance; - final String finalFlashMode = flashMode; - final String finalSceneMode = - Parameters.SCENE_MODE_AUTO.equals(sceneMode) - ? SCENE_MODE_OFF - : SCENE_MODE_ON; - - mHandler.post(new Runnable() { - public void run() { - mFocusIndicator.setMode(mFocusMode); - mWhitebalanceIndicator.setMode(finalWhiteBalance); - mSceneModeIndicator.setMode(finalSceneMode); - mFlashIndicator.setMode(finalFlashMode); - } - }); - } - - private void gotoGallery() { - MenuHelper.gotoCameraImageGallery(this); - } - - private void viewLastImage() { - if (mThumbController.isUriValid()) { - Uri targetUri = mThumbController.getUri(); - targetUri = targetUri.buildUpon().appendQueryParameter( - "bucketId", ImageManager.CAMERA_IMAGE_BUCKET_ID).build(); - Intent intent = new Intent(this, ReviewImage.class); - intent.setData(targetUri); - intent.putExtra(MediaStore.EXTRA_FULL_SCREEN, true); - intent.putExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, true); - intent.putExtra("com.android.camera.ReviewMode", true); - try { - startActivity(intent); - } catch (ActivityNotFoundException ex) { - Log.e(TAG, "review image fail", ex); - } - } else { - Log.e(TAG, "Can't view last image."); - } - } - - private void startReceivingLocationUpdates() { - if (mLocationManager != null) { - try { - mLocationManager.requestLocationUpdates( - LocationManager.NETWORK_PROVIDER, - 1000, - 0F, - mLocationListeners[1]); - } catch (java.lang.SecurityException ex) { - Log.i(TAG, "fail to request location update, ignore", ex); - } catch (IllegalArgumentException ex) { - Log.d(TAG, "provider does not exist " + ex.getMessage()); - } - try { - mLocationManager.requestLocationUpdates( - LocationManager.GPS_PROVIDER, - 1000, - 0F, - mLocationListeners[0]); - } catch (java.lang.SecurityException ex) { - Log.i(TAG, "fail to request location update, ignore", ex); - } catch (IllegalArgumentException ex) { - Log.d(TAG, "provider does not exist " + ex.getMessage()); - } - } - } - - private void stopReceivingLocationUpdates() { - if (mLocationManager != null) { - for (int i = 0; i < mLocationListeners.length; i++) { - try { - mLocationManager.removeUpdates(mLocationListeners[i]); - } catch (Exception ex) { - Log.i(TAG, "fail to remove location listners, ignore", ex); - } - } - } - } - - private Location getCurrentLocation() { - // go in best to worst order - for (int i = 0; i < mLocationListeners.length; i++) { - Location l = mLocationListeners[i].current(); - if (l != null) return l; - } - return null; - } - - private boolean isCameraIdle() { - return mStatus == IDLE && mFocusState == FOCUS_NOT_STARTED; - } - - private boolean isImageCaptureIntent() { - String action = getIntent().getAction(); - return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action)); - } - - private void setupCaptureParams() { - Bundle myExtras = getIntent().getExtras(); - if (myExtras != null) { - mSaveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); - mCropValue = myExtras.getString("crop"); - } - } - - private void showPostCaptureAlert() { - if (mIsImageCaptureIntent) { - findViewById(R.id.shutter_button).setVisibility(View.INVISIBLE); - int[] pickIds = {R.id.btn_retake, R.id.btn_done}; - for (int id : pickIds) { - View button = findViewById(id); - ((View) button.getParent()).setVisibility(View.VISIBLE); - } - } - } - - private void hidePostCaptureAlert() { - if (mIsImageCaptureIntent) { - findViewById(R.id.shutter_button).setVisibility(View.VISIBLE); - int[] pickIds = {R.id.btn_retake, R.id.btn_done}; - for (int id : pickIds) { - View button = findViewById(id); - ((View) button.getParent()).setVisibility(View.GONE); - } - } - } - - private int calculatePicturesRemaining() { - mPicturesRemaining = MenuHelper.calculatePicturesRemaining(); - return mPicturesRemaining; - } - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - // Only show the menu when camera is idle. - for (int i = 0; i < menu.size(); i++) { - menu.getItem(i).setVisible(isCameraIdle()); - } - - return true; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - - if (mIsImageCaptureIntent) { - // No options menu for attach mode. - return false; - } else { - addBaseMenuItems(menu); - } - return true; - } - - private void addBaseMenuItems(Menu menu) { - MenuItem gallery = menu.add(Menu.NONE, Menu.NONE, - MenuHelper.POSITION_GOTO_GALLERY, - R.string.camera_gallery_photos_text) - .setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - gotoGallery(); - return true; - } - }); - gallery.setIcon(android.R.drawable.ic_menu_gallery); - mGalleryItems.add(gallery); - - MenuItem item = menu.add(Menu.NONE, Menu.NONE, - MenuHelper.POSITION_CAMERA_SETTING, R.string.settings) - .setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - showOnScreenSettings(); - return true; - } - }); - item.setIcon(android.R.drawable.ic_menu_preferences); - } - - public boolean onSwitchChanged(Switcher source, boolean onOff) { - if (onOff == SWITCH_VIDEO) { - if (!isCameraIdle()) return false; - MenuHelper.gotoVideoMode(this); - finish(); - } - return true; - } - - public void onSharedPreferenceChanged( - SharedPreferences preferences, String key) { - // ignore the events after "onPause()" - if (mPausing) return; - - if (CameraSettings.KEY_RECORD_LOCATION.equals(key)) { - mRecordLocation = preferences.getBoolean(key, false); - if (mRecordLocation) { - startReceivingLocationUpdates(); - } else { - stopReceivingLocationUpdates(); - } - } else { - // All preferences except RECORD_LOCATION are camera parameters. - // Call setCameraParameters to take effect now. - setCameraParameters(); - } - } - - @Override - public void onUserInteraction() { - super.onUserInteraction(); - keepScreenOnAwhile(); - } - - private void resetScreenOn() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - - private void keepScreenOnAwhile() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); - } -} - -class FocusRectangle extends View { - - @SuppressWarnings("unused") - private static final String TAG = "FocusRectangle"; - - public FocusRectangle(Context context, AttributeSet attrs) { - super(context, attrs); - } - - private void setDrawable(int resid) { - setBackgroundDrawable(getResources().getDrawable(resid)); - } - - public void showStart() { - setDrawable(R.drawable.focus_focusing); - } - - public void showSuccess() { - setDrawable(R.drawable.focus_focused); - } - - public void showFail() { - setDrawable(R.drawable.focus_focus_failed); - } - - public void clear() { - setBackgroundDrawable(null); - } -} diff --git a/src/com/android/camera/CameraButtonIntentReceiver.java b/src/com/android/camera/CameraButtonIntentReceiver.java deleted file mode 100644 index 4153104..0000000 --- a/src/com/android/camera/CameraButtonIntentReceiver.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2007 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.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -public class CameraButtonIntentReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - // Try to get the camera hardware - CameraHolder holder = CameraHolder.instance(); - if (holder.tryOpen() == null) return; - - // We are going to launch the camera, so hold the camera for later use - holder.keep(); - holder.release(); - Intent i = new Intent(Intent.ACTION_MAIN); - i.setClass(context, Camera.class); - i.addCategory(Intent.CATEGORY_LAUNCHER); - i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_CLEAR_TOP); - context.startActivity(i); - } -} diff --git a/src/com/android/camera/CameraHardwareException.java b/src/com/android/camera/CameraHardwareException.java deleted file mode 100644 index a975cbd..0000000 --- a/src/com/android/camera/CameraHardwareException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2009 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; - -public class CameraHardwareException extends Exception { - private static final long serialVersionUID = -4453804913829319918L; - - public CameraHardwareException() { - } - - public CameraHardwareException(Throwable t) { - super(t); - } -} diff --git a/src/com/android/camera/CameraHolder.java b/src/com/android/camera/CameraHolder.java deleted file mode 100644 index 7fd2b4e..0000000 --- a/src/com/android/camera/CameraHolder.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2009 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 static com.android.camera.Util.Assert; - -import android.hardware.Camera.Parameters; -import android.os.Build; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import java.io.IOException; - -// -// CameraHolder is used to hold an android.hardware.Camera instance. -// -// The open() and release() calls are similar to the ones in -// android.hardware.Camera. The difference is if keep() is called before -// release(), CameraHolder will try to hold the android.hardware.Camera -// instance for a while, so if open() call called soon after, we can avoid -// the cost of open() in android.hardware.Camera. -// -// This is used in switching between Camera and VideoCamera activities. -// -public class CameraHolder { - private static final String TAG = "CameraHolder"; - private android.hardware.Camera mCameraDevice; - private long mKeepBeforeTime = 0; // Keep the Camera before this time. - private final Handler mHandler; - private int mUsers = 0; // number of open() - number of release() - - // We store the camera parameters when we actually open the device, - // so we can restore them in the subsequent open() requests by the user. - // This prevents the parameters set by the Camera activity used by - // the VideoCamera activity inadvertently. - private Parameters mParameters; - - // Use a singleton. - private static CameraHolder sHolder; - public static synchronized CameraHolder instance() { - if (sHolder == null) { - sHolder = new CameraHolder(); - } - return sHolder; - } - - private static final int RELEASE_CAMERA = 1; - private class MyHandler extends Handler { - MyHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch(msg.what) { - case RELEASE_CAMERA: - releaseCamera(); - break; - } - } - } - - private CameraHolder() { - HandlerThread ht = new HandlerThread("CameraHolder"); - ht.start(); - mHandler = new MyHandler(ht.getLooper()); - } - - public synchronized android.hardware.Camera open() - throws CameraHardwareException { - Assert(mUsers == 0); - if (mCameraDevice == null) { - try { - mCameraDevice = android.hardware.Camera.open(); - } catch (RuntimeException e) { - Log.e(TAG, "fail to connect Camera", e); - throw new CameraHardwareException(e); - } - mParameters = mCameraDevice.getParameters(); - } else { - try { - mCameraDevice.reconnect(); - } catch (IOException e) { - Log.e(TAG, "reconnect failed."); - throw new CameraHardwareException(e); - } - mCameraDevice.setParameters(mParameters); - } - ++mUsers; - mHandler.removeMessages(RELEASE_CAMERA); - mKeepBeforeTime = 0; - return mCameraDevice; - } - - /** - * Tries to open the hardware camera. If the camera is being used or - * unavailable then return {@code null}. - */ - public synchronized android.hardware.Camera tryOpen() { - try { - return mUsers == 0 ? open() : null; - } catch (CameraHardwareException e) { - // In eng build, we throw the exception so that test tool - // can detect it and report it - if ("eng".equals(Build.TYPE)) { - throw new RuntimeException(e); - } - return null; - } - } - - public synchronized void release() { - Assert(mUsers == 1); - --mUsers; - mCameraDevice.stopPreview(); - releaseCamera(); - } - - private synchronized void releaseCamera() { - Assert(mUsers == 0); - Assert(mCameraDevice != null); - long now = System.currentTimeMillis(); - if (now < mKeepBeforeTime) { - mHandler.sendEmptyMessageDelayed(RELEASE_CAMERA, - mKeepBeforeTime - now); - return; - } - mCameraDevice.release(); - mCameraDevice = null; - } - - public synchronized void keep() { - // We allow (mUsers == 0) for the convenience of the calling activity. - // The activity may not have a chance to call open() before the user - // choose the menu item to switch to another activity. - Assert(mUsers == 1 || mUsers == 0); - // Keep the camera instance for 3 seconds. - mKeepBeforeTime = System.currentTimeMillis() + 3000; - } -} diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java deleted file mode 100644 index 46f1ed5..0000000 --- a/src/com/android/camera/CameraSettings.java +++ /dev/null @@ -1,258 +0,0 @@ -package com.android.camera; - -import com.android.gallery.R; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.graphics.drawable.Drawable; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.Size; -import android.os.SystemProperties; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceGroup; -import android.preference.PreferenceManager; -import android.preference.PreferenceScreen; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; - -public class CameraSettings { - private static final int FIRST_REQUEST_CODE = 100; - private static final int NOT_FOUND = -1; - - public static final String KEY_VERSION = "pref_version_key"; - public static final String KEY_RECORD_LOCATION = - "pref_camera_recordlocation_key"; - public static final String KEY_VIDEO_QUALITY = - "pref_camera_videoquality_key"; - public static final String KEY_VIDEO_DURATION = - "pref_camera_video_duration_key"; - public static final String KEY_PICTURE_SIZE = "pref_camera_picturesize_key"; - public static final String KEY_JPEG_QUALITY = "pref_camera_jpegquality_key"; - public static final String KEY_FOCUS_MODE = "pref_camera_focusmode_key"; - public static final String KEY_FLASH_MODE = "pref_camera_flashmode_key"; - public static final String KEY_COLOR_EFFECT = "pref_camera_coloreffect_key"; - public static final String KEY_WHITE_BALANCE = - "pref_camera_whitebalance_key"; - public static final String KEY_SCENE_MODE = "pref_camera_scenemode_key"; - - public static final int CURRENT_VERSION = 1; - - // max mms video duration in seconds. - public static final int MMS_VIDEO_DURATION = - SystemProperties.getInt("ro.media.enc.lprof.duration", 60); - - public static final boolean DEFAULT_VIDEO_QUALITY_VALUE = true; - - // MMS video length - public static final int DEFAULT_VIDEO_DURATION_VALUE = -1; - - @SuppressWarnings("unused") - private static final String TAG = "CameraSettings"; - - private final Context mContext; - private final Parameters mParameters; - private final PreferenceManager mManager; - - public CameraSettings(Activity activity, Parameters parameters) { - mContext = activity; - mParameters = parameters; - mManager = new PreferenceManager(activity, FIRST_REQUEST_CODE); - } - - public PreferenceScreen getPreferenceScreen(int preferenceRes) { - PreferenceScreen screen = mManager.createPreferenceScreen(mContext); - mManager.inflateFromResource(mContext, preferenceRes, screen); - initPreference(screen); - return screen; - } - - public static void initialCameraPictureSize( - Context context, Parameters parameters) { - // When launching the camera app first time, we will set the picture - // size to the first one in the list defined in "arrays.xml" and is also - // supported by the driver. - List<Size> supported = parameters.getSupportedPictureSizes(); - if (supported == null) return; - for (String candidate : context.getResources().getStringArray( - R.array.pref_camera_picturesize_entryvalues)) { - if (setCameraPictureSize(candidate, supported, parameters)) { - SharedPreferences.Editor editor = PreferenceManager - .getDefaultSharedPreferences(context).edit(); - editor.putString(KEY_PICTURE_SIZE, candidate); - editor.commit(); - return; - } - } - } - - public static void removePreferenceFromScreen( - PreferenceScreen screen, String key) { - Preference pref = screen.findPreference(key); - if (pref == null) { - Log.i(TAG, "No preference found based the key : " + key); - throw new IllegalArgumentException(); - } else { - removePreference(screen, pref); - } - } - - public static boolean setCameraPictureSize( - String candidate, List<Size> supported, Parameters parameters) { - int index = candidate.indexOf('x'); - if (index == NOT_FOUND) return false; - int width = Integer.parseInt(candidate.substring(0, index)); - int height = Integer.parseInt(candidate.substring(index + 1)); - for (Size size: supported) { - if (size.width == width && size.height == height) { - parameters.setPictureSize(width, height); - return true; - } - } - return false; - } - - private void initPreference(PreferenceScreen screen) { - ListPreference videoDuration = - (ListPreference) screen.findPreference(KEY_VIDEO_DURATION); - ListPreference pictureSize = - (ListPreference) screen.findPreference(KEY_PICTURE_SIZE); - ListPreference whiteBalance = - (ListPreference) screen.findPreference(KEY_WHITE_BALANCE); - ListPreference colorEffect = - (ListPreference) screen.findPreference(KEY_COLOR_EFFECT); - ListPreference sceneMode = - (ListPreference) screen.findPreference(KEY_SCENE_MODE); - ListPreference flashMode = - (ListPreference) screen.findPreference(KEY_FLASH_MODE); - ListPreference focusMode = - (ListPreference) screen.findPreference(KEY_FOCUS_MODE); - - // Since the screen could be loaded from different resources, we need - // to check if the preference is available here - if (videoDuration != null) { - // Modify video duration settings. - // The first entry is for MMS video duration, and we need to fill - // in the device-dependent value (in seconds). - CharSequence[] entries = videoDuration.getEntries(); - entries[0] = String.format( - entries[0].toString(), MMS_VIDEO_DURATION); - } - - // Filter out unsupported settings / options - if (pictureSize != null) { - filterUnsupportedOptions(screen, pictureSize, sizeListToStringList( - mParameters.getSupportedPictureSizes())); - } - if (whiteBalance != null) { - filterUnsupportedOptions(screen, - whiteBalance, mParameters.getSupportedWhiteBalance()); - } - if (colorEffect != null) { - filterUnsupportedOptions(screen, - colorEffect, mParameters.getSupportedColorEffects()); - } - if (sceneMode != null) { - filterUnsupportedOptions(screen, - sceneMode, mParameters.getSupportedSceneModes()); - } - if (flashMode != null) { - filterUnsupportedOptions(screen, - flashMode, mParameters.getSupportedFlashModes()); - } - if (focusMode != null) { - filterUnsupportedOptions(screen, - focusMode, mParameters.getSupportedFocusModes()); - } - } - - private static boolean removePreference(PreferenceGroup group, - Preference remove) { - if (group.removePreference(remove)) return true; - - for (int i = 0; i < group.getPreferenceCount(); i++) { - final Preference child = group.getPreference(i); - if (child instanceof PreferenceGroup) { - if (removePreference((PreferenceGroup) child, remove)) { - return true; - } - } - } - return false; - } - - private void filterUnsupportedOptions(PreferenceScreen screen, - ListPreference pref, List<String> supported) { - - CharSequence[] allEntries = pref.getEntries(); - - // Remove the preference if the parameter is not supported or there is - // only one options for the settings. - if (supported == null || supported.size() <= 1) { - removePreference(screen, pref); - return; - } - - CharSequence[] allEntryValues = pref.getEntryValues(); - Drawable[] allIcons = (pref instanceof IconListPreference) - ? ((IconListPreference) pref).getIcons() - : null; - ArrayList<CharSequence> entries = new ArrayList<CharSequence>(); - ArrayList<CharSequence> entryValues = new ArrayList<CharSequence>(); - ArrayList<Drawable> icons = - allIcons == null ? null : new ArrayList<Drawable>(); - for (int i = 0, len = allEntryValues.length; i < len; i++) { - if (supported.indexOf(allEntryValues[i].toString()) != NOT_FOUND) { - entries.add(allEntries[i]); - entryValues.add(allEntryValues[i]); - if (allIcons != null) icons.add(allIcons[i]); - } - } - - // Set entries and entry values to list preference. - int size = entries.size(); - pref.setEntries(entries.toArray(new CharSequence[size])); - pref.setEntryValues(entryValues.toArray(new CharSequence[size])); - if (allIcons != null) { - ((IconListPreference) pref) - .setIcons(icons.toArray(new Drawable[size])); - } - - // Set the value to the first entry if it is invalid. - String value = pref.getValue(); - if (pref.findIndexOfValue(value) == NOT_FOUND) { - pref.setValueIndex(0); - } - } - - private static List<String> sizeListToStringList(List<Size> sizes) { - ArrayList<String> list = new ArrayList<String>(); - for (Size size : sizes) { - list.add(String.format("%dx%d", size.width, size.height)); - } - return list; - } - - public static void upgradePreferences(SharedPreferences pref) { - int version; - try { - version = pref.getInt(KEY_VERSION, 0); - } catch (Exception ex) { - version = 0; - } - if (version == CURRENT_VERSION) return; - - SharedPreferences.Editor editor = pref.edit(); - if (version == 0) { - // For old version, change 1 to 10 for video duration preference. - if (pref.getString(KEY_VIDEO_DURATION, "1").equals("1")) { - editor.putString(KEY_VIDEO_DURATION, "10"); - } - } - editor.putInt(KEY_VERSION, CURRENT_VERSION); - editor.commit(); - } -} diff --git a/src/com/android/camera/DrmWallpaper.java b/src/com/android/camera/DrmWallpaper.java deleted file mode 100644 index 643b876..0000000 --- a/src/com/android/camera/DrmWallpaper.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2007 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.Intent; - -/** - * Wallpaper picker for DRM images. This just redirects to the standard pick - * action. - */ -public class DrmWallpaper extends Wallpaper { - - @Override - protected void formatIntent(Intent intent) { - super.formatIntent(intent); - intent.putExtra("pick-drm", true); - } -} diff --git a/src/com/android/camera/IconIndicator.java b/src/com/android/camera/IconIndicator.java deleted file mode 100644 index e180a3d..0000000 --- a/src/com/android/camera/IconIndicator.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2009 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 com.android.gallery.R; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.widget.ImageView; - -public class IconIndicator extends ImageView { - - private Drawable[] mIcons; - private CharSequence[] mModes; - - public IconIndicator(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.IconIndicator, defStyle, 0); - Drawable icons[] = loadIcons(context.getResources(), - a.getResourceId(R.styleable.IconIndicator_icons, 0)); - CharSequence modes[] = - a.getTextArray(R.styleable.IconIndicator_modes); - a.recycle(); - - setModesAndIcons(modes, icons); - setImageDrawable(mIcons.length > 0 ? mIcons[0]: null); - } - - public IconIndicator(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - private Drawable[] loadIcons(Resources resources, int iconsId) { - TypedArray array = resources.obtainTypedArray(iconsId); - int n = array.length(); - Drawable drawable[] = new Drawable[n]; - for (int i = 0; i < n; ++i) { - int id = array.getResourceId(i, 0); - drawable[i] = id == 0 ? null : resources.getDrawable(id); - } - array.recycle(); - return drawable; - } - - private void setModesAndIcons(CharSequence[] modes, Drawable icons[]) { - if (modes.length != icons.length || icons.length == 0) { - throw new IllegalArgumentException(); - } - mIcons = icons; - mModes = modes; - } - - public void setMode(String mode) { - for (int i = 0, n = mModes.length; i < n; ++i) { - if (mModes[i].equals(mode)) { - setImageDrawable(mIcons[i]); - return; - } - } - throw new IllegalArgumentException("unknown mode: " + mode); - } -} diff --git a/src/com/android/camera/IconListPreference.java b/src/com/android/camera/IconListPreference.java deleted file mode 100644 index 6e5d8d8..0000000 --- a/src/com/android/camera/IconListPreference.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2009 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 com.android.gallery.R; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.preference.ListPreference; -import android.util.AttributeSet; - -public class IconListPreference extends ListPreference { - private Drawable mIcons[]; - private Resources mResources; - - public IconListPreference(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.IconListPreference, 0, 0); - mResources = context.getResources(); - setIcons(a.getResourceId(R.styleable.IconListPreference_icons, 0)); - a.recycle(); - } - - public Drawable[] getIcons() { - return mIcons; - } - - private void setIcons(int iconsRes) { - TypedArray array = mResources.obtainTypedArray(iconsRes); - int n = array.length(); - Drawable drawable[] = new Drawable[n]; - for (int i = 0; i < n; ++i) { - int id = array.getResourceId(i, 0); - drawable[i] = id == 0 ? null : mResources.getDrawable(id); - } - array.recycle(); - mIcons = drawable; - } - - public void setIcons(Drawable[] icons) { - mIcons = icons; - } -} diff --git a/src/com/android/camera/ImageManager.java b/src/com/android/camera/ImageManager.java index f2c931d..04b7bd2 100644 --- a/src/com/android/camera/ImageManager.java +++ b/src/com/android/camera/ImageManager.java @@ -161,29 +161,6 @@ public class ImageManager { } } - public static int roundOrientation(int orientationInput) { - int orientation = orientationInput; - if (orientation == -1) { - orientation = 0; - } - - orientation = orientation % 360; - int retVal; - if (orientation < (0 * 90) + 45) { - retVal = 0; - } else if (orientation < (1 * 90) + 45) { - retVal = 90; - } else if (orientation < (2 * 90) + 45) { - retVal = 180; - } else if (orientation < (3 * 90) + 45) { - retVal = 270; - } else { - retVal = 0; - } - - return retVal; - } - /** * @return true if the mimetype is an image mimetype. */ @@ -216,12 +193,6 @@ public class ImageManager { return (image instanceof VideoObject); } - public static void setImageSize(ContentResolver cr, Uri uri, long size) { - ContentValues values = new ContentValues(); - values.put(Images.Media.SIZE, size); - cr.update(uri, values, null, null); - } - // // Stores a bitmap or a jpeg byte array to a file (using the specified // directory and filename). Also add an entry to the media store for @@ -559,19 +530,4 @@ public class ImageManager { return result; } - - public static String getLastImageThumbPath() { - return Environment.getExternalStorageDirectory().toString() + - "/DCIM/.thumbnails/image_last_thumb"; - } - - public static String getLastVideoThumbPath() { - return Environment.getExternalStorageDirectory().toString() + - "/DCIM/.thumbnails/video_last_thumb"; - } - - public static String getTempJpegPath() { - return Environment.getExternalStorageDirectory().toString() + - "/DCIM/.tempjpeg"; - } } diff --git a/src/com/android/camera/MenuHelper.java b/src/com/android/camera/MenuHelper.java index 055025a..2d1eb4a 100644 --- a/src/com/android/camera/MenuHelper.java +++ b/src/com/android/camera/MenuHelper.java @@ -864,10 +864,6 @@ public class MenuHelper { deleteImpl(activity, onDelete, true); } - static void deleteVideo(Activity activity, Runnable onDelete) { - deleteImpl(activity, onDelete, false); - } - static void deleteImage( Activity activity, Runnable onDelete, IImage image) { deleteImpl(activity, onDelete, ImageManager.isImage(image)); @@ -923,54 +919,6 @@ public class MenuHelper { .show(); } - private static void startCameraActivity(Activity activity, String action) { - Intent intent = new Intent(action); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); - - // Keep the camera instance for a while. - // This avoids re-opening the camera and saves time. - CameraHolder.instance().keep(); - - activity.startActivity(intent); - } - - public static void gotoVideoMode(Activity activity) { - startCameraActivity(activity, MediaStore.INTENT_ACTION_VIDEO_CAMERA); - } - - public static void gotoCameraMode(Activity activity) { - startCameraActivity( - activity, MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); - } - - public static void gotoCameraImageGallery(Activity activity) { - gotoGallery(activity, R.string.gallery_camera_bucket_name, - ImageManager.INCLUDE_IMAGES); - } - - public static void gotoCameraVideoGallery(Activity activity) { - gotoGallery(activity, R.string.gallery_camera_videos_bucket_name, - ImageManager.INCLUDE_VIDEOS); - } - - private static void gotoGallery(Activity activity, int windowTitleId, - int mediaTypes) { - Uri target = Images.Media.INTERNAL_CONTENT_URI.buildUpon() - .appendQueryParameter("bucketId", - ImageManager.CAMERA_IMAGE_BUCKET_ID).build(); - Intent intent = new Intent(Intent.ACTION_VIEW, target); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.putExtra("windowTitle", activity.getString(windowTitleId)); - intent.putExtra("mediaTypes", mediaTypes); - - try { - activity.startActivity(intent); - } catch (ActivityNotFoundException e) { - Log.e(TAG, "Could not start gallery activity", e); - } - } - static void addCapturePictureMenuItems(Menu menu, final Activity activity) { menu.add(Menu.NONE, Menu.NONE, POSITION_CAPTURE_PICTURE, R.string.capture_picture) diff --git a/src/com/android/camera/OnScreenHint.java b/src/com/android/camera/OnScreenHint.java deleted file mode 100644 index fdda528..0000000 --- a/src/com/android/camera/OnScreenHint.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2009 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 com.android.gallery.R; - -import android.content.Context; -import android.graphics.PixelFormat; -import android.os.Handler; -import android.view.Gravity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.WindowManager; -import android.widget.TextView; - -/** - * A on-screen hint is a view containing a little message for the user and will - * be shown on the screen continuously. This class helps you create and show - * those. - * - * <p> - * When the view is shown to the user, appears as a floating view over the - * application. - * <p> - * The easiest way to use this class is to call one of the static methods that - * constructs everything you need and returns a new OnScreenHint object. - */ -public class OnScreenHint { - static final String TAG = "OnScreenHint"; - static final boolean LOCAL_LOGV = false; - - final Context mContext; - int mGravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; - int mX, mY; - float mHorizontalMargin; - float mVerticalMargin; - View mView; - View mNextView; - - private final WindowManager.LayoutParams mParams = - new WindowManager.LayoutParams(); - private final WindowManager mWM; - private final Handler mHandler = new Handler(); - - /** - * Construct an empty OnScreenHint object. You must call {@link #setView} - * before you can call {@link #show}. - * - * @param context The context to use. Usually your - * {@link android.app.Application} or - * {@link android.app.Activity} object. - */ - public OnScreenHint(Context context) { - mContext = context; - mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - mY = context.getResources().getDimensionPixelSize( - R.dimen.hint_y_offset); - - mParams.height = WindowManager.LayoutParams.WRAP_CONTENT; - mParams.width = WindowManager.LayoutParams.WRAP_CONTENT; - mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; - mParams.format = PixelFormat.TRANSLUCENT; - mParams.windowAnimations = R.style.Animation_OnScreenHint; - mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; - mParams.setTitle("OnScreenHint"); - } - - /** - * Show the view on the screen. - */ - public void show() { - if (mNextView == null) { - throw new RuntimeException("setView must have been called"); - } - mHandler.post(mShow); - } - - /** - * Close the view if it's showing. - */ - public void cancel() { - mHandler.post(mHide); - } - - /** - * Make a standard hint that just contains a text view. - * - * @param context The context to use. Usually your - * {@link android.app.Application} or - * {@link android.app.Activity} object. - * @param text The text to show. Can be formatted text. - * - */ - public static OnScreenHint makeText(Context context, CharSequence text) { - OnScreenHint result = new OnScreenHint(context); - - LayoutInflater inflate = - (LayoutInflater) context.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - View v = inflate.inflate(R.layout.on_screen_hint, null); - TextView tv = (TextView) v.findViewById(R.id.message); - tv.setText(text); - - result.mNextView = v; - - return result; - } - - /** - * Update the text in a OnScreenHint that was previously created using one - * of the makeText() methods. - * @param s The new text for the OnScreenHint. - */ - public void setText(CharSequence s) { - if (mNextView == null) { - throw new RuntimeException("This OnScreenHint was not " - + "created with OnScreenHint.makeText()"); - } - TextView tv = (TextView) mNextView.findViewById(R.id.message); - if (tv == null) { - throw new RuntimeException("This OnScreenHint was not " - + "created with OnScreenHint.makeText()"); - } - tv.setText(s); - } - - private synchronized void handleShow() { - if (mView != mNextView) { - // remove the old view if necessary - handleHide(); - mView = mNextView; - final int gravity = mGravity; - mParams.gravity = gravity; - if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) - == Gravity.FILL_HORIZONTAL) { - mParams.horizontalWeight = 1.0f; - } - if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) - == Gravity.FILL_VERTICAL) { - mParams.verticalWeight = 1.0f; - } - mParams.x = mX; - mParams.y = mY; - mParams.verticalMargin = mVerticalMargin; - mParams.horizontalMargin = mHorizontalMargin; - if (mView.getParent() != null) { - mWM.removeView(mView); - } - mWM.addView(mView, mParams); - } - } - - private synchronized void handleHide() { - if (mView != null) { - // note: checking parent() just to make sure the view has - // been added... i have seen cases where we get here when - // the view isn't yet added, so let's try not to crash. - if (mView.getParent() != null) { - mWM.removeView(mView); - } - mView = null; - } - } - - private final Runnable mShow = new Runnable() { - public void run() { - handleShow(); - } - }; - - private final Runnable mHide = new Runnable() { - public void run() { - handleHide(); - } - }; -} - diff --git a/src/com/android/camera/OnScreenSettings.java b/src/com/android/camera/OnScreenSettings.java deleted file mode 100644 index 2fd00c0..0000000 --- a/src/com/android/camera/OnScreenSettings.java +++ /dev/null @@ -1,495 +0,0 @@ -package com.android.camera; - -import com.android.gallery.R; - -import android.content.Context; -import android.graphics.PixelFormat; -import android.os.Handler; -import android.os.Message; -import android.preference.ListPreference; -import android.preference.Preference; -import android.preference.PreferenceGroup; -import android.preference.PreferenceScreen; -import android.view.animation.Animation; -import android.view.animation.Animation.AnimationListener; -import android.view.Display; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.view.WindowManager.LayoutParams; -import android.widget.AdapterView; -import android.widget.BaseAdapter; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.RadioButton; -import android.widget.TextView; -import android.widget.AdapterView.OnItemClickListener; - -import java.util.ArrayList; -import java.util.HashMap; - -// Please reference to {@link android.widget.ZoomButtonsController} for detail -// information about adding window to WindowManager. -public class OnScreenSettings { - @SuppressWarnings("unused") - private static final String TAG = "OnScreenSettings"; - private static final int MSG_POST_SET_VISIBLE = 1; - - public interface OnVisibilityChangedListener { - public void onVisibilityChanged(boolean visibility); - } - - private LayoutParams mContainerLayoutParams; - private final Context mContext; - private final Container mContainer; - private final WindowManager mWindowManager; - private final View mOwnerView; - private ListView mMainMenu; - private ListView mSubMenu; - private View mMainPanel; - private boolean mIsVisible = false; - private OnVisibilityChangedListener mVisibilityListener; - private MainMenuAdapter mMainAdapter; - - private final LayoutInflater mInflater; - - // We store the override values here. For a given preference, - // if the mapping value of the preference key is not null, we will - // use the value in this map instead of the value read from the preference - // - // This is design for the scene mode, for example, in the scene mode - // "Action", the focus mode will become "infinite" no matter what in the - // preference settings. So, we need to put a {pref_camera_focusmode_key, - // "infinite"} entry in this map. - private HashMap<String, String> mOverride = new HashMap<String, String>(); - - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_POST_SET_VISIBLE: - setVisible(true); - break; - } - } - }; - - public OnScreenSettings(View ownerView) { - mContext = ownerView.getContext(); - mInflater = (LayoutInflater) - mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - mWindowManager = (WindowManager) - mContext.getSystemService(Context.WINDOW_SERVICE); - mOwnerView = ownerView; - mContainer = createContainer(); - } - - public boolean isVisible() { - return mIsVisible; - } - - public void setOnVisibilityChangedListener( - OnVisibilityChangedListener listener) { - mVisibilityListener = listener; - } - - public void setVisible(boolean visible) { - mHandler.removeMessages(MSG_POST_SET_VISIBLE); - if (visible) { - if (mOwnerView.getWindowToken() == null) { - /* - * We need a window token to show ourselves, maybe the owner's - * window hasn't been created yet but it will have been by the - * time the looper is idle, so post the setVisible(true) call. - */ - mHandler.sendEmptyMessage(MSG_POST_SET_VISIBLE); - return; - } - } - - if (mIsVisible == visible) { - return; - } - mIsVisible = visible; - - if (visible) { - // Update main adapter before show up - if (mMainAdapter != null) mMainAdapter.notifyDataSetChanged(); - if (mContainerLayoutParams.token == null) { - mContainerLayoutParams.token = mOwnerView.getWindowToken(); - } - mSubMenu.setVisibility(View.INVISIBLE); - mMainMenu.setVisibility(View.VISIBLE); - mWindowManager.addView(mContainer, mContainerLayoutParams); - updateLayout(); - } else { - // Reset the two menus - - mWindowManager.removeView(mContainer); - } - if (mVisibilityListener != null) { - mVisibilityListener.onVisibilityChanged(mIsVisible); - } - } - - // Override the preference settings, if value == null, then disable the - // override. - public void overrideSettings(String key, String value) { - if (value == null) { - if (mOverride.remove(key) != null && mMainAdapter != null) { - mMainAdapter.notifyDataSetChanged(); - } - } else { - if (mOverride.put(key, value) == null && mMainAdapter != null) { - mMainAdapter.notifyDataSetChanged(); - } - } - } - - public void updateLayout() { - // if the mOwnerView is detached from window then skip. - if (mOwnerView.getWindowToken() == null) return; - Display display = mWindowManager.getDefaultDisplay(); - - mContainerLayoutParams.x = 0; - mContainerLayoutParams.y = 0; - - mContainerLayoutParams.width = display.getWidth() / 2; - mContainerLayoutParams.height = display.getHeight(); - - if (mIsVisible) { - mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); - } - } - - private void showSubMenu() { - Util.slideOut(mMainMenu, Util.DIRECTION_LEFT); - Util.slideIn(mSubMenu, Util.DIRECTION_RIGHT); - mSubMenu.requestFocus(); - } - - private void closeSubMenu() { - Util.slideOut(mSubMenu, Util.DIRECTION_RIGHT); - Util.slideIn(mMainMenu, Util.DIRECTION_LEFT); - } - - private Container createContainer() { - LayoutParams lp = new LayoutParams( - LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - lp.flags = LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; - lp.gravity = Gravity.TOP | Gravity.LEFT; - lp.height = LayoutParams.WRAP_CONTENT; - lp.width = LayoutParams.WRAP_CONTENT; - lp.type = LayoutParams.TYPE_APPLICATION_PANEL; - lp.format = PixelFormat.OPAQUE; - lp.windowAnimations = R.style.Animation_OnScreenMenu; - - mContainerLayoutParams = lp; - - Container container = new Container(mContext); - container.setLayoutParams(lp); - - mInflater.inflate(R.layout.on_screen_menu, container); - - mMainPanel = container.findViewById(R.id.main_panel); - mMainMenu = (ListView) container.findViewById(R.id.menu_view); - mSubMenu = (ListView) container.findViewById(R.id.sub_menu); - - container.findViewById(R.id.btn_gripper) - .setOnTouchListener(new GripperTouchListener()); - - return container; - } - - private class GripperTouchListener implements View.OnTouchListener { - public boolean onTouch(View view, MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - return true; - case MotionEvent.ACTION_UP: - setVisible(false); - return true; - } - return false; - } - } - - private boolean onContainerKey(KeyEvent event) { - switch (event.getKeyCode()) { - case KeyEvent.KEYCODE_CAMERA: - case KeyEvent.KEYCODE_FOCUS: - case KeyEvent.KEYCODE_BACK: - case KeyEvent.KEYCODE_MENU: - if (event.getAction() == KeyEvent.ACTION_UP) { - setVisible(false); - return true; - } - } - return false; - } - - // Add the preference and it's children recursively to the given list. So - // that we can show the preference (and it's children) in the list view. - private static void addPreference( - Preference preference, ArrayList<Preference> list) { - list.add(preference); - if (preference instanceof PreferenceGroup) { - PreferenceGroup group = (PreferenceGroup) preference; - for (int i = 0, n = group.getPreferenceCount(); i < n; ++i) { - Preference child = group.getPreference(i); - addPreference(child, list); - } - } - } - - public void setPreferenceScreen(PreferenceScreen screen) { - ArrayList<Preference> list = new ArrayList<Preference>(); - - // We don't want the screen add to the list, we add the first level - // preference here. - for (int i = 0, n = screen.getPreferenceCount(); i < n; ++i) { - addPreference(screen.getPreference(i), list); - } - mMainAdapter = new MainMenuAdapter(mContext, list); - mMainMenu.setAdapter(mMainAdapter); - mMainMenu.setOnItemClickListener(mMainAdapter); - } - - private View inflateIfNeed( - View view, int resource, ViewGroup root, boolean attachToRoot) { - if (view != null) return view; - return mInflater.inflate(resource, root, attachToRoot); - } - - private class MainMenuAdapter extends BaseAdapter - implements OnItemClickListener { - private final ArrayList<Preference> mPreferences; - - public MainMenuAdapter( - Context context, ArrayList<Preference> preferences) { - mPreferences = preferences; - } - - public void onItemClick( - AdapterView<?> parent, View view, int position, long id) { - Preference preference = mPreferences.get(position); - SubMenuAdapter adapter = new SubMenuAdapter( - mContext, (ListPreference) preference); - mSubMenu.setAdapter(adapter); - mSubMenu.setOnItemClickListener(adapter); - showSubMenu(); - } - - public View getView(int position, View convertView, ViewGroup parent) { - Preference preference = mPreferences.get(position); - - if (preference instanceof PreferenceGroup) { - convertView = inflateIfNeed(convertView, - R.layout.on_screen_menu_header, parent, false); - PreferenceGroup group = (PreferenceGroup) preference; - ((TextView) convertView.findViewById( - R.id.title)).setText(group.getTitle()); - } else { - convertView = inflateIfNeed(convertView, - R.layout.on_screen_menu_list_item, parent, false); - - String override = mOverride.get(preference.getKey()); - TextView title = (TextView) - convertView.findViewById(R.id.title); - title.setText(preference.getTitle()); - title.setEnabled(override == null); - - TextView summary = (TextView) - convertView.findViewById(R.id.summary); - summary.setText(override == null - ? ((ListPreference) preference).getEntry() - : override); - summary.setEnabled(override == null); - - // A little trick here, making the view focusable will eat - // both touch/key events on the view and thus make it looks - // like disabled. - convertView.setFocusable(override != null); - } - return convertView; - } - - @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int position) { - Preference preference = mPreferences.get(position); - return !(preference instanceof PreferenceGroup); - } - - public int getCount() { - return mPreferences.size(); - } - - public Object getItem(int position) { - return null; - } - - public long getItemId(int position) { - return position; - } - - @Override - public int getItemViewType(int position) { - Preference pref = mPreferences.get(position); - if (pref instanceof PreferenceGroup) return 0; - if (pref instanceof ListPreference) return 1; - throw new IllegalStateException(); - } - - @Override - public int getViewTypeCount() { - // we have two types, see getItemViewType() - return 2; - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public boolean isEmpty() { - return mPreferences.isEmpty(); - } - } - - private class SubMenuAdapter extends BaseAdapter - implements OnItemClickListener { - private final ListPreference mPreference; - private final IconListPreference mIconPreference; - - public SubMenuAdapter(Context context, ListPreference preference) { - mPreference = preference; - mIconPreference = (preference instanceof IconListPreference) - ? (IconListPreference) preference - : null; - } - - public View getView(int position, View convertView, ViewGroup parent) { - CharSequence entry[] = mPreference.getEntries(); - if (position == 0) { - convertView = inflateIfNeed(convertView, - R.layout.on_screen_menu_header, parent, false); - ((TextView) convertView.findViewById( - R.id.title)).setText(mPreference.getDialogTitle()); - } else { - int index = position - 1; - convertView = inflateIfNeed(convertView, - R.layout.on_screen_submenu_item, parent, false); - boolean checked = mPreference.getValue().equals( - mPreference.getEntryValues()[index]); - ((TextView) convertView.findViewById( - R.id.title)).setText(entry[index]); - ((RadioButton) convertView.findViewById( - R.id.radio_button)).setChecked(checked); - ImageView icon = (ImageView) - convertView.findViewById(R.id.icon); - if (mIconPreference != null) { - icon.setVisibility(View.VISIBLE); - icon.setImageDrawable( - mIconPreference.getIcons()[position-1]); - } else { - icon.setVisibility(View.GONE); - } - } - return convertView; - } - - @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int position) { - return getItemViewType(position) != 0; - } - - public int getCount() { - // add one for the header - return mPreference.getEntries().length + 1; - } - - public Object getItem(int position) { - return null; - } - - public long getItemId(int position) { - return position; - } - - @Override - public int getItemViewType(int position) { - return position == 0 ? 0 : 1; - } - - @Override - public int getViewTypeCount() { - return 2; - } - - @Override - public boolean hasStableIds() { - return true; - } - - public void onItemClick( - AdapterView<?> parent, View view, int position, long id) { - CharSequence values[] = mPreference.getEntryValues(); - int idx = mPreference.findIndexOfValue(mPreference.getValue()); - if (idx != position - 1) { - mPreference.setValueIndex(position - 1); - notifyDataSetChanged(); - mMainAdapter.notifyDataSetChanged(); - return; - } - - // Close the sub menu when user presses the original option. - closeSubMenu(); - } - } - - private class Container extends FrameLayout { - public Container(Context context) { - super(context); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (super.onTouchEvent(event)) return true; - if (event.getAction() == MotionEvent.ACTION_DOWN) { - setVisible(false); - return true; - } - return false; - } - - /* - * Need to override this to intercept the key events. Otherwise, we - * would attach a key listener to the container but its superclass - * ViewGroup gives it to the focused View instead of calling the key - * listener, and so we wouldn't get the events. - */ - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - return onContainerKey(event) - ? true - : super.dispatchKeyEvent(event); - } - } -} diff --git a/src/com/android/camera/PreviewFrameLayout.java b/src/com/android/camera/PreviewFrameLayout.java deleted file mode 100644 index 49a39ef..0000000 --- a/src/com/android/camera/PreviewFrameLayout.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2009 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 com.android.gallery.R; - -import android.app.Activity; -import android.content.Context; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.FrameLayout; - -public class PreviewFrameLayout extends ViewGroup { - private static final int MIN_HORIZONTAL_MARGIN = 10; // 10dp - - public interface OnSizeChangedListener { - public void onSizeChanged(); - } - - private double mAspectRatio = 4.0 / 3.0; - private ImageView mGripper; - private FrameLayout mFrame; - private OnSizeChangedListener mSizeListener; - private DisplayMetrics mMetrics = new DisplayMetrics(); - - public PreviewFrameLayout(Context context, AttributeSet attrs) { - super(context, attrs); - ((Activity) context).getWindowManager() - .getDefaultDisplay().getMetrics(mMetrics); - } - - public void setOnSizeChangedListener(OnSizeChangedListener listener) { - mSizeListener = listener; - } - - @Override - protected void onFinishInflate() { - mGripper = (ImageView) findViewById(R.id.btn_gripper); - mFrame = (FrameLayout) findViewById(R.id.frame); - if (mFrame == null) { - throw new IllegalStateException( - "must provide child with id as \"frame\""); - } - } - - public void setAspectRatio(double ratio) { - if (ratio <= 0.0) throw new IllegalArgumentException(); - - if (mAspectRatio != ratio) { - mAspectRatio = ratio; - requestLayout(); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - int gripperWidth = 0; - int gripperHeight = 0; - - if (mGripper != null) { - measureChild(mGripper, widthMeasureSpec, heightMeasureSpec); - gripperWidth = mGripper.getMeasuredWidth(); - gripperHeight = mGripper.getMeasuredHeight(); - } - - int frameWidth = getMeasuredWidth() - (int) Math.max( - gripperWidth, MIN_HORIZONTAL_MARGIN * mMetrics.density); - int frameHeight = getMeasuredHeight(); - - FrameLayout f = mFrame; - - int horizontalPadding = f.getPaddingLeft() + f.getPaddingRight(); - int verticalPadding = f.getPaddingBottom() + f.getPaddingTop(); - - int previewWidth = frameWidth - horizontalPadding; - int previewHeight = frameHeight - verticalPadding; - - // resize frame and preview for aspect ratio - if (previewWidth > previewHeight * mAspectRatio) { - previewWidth = (int) (previewHeight * mAspectRatio + .5); - } else { - previewHeight = (int) (previewWidth / mAspectRatio + .5); - } - frameWidth = previewWidth + horizontalPadding; - frameHeight = previewHeight + verticalPadding; - - measureChild(mFrame, - MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, frameWidth), - MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, frameHeight)); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - // Try to layout the "frame" in the center of the area, and put - // "gripper" just to the left of it. If there is no enough space for - // the gripper, the "frame" will be moved a little right so that - // they won't overlap with each other. - - int frameWidth = mFrame.getMeasuredWidth(); - int frameHeight = mFrame.getMeasuredHeight(); - - int leftSpace = ((r - l) - frameWidth) / 2; - int topSpace = ((b - t) - frameHeight) / 2; - - int gripperWidth = 0; - int gripperHeight = 0; - if (mGripper != null) { - gripperWidth = mGripper.getMeasuredWidth(); - gripperHeight = mGripper.getMeasuredHeight(); - myLayoutChild(mGripper, - Math.max(l, l + (leftSpace - gripperWidth)), - t + ((b - t) - gripperHeight) / 2, - gripperWidth, gripperHeight); - } - myLayoutChild(mFrame, Math.max(l + leftSpace, l + gripperWidth), - t + topSpace, frameWidth, frameHeight); - if (mSizeListener != null) { - mSizeListener.onSizeChanged(); - } - } - - private static void myLayoutChild(View child, int l, int t, int w, int h) { - child.layout(l, t, l + w, t + h); - } -} - diff --git a/src/com/android/camera/ReviewImage.java b/src/com/android/camera/ReviewImage.java deleted file mode 100644 index b87cca0..0000000 --- a/src/com/android/camera/ReviewImage.java +++ /dev/null @@ -1,855 +0,0 @@ -/* - * Copyright (C) 2007 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 com.android.gallery.R; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Bundle; -import android.provider.MediaStore; -import android.util.AttributeSet; -import android.util.Log; -import android.view.GestureDetector; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.view.View.OnTouchListener; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.widget.Toast; -import android.widget.ZoomButtonsController; - -import com.android.camera.gallery.IImage; -import com.android.camera.gallery.IImageList; -import com.android.camera.gallery.VideoObject; - -// This activity can display a whole picture and navigate them in a specific -// gallery. It has two modes: normal mode and slide show mode. In normal mode -// the user view one image at a time, and can click "previous" and "next" -// button to see the previous or next image. In slide show mode it shows one -// image after another, with some transition effect. -public class ReviewImage extends NoSearchActivity implements View.OnClickListener { - private static final String STATE_URI = "uri"; - private static final String TAG = "ReviewImage"; - private static final double ASPECT_RATIO = 4.0 / 3.0; - - private ImageGetter mGetter; - private Uri mSavedUri; - boolean mPaused = true; - private boolean mShowControls = true; - - // Choices for what adjacents to load. - private static final int[] sOrderAdjacents = new int[] {0, 1, -1}; - - final GetterHandler mHandler = new GetterHandler(); - - private boolean mFullScreenInNormalMode; - - int mCurrentPosition = 0; - - private View mRootView; - private View mControlBar; - private View mNextImageView; - private View mPrevImageView; - private final Animation mHideNextImageViewAnimation = - new AlphaAnimation(1F, 0F); - private final Animation mHidePrevImageViewAnimation = - new AlphaAnimation(1F, 0F); - private final Animation mShowNextImageViewAnimation = - new AlphaAnimation(0F, 1F); - private final Animation mShowPrevImageViewAnimation = - new AlphaAnimation(0F, 1F); - - public static final String KEY_IMAGE_LIST = "image_list"; - private static final String STATE_SHOW_CONTROLS = "show_controls"; - - ImageManager.ImageListParam mParam; - IImageList mAllImages; - - private final ImageViewTouchBase [] mSlideShowImageViews = - new ImageViewTouchBase[2]; - - GestureDetector mGestureDetector; - private ZoomButtonsController mZoomButtonsController; - - // The image view displayed for normal mode. - private ImageViewTouch2 mImageView; - // This is the cache for thumbnail bitmaps. - private BitmapCache mCache; - private MenuHelper.MenuItemsResult mImageMenuRunnable; - private final Runnable mDismissOnScreenControlRunner = new Runnable() { - public void run() { - hideOnScreenControls(); - } - }; - - private void updateNextPrevControls() { - boolean showPrev = mCurrentPosition > 0; - boolean showNext = mCurrentPosition < mAllImages.getCount() - 1; - - boolean prevIsVisible = mPrevImageView.getVisibility() == View.VISIBLE; - boolean nextIsVisible = mNextImageView.getVisibility() == View.VISIBLE; - - if (showPrev && !prevIsVisible) { - Animation a = mShowPrevImageViewAnimation; - a.setDuration(500); - mPrevImageView.startAnimation(a); - mPrevImageView.setVisibility(View.VISIBLE); - } else if (!showPrev && prevIsVisible) { - Animation a = mHidePrevImageViewAnimation; - a.setDuration(500); - mPrevImageView.startAnimation(a); - mPrevImageView.setVisibility(View.GONE); - } - - if (showNext && !nextIsVisible) { - Animation a = mShowNextImageViewAnimation; - a.setDuration(500); - mNextImageView.startAnimation(a); - mNextImageView.setVisibility(View.VISIBLE); - } else if (!showNext && nextIsVisible) { - Animation a = mHideNextImageViewAnimation; - a.setDuration(500); - mNextImageView.startAnimation(a); - mNextImageView.setVisibility(View.GONE); - } - } - - private void showOnScreenControls() { - - // If the view has not been attached to the window yet, the - // zoomButtonControls will not able to show up. So delay it until the - // view has attached to window. - if (mRootView.getWindowToken() == null) { - mHandler.postGetterCallback(new Runnable() { - public void run() { - showOnScreenControls(); - } - }); - return; - } - - // we may need to update the next/prev button due to index changing - updateNextPrevControls(); - - if (ImageManager.isImage(mAllImages.getImageAt(mCurrentPosition))) { - updateZoomButtonsEnabled(); - mZoomButtonsController.setVisible(true); - } else { - mZoomButtonsController.setVisible(false); - } - } - - private void hideOnScreenControls() { - if (mNextImageView.getVisibility() == View.VISIBLE) { - Animation a = mHideNextImageViewAnimation; - a.setDuration(500); - mNextImageView.startAnimation(a); - mNextImageView.setVisibility(View.INVISIBLE); - } - - if (mPrevImageView.getVisibility() == View.VISIBLE) { - Animation a = mHidePrevImageViewAnimation; - a.setDuration(500); - mPrevImageView.startAnimation(a); - mPrevImageView.setVisibility(View.INVISIBLE); - } - - mZoomButtonsController.setVisible(false); - } - - private void scheduleDismissOnScreenControls() { - mHandler.removeCallbacks(mDismissOnScreenControlRunner); - mHandler.postDelayed(mDismissOnScreenControlRunner, 2000); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent m) { - if (mZoomButtonsController.isVisible()) { - scheduleDismissOnScreenControls(); - } - return super.dispatchTouchEvent(m); - } - - private void updateZoomButtonsEnabled() { - ImageViewTouch2 imageView = mImageView; - float scale = imageView.getScale(); - mZoomButtonsController.setZoomInEnabled(scale < imageView.mMaxZoom); - mZoomButtonsController.setZoomOutEnabled(scale > 1); - } - - @Override - protected void onDestroy() { - // This is necessary to make the ZoomButtonsController unregister - // its configuration change receiver. - if (mZoomButtonsController != null) { - mZoomButtonsController.setVisible(false); - } - - super.onDestroy(); - } - - private void setupOnScreenControls(View rootView, View ownerView) { - mNextImageView = rootView.findViewById(R.id.next_image); - mPrevImageView = rootView.findViewById(R.id.prev_image); - - mNextImageView.setOnClickListener(this); - mPrevImageView.setOnClickListener(this); - - setupZoomButtonController(ownerView); - setupOnTouchListeners(rootView); - } - - private void setupZoomButtonController(final View ownerView) { - mZoomButtonsController = new ZoomButtonsController(ownerView); - mZoomButtonsController.setAutoDismissed(false); - mZoomButtonsController.setZoomSpeed(100); - mZoomButtonsController.setOnZoomListener( - new ZoomButtonsController.OnZoomListener() { - public void onVisibilityChanged(boolean visible) { - if (visible) { - updateZoomButtonsEnabled(); - } - } - - public void onZoom(boolean zoomIn) { - if (zoomIn) { - mImageView.zoomIn(); - } else { - mImageView.zoomOut(); - } - mZoomButtonsController.setVisible(true); - updateZoomButtonsEnabled(); - } - }); - } - - private void setupOnTouchListeners(View rootView) { - mGestureDetector = new GestureDetector(this, new MyGestureListener()); - - // If the user touches anywhere on the panel (including the - // next/prev button). We show the on-screen controls. In addition - // to that, if the touch is not on the prev/next button, we - // pass the event to the gesture detector to detect double tap. - final OnTouchListener buttonListener = new OnTouchListener() { - public boolean onTouch(View v, MotionEvent event) { - scheduleDismissOnScreenControls(); - return false; - } - }; - - OnTouchListener rootListener = new OnTouchListener() { - public boolean onTouch(View v, MotionEvent event) { - buttonListener.onTouch(v, event); - mGestureDetector.onTouchEvent(event); - - // We do not use the return value of - // mGestureDetector.onTouchEvent because we will not receive - // the "up" event if we return false for the "down" event. - return true; - } - }; - - mNextImageView.setOnTouchListener(buttonListener); - mPrevImageView.setOnTouchListener(buttonListener); - rootView.setOnTouchListener(rootListener); - } - - private class MyGestureListener extends - GestureDetector.SimpleOnGestureListener { - - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { - if (mPaused) return false; - ImageViewTouch2 imageView = mImageView; - if (imageView.getScale() > 1F) { - imageView.postTranslateCenter(-distanceX, -distanceY); - } - return true; - } - - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { - if (mPaused) return false; - showOnScreenControls(); - scheduleDismissOnScreenControls(); - return true; - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - if (mPaused) return false; - ImageViewTouch2 imageView = mImageView; - - // Switch between the original scale and 3x scale. - if (imageView.getScale() > 2F) { - mImageView.zoomTo(1f); - } else { - mImageView.zoomToPoint(3f, e.getX(), e.getY()); - } - return true; - } - } - - boolean isPickIntent() { - String action = getIntent().getAction(); - return (Intent.ACTION_PICK.equals(action) - || Intent.ACTION_GET_CONTENT.equals(action)); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - - // These are the menu items already covered by the side buttons. - int sideButtons = MenuHelper.INCLUDE_DELETE_MENU - | MenuHelper.INCLUDE_SHARE_MENU - | MenuHelper.INCLUDE_SET_MENU - | MenuHelper.INCLUDE_VIEWPLAY_MENU; - - mImageMenuRunnable = MenuHelper.addImageMenuItems( - menu, - MenuHelper.INCLUDE_ALL & ~sideButtons, - ReviewImage.this, - mHandler, - mDeletePhotoRunnable, - new MenuHelper.MenuInvoker() { - public void run(final MenuHelper.MenuCallback cb) { - if (mPaused) return; - IImage image = mAllImages.getImageAt(mCurrentPosition); - Uri uri = image.fullSizeImageUri(); - cb.run(uri, image); - - mImageView.clear(); - setImage(mCurrentPosition, false); - } - }); - - return true; - } - - protected Runnable mDeletePhotoRunnable = new Runnable() { - public void run() { - mAllImages.removeImageAt(mCurrentPosition); - if (mAllImages.getCount() == 0) { - finish(); - return; - } else { - if (mCurrentPosition == mAllImages.getCount()) { - mCurrentPosition -= 1; - } - } - mImageView.clear(); - mCache.clear(); // Because the position number is changed. - setImage(mCurrentPosition, true); - } - }; - - @Override - public boolean onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - if (mPaused) return false; - - IImage image = mAllImages.getImageAt(mCurrentPosition); - if (mImageMenuRunnable != null) { - mImageMenuRunnable.gettingReadyToOpen(menu, image); - } - - Uri uri = mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri(); - MenuHelper.enableShareMenuItem(menu, MenuHelper.isWhiteListUri(uri)); - - MenuHelper.enableShowOnMapMenuItem(menu, MenuHelper.hasLatLngData(image)); - - return true; - } - - @Override - public boolean onMenuItemSelected(int featureId, MenuItem item) { - boolean b = super.onMenuItemSelected(featureId, item); - if (mImageMenuRunnable != null) { - mImageMenuRunnable.aboutToCall(item, - mAllImages.getImageAt(mCurrentPosition)); - } - return b; - } - - void setImage(int pos, boolean showControls) { - mCurrentPosition = pos; - - Bitmap b = mCache.getBitmap(pos); - if (b != null) { - IImage image = mAllImages.getImageAt(pos); - mImageView.setImageRotateBitmapResetBase( - new RotateBitmap(b, image.getDegreesRotated()), true); - updateZoomButtonsEnabled(); - } - - ImageGetterCallback cb = new ImageGetterCallback() { - public void completed() { - } - - public boolean wantsThumbnail(int pos, int offset) { - return !mCache.hasBitmap(pos + offset); - } - - public boolean wantsFullImage(int pos, int offset) { - return offset == 0; - } - - public int fullImageSizeToUse(int pos, int offset) { - // this number should be bigger so that we can zoom. we may - // need to get fancier and read in the fuller size image as the - // user starts to zoom. - // Originally the value is set to 480 in order to avoid OOM. - // Now we set it to 2048 because of using - // native memory allocation for Bitmaps. - final int imageViewSize = 2048; - return imageViewSize; - } - - public int [] loadOrder() { - return sOrderAdjacents; - } - - public void imageLoaded(int pos, int offset, RotateBitmap bitmap, - boolean isThumb) { - // shouldn't get here after onPause() - - // We may get a result from a previous request. Ignore it. - if (pos != mCurrentPosition) { - bitmap.recycle(); - return; - } - - if (isThumb) { - mCache.put(pos + offset, bitmap.getBitmap()); - } - if (offset == 0) { - // isThumb: We always load thumb bitmap first, so we will - // reset the supp matrix for then thumb bitmap, and keep - // the supp matrix when the full bitmap is loaded. - mImageView.setImageRotateBitmapResetBase(bitmap, isThumb); - updateZoomButtonsEnabled(); - } - } - }; - - // Could be null if we're stopping a slide show in the course of pausing - if (mGetter != null) { - mGetter.setPosition(pos, cb, mAllImages, mHandler); - } - updateActionIcons(); - if (showControls) showOnScreenControls(); - scheduleDismissOnScreenControls(); - } - - @Override - public void onCreate(Bundle instanceState) { - super.onCreate(instanceState); - - Intent intent = getIntent(); - mFullScreenInNormalMode = intent.getBooleanExtra( - MediaStore.EXTRA_FULL_SCREEN, true); - - setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT); - requestWindowFeature(Window.FEATURE_NO_TITLE); - setContentView(R.layout.review_image); - - mRootView = findViewById(R.id.root); - mControlBar = findViewById(R.id.control_bar); - mImageView = (ImageViewTouch2) findViewById(R.id.image); - mImageView.setEnableTrackballScroll(true); - mCache = new BitmapCache(3); - mImageView.setRecycler(mCache); - - ((PreviewFrameLayout) findViewById( - R.id.frame_layout)).setAspectRatio(ASPECT_RATIO); - - - makeGetter(); - - mSlideShowImageViews[0] = - (ImageViewTouchBase) findViewById(R.id.image1_slideShow); - mSlideShowImageViews[1] = - (ImageViewTouchBase) findViewById(R.id.image2_slideShow); - for (ImageViewTouchBase v : mSlideShowImageViews) { - v.setVisibility(View.INVISIBLE); - v.setRecycler(mCache); - } - - mParam = getIntent().getParcelableExtra(KEY_IMAGE_LIST); - - if (instanceState != null) { - mSavedUri = instanceState.getParcelable(STATE_URI); - mShowControls = instanceState.getBoolean(STATE_SHOW_CONTROLS, true); - } else { - mSavedUri = getIntent().getData(); - } - - int[] pickIds = {R.id.attach, R.id.cancel}; - int[] reviewIds = {R.id.btn_delete, R.id.btn_share, R.id.btn_set_as, - R.id.btn_play, R.id.btn_done}; - int[] connectIds = isPickIntent() ? pickIds : reviewIds; - for (int id : connectIds) { - View view = mControlBar.findViewById(id); - view.setOnClickListener(this); - // Set the LinearLayout of the given button to visible - ((View) view.getParent()).setVisibility(View.VISIBLE); - } - - if (mFullScreenInNormalMode) { - getWindow().addFlags( - WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - - setupOnScreenControls(findViewById(R.id.mainPanel), mImageView); - } - - private void setButtonPanelVisibility(int id, int visibility) { - View button = mControlBar.findViewById(id); - ((View) button.getParent()).setVisibility(visibility); - } - - private void updateActionIcons() { - if (isPickIntent()) return; - - IImage image = mAllImages.getImageAt(mCurrentPosition); - if (image instanceof VideoObject) { - setButtonPanelVisibility(R.id.btn_set_as, View.GONE); - setButtonPanelVisibility(R.id.btn_play, View.VISIBLE); - } else { - setButtonPanelVisibility(R.id.btn_set_as, View.VISIBLE); - setButtonPanelVisibility(R.id.btn_play, View.GONE); - } - } - - private void makeGetter() { - mGetter = new ImageGetter(getContentResolver()); - } - - private IImageList buildImageListFromUri(Uri uri) { - int sort = ImageManager.SORT_ASCENDING; - return ImageManager.makeImageList(getContentResolver(), uri, sort); - } - - private boolean init(Uri uri) { - if (uri == null) return false; - mAllImages = (mParam == null) - ? buildImageListFromUri(uri) - : ImageManager.makeImageList(getContentResolver(), mParam); - IImage image = mAllImages.getImageForUri(uri); - if (image == null) return false; - mCurrentPosition = mAllImages.getImageIndex(image); - return true; - } - - private Uri getCurrentUri() { - if (mAllImages.getCount() == 0) return null; - IImage image = mAllImages.getImageAt(mCurrentPosition); - return image.fullSizeImageUri(); - } - - @Override - public void onSaveInstanceState(Bundle b) { - super.onSaveInstanceState(b); - b.putParcelable(STATE_URI, - mAllImages.getImageAt(mCurrentPosition).fullSizeImageUri()); - b.putBoolean(STATE_SHOW_CONTROLS, mShowControls); - } - - @Override - public void onStart() { - super.onStart(); - mPaused = false; - - if (!init(mSavedUri)) { - Log.w(TAG, "init failed: " + mSavedUri); - finish(); - return; - } - - // normally this will never be zero but if one "backs" into this - // activity after removing the sdcard it could be zero. in that - // case just "finish" since there's nothing useful that can happen. - int count = mAllImages.getCount(); - if (count == 0) { - finish(); - return; - } else if (count <= mCurrentPosition) { - mCurrentPosition = count - 1; - } - - if (mGetter == null) { - makeGetter(); - } - - //show controls only for first time - setImage(mCurrentPosition, mShowControls); - mShowControls = false; - } - - @Override - public void onStop() { - super.onStop(); - mPaused = true; - - // mGetter could be null if we call finish() and leave early in - // onStart(). - if (mGetter != null) { - mGetter.cancelCurrent(); - mGetter.stop(); - mGetter = null; - } - - // removing all callback in the message queue - mHandler.removeAllGetterCallbacks(); - - if (mAllImages != null) { - mSavedUri = getCurrentUri(); - mAllImages.close(); - mAllImages = null; - } - - hideOnScreenControls(); - mImageView.clear(); - mCache.clear(); - - for (ImageViewTouchBase iv : mSlideShowImageViews) { - iv.clear(); - } - } - - private void startShareMediaActivity(IImage image) { - boolean isVideo = image instanceof VideoObject; - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_SEND); - intent.setType(image.getMimeType()); - intent.putExtra(Intent.EXTRA_STREAM, image.fullSizeImageUri()); - try { - startActivity(Intent.createChooser(intent, getText( - isVideo ? R.string.sendVideo : R.string.sendImage))); - } catch (android.content.ActivityNotFoundException ex) { - Toast.makeText(this, isVideo - ? R.string.no_way_to_share_image - : R.string.no_way_to_share_video, - Toast.LENGTH_SHORT).show(); - } - } - - private void startPlayVideoActivity() { - IImage image = mAllImages.getImageAt(mCurrentPosition); - Intent intent = new Intent( - Intent.ACTION_VIEW, image.fullSizeImageUri()); - try { - startActivity(intent); - } catch (android.content.ActivityNotFoundException ex) { - Log.e(TAG, "Couldn't view video " + image.fullSizeImageUri(), ex); - } - } - - public void onClick(View v) { - switch (v.getId()) { - case R.id.btn_delete: - MenuHelper.deleteImage(this, mDeletePhotoRunnable, - mAllImages.getImageAt(mCurrentPosition)); - break; - case R.id.btn_play: - startPlayVideoActivity(); - break; - case R.id.btn_share: { - IImage image = mAllImages.getImageAt(mCurrentPosition); - if (!MenuHelper.isWhiteListUri(image.fullSizeImageUri())) { - return; - } - startShareMediaActivity(image); - break; - } - case R.id.btn_set_as: { - IImage image = mAllImages.getImageAt(mCurrentPosition); - Intent intent = Util.createSetAsIntent(image); - try { - startActivity(Intent.createChooser( - intent, getText(R.string.setImage))); - } catch (android.content.ActivityNotFoundException ex) { - Toast.makeText(this, R.string.no_way_to_share_video, - Toast.LENGTH_SHORT).show(); - } - break; - } - case R.id.btn_done: - finish(); - break; - case R.id.next_image: - moveNextOrPrevious(1); - break; - case R.id.prev_image: - moveNextOrPrevious(-1); - break; - } - } - - private void moveNextOrPrevious(int delta) { - int nextImagePos = mCurrentPosition + delta; - if ((0 <= nextImagePos) && (nextImagePos < mAllImages.getCount())) { - setImage(nextImagePos, true); - showOnScreenControls(); - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, - Intent data) { - switch (requestCode) { - case MenuHelper.RESULT_COMMON_MENU_CROP: - if (resultCode == RESULT_OK) { - // The CropImage activity passes back the Uri of the - // cropped image as the Action rather than the Data. - mSavedUri = Uri.parse(data.getAction()); - - // if onStart() runs before, then set the returned - // image as currentImage. - if (mAllImages != null) { - IImage image = mAllImages.getImageForUri(mSavedUri); - // image could be null if SD card is removed. - if (image == null) { - finish(); - } else { - mCurrentPosition = mAllImages.getImageIndex(image); - setImage(mCurrentPosition, false); - } - } - } - break; - } - } -} - -class ImageViewTouch2 extends ImageViewTouchBase { - private final ReviewImage mViewImage; - private boolean mEnableTrackballScroll; - - public ImageViewTouch2(Context context) { - super(context); - mViewImage = (ReviewImage) context; - } - - public ImageViewTouch2(Context context, AttributeSet attrs) { - super(context, attrs); - mViewImage = (ReviewImage) context; - } - - public void setEnableTrackballScroll(boolean enable) { - mEnableTrackballScroll = enable; - } - - protected void postTranslateCenter(float dx, float dy) { - super.postTranslate(dx, dy); - center(true, true); - } - - private static final float PAN_RATE = 20; - - // This is the time we allow the dpad to change the image position again. - private long mNextChangePositionTime; - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (mViewImage.mPaused) return false; - - // Don't respond to arrow keys if trackball scrolling is not enabled - if (!mEnableTrackballScroll) { - if ((keyCode >= KeyEvent.KEYCODE_DPAD_UP) - && (keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT)) { - return super.onKeyDown(keyCode, event); - } - } - - int current = mViewImage.mCurrentPosition; - - int nextImagePos = -2; // default no next image - try { - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_CENTER: { - if (mViewImage.isPickIntent()) { - IImage img = mViewImage.mAllImages - .getImageAt(mViewImage.mCurrentPosition); - mViewImage.setResult(ReviewImage.RESULT_OK, - new Intent().setData(img.fullSizeImageUri())); - mViewImage.finish(); - } - break; - } - case KeyEvent.KEYCODE_DPAD_LEFT: { - if (getScale() <= 1F && event.getEventTime() - >= mNextChangePositionTime) { - nextImagePos = current - 1; - mNextChangePositionTime = event.getEventTime() + 500; - } else { - panBy(PAN_RATE, 0); - center(true, false); - } - return true; - } - case KeyEvent.KEYCODE_DPAD_RIGHT: { - if (getScale() <= 1F && event.getEventTime() - >= mNextChangePositionTime) { - nextImagePos = current + 1; - mNextChangePositionTime = event.getEventTime() + 500; - } else { - panBy(-PAN_RATE, 0); - center(true, false); - } - return true; - } - case KeyEvent.KEYCODE_DPAD_UP: { - panBy(0, PAN_RATE); - center(false, true); - return true; - } - case KeyEvent.KEYCODE_DPAD_DOWN: { - panBy(0, -PAN_RATE); - center(false, true); - return true; - } - case KeyEvent.KEYCODE_DEL: - MenuHelper.deletePhoto( - mViewImage, mViewImage.mDeletePhotoRunnable); - break; - } - } finally { - if (nextImagePos >= 0 - && nextImagePos < mViewImage.mAllImages.getCount()) { - synchronized (mViewImage) { - mViewImage.setImage(nextImagePos, true); - } - } else if (nextImagePos != -2) { - center(true, true); - } - } - - return super.onKeyDown(keyCode, event); - } -} diff --git a/src/com/android/camera/ShutterButton.java b/src/com/android/camera/ShutterButton.java deleted file mode 100644 index 1fb9258..0000000 --- a/src/com/android/camera/ShutterButton.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2008 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.Context; -import android.util.AttributeSet; -import android.widget.ImageView; - -/** - * A button designed to be used for the on-screen shutter button. - * It's currently an ImageView that can call a delegate when the pressed state - * changes. - */ -public class ShutterButton extends ImageView { - /** - * Interface definition for a callback to be invoked when a ModeButton's - * pressed state changes. - */ - public interface OnShutterButtonListener { - /** - * Called when a ShutterButton has been pressed. - * - * @param b The ShutterButton that was pressed. - */ - void onShutterButtonFocus(ShutterButton b, boolean pressed); - void onShutterButtonClick(ShutterButton b); - } - - private OnShutterButtonListener mListener; - private boolean mOldPressed; - - public ShutterButton(Context context) { - super(context); - } - - public ShutterButton(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ShutterButton(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public void setOnShutterButtonListener(OnShutterButtonListener listener) { - mListener = listener; - } - - /** - * Hook into the drawable state changing to get changes to isPressed -- the - * onPressed listener doesn't always get called when the pressed state - * changes. - */ - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - final boolean pressed = isPressed(); - if (pressed != mOldPressed) { - if (!pressed) { - // When pressing the physical camera button the sequence of - // events is: - // focus pressed, optional camera pressed, focus released. - // We want to emulate this sequence of events with the shutter - // button. When clicking using a trackball button, the view - // system changes the the drawable state before posting click - // notification, so the sequence of events is: - // pressed(true), optional click, pressed(false) - // When clicking using touch events, the view system changes the - // drawable state after posting click notification, so the - // sequence of events is: - // pressed(true), pressed(false), optional click - // Since we're emulating the physical camera button, we want to - // have the same order of events. So we want the optional click - // callback to be delivered before the pressed(false) callback. - // - // To do this, we delay the posting of the pressed(false) event - // slightly by pushing it on the event queue. This moves it - // after the optional click notification, so our client always - // sees events in this sequence: - // pressed(true), optional click, pressed(false) - post(new Runnable() { - public void run() { - callShutterButtonFocus(pressed); - } - }); - } else { - callShutterButtonFocus(pressed); - } - mOldPressed = pressed; - } - } - - private void callShutterButtonFocus(boolean pressed) { - if (mListener != null) { - mListener.onShutterButtonFocus(this, pressed); - } - } - - @Override - public boolean performClick() { - boolean result = super.performClick(); - if (mListener != null) { - mListener.onShutterButtonClick(this); - } - return result; - } -} diff --git a/src/com/android/camera/Switcher.java b/src/com/android/camera/Switcher.java deleted file mode 100644 index cb0d4f1..0000000 --- a/src/com/android/camera/Switcher.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2009 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.Context; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.animation.AnimationUtils; -import android.widget.ImageView; - -public class Switcher extends ImageView implements View.OnTouchListener { - - @SuppressWarnings("unused") - private static final String TAG = "Switcher"; - - public interface OnSwitchListener { - // Returns true if the listener agrees that the switch can be changed. - public boolean onSwitchChanged(Switcher source, boolean onOff); - } - - private static final int ANIMATION_SPEED = 200; - private static final long NO_ANIMATION = -1; - - private boolean mSwitch = false; - private int mPosition = 0; - private long mAnimationStartTime = 0; - private int mAnimationStartPosition; - private OnSwitchListener mListener; - - public Switcher(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void setSwitch(boolean onOff) { - if (mSwitch == onOff) return; - mSwitch = onOff; - invalidate(); - } - - // Try to change the switch position. (The client can veto it.) - private void tryToSetSwitch(boolean onOff) { - try { - if (mSwitch == onOff) return; - - if (mListener != null) { - if (!mListener.onSwitchChanged(this, onOff)) { - return; - } - } - - mSwitch = onOff; - } finally { - startParkingAnimation(); - } - } - - public void setOnSwitchListener(OnSwitchListener listener) { - mListener = listener; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (!isEnabled()) return false; - - final int available = getHeight() - mPaddingTop - mPaddingBottom - - getDrawable().getIntrinsicHeight(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mAnimationStartTime = NO_ANIMATION; - setPressed(true); - trackTouchEvent(event); - break; - - case MotionEvent.ACTION_MOVE: - trackTouchEvent(event); - break; - - case MotionEvent.ACTION_UP: - trackTouchEvent(event); - tryToSetSwitch(mPosition >= available / 2); - setPressed(false); - break; - - case MotionEvent.ACTION_CANCEL: - tryToSetSwitch(mSwitch); - setPressed(false); - break; - } - return true; - } - - private void startParkingAnimation() { - mAnimationStartTime = AnimationUtils.currentAnimationTimeMillis(); - mAnimationStartPosition = mPosition; - } - - private void trackTouchEvent(MotionEvent event) { - Drawable drawable = getDrawable(); - int drawableHeight = drawable.getIntrinsicHeight(); - final int height = getHeight(); - final int available = height - mPaddingTop - mPaddingBottom - - drawableHeight; - int x = (int) event.getY(); - mPosition = x - mPaddingTop - drawableHeight / 2; - if (mPosition < 0) mPosition = 0; - if (mPosition > available) mPosition = available; - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - - Drawable drawable = getDrawable(); - int drawableHeight = drawable.getIntrinsicHeight(); - int drawableWidth = drawable.getIntrinsicWidth(); - - if (drawableWidth == 0 || drawableHeight == 0) { - return; // nothing to draw (empty bounds) - } - - if (mAnimationStartTime != NO_ANIMATION) { - final int available = getHeight() - mPaddingTop - mPaddingBottom - - drawableHeight; - long time = AnimationUtils.currentAnimationTimeMillis(); - int deltaTime = (int)(time - mAnimationStartTime); - mPosition = mAnimationStartPosition + - ANIMATION_SPEED * (mSwitch ? deltaTime : -deltaTime) / 1000; - if (mPosition < 0) mPosition = 0; - if (mPosition > available) mPosition = available; - boolean done = (mPosition == (mSwitch ? available : 0)); - if (!done) { - invalidate(); - } else { - mAnimationStartTime = NO_ANIMATION; - } - } - - int offsetTop = mPaddingTop + mPosition; - int offsetLeft = (getWidth() - - drawableWidth - mPaddingLeft - mPaddingRight) / 2; - int saveCount = canvas.getSaveCount(); - canvas.save(); - canvas.translate(offsetLeft, offsetTop); - drawable.draw(canvas); - canvas.restoreToCount(saveCount); - } - - // Consume the touch events for the specified view. - public void addTouchView(View v) { - v.setOnTouchListener(this); - } - - // This implements View.OnTouchListener so we intercept the touch events - // and pass them to ourselves. - public boolean onTouch(View v, MotionEvent event) { - onTouchEvent(event); - return true; - } -} diff --git a/src/com/android/camera/ThumbnailController.java b/src/com/android/camera/ThumbnailController.java deleted file mode 100644 index 2ae8e20..0000000 --- a/src/com/android/camera/ThumbnailController.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2009 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.ContentResolver; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.TransitionDrawable; -import android.media.ThumbnailUtil; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.util.Log; -import android.view.ViewGroup.LayoutParams; -import android.widget.ImageView; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -/** A controller shows thumbnail picture on a button. The thumbnail picture - * corresponds to a URI of the original picture/video. The thumbnail bitmap - * and the URI can be saved to a file (and later loaded from it). - * <pre> - * public ThumbnailController(ImageView button) - * public void setData(Uri uri, Bitmap original) - * public void updateDisplayIfNeeded() - * public Uri getUri() - * public boolean storeData(String filePath) - * public boolean loadData(String filePath) - * </pre> - */ -public class ThumbnailController { - - @SuppressWarnings("unused") - private static final String TAG = "ThumbnailController"; - private final ContentResolver mContentResolver; - private Uri mUri; - private Bitmap mThumb; - private final ImageView mButton; - private Drawable[] mThumbs; - private TransitionDrawable mThumbTransition; - private boolean mShouldAnimateThumb; - private final Resources mResources; - - // The "frame" is a drawable we want to put on top of the thumbnail. - public ThumbnailController(Resources resources, - ImageView button, ContentResolver contentResolver) { - mResources = resources; - mButton = button; - mContentResolver = contentResolver; - } - - public void setData(Uri uri, Bitmap original) { - // Make sure uri and original are consistently both null or both - // non-null. - if (uri == null || original == null) { - uri = null; - original = null; - } - mUri = uri; - updateThumb(original); - } - - public Uri getUri() { - return mUri; - } - - private static final int BUFSIZE = 4096; - - // Stores the data from the specified file. - // Returns true for success. - public boolean storeData(String filePath) { - if (mUri == null) { - return false; - } - - FileOutputStream f = null; - BufferedOutputStream b = null; - DataOutputStream d = null; - try { - f = new FileOutputStream(filePath); - b = new BufferedOutputStream(f, BUFSIZE); - d = new DataOutputStream(b); - d.writeUTF(mUri.toString()); - mThumb.compress(Bitmap.CompressFormat.PNG, 100, d); - d.close(); - } catch (IOException e) { - return false; - } finally { - MenuHelper.closeSilently(f); - MenuHelper.closeSilently(b); - MenuHelper.closeSilently(d); - } - return true; - } - - // Loads the data from the specified file. - // Returns true for success. - public boolean loadData(String filePath) { - FileInputStream f = null; - BufferedInputStream b = null; - DataInputStream d = null; - try { - f = new FileInputStream(filePath); - b = new BufferedInputStream(f, BUFSIZE); - d = new DataInputStream(b); - Uri uri = Uri.parse(d.readUTF()); - Bitmap thumb = BitmapFactory.decodeStream(d); - setData(uri, thumb); - d.close(); - } catch (IOException e) { - return false; - } finally { - MenuHelper.closeSilently(f); - MenuHelper.closeSilently(b); - MenuHelper.closeSilently(d); - } - return true; - } - - public void updateDisplayIfNeeded() { - if (mUri == null) { - mButton.setImageDrawable(null); - return; - } - - if (mShouldAnimateThumb) { - mThumbTransition.startTransition(500); - mShouldAnimateThumb = false; - } - } - - private void updateThumb(Bitmap original) { - if (original == null) { - mThumb = null; - mThumbs = null; - return; - } - - // Make the mini-thumb size smaller than the button size so that the - // image corners don't peek out from the rounded corners of the - // frame_thumb graphic: - final int PADDING_WIDTH = 2; - final int PADDING_HEIGHT = 2; - LayoutParams param = mButton.getLayoutParams(); - final int miniThumbWidth = param.width - 2 * PADDING_WIDTH; - final int miniThumbHeight = param.height - 2 * PADDING_HEIGHT; - mThumb = ThumbnailUtil.extractMiniThumb( - original, miniThumbWidth, miniThumbHeight, - Util.NO_RECYCLE_INPUT); - Drawable drawable; - if (mThumbs == null) { - mThumbs = new Drawable[2]; - mThumbs[1] = new BitmapDrawable(mResources, mThumb); - drawable = mThumbs[1]; - mShouldAnimateThumb = false; - } else { - mThumbs[0] = mThumbs[1]; - mThumbs[1] = new BitmapDrawable(mResources, mThumb); - mThumbTransition = new TransitionDrawable(mThumbs); - drawable = mThumbTransition; - mShouldAnimateThumb = true; - } - mButton.setImageDrawable(drawable); - } - - public boolean isUriValid() { - if (mUri == null) { - return false; - } - try { - ParcelFileDescriptor pfd = - mContentResolver.openFileDescriptor(mUri, "r"); - if (pfd == null) { - Log.e(TAG, "Fail to open URI."); - return false; - } - pfd.close(); - } catch (IOException ex) { - return false; - } - return true; - } -} diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java index 69e608a..c90a011 100644 --- a/src/com/android/camera/Util.java +++ b/src/com/android/camera/Util.java @@ -330,30 +330,6 @@ public class Util { } } - public static Bitmap makeBitmap(byte[] jpegData, int maxNumOfPixels) { - try { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, - options); - if (options.mCancel || options.outWidth == -1 - || options.outHeight == -1) { - return null; - } - options.inSampleSize = computeSampleSize( - options, IImage.UNCONSTRAINED, maxNumOfPixels); - options.inJustDecodeBounds = false; - - options.inDither = false; - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, - options); - } catch (OutOfMemoryError ex) { - Log.e(TAG, "Got oom exception ", ex); - return null; - } - } - private static ParcelFileDescriptor makeInputStream( Uri uri, ContentResolver cr) { try { @@ -459,69 +435,4 @@ public class Util { options.inNativeAlloc = true; return options; } - - public static void showFatalErrorAndFinish( - final Activity activity, String title, String message) { - DialogInterface.OnClickListener buttonListener = - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - activity.finish(); - } - }; - new AlertDialog.Builder(activity) - .setCancelable(false) - .setIcon(android.R.drawable.ic_dialog_alert) - .setTitle(title) - .setMessage(message) - .setNeutralButton(R.string.details_ok, buttonListener) - .show(); - } - - public static Animation slideOut(View view, int to) { - view.setVisibility(View.INVISIBLE); - Animation anim; - switch (to) { - case DIRECTION_LEFT: - anim = new TranslateAnimation(0, -view.getWidth(), 0, 0); - break; - case DIRECTION_RIGHT: - anim = new TranslateAnimation(0, view.getWidth(), 0, 0); - break; - case DIRECTION_UP: - anim = new TranslateAnimation(0, 0, 0, -view.getHeight()); - break; - case DIRECTION_DOWN: - anim = new TranslateAnimation(0, 0, 0, view.getHeight()); - break; - default: - throw new IllegalArgumentException(Integer.toString(to)); - } - anim.setDuration(500); - view.startAnimation(anim); - return anim; - } - - public static Animation slideIn(View view, int from) { - view.setVisibility(View.VISIBLE); - Animation anim; - switch (from) { - case DIRECTION_LEFT: - anim = new TranslateAnimation(-view.getWidth(), 0, 0, 0); - break; - case DIRECTION_RIGHT: - anim = new TranslateAnimation(view.getWidth(), 0, 0, 0); - break; - case DIRECTION_UP: - anim = new TranslateAnimation(0, 0, -view.getHeight(), 0); - break; - case DIRECTION_DOWN: - anim = new TranslateAnimation(0, 0, view.getHeight(), 0); - break; - default: - throw new IllegalArgumentException(Integer.toString(from)); - } - anim.setDuration(500); - view.startAnimation(anim); - return anim; - } } diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java deleted file mode 100644 index c9dc27f..0000000 --- a/src/com/android/camera/VideoCamera.java +++ /dev/null @@ -1,1598 +0,0 @@ -/* - * Copyright (C) 2007 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 com.android.gallery.R; - -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.Size; -import android.media.MediaRecorder; -import android.media.ThumbnailUtil; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Environment; -import android.os.Handler; -import android.os.Message; -import android.os.StatFs; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.preference.PreferenceManager; -import android.preference.PreferenceScreen; -import android.provider.MediaStore; -import android.provider.MediaStore.Video; -import android.text.format.DateFormat; -import android.util.Log; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.view.MenuItem.OnMenuItemClickListener; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import com.android.camera.PreviewFrameLayout.OnSizeChangedListener; -import com.android.camera.gallery.IImage; -import com.android.camera.gallery.IImageList; - -import java.io.File; -import java.io.FileDescriptor; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; - -/** - * The Camcorder activity. - */ -public class VideoCamera extends NoSearchActivity implements View.OnClickListener, - ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback, - MediaRecorder.OnErrorListener, MediaRecorder.OnInfoListener, - Switcher.OnSwitchListener, OnSharedPreferenceChangeListener, - OnScreenSettings.OnVisibilityChangedListener, - PreviewFrameLayout.OnSizeChangedListener { - - private static final String TAG = "videocamera"; - - private static final int INIT_RECORDER = 3; - private static final int CLEAR_SCREEN_DELAY = 4; - private static final int UPDATE_RECORD_TIME = 5; - - private static final int SCREEN_DELAY = 2 * 60 * 1000; - - private static final long NO_STORAGE_ERROR = -1L; - private static final long CANNOT_STAT_ERROR = -2L; - private static final long LOW_STORAGE_THRESHOLD = 512L * 1024L; - - private static final int STORAGE_STATUS_OK = 0; - private static final int STORAGE_STATUS_LOW = 1; - private static final int STORAGE_STATUS_NONE = 2; - - private static final boolean SWITCH_CAMERA = true; - private static final boolean SWITCH_VIDEO = false; - - private SharedPreferences mPreferences; - - private PreviewFrameLayout mPreviewFrameLayout; - private SurfaceView mVideoPreview; - private SurfaceHolder mSurfaceHolder = null; - private ImageView mVideoFrame; - - private boolean mIsVideoCaptureIntent; - // mLastPictureButton and mThumbController - // are non-null only if mIsVideoCaptureIntent is true. - private ImageView mLastPictureButton; - private ThumbnailController mThumbController; - private boolean mStartPreviewFail = false; - - private int mStorageStatus = STORAGE_STATUS_OK; - - private MediaRecorder mMediaRecorder; - private boolean mMediaRecorderRecording = false; - private long mRecordingStartTime; - // The video file that the hardware camera is about to record into - // (or is recording into.) - private String mCameraVideoFilename; - private FileDescriptor mCameraVideoFileDescriptor; - - // The video file that has already been recorded, and that is being - // examined by the user. - private String mCurrentVideoFilename; - private Uri mCurrentVideoUri; - private ContentValues mCurrentVideoValues; - - private MediaRecorderProfile mProfile; - - // The video duration limit. 0 menas no limit. - private int mMaxVideoDurationInMs; - - boolean mPausing = false; - boolean mPreviewing = false; // True if preview is started. - - private ContentResolver mContentResolver; - - private ShutterButton mShutterButton; - private TextView mRecordingTimeView; - private View mGripper; - private Switcher mSwitcher; - private boolean mRecordingTimeCountsDown = false; - - private final ArrayList<MenuItem> mGalleryItems = new ArrayList<MenuItem>(); - - private final Handler mHandler = new MainHandler(); - private Parameters mParameters; - private OnScreenSettings mSettings; - - // This Handler is used to post message back onto the main thread of the - // application - private class MainHandler extends Handler { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - - case CLEAR_SCREEN_DELAY: { - getWindow().clearFlags( - WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - break; - } - - case UPDATE_RECORD_TIME: { - updateRecordingTime(); - break; - } - - case INIT_RECORDER: { - initializeRecorder(); - break; - } - - default: - Log.v(TAG, "Unhandled message: " + msg.what); - break; - } - } - } - - private BroadcastReceiver mReceiver = null; - - private class MyBroadcastReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(Intent.ACTION_MEDIA_EJECT)) { - updateAndShowStorageHint(false); - stopVideoRecording(); - } else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) { - updateAndShowStorageHint(true); - initializeRecorder(); - } else if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED)) { - // SD card unavailable - // handled in ACTION_MEDIA_EJECT - } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) { - Toast.makeText(VideoCamera.this, - getResources().getString(R.string.wait), 5000); - } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) { - updateAndShowStorageHint(true); - } - } - } - - private static String createName(long dateTaken) { - return DateFormat.format("yyyy-MM-dd kk.mm.ss", dateTaken).toString(); - } - - private void showCameraBusyAndFinish() { - Resources ress = getResources(); - Util.showFatalErrorAndFinish(VideoCamera.this, - ress.getString(R.string.camera_error_title), - ress.getString(R.string.cannot_connect_camera)); - } - - /** Called with the activity is first created. */ - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - mPreferences = PreferenceManager.getDefaultSharedPreferences(this); - CameraSettings.upgradePreferences(mPreferences); - - readVideoPreferences(); - - /* - * To reduce startup time, we start the preview in another thread. - * We make sure the preview is started at the end of onCreate. - */ - Thread startPreviewThread = new Thread(new Runnable() { - public void run() { - try { - mStartPreviewFail = false; - startPreview(); - } catch (CameraHardwareException e) { - // In eng build, we throw the exception so that test tool - // can detect it and report it - if ("eng".equals(Build.TYPE)) { - throw new RuntimeException(e); - } - mStartPreviewFail = true; - } - } - }); - startPreviewThread.start(); - - mContentResolver = getContentResolver(); - - requestWindowFeature(Window.FEATURE_PROGRESS); - setContentView(R.layout.video_camera); - - mPreviewFrameLayout = (PreviewFrameLayout) - findViewById(R.id.frame_layout); - mPreviewFrameLayout.setOnSizeChangedListener(this); - resizeForPreviewAspectRatio(); - - mVideoPreview = (SurfaceView) findViewById(R.id.camera_preview); - mVideoFrame = (ImageView) findViewById(R.id.video_frame); - - // don't set mSurfaceHolder here. We have it set ONLY within - // surfaceCreated / surfaceDestroyed, other parts of the code - // assume that when it is set, the surface is also set. - SurfaceHolder holder = mVideoPreview.getHolder(); - holder.addCallback(this); - holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); - - mIsVideoCaptureIntent = isVideoCaptureIntent(); - mRecordingTimeView = (TextView) findViewById(R.id.recording_time); - - ViewGroup rootView = (ViewGroup) findViewById(R.id.video_camera); - LayoutInflater inflater = this.getLayoutInflater(); - if (!mIsVideoCaptureIntent) { - View controlBar = inflater.inflate( - R.layout.camera_control, rootView); - mLastPictureButton = - (ImageView) controlBar.findViewById(R.id.review_thumbnail); - mThumbController = new ThumbnailController( - getResources(), mLastPictureButton, mContentResolver); - mLastPictureButton.setOnClickListener(this); - mThumbController.loadData(ImageManager.getLastVideoThumbPath()); - mSwitcher = ((Switcher) findViewById(R.id.camera_switch)); - mSwitcher.setOnSwitchListener(this); - mSwitcher.addTouchView(findViewById(R.id.camera_switch_set)); - } else { - View controlBar = inflater.inflate( - R.layout.attach_camera_control, rootView); - controlBar.findViewById(R.id.btn_cancel).setOnClickListener(this); - ImageView retake = - (ImageView) controlBar.findViewById(R.id.btn_retake); - retake.setOnClickListener(this); - retake.setImageResource(R.drawable.btn_ic_review_retake_video); - controlBar.findViewById(R.id.btn_play).setOnClickListener(this); - controlBar.findViewById(R.id.btn_done).setOnClickListener(this); - } - - mShutterButton = (ShutterButton) findViewById(R.id.shutter_button); - mShutterButton.setImageResource(R.drawable.btn_ic_video_record); - mShutterButton.setOnShutterButtonListener(this); - mShutterButton.requestFocus(); - mGripper = findViewById(R.id.btn_gripper); - mGripper.setOnTouchListener(new GripperTouchListener()); - - // Make sure preview is started. - try { - startPreviewThread.join(); - if (mStartPreviewFail) { - showCameraBusyAndFinish(); - return; - } - } catch (InterruptedException ex) { - // ignore - } - } - - @Override - protected void onStart() { - super.onStart(); - if (!mIsVideoCaptureIntent) { - mSwitcher.setSwitch(SWITCH_VIDEO); - } - } - - private void startShareVideoActivity() { - Intent intent = new Intent(); - intent.setAction(Intent.ACTION_SEND); - intent.setType("video/3gpp"); - intent.putExtra(Intent.EXTRA_STREAM, mCurrentVideoUri); - try { - startActivity(Intent.createChooser(intent, - getText(R.string.sendVideo))); - } catch (android.content.ActivityNotFoundException ex) { - Toast.makeText(VideoCamera.this, R.string.no_way_to_share_video, - Toast.LENGTH_SHORT).show(); - } - } - - private void startPlayVideoActivity() { - Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri); - try { - startActivity(intent); - } catch (android.content.ActivityNotFoundException ex) { - Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex); - } - } - - - public void onClick(View v) { - switch (v.getId()) { - case R.id.btn_retake: - discardCurrentVideoAndInitRecorder(); - break; - case R.id.btn_play: - startPlayVideoActivity(); - break; - case R.id.btn_done: - doReturnToCaller(true); - break; - case R.id.btn_cancel: - stopVideoRecording(); - doReturnToCaller(false); - break; - case R.id.discard: { - Runnable deleteCallback = new Runnable() { - public void run() { - discardCurrentVideoAndInitRecorder(); - } - }; - MenuHelper.deleteVideo(this, deleteCallback); - break; - } - case R.id.share: { - startShareVideoActivity(); - break; - } - case R.id.play: { - doPlayCurrentVideo(); - break; - } - case R.id.review_thumbnail: { - stopVideoRecordingAndShowReview(); - initializeRecorder(); - break; - } - } - } - - public void onShutterButtonFocus(ShutterButton button, boolean pressed) { - // Do nothing (everything happens in onShutterButtonClick). - } - - public void onShutterButtonClick(ShutterButton button) { - switch (button.getId()) { - case R.id.shutter_button: - if (mMediaRecorderRecording) { - if (mIsVideoCaptureIntent) { - stopVideoRecordingAndShowAlert(); - } else { - stopVideoRecordingAndGetThumbnail(); - initializeRecorder(); - } - } else if (mMediaRecorder != null) { - // If the click comes before recorder initialization, it is - // ignored. If users click the button during initialization, - // the event is put in the queue and record will be started - // eventually. - startVideoRecording(); - } - break; - } - } - - private void doPlayCurrentVideo() { - Log.v(TAG, "Playing current video: " + mCurrentVideoUri); - Intent intent = new Intent(Intent.ACTION_VIEW, mCurrentVideoUri); - try { - startActivity(intent); - } catch (android.content.ActivityNotFoundException ex) { - Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex); - } - } - - private void discardCurrentVideoAndInitRecorder() { - deleteCurrentVideo(); - hideAlertAndInitializeRecorder(); - } - - private OnScreenHint mStorageHint; - - private void updateAndShowStorageHint(boolean mayHaveSd) { - mStorageStatus = getStorageStatus(mayHaveSd); - showStorageHint(); - } - - private void showStorageHint() { - String errorMessage = null; - switch (mStorageStatus) { - case STORAGE_STATUS_NONE: - errorMessage = getString(R.string.no_storage); - break; - case STORAGE_STATUS_LOW: - errorMessage = getString(R.string.spaceIsLow_content); - } - if (errorMessage != null) { - if (mStorageHint == null) { - mStorageHint = OnScreenHint.makeText(this, errorMessage); - } else { - mStorageHint.setText(errorMessage); - } - mStorageHint.show(); - } else if (mStorageHint != null) { - mStorageHint.cancel(); - mStorageHint = null; - } - } - - private int getStorageStatus(boolean mayHaveSd) { - long remaining = mayHaveSd ? getAvailableStorage() : NO_STORAGE_ERROR; - if (remaining == NO_STORAGE_ERROR) { - return STORAGE_STATUS_NONE; - } - return remaining < LOW_STORAGE_THRESHOLD - ? STORAGE_STATUS_LOW - : STORAGE_STATUS_OK; - } - - private void readVideoPreferences() { - boolean videoQualityHigh = - getBooleanPreference(CameraSettings.KEY_VIDEO_QUALITY, - CameraSettings.DEFAULT_VIDEO_QUALITY_VALUE); - - // Set video quality. - Intent intent = getIntent(); - if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) { - int extraVideoQuality = - intent.getIntExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); - videoQualityHigh = (extraVideoQuality > 0); - } - - // Set video duration limit. The limit is read from the preference, - // unless it is specified in the intent. - if (intent.hasExtra(MediaStore.EXTRA_DURATION_LIMIT)) { - int seconds = - intent.getIntExtra(MediaStore.EXTRA_DURATION_LIMIT, 0); - mMaxVideoDurationInMs = 1000 * seconds; - } else { - int minutes = getIntPreference(CameraSettings.KEY_VIDEO_DURATION, - CameraSettings.DEFAULT_VIDEO_DURATION_VALUE); - if (minutes == -1) { - // This is a special case: the value -1 means we want to use the - // device-dependent duration for MMS messages. The value is - // represented in seconds. - mMaxVideoDurationInMs = - 1000 * CameraSettings.MMS_VIDEO_DURATION; - } else { - // 1 minute = 60000ms - mMaxVideoDurationInMs = 60000 * minutes; - } - } - - mProfile = new MediaRecorderProfile(videoQualityHigh); - } - - private void resizeForPreviewAspectRatio() { - mPreviewFrameLayout.setAspectRatio( - (double) mProfile.mVideoWidth / mProfile.mVideoHeight); - } - - @Override - public void onResume() { - super.onResume(); - mPausing = false; - - readVideoPreferences(); - resizeForPreviewAspectRatio(); - if (!mPreviewing && !mStartPreviewFail) { - try { - startPreview(); - } catch (CameraHardwareException e) { - showCameraBusyAndFinish(); - return; - } - } - keepScreenOnAwhile(); - - // install an intent filter to receive SD card related events. - IntentFilter intentFilter = - new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); - intentFilter.addAction(Intent.ACTION_MEDIA_EJECT); - intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); - intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); - intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); - intentFilter.addDataScheme("file"); - mReceiver = new MyBroadcastReceiver(); - registerReceiver(mReceiver, intentFilter); - mStorageStatus = getStorageStatus(true); - - mHandler.postDelayed(new Runnable() { - public void run() { - showStorageHint(); - } - }, 200); - - if (mSurfaceHolder != null) { - mHandler.sendEmptyMessage(INIT_RECORDER); - } - } - - private void setPreviewDisplay(SurfaceHolder holder) { - try { - mCameraDevice.setPreviewDisplay(holder); - } catch (Throwable ex) { - closeCamera(); - throw new RuntimeException("setPreviewDisplay failed", ex); - } - } - - private void startPreview() throws CameraHardwareException { - Log.v(TAG, "startPreview"); - if (mPreviewing) { - // After recording a video, preview is not stopped. So just return. - return; - } - - if (mCameraDevice == null) { - // If the activity is paused and resumed, camera device has been - // released and we need to open the camera. - mCameraDevice = CameraHolder.instance().open(); - } - - mCameraDevice.lock(); - setCameraParameters(); - setPreviewDisplay(mSurfaceHolder); - - try { - mCameraDevice.startPreview(); - mPreviewing = true; - } catch (Throwable ex) { - closeCamera(); - throw new RuntimeException("startPreview failed", ex); - } - - // If setPreviewDisplay has been set with a valid surface, unlock now. - // If surface is null, unlock later. Otherwise, setPreviewDisplay in - // surfaceChanged will fail. - if (mSurfaceHolder != null) { - mCameraDevice.unlock(); - } - } - - private void closeCamera() { - Log.v(TAG, "closeCamera"); - if (mCameraDevice == null) { - Log.d(TAG, "already stopped."); - return; - } - // If we don't lock the camera, release() will fail. - mCameraDevice.lock(); - CameraHolder.instance().release(); - mCameraDevice = null; - mPreviewing = false; - } - - @Override - protected void onPause() { - super.onPause(); - - mPausing = true; - - if (mSettings != null && mSettings.isVisible()) { - mSettings.setVisible(false); - } - - // This is similar to what mShutterButton.performClick() does, - // but not quite the same. - if (mMediaRecorderRecording) { - if (mIsVideoCaptureIntent) { - stopVideoRecording(); - showAlert(); - } else { - stopVideoRecordingAndGetThumbnail(); - } - } else { - stopVideoRecording(); - } - closeCamera(); - - if (mReceiver != null) { - unregisterReceiver(mReceiver); - mReceiver = null; - } - resetScreenOn(); - - if (!mIsVideoCaptureIntent) { - mThumbController.storeData(ImageManager.getLastVideoThumbPath()); - } - - if (mStorageHint != null) { - mStorageHint.cancel(); - mStorageHint = null; - } - - mHandler.removeMessages(INIT_RECORDER); - } - - @Override - public void onUserInteraction() { - super.onUserInteraction(); - if (!mMediaRecorderRecording) keepScreenOnAwhile(); - } - - @Override - public void onBackPressed() { - if (mPausing) return; - if (mMediaRecorderRecording) { - mShutterButton.performClick(); - return; - } - super.onBackPressed(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - // Do not handle any key if the activity is paused. - if (mPausing) { - return true; - } - - switch (keyCode) { - case KeyEvent.KEYCODE_CAMERA: - if (event.getRepeatCount() == 0) { - mShutterButton.performClick(); - return true; - } - break; - case KeyEvent.KEYCODE_DPAD_CENTER: - if (event.getRepeatCount() == 0) { - mShutterButton.performClick(); - return true; - } - break; - case KeyEvent.KEYCODE_MENU: - if (mMediaRecorderRecording) { - mShutterButton.performClick(); - return true; - } - break; - } - - return super.onKeyDown(keyCode, event); - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_CAMERA: - mShutterButton.setPressed(false); - return true; - case KeyEvent.KEYCODE_MENU: - if (this.mIsVideoCaptureIntent) { - showOnScreenSettings(); - return true; - } - break; - } - return super.onKeyUp(keyCode, event); - } - - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - // Make sure we have a surface in the holder before proceeding. - if (holder.getSurface() == null) { - Log.d(TAG, "holder.getSurface() == null"); - return; - } - - if (mPausing) { - // We're pausing, the screen is off and we already stopped - // video recording. We don't want to start the camera again - // in this case in order to conserve power. - // The fact that surfaceChanged is called _after_ an onPause appears - // to be legitimate since in that case the lockscreen always returns - // to portrait orientation possibly triggering the notification. - return; - } - - // The mCameraDevice will be null if it is fail to connect to the - // camera hardware. In this case we will show a dialog and then - // finish the activity, so it's OK to ignore it. - if (mCameraDevice == null) return; - - if (mMediaRecorderRecording) { - stopVideoRecording(); - } - - // Set preview display if the surface is being created. Preview was - // already started. - if (holder.isCreating()) { - setPreviewDisplay(holder); - mCameraDevice.unlock(); - mHandler.sendEmptyMessage(INIT_RECORDER); - } - } - - public void surfaceCreated(SurfaceHolder holder) { - mSurfaceHolder = holder; - } - - public void surfaceDestroyed(SurfaceHolder holder) { - mSurfaceHolder = null; - } - - private void gotoGallery() { - MenuHelper.gotoCameraVideoGallery(this); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - - if (mIsVideoCaptureIntent) { - // No options menu for attach mode. - return false; - } else { - addBaseMenuItems(menu); - } - return true; - } - - private boolean isVideoCaptureIntent() { - String action = getIntent().getAction(); - return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action)); - } - - private void doReturnToCaller(boolean success) { - Intent resultIntent = new Intent(); - int resultCode; - if (success) { - resultCode = RESULT_OK; - resultIntent.setData(mCurrentVideoUri); - } else { - resultCode = RESULT_CANCELED; - } - setResult(resultCode, resultIntent); - finish(); - } - - /** - * Returns - * - * @return number of bytes available, or an ERROR code. - */ - private static long getAvailableStorage() { - try { - if (!ImageManager.hasStorage()) { - return NO_STORAGE_ERROR; - } else { - String storageDirectory = - Environment.getExternalStorageDirectory().toString(); - StatFs stat = new StatFs(storageDirectory); - return (long) stat.getAvailableBlocks() - * (long) stat.getBlockSize(); - } - } catch (RuntimeException ex) { - // if we can't stat the filesystem then we don't know how many - // free bytes exist. It might be zero but just leave it - // blank since we really don't know. - return CANNOT_STAT_ERROR; - } - } - - private void cleanupEmptyFile() { - if (mCameraVideoFilename != null) { - File f = new File(mCameraVideoFilename); - if (f.length() == 0 && f.delete()) { - Log.v(TAG, "Empty video file deleted: " + mCameraVideoFilename); - mCameraVideoFilename = null; - } - } - } - - private android.hardware.Camera mCameraDevice; - - // Prepares media recorder. - private void initializeRecorder() { - Log.v(TAG, "initializeRecorder"); - if (mMediaRecorder != null) return; - - // We will call initializeRecorder() again when the alert is hidden. - // If the mCameraDevice is null, then this activity is going to finish - if (isAlertVisible() || mCameraDevice == null) return; - - Intent intent = getIntent(); - Bundle myExtras = intent.getExtras(); - - long requestedSizeLimit = 0; - if (mIsVideoCaptureIntent && myExtras != null) { - Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); - if (saveUri != null) { - try { - mCameraVideoFileDescriptor = - mContentResolver.openFileDescriptor(saveUri, "rw") - .getFileDescriptor(); - mCurrentVideoUri = saveUri; - } catch (java.io.FileNotFoundException ex) { - // invalid uri - Log.e(TAG, ex.toString()); - } - } - requestedSizeLimit = myExtras.getLong(MediaStore.EXTRA_SIZE_LIMIT); - } - mMediaRecorder = new MediaRecorder(); - - mMediaRecorder.setCamera(mCameraDevice); - mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); - mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); - mMediaRecorder.setOutputFormat(mProfile.mOutputFormat); - mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs); - - // Set output file. - if (mStorageStatus != STORAGE_STATUS_OK) { - mMediaRecorder.setOutputFile("/dev/null"); - } else { - // Try Uri in the intent first. If it doesn't exist, use our own - // instead. - if (mCameraVideoFileDescriptor != null) { - mMediaRecorder.setOutputFile(mCameraVideoFileDescriptor); - } else { - createVideoPath(); - mMediaRecorder.setOutputFile(mCameraVideoFilename); - } - } - - // Use the same frame rate for both, since internally - // if the frame rate is too large, it can cause camera to become - // unstable. We need to fix the MediaRecorder to disable the support - // of setting frame rate for now. - mMediaRecorder.setVideoFrameRate(mProfile.mVideoFps); - mMediaRecorder.setVideoSize( - mProfile.mVideoWidth, mProfile.mVideoHeight); - mMediaRecorder.setParameters(String.format( - "video-param-encoding-bitrate=%d", mProfile.mVideoBitrate)); - mMediaRecorder.setParameters(String.format( - "audio-param-encoding-bitrate=%d", mProfile.mAudioBitrate)); - mMediaRecorder.setParameters(String.format( - "audio-param-number-of-channels=%d", mProfile.mAudioChannels)); - mMediaRecorder.setParameters(String.format( - "audio-param-sampling-rate=%d", mProfile.mAudioSamplingRate)); - mMediaRecorder.setVideoEncoder(mProfile.mVideoEncoder); - mMediaRecorder.setAudioEncoder(mProfile.mAudioEncoder); - mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); - - // Set maximum file size. - // remaining >= LOW_STORAGE_THRESHOLD at this point, reserve a quarter - // of that to make it more likely that recording can complete - // successfully. - long maxFileSize = getAvailableStorage() - LOW_STORAGE_THRESHOLD / 4; - if (requestedSizeLimit > 0 && requestedSizeLimit < maxFileSize) { - maxFileSize = requestedSizeLimit; - } - - try { - mMediaRecorder.setMaxFileSize(maxFileSize); - } catch (RuntimeException exception) { - // We are going to ignore failure of setMaxFileSize here, as - // a) The composer selected may simply not support it, or - // b) The underlying media framework may not handle 64-bit range - // on the size restriction. - } - - try { - mMediaRecorder.prepare(); - } catch (IOException e) { - Log.e(TAG, "prepare failed for " + mCameraVideoFilename); - releaseMediaRecorder(); - throw new RuntimeException(e); - } - mMediaRecorderRecording = false; - - // Update the last video thumbnail. - if (!mIsVideoCaptureIntent) { - if (!mThumbController.isUriValid()) { - updateLastVideo(); - } - mThumbController.updateDisplayIfNeeded(); - } - } - - private void releaseMediaRecorder() { - Log.v(TAG, "Releasing media recorder."); - if (mMediaRecorder != null) { - cleanupEmptyFile(); - mMediaRecorder.reset(); - mMediaRecorder.release(); - mMediaRecorder = null; - } - } - - private int getIntPreference(String key, int defaultValue) { - String s = mPreferences.getString(key, ""); - int result = defaultValue; - try { - result = Integer.parseInt(s); - } catch (NumberFormatException e) { - // Ignore, result is already the default value. - } - return result; - } - - private boolean getBooleanPreference(String key, boolean defaultValue) { - return getIntPreference(key, defaultValue ? 1 : 0) != 0; - } - - private void createVideoPath() { - long dateTaken = System.currentTimeMillis(); - String title = createName(dateTaken); - String displayName = title + ".3gp"; // Used when emailing. - String cameraDirPath = ImageManager.CAMERA_IMAGE_BUCKET_NAME; - File cameraDir = new File(cameraDirPath); - cameraDir.mkdirs(); - SimpleDateFormat dateFormat = new SimpleDateFormat( - getString(R.string.video_file_name_format)); - Date date = new Date(dateTaken); - String filepart = dateFormat.format(date); - String filename = cameraDirPath + "/" + filepart + ".3gp"; - ContentValues values = new ContentValues(7); - values.put(Video.Media.TITLE, title); - values.put(Video.Media.DISPLAY_NAME, displayName); - values.put(Video.Media.DATE_TAKEN, dateTaken); - values.put(Video.Media.MIME_TYPE, "video/3gpp"); - values.put(Video.Media.DATA, filename); - mCameraVideoFilename = filename; - Log.v(TAG, "Current camera video filename: " + mCameraVideoFilename); - mCurrentVideoValues = values; - } - - private void registerVideo() { - if (mCameraVideoFileDescriptor == null) { - Uri videoTable = Uri.parse("content://media/external/video/media"); - mCurrentVideoValues.put(Video.Media.SIZE, - new File(mCurrentVideoFilename).length()); - mCurrentVideoUri = mContentResolver.insert(videoTable, - mCurrentVideoValues); - Log.v(TAG, "Current video URI: " + mCurrentVideoUri); - } - mCurrentVideoValues = null; - } - - private void deleteCurrentVideo() { - if (mCurrentVideoFilename != null) { - deleteVideoFile(mCurrentVideoFilename); - mCurrentVideoFilename = null; - } - if (mCurrentVideoUri != null) { - mContentResolver.delete(mCurrentVideoUri, null, null); - mCurrentVideoUri = null; - } - updateAndShowStorageHint(true); - } - - private void deleteVideoFile(String fileName) { - Log.v(TAG, "Deleting video " + fileName); - File f = new File(fileName); - if (!f.delete()) { - Log.v(TAG, "Could not delete " + fileName); - } - } - - private void addBaseMenuItems(Menu menu) { - MenuItem gallery = menu.add(Menu.NONE, Menu.NONE, - MenuHelper.POSITION_GOTO_GALLERY, - R.string.camera_gallery_photos_text) - .setOnMenuItemClickListener( - new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - gotoGallery(); - return true; - } - }); - gallery.setIcon(android.R.drawable.ic_menu_gallery); - mGalleryItems.add(gallery); - - MenuItem item = menu.add(Menu.NONE, Menu.NONE, - MenuHelper.POSITION_CAMERA_SETTING, R.string.settings) - .setOnMenuItemClickListener(new OnMenuItemClickListener() { - public boolean onMenuItemClick(MenuItem item) { - showOnScreenSettings(); - return true; - }}); - item.setIcon(android.R.drawable.ic_menu_preferences); - } - - private void showOnScreenSettings() { - if (mSettings == null) { - mSettings = new OnScreenSettings( - findViewById(R.id.camera_preview)); - CameraSettings helper = new CameraSettings(this, mParameters); - PreferenceScreen screen = helper - .getPreferenceScreen(R.xml.video_preferences); - if (mIsVideoCaptureIntent) { - screen = filterPreferenceScreenByIntent(screen); - } - - mSettings.setPreferenceScreen(screen); - mSettings.setOnVisibilityChangedListener(this); - } - mSettings.setVisible(true); - } - - private PreferenceScreen filterPreferenceScreenByIntent( - PreferenceScreen screen) { - Intent intent = getIntent(); - if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) { - CameraSettings.removePreferenceFromScreen(screen, - CameraSettings.KEY_VIDEO_QUALITY); - } - - if (intent.hasExtra(MediaStore.EXTRA_DURATION_LIMIT)) { - CameraSettings.removePreferenceFromScreen(screen, - CameraSettings.KEY_VIDEO_DURATION); - } - return screen; - } - - private class GripperTouchListener implements View.OnTouchListener { - public boolean onTouch(View view, MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - return true; - case MotionEvent.ACTION_UP: - showOnScreenSettings(); - return true; - } - return false; - } - } - - public void onVisibilityChanged(boolean visible) { - // At this point, we are not recording. - mGripper.setVisibility(visible ? View.INVISIBLE : View.VISIBLE); - if (visible) { - releaseMediaRecorder(); - mPreferences.registerOnSharedPreferenceChangeListener(this); - } else { - initializeRecorder(); - mPreferences.unregisterOnSharedPreferenceChangeListener(this); - } - } - - // from MediaRecorder.OnErrorListener - public void onError(MediaRecorder mr, int what, int extra) { - if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) { - // We may have run out of space on the sdcard. - stopVideoRecording(); - updateAndShowStorageHint(true); - } - } - - // from MediaRecorder.OnInfoListener - public void onInfo(MediaRecorder mr, int what, int extra) { - if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { - mShutterButton.performClick(); - } else if (what - == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) { - mShutterButton.performClick(); - // Show the toast. - Toast.makeText(VideoCamera.this, R.string.video_reach_size_limit, - Toast.LENGTH_LONG).show(); - } - } - - /* - * Make sure we're not recording music playing in the background, ask the - * MediaPlaybackService to pause playback. - */ - private void pauseAudioPlayback() { - // Shamelessly copied from MediaPlaybackService.java, which - // should be public, but isn't. - Intent i = new Intent("com.android.music.musicservicecommand"); - i.putExtra("command", "pause"); - - sendBroadcast(i); - } - - private void startVideoRecording() { - Log.v(TAG, "startVideoRecording"); - if (!mMediaRecorderRecording) { - - if (mStorageStatus != STORAGE_STATUS_OK) { - Log.v(TAG, "Storage issue, ignore the start request"); - return; - } - - // Check mMediaRecorder to see whether it is initialized or not. - if (mMediaRecorder == null) { - Log.e(TAG, "MediaRecorder is not initialized."); - return; - } - - pauseAudioPlayback(); - - try { - mMediaRecorder.setOnErrorListener(this); - mMediaRecorder.setOnInfoListener(this); - mMediaRecorder.start(); // Recording is now started - } catch (RuntimeException e) { - Log.e(TAG, "Could not start media recorder. ", e); - return; - } - mMediaRecorderRecording = true; - mRecordingStartTime = SystemClock.uptimeMillis(); - updateRecordingIndicator(false); - mRecordingTimeView.setText(""); - mRecordingTimeView.setVisibility(View.VISIBLE); - updateRecordingTime(); - keepScreenOn(); - mGripper.setVisibility(View.INVISIBLE); - } - } - - private void updateRecordingIndicator(boolean showRecording) { - int drawableId = - showRecording ? R.drawable.btn_ic_video_record - : R.drawable.btn_ic_video_record_stop; - Drawable drawable = getResources().getDrawable(drawableId); - mShutterButton.setImageDrawable(drawable); - } - - private void stopVideoRecordingAndGetThumbnail() { - stopVideoRecording(); - acquireVideoThumb(); - } - - private void stopVideoRecordingAndShowAlert() { - stopVideoRecording(); - showAlert(); - } - - private void showAlert() { - fadeOut(findViewById(R.id.shutter_button)); - if (mCurrentVideoFilename != null) { - mVideoFrame.setImageBitmap( - ThumbnailUtil.createVideoThumbnail(mCurrentVideoFilename)); - mVideoFrame.setVisibility(View.VISIBLE); - } - int[] pickIds = {R.id.btn_retake, R.id.btn_done, R.id.btn_play}; - for (int id : pickIds) { - View button = findViewById(id); - fadeIn(((View) button.getParent())); - } - } - - private void hideAlert() { - mVideoFrame.setVisibility(View.INVISIBLE); - fadeIn(findViewById(R.id.shutter_button)); - int[] pickIds = {R.id.btn_retake, R.id.btn_done, R.id.btn_play}; - for (int id : pickIds) { - View button = findViewById(id); - fadeOut(((View) button.getParent())); - } - } - - private static void fadeIn(View view) { - view.setVisibility(View.VISIBLE); - Animation animation = new AlphaAnimation(0F, 1F); - animation.setDuration(500); - view.startAnimation(animation); - } - - private static void fadeOut(View view) { - view.setVisibility(View.INVISIBLE); - Animation animation = new AlphaAnimation(1F, 0F); - animation.setDuration(500); - view.startAnimation(animation); - } - - private boolean isAlertVisible() { - return this.mVideoFrame.getVisibility() == View.VISIBLE; - } - - private void stopVideoRecordingAndShowReview() { - stopVideoRecording(); - if (mThumbController.isUriValid()) { - Uri targetUri = mThumbController.getUri(); - Intent intent = new Intent(this, ReviewImage.class); - intent.setData(targetUri); - intent.putExtra(MediaStore.EXTRA_FULL_SCREEN, true); - intent.putExtra(MediaStore.EXTRA_SHOW_ACTION_ICONS, true); - intent.putExtra("com.android.camera.ReviewMode", true); - try { - startActivity(intent); - } catch (ActivityNotFoundException ex) { - Log.e(TAG, "review video fail", ex); - } - } else { - Log.e(TAG, "Can't view last video."); - } - } - - private void stopVideoRecording() { - Log.v(TAG, "stopVideoRecording"); - boolean needToRegisterRecording = false; - if (mMediaRecorderRecording || mMediaRecorder != null) { - if (mMediaRecorderRecording && mMediaRecorder != null) { - try { - mMediaRecorder.setOnErrorListener(null); - mMediaRecorder.setOnInfoListener(null); - mMediaRecorder.stop(); - } catch (RuntimeException e) { - Log.e(TAG, "stop fail: " + e.getMessage()); - } - - mCurrentVideoFilename = mCameraVideoFilename; - Log.v(TAG, "Setting current video filename: " - + mCurrentVideoFilename); - needToRegisterRecording = true; - mMediaRecorderRecording = false; - } - releaseMediaRecorder(); - updateRecordingIndicator(true); - mRecordingTimeView.setVisibility(View.GONE); - keepScreenOnAwhile(); - mGripper.setVisibility(View.VISIBLE); - } - if (needToRegisterRecording && mStorageStatus == STORAGE_STATUS_OK) { - registerVideo(); - } - - mCameraVideoFilename = null; - mCameraVideoFileDescriptor = null; - } - - private void resetScreenOn() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - - private void keepScreenOnAwhile() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); - } - - private void keepScreenOn() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - - private void hideAlertAndInitializeRecorder() { - hideAlert(); - mHandler.sendEmptyMessage(INIT_RECORDER); - } - - private void acquireVideoThumb() { - Bitmap videoFrame = ThumbnailUtil.createVideoThumbnail(mCurrentVideoFilename); - mThumbController.setData(mCurrentVideoUri, videoFrame); - } - - private static ImageManager.DataLocation dataLocation() { - return ImageManager.DataLocation.EXTERNAL; - } - - private void updateLastVideo() { - IImageList list = ImageManager.makeImageList( - mContentResolver, - dataLocation(), - ImageManager.INCLUDE_VIDEOS, - ImageManager.SORT_ASCENDING, - ImageManager.CAMERA_IMAGE_BUCKET_ID); - int count = list.getCount(); - if (count > 0) { - IImage image = list.getImageAt(count - 1); - Uri uri = image.fullSizeImageUri(); - mThumbController.setData(uri, image.miniThumbBitmap()); - } else { - mThumbController.setData(null, null); - } - list.close(); - } - - private void updateRecordingTime() { - if (!mMediaRecorderRecording) { - return; - } - long now = SystemClock.uptimeMillis(); - long delta = now - mRecordingStartTime; - - // Starting a minute before reaching the max duration - // limit, we'll countdown the remaining time instead. - boolean countdownRemainingTime = (mMaxVideoDurationInMs != 0 - && delta >= mMaxVideoDurationInMs - 60000); - - long next_update_delay = 1000 - (delta % 1000); - long seconds; - if (countdownRemainingTime) { - delta = Math.max(0, mMaxVideoDurationInMs - delta); - seconds = (delta + 999) / 1000; - } else { - seconds = delta / 1000; // round to nearest - } - - long minutes = seconds / 60; - long hours = minutes / 60; - long remainderMinutes = minutes - (hours * 60); - long remainderSeconds = seconds - (minutes * 60); - - String secondsString = Long.toString(remainderSeconds); - if (secondsString.length() < 2) { - secondsString = "0" + secondsString; - } - String minutesString = Long.toString(remainderMinutes); - if (minutesString.length() < 2) { - minutesString = "0" + minutesString; - } - String text = minutesString + ":" + secondsString; - if (hours > 0) { - String hoursString = Long.toString(hours); - if (hoursString.length() < 2) { - hoursString = "0" + hoursString; - } - text = hoursString + ":" + text; - } - mRecordingTimeView.setText(text); - - if (mRecordingTimeCountsDown != countdownRemainingTime) { - // Avoid setting the color on every update, do it only - // when it needs changing. - mRecordingTimeCountsDown = countdownRemainingTime; - - int color = getResources().getColor(countdownRemainingTime - ? R.color.recording_time_remaining_text - : R.color.recording_time_elapsed_text); - - mRecordingTimeView.setTextColor(color); - } - - mHandler.sendEmptyMessageDelayed( - UPDATE_RECORD_TIME, next_update_delay); - } - - private void setCameraParameters() { - mParameters = mCameraDevice.getParameters(); - - mParameters.setPreviewSize(mProfile.mVideoWidth, mProfile.mVideoHeight); - mParameters.setPreviewFrameRate(mProfile.mVideoFps); - - // Set white balance parameter. - if (mParameters.getSupportedWhiteBalance() != null) { - String whiteBalance = mPreferences.getString( - CameraSettings.KEY_WHITE_BALANCE, - getString(R.string.pref_camera_whitebalance_default)); - mParameters.setWhiteBalance(whiteBalance); - } - - // Set color effect parameter. - if (mParameters.getSupportedColorEffects() != null) { - String colorEffect = mPreferences.getString( - CameraSettings.KEY_COLOR_EFFECT, - getString(R.string.pref_camera_coloreffect_default)); - mParameters.setColorEffect(colorEffect); - } - - mCameraDevice.setParameters(mParameters); - } - - public boolean onSwitchChanged(Switcher source, boolean onOff) { - if (onOff == SWITCH_CAMERA) { - MenuHelper.gotoCameraMode(this); - finish(); - } - return true; - } - - public void onSharedPreferenceChanged( - SharedPreferences preferences, String key) { - // ignore the events after "onPause()" or preview has not started yet - if (mPausing) return; - - if (CameraSettings.KEY_VIDEO_DURATION.equals(key) - || CameraSettings.KEY_VIDEO_QUALITY.equals(key)) { - readVideoPreferences(); - } - - // If mCameraDevice is not ready then we can set the parameter in - // startPreview(). - if (mCameraDevice == null) return; - - // We need to restart the preview if preview size is changed. - Size size = mParameters.getPreviewSize(); - if (size.width != mProfile.mVideoWidth - || size.height != mProfile.mVideoHeight) { - // It is assumed media recorder is released before - // onSharedPreferenceChanged, so we can close the camera here. - closeCamera(); - try { - resizeForPreviewAspectRatio(); - startPreview(); // Parameters will be set in startPreview(). - } catch (CameraHardwareException e) { - showCameraBusyAndFinish(); - } - } else { - try { - // We need to lock the camera before writing parameters. - mCameraDevice.lock(); - } catch (RuntimeException e) { - // When preferences are added for the first time, this method - // will be called. But OnScreenSetting is not displayed yet and - // media recorder still owns the camera. Lock will fail and we - // just ignore it. - return; - } - setCameraParameters(); - mCameraDevice.unlock(); - } - } - - public void onSizeChanged() { - if (mSettings != null) { - mSettings.updateLayout(); - } - - } -} - -// -// DefaultHashMap is a HashMap which returns a default value if the specified -// key is not found. -// -@SuppressWarnings("serial") -class DefaultHashMap<K, V> extends HashMap<K, V> { - private V mDefaultValue; - - public void putDefault(V defaultValue) { - mDefaultValue = defaultValue; - } - - @Override - public V get(Object key) { - V value = super.get(key); - return (value == null) ? mDefaultValue : value; - } -} - -// -// MediaRecorderProfile reads from system properties to determine the proper -// values for various parameters for MediaRecorder. -// -class MediaRecorderProfile { - - @SuppressWarnings("unused") - private static final String TAG = "MediaRecorderProfile"; - public final boolean mHiQuality; - public final int mOutputFormat; - public final int mVideoEncoder; - public final int mAudioEncoder; - public final int mVideoWidth; - public final int mVideoHeight; - public final int mVideoFps; - public final int mVideoBitrate; - public final int mAudioBitrate; - public final int mAudioChannels; - public final int mAudioSamplingRate; - - MediaRecorderProfile(boolean hiQuality) { - mHiQuality = hiQuality; - - mOutputFormat = getFromTable("ro.media.enc.hprof.file.format", - "ro.media.enc.lprof.file.format", - OUTPUT_FORMAT_TABLE); - - mVideoEncoder = getFromTable("ro.media.enc.hprof.codec.vid", - "ro.media.enc.lprof.codec.vid", - VIDEO_ENCODER_TABLE); - - mAudioEncoder = getFromTable("ro.media.enc.hprof.codec.aud", - "ro.media.enc.lprof.codec.aud", - AUDIO_ENCODER_TABLE); - - mVideoWidth = getInt("ro.media.enc.hprof.vid.width", - "ro.media.enc.lprof.vid.width", - 352, 176); - - mVideoHeight = getInt("ro.media.enc.hprof.vid.height", - "ro.media.enc.lprof.vid.height", - 288, 144); - - mVideoFps = getInt("ro.media.enc.hprof.vid.fps", - "ro.media.enc.lprof.vid.fps", - 20, 20); - - mVideoBitrate = getInt("ro.media.enc.hprof.vid.bps", - "ro.media.enc.lprof.vid.bps", - 360000, 192000); - - mAudioBitrate = getInt("ro.media.enc.hprof.aud.bps", - "ro.media.enc.lprof.aud.bps", - 23450, 23450); - - mAudioChannels = getInt("ro.media.enc.hprof.aud.ch", - "ro.media.enc.lprof.aud.ch", - 1, 1); - - mAudioSamplingRate = getInt("ro.media.enc.hprof.aud.hz", - "ro.media.enc.lprof.aud.hz", - 8000, 8000); - } - - private int getFromTable(String highKey, String lowKey, - DefaultHashMap<String, Integer> table) { - String s; - s = SystemProperties.get(mHiQuality ? highKey : lowKey); - return table.get(s); - } - - private int getInt(String highKey, String lowKey, int highDefault, - int lowDefault) { - String key = mHiQuality ? highKey : lowKey; - int defaultValue = mHiQuality ? highDefault : lowDefault; - return SystemProperties.getInt(key, defaultValue); - } - - private static final DefaultHashMap<String, Integer> - OUTPUT_FORMAT_TABLE = new DefaultHashMap<String, Integer>(); - private static final DefaultHashMap<String, Integer> - VIDEO_ENCODER_TABLE = new DefaultHashMap<String, Integer>(); - private static final DefaultHashMap<String, Integer> - AUDIO_ENCODER_TABLE = new DefaultHashMap<String, Integer>(); - - static { - OUTPUT_FORMAT_TABLE.put("3gp", MediaRecorder.OutputFormat.THREE_GPP); - OUTPUT_FORMAT_TABLE.put("mp4", MediaRecorder.OutputFormat.MPEG_4); - OUTPUT_FORMAT_TABLE.putDefault(MediaRecorder.OutputFormat.DEFAULT); - - VIDEO_ENCODER_TABLE.put("h263", MediaRecorder.VideoEncoder.H263); - VIDEO_ENCODER_TABLE.put("h264", MediaRecorder.VideoEncoder.H264); - VIDEO_ENCODER_TABLE.put("m4v", MediaRecorder.VideoEncoder.MPEG_4_SP); - VIDEO_ENCODER_TABLE.putDefault(MediaRecorder.VideoEncoder.DEFAULT); - - AUDIO_ENCODER_TABLE.put("amrnb", MediaRecorder.AudioEncoder.AMR_NB); - AUDIO_ENCODER_TABLE.put("amrwb", MediaRecorder.AudioEncoder.AMR_WB); - AUDIO_ENCODER_TABLE.put("aac", MediaRecorder.AudioEncoder.AAC); - AUDIO_ENCODER_TABLE.put("aacplus", MediaRecorder.AudioEncoder.AAC_PLUS); - AUDIO_ENCODER_TABLE.put("eaacplus", - MediaRecorder.AudioEncoder.EAAC_PLUS); - AUDIO_ENCODER_TABLE.putDefault(MediaRecorder.AudioEncoder.DEFAULT); - } -} diff --git a/src/com/android/camera/gallery/BaseImage.java b/src/com/android/camera/gallery/BaseImage.java index 6e2f8f1..42d0f66 100644 --- a/src/com/android/camera/gallery/BaseImage.java +++ b/src/com/android/camera/gallery/BaseImage.java @@ -117,10 +117,6 @@ public abstract class BaseImage implements IImage { } } - public long fullSizeImageId() { - return mId; - } - public Uri fullSizeImageUri() { return mUri; } diff --git a/src/com/android/camera/gallery/IImage.java b/src/com/android/camera/gallery/IImage.java index bad41cc..8b443d6 100644 --- a/src/com/android/camera/gallery/IImage.java +++ b/src/com/android/camera/gallery/IImage.java @@ -47,7 +47,6 @@ public interface IImage { /** Get the input stream associated with a given full size image. */ public abstract InputStream fullSizeImageData(); - public abstract long fullSizeImageId(); public abstract Uri fullSizeImageUri(); /** Get the path of the (full size) image data. */ diff --git a/src/com/android/camera/gallery/UriImage.java b/src/com/android/camera/gallery/UriImage.java index 0db1633..0f27b24 100644 --- a/src/com/android/camera/gallery/UriImage.java +++ b/src/com/android/camera/gallery/UriImage.java @@ -156,10 +156,6 @@ class UriImage implements IImage { return (options != null) ? options.outWidth : 0; } - public long fullSizeImageId() { - return 0; - } - public IImageList getContainer() { return mContainer; } diff --git a/src/com/android/camera/gallery/VideoObject.java b/src/com/android/camera/gallery/VideoObject.java index 589e42f..d6e5060 100644 --- a/src/com/android/camera/gallery/VideoObject.java +++ b/src/com/android/camera/gallery/VideoObject.java @@ -79,11 +79,6 @@ public class VideoObject extends BaseImage implements IImage { } @Override - public long fullSizeImageId() { - return mId; - } - - @Override public int getHeight() { return 0; } @@ -125,4 +120,4 @@ public class VideoObject extends BaseImage implements IImage { public String toString() { return new StringBuilder("VideoObject").append(mId).toString(); } -}
\ No newline at end of file +} |