diff options
author | Sascha Haeberling <haeberling@google.com> | 2013-08-08 11:27:09 -0700 |
---|---|---|
committer | Sascha Haeberling <haeberling@google.com> | 2013-08-08 18:31:53 -0700 |
commit | 723bf81990245a07739146ac10357703c9839de1 (patch) | |
tree | 0c86a8a133077db5191907a760d5f4b3ab441b77 | |
parent | a6b80cccafe0a4c2de575ec69d1960c3c0d88062 (diff) | |
download | android_packages_apps_Gallery2-723bf81990245a07739146ac10357703c9839de1.tar.gz android_packages_apps_Gallery2-723bf81990245a07739146ac10357703c9839de1.tar.bz2 android_packages_apps_Gallery2-723bf81990245a07739146ac10357703c9839de1.zip |
Remove Camera from Gallery2.
Change-Id: I89adebffcacd1269217d7bd8c630c2f78886f590
151 files changed, 54 insertions, 30268 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ef1d91459..7aee8663d 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -42,11 +42,8 @@ android:logo="@mipmap/ic_launcher_gallery" android:hardwareAccelerated="true" android:largeHeap="true" - android:backupAgent="com.android.camera.CameraBackupAgent" android:restoreAnyVersion="true"> <uses-library android:name="com.google.android.media.effects" android:required="false" /> - <meta-data android:name="com.google.android.backup.api_key" - android:value="AEdPqrEAAAAIRIXquXawbz6duuuCIUAZ_YJv1zbFMMcjZ0NoVw" /> <activity android:name="com.android.gallery3d.app.MovieActivity" android:label="@string/movie_view_label" android:configChanges="orientation|keyboardHidden|screenSize"> @@ -288,81 +285,6 @@ <activity android:name="com.android.gallery3d.gadget.WidgetTypeChooser" android:configChanges="keyboardHidden|orientation|screenSize" android:theme="@style/Theme.Gallery.Dialog"/> - <activity android:name="com.android.camera.CameraActivity" - android:taskAffinity="com.android.camera.CameraActivity" - android:label="@string/camera_label" - android:theme="@style/Theme.Camera" - android:icon="@mipmap/ic_launcher_camera" - android:configChanges="orientation|screenSize|keyboardHidden" - android:clearTaskOnLaunch="true" - android:windowSoftInputMode="stateAlwaysHidden|adjustPan"> - <intent-filter> - <action android:name="android.media.action.IMAGE_CAPTURE" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - <intent-filter> - <action android:name="android.media.action.STILL_IMAGE_CAMERA" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - <meta-data android:name="com.android.keyguard.layout" - android:resource="@layout/keyguard_widget" /> - </activity> - - <activity android:name="com.android.camera.SecureCameraActivity" - android:taskAffinity="com.android.camera.SecureCameraActivity" - android:excludeFromRecents="true" - android:label="@string/camera_label" - android:theme="@style/Theme.Camera" - android:icon="@mipmap/ic_launcher_camera" - android:configChanges="orientation|screenSize|keyboardHidden" - android:clearTaskOnLaunch="true" - android:windowSoftInputMode="stateAlwaysHidden|adjustPan"> - <intent-filter> - <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - <intent-filter> - <action android:name="android.media.action.IMAGE_CAPTURE_SECURE" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - <meta-data android:name="com.android.keyguard.layout" - android:resource="@layout/keyguard_widget" /> - </activity> - - <activity-alias android:icon="@mipmap/ic_launcher_camera" - android:label="@string/camera_label" - android:name="com.android.camera.CameraLauncher" - android:targetActivity="com.android.camera.CameraActivity" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity-alias> - - <activity-alias android:icon="@mipmap/ic_launcher_camera" - android:label="@string/camera_label" - android:name="com.android.camera.Camera" - android:targetActivity="com.android.camera.CameraActivity" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity-alias> - - <activity-alias android:icon="@mipmap/ic_launcher_video_camera" - android:label="@string/video_camera_label" - android:name="com.android.camera.VideoCamera" - android:targetActivity="com.android.camera.CameraActivity" > - <intent-filter> - <action android:name="android.media.action.VIDEO_CAMERA" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - <intent-filter> - <action android:name="android.media.action.VIDEO_CAPTURE" /> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity-alias> <receiver android:name="com.android.gallery3d.gadget.PhotoAppWidgetProvider" android:label="@string/appwidget_title"> @@ -381,16 +303,6 @@ </intent-filter> </receiver> <service android:name="com.android.gallery3d.app.PackagesMonitor$AsyncService"/> - <receiver android:name="com.android.camera.CameraButtonIntentReceiver"> - <intent-filter> - <action android:name="android.intent.action.CAMERA_BUTTON"/> - </intent-filter> - </receiver> - <receiver android:name="com.android.camera.DisableCameraReceiver"> - <intent-filter> - <action android:name="android.intent.action.BOOT_COMPLETED" /> - </intent-filter> - </receiver> <service android:name="com.android.gallery3d.gadget.WidgetService" android:permission="android.permission.BIND_REMOTEVIEWS"/> <activity android:name="com.android.gallery3d.gadget.WidgetConfigure" @@ -400,9 +312,6 @@ <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> </intent-filter> </activity> - <activity android:name="com.android.camera.ProxyLauncher" - android:theme="@style/Theme.ProxyLauncher"> - </activity> <service android:name="com.android.gallery3d.app.BatchService" /> <service android:name="com.android.camera.MediaSaveService" /> </application> diff --git a/src/com/android/camera/AndroidCameraManagerImpl.java b/src/com/android/camera/AndroidCameraManagerImpl.java deleted file mode 100644 index 897aa9252..000000000 --- a/src/com/android/camera/AndroidCameraManagerImpl.java +++ /dev/null @@ -1,779 +0,0 @@ -/* - * Copyright (C) 2013 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.annotation.TargetApi; -import android.graphics.SurfaceTexture; -import android.hardware.Camera; -import android.hardware.Camera.AutoFocusCallback; -import android.hardware.Camera.AutoFocusMoveCallback; -import android.hardware.Camera.ErrorCallback; -import android.hardware.Camera.FaceDetectionListener; -import android.hardware.Camera.OnZoomChangeListener; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.PictureCallback; -import android.hardware.Camera.PreviewCallback; -import android.hardware.Camera.ShutterCallback; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.util.Log; -import android.view.SurfaceHolder; - -import com.android.gallery3d.common.ApiHelper; - -import java.io.IOException; - -/** - * A class to implement {@link CameraManager} of the Android camera framework. - */ -class AndroidCameraManagerImpl implements CameraManager { - private static final String TAG = "CAM_" + - AndroidCameraManagerImpl.class.getSimpleName(); - - private Parameters mParameters; - private boolean mParametersIsDirty; - private IOException mReconnectIOException; - - /* Messages used in CameraHandler. */ - // Camera initialization/finalization - private static final int OPEN_CAMERA = 1; - private static final int RELEASE = 2; - private static final int RECONNECT = 3; - private static final int UNLOCK = 4; - private static final int LOCK = 5; - // Preview - private static final int SET_PREVIEW_TEXTURE_ASYNC = 101; - private static final int START_PREVIEW_ASYNC = 102; - private static final int STOP_PREVIEW = 103; - private static final int SET_PREVIEW_CALLBACK_WITH_BUFFER = 104; - private static final int ADD_CALLBACK_BUFFER = 105; - private static final int SET_PREVIEW_DISPLAY_ASYNC = 106; - private static final int SET_PREVIEW_CALLBACK = 107; - // Parameters - private static final int SET_PARAMETERS = 201; - private static final int GET_PARAMETERS = 202; - private static final int REFRESH_PARAMETERS = 203; - // Focus, Zoom - private static final int AUTO_FOCUS = 301; - private static final int CANCEL_AUTO_FOCUS = 302; - private static final int SET_AUTO_FOCUS_MOVE_CALLBACK = 303; - private static final int SET_ZOOM_CHANGE_LISTENER = 304; - // Face detection - private static final int SET_FACE_DETECTION_LISTENER = 461; - private static final int START_FACE_DETECTION = 462; - private static final int STOP_FACE_DETECTION = 463; - private static final int SET_ERROR_CALLBACK = 464; - // Presentation - private static final int ENABLE_SHUTTER_SOUND = 501; - private static final int SET_DISPLAY_ORIENTATION = 502; - - private CameraHandler mCameraHandler; - private android.hardware.Camera mCamera; - - // Used to retain a copy of Parameters for setting parameters. - private Parameters mParamsToSet; - - AndroidCameraManagerImpl() { - HandlerThread ht = new HandlerThread("Camera Handler Thread"); - ht.start(); - mCameraHandler = new CameraHandler(ht.getLooper()); - } - - private class CameraHandler extends Handler { - CameraHandler(Looper looper) { - super(looper); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void startFaceDetection() { - mCamera.startFaceDetection(); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void stopFaceDetection() { - mCamera.stopFaceDetection(); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void setFaceDetectionListener(FaceDetectionListener listener) { - mCamera.setFaceDetectionListener(listener); - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - private void setPreviewTexture(Object surfaceTexture) { - try { - mCamera.setPreviewTexture((SurfaceTexture) surfaceTexture); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN_MR1) - private void enableShutterSound(boolean enable) { - mCamera.enableShutterSound(enable); - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private void setAutoFocusMoveCallback( - android.hardware.Camera camera, Object cb) { - camera.setAutoFocusMoveCallback((AutoFocusMoveCallback) cb); - } - - public void requestTakePicture( - final ShutterCallback shutter, - final PictureCallback raw, - final PictureCallback postView, - final PictureCallback jpeg) { - post(new Runnable() { - @Override - public void run() { - try { - mCamera.takePicture(shutter, raw, postView, jpeg); - } catch (RuntimeException e) { - // TODO: output camera state and focus state for debugging. - Log.e(TAG, "take picture failed."); - throw e; - } - } - }); - } - - /** - * Waits for all the {@code Message} and {@code Runnable} currently in the queue - * are processed. - * - * @return {@code false} if the wait was interrupted, {@code true} otherwise. - */ - public boolean waitDone() { - final Object waitDoneLock = new Object(); - final Runnable unlockRunnable = new Runnable() { - @Override - public void run() { - synchronized (waitDoneLock) { - waitDoneLock.notifyAll(); - } - } - }; - - synchronized (waitDoneLock) { - mCameraHandler.post(unlockRunnable); - try { - waitDoneLock.wait(); - } catch (InterruptedException ex) { - Log.v(TAG, "waitDone interrupted"); - return false; - } - } - return true; - } - - /** - * This method does not deal with the API level check. Everyone should - * check first for supported operations before sending message to this handler. - */ - @Override - public void handleMessage(final Message msg) { - try { - switch (msg.what) { - case OPEN_CAMERA: - mCamera = android.hardware.Camera.open(msg.arg1); - if (mCamera != null) { - mParametersIsDirty = true; - - // Get a instance of Camera.Parameters for later use. - if (mParamsToSet == null) { - mParamsToSet = mCamera.getParameters(); - } - } - return; - - case RELEASE: - mCamera.release(); - mCamera = null; - return; - - case RECONNECT: - mReconnectIOException = null; - try { - mCamera.reconnect(); - } catch (IOException ex) { - mReconnectIOException = ex; - } - return; - - case UNLOCK: - mCamera.unlock(); - return; - - case LOCK: - mCamera.lock(); - return; - - case SET_PREVIEW_TEXTURE_ASYNC: - setPreviewTexture(msg.obj); - return; - - case SET_PREVIEW_DISPLAY_ASYNC: - try { - mCamera.setPreviewDisplay((SurfaceHolder) msg.obj); - } catch (IOException e) { - throw new RuntimeException(e); - } - return; - - case START_PREVIEW_ASYNC: - mCamera.startPreview(); - return; - - case STOP_PREVIEW: - mCamera.stopPreview(); - return; - - case SET_PREVIEW_CALLBACK_WITH_BUFFER: - mCamera.setPreviewCallbackWithBuffer( - (PreviewCallback) msg.obj); - return; - - case ADD_CALLBACK_BUFFER: - mCamera.addCallbackBuffer((byte[]) msg.obj); - return; - - case AUTO_FOCUS: - mCamera.autoFocus((AutoFocusCallback) msg.obj); - return; - - case CANCEL_AUTO_FOCUS: - mCamera.cancelAutoFocus(); - return; - - case SET_AUTO_FOCUS_MOVE_CALLBACK: - setAutoFocusMoveCallback(mCamera, msg.obj); - return; - - case SET_DISPLAY_ORIENTATION: - mCamera.setDisplayOrientation(msg.arg1); - return; - - case SET_ZOOM_CHANGE_LISTENER: - mCamera.setZoomChangeListener( - (OnZoomChangeListener) msg.obj); - return; - - case SET_FACE_DETECTION_LISTENER: - setFaceDetectionListener((FaceDetectionListener) msg.obj); - return; - - case START_FACE_DETECTION: - startFaceDetection(); - return; - - case STOP_FACE_DETECTION: - stopFaceDetection(); - return; - - case SET_ERROR_CALLBACK: - mCamera.setErrorCallback((ErrorCallback) msg.obj); - return; - - case SET_PARAMETERS: - mParametersIsDirty = true; - mParamsToSet.unflatten((String) msg.obj); - mCamera.setParameters(mParamsToSet); - return; - - case GET_PARAMETERS: - if (mParametersIsDirty) { - mParameters = mCamera.getParameters(); - mParametersIsDirty = false; - } - return; - - case SET_PREVIEW_CALLBACK: - mCamera.setPreviewCallback((PreviewCallback) msg.obj); - return; - - case ENABLE_SHUTTER_SOUND: - enableShutterSound((msg.arg1 == 1) ? true : false); - return; - - case REFRESH_PARAMETERS: - mParametersIsDirty = true; - return; - - default: - throw new RuntimeException("Invalid CameraProxy message=" + msg.what); - } - } catch (RuntimeException e) { - if (msg.what != RELEASE && mCamera != null) { - try { - mCamera.release(); - } catch (Exception ex) { - Log.e(TAG, "Fail to release the camera."); - } - mCamera = null; - } - throw e; - } - } - } - - @Override - public CameraManager.CameraProxy cameraOpen(int cameraId) { - mCameraHandler.obtainMessage(OPEN_CAMERA, cameraId, 0).sendToTarget(); - mCameraHandler.waitDone(); - if (mCamera != null) { - return new AndroidCameraProxyImpl(); - } else { - return null; - } - } - - /** - * A class which implements {@link CameraManager.CameraProxy} and - * camera handler thread. - */ - public class AndroidCameraProxyImpl implements CameraManager.CameraProxy { - - private AndroidCameraProxyImpl() { - Assert(mCamera != null); - } - - @Override - public android.hardware.Camera getCamera() { - return mCamera; - } - - @Override - public void release() { - // release() must be synchronous so we know exactly when the camera - // is released and can continue on. - mCameraHandler.sendEmptyMessage(RELEASE); - mCameraHandler.waitDone(); - } - - @Override - public void reconnect() throws IOException { - mCameraHandler.sendEmptyMessage(RECONNECT); - mCameraHandler.waitDone(); - if (mReconnectIOException != null) { - throw mReconnectIOException; - } - } - - @Override - public void unlock() { - mCameraHandler.sendEmptyMessage(UNLOCK); - mCameraHandler.waitDone(); - } - - @Override - public void lock() { - mCameraHandler.sendEmptyMessage(LOCK); - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - public void setPreviewTexture(SurfaceTexture surfaceTexture) { - mCameraHandler.obtainMessage(SET_PREVIEW_TEXTURE_ASYNC, surfaceTexture).sendToTarget(); - } - - @Override - public void setPreviewDisplay(SurfaceHolder surfaceHolder) { - mCameraHandler.obtainMessage(SET_PREVIEW_DISPLAY_ASYNC, surfaceHolder).sendToTarget(); - } - - @Override - public void startPreview() { - mCameraHandler.sendEmptyMessage(START_PREVIEW_ASYNC); - } - - @Override - public void stopPreview() { - mCameraHandler.sendEmptyMessage(STOP_PREVIEW); - mCameraHandler.waitDone(); - } - - @Override - public void setPreviewDataCallback( - Handler handler, CameraPreviewDataCallback cb) { - mCameraHandler.obtainMessage( - SET_PREVIEW_CALLBACK, - PreviewCallbackForward.getNewInstance(handler, this, cb)).sendToTarget(); - } - - @Override - public void setPreviewDataCallbackWithBuffer( - Handler handler, CameraPreviewDataCallback cb) { - mCameraHandler.obtainMessage( - SET_PREVIEW_CALLBACK_WITH_BUFFER, - PreviewCallbackForward.getNewInstance(handler, this, cb)).sendToTarget(); - } - - @Override - public void addCallbackBuffer(byte[] callbackBuffer) { - mCameraHandler.obtainMessage(ADD_CALLBACK_BUFFER, callbackBuffer).sendToTarget(); - } - - @Override - public void autoFocus(Handler handler, CameraAFCallback cb) { - mCameraHandler.obtainMessage( - AUTO_FOCUS, - AFCallbackForward.getNewInstance(handler, this, cb)).sendToTarget(); - } - - @Override - public void cancelAutoFocus() { - mCameraHandler.removeMessages(AUTO_FOCUS); - mCameraHandler.sendEmptyMessage(CANCEL_AUTO_FOCUS); - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - @Override - public void setAutoFocusMoveCallback( - Handler handler, CameraAFMoveCallback cb) { - mCameraHandler.obtainMessage( - SET_AUTO_FOCUS_MOVE_CALLBACK, - AFMoveCallbackForward.getNewInstance(handler, this, cb)).sendToTarget(); - } - - @Override - public void takePicture( - Handler handler, - CameraShutterCallback shutter, - CameraPictureCallback raw, - CameraPictureCallback post, - CameraPictureCallback jpeg) { - mCameraHandler.requestTakePicture( - ShutterCallbackForward.getNewInstance(handler, this, shutter), - PictureCallbackForward.getNewInstance(handler, this, raw), - PictureCallbackForward.getNewInstance(handler, this, post), - PictureCallbackForward.getNewInstance(handler, this, jpeg)); - } - - @Override - public void setDisplayOrientation(int degrees) { - mCameraHandler.obtainMessage(SET_DISPLAY_ORIENTATION, degrees, 0) - .sendToTarget(); - } - - @Override - public void setZoomChangeListener(OnZoomChangeListener listener) { - mCameraHandler.obtainMessage(SET_ZOOM_CHANGE_LISTENER, listener).sendToTarget(); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - public void setFaceDetectionCallback( - Handler handler, CameraFaceDetectionCallback cb) { - mCameraHandler.obtainMessage( - SET_FACE_DETECTION_LISTENER, - FaceDetectionCallbackForward.getNewInstance(handler, this, cb)).sendToTarget(); - } - - @Override - public void startFaceDetection() { - mCameraHandler.sendEmptyMessage(START_FACE_DETECTION); - } - - @Override - public void stopFaceDetection() { - mCameraHandler.sendEmptyMessage(STOP_FACE_DETECTION); - } - - @Override - public void setErrorCallback(ErrorCallback cb) { - mCameraHandler.obtainMessage(SET_ERROR_CALLBACK, cb).sendToTarget(); - } - - @Override - public void setParameters(Parameters params) { - if (params == null) { - Log.v(TAG, "null parameters in setParameters()"); - return; - } - mCameraHandler.obtainMessage(SET_PARAMETERS, params.flatten()) - .sendToTarget(); - } - - @Override - public Parameters getParameters() { - mCameraHandler.sendEmptyMessage(GET_PARAMETERS); - mCameraHandler.waitDone(); - return mParameters; - } - - @Override - public void refreshParameters() { - mCameraHandler.sendEmptyMessage(REFRESH_PARAMETERS); - } - - @Override - public void enableShutterSound(boolean enable) { - mCameraHandler.obtainMessage( - ENABLE_SHUTTER_SOUND, (enable ? 1 : 0), 0).sendToTarget(); - } - } - - /** - * A helper class to forward AutoFocusCallback to another thread. - */ - private static class AFCallbackForward implements AutoFocusCallback { - private final Handler mHandler; - private final CameraProxy mCamera; - private final CameraAFCallback mCallback; - - /** - * Returns a new instance of {@link AFCallbackForward}. - * - * @param handler The handler in which the callback will be invoked in. - * @param camera The {@link CameraProxy} which the callback is from. - * @param cb The callback to be invoked. - * @return The instance of the {@link AFCallbackForward}, - * or null if any parameter is null. - */ - public static AFCallbackForward getNewInstance( - Handler handler, CameraProxy camera, CameraAFCallback cb) { - if (handler == null || camera == null || cb == null) return null; - return new AFCallbackForward(handler, camera, cb); - } - - private AFCallbackForward( - Handler h, CameraProxy camera, CameraAFCallback cb) { - mHandler = h; - mCamera = camera; - mCallback = cb; - } - - @Override - public void onAutoFocus(final boolean b, Camera camera) { - mHandler.post(new Runnable() { - @Override - public void run() { - mCallback.onAutoFocus(b, mCamera); - } - }); - } - } - - /** A helper class to forward AutoFocusMoveCallback to another thread. */ - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private static class AFMoveCallbackForward implements AutoFocusMoveCallback { - private final Handler mHandler; - private final CameraAFMoveCallback mCallback; - private final CameraProxy mCamera; - - /** - * Returns a new instance of {@link AFMoveCallbackForward}. - * - * @param handler The handler in which the callback will be invoked in. - * @param camera The {@link CameraProxy} which the callback is from. - * @param cb The callback to be invoked. - * @return The instance of the {@link AFMoveCallbackForward}, - * or null if any parameter is null. - */ - public static AFMoveCallbackForward getNewInstance( - Handler handler, CameraProxy camera, CameraAFMoveCallback cb) { - if (handler == null || camera == null || cb == null) return null; - return new AFMoveCallbackForward(handler, camera, cb); - } - - private AFMoveCallbackForward( - Handler h, CameraProxy camera, CameraAFMoveCallback cb) { - mHandler = h; - mCamera = camera; - mCallback = cb; - } - - @Override - public void onAutoFocusMoving( - final boolean moving, android.hardware.Camera camera) { - mHandler.post(new Runnable() { - @Override - public void run() { - mCallback.onAutoFocusMoving(moving, mCamera); - } - }); - } - } - - /** - * A helper class to forward ShutterCallback to to another thread. - */ - private static class ShutterCallbackForward implements ShutterCallback { - private final Handler mHandler; - private final CameraShutterCallback mCallback; - private final CameraProxy mCamera; - - /** - * Returns a new instance of {@link ShutterCallbackForward}. - * - * @param handler The handler in which the callback will be invoked in. - * @param camera The {@link CameraProxy} which the callback is from. - * @param cb The callback to be invoked. - * @return The instance of the {@link ShutterCallbackForward}, - * or null if any parameter is null. - */ - public static ShutterCallbackForward getNewInstance( - Handler handler, CameraProxy camera, CameraShutterCallback cb) { - if (handler == null || camera == null || cb == null) return null; - return new ShutterCallbackForward(handler, camera, cb); - } - - private ShutterCallbackForward( - Handler h, CameraProxy camera, CameraShutterCallback cb) { - mHandler = h; - mCamera = camera; - mCallback = cb; - } - - @Override - public void onShutter() { - mHandler.post(new Runnable() { - @Override - public void run() { - mCallback.onShutter(mCamera); - } - }); - } - } - - /** - * A helper class to forward PictureCallback to another thread. - */ - private static class PictureCallbackForward implements PictureCallback { - private final Handler mHandler; - private final CameraPictureCallback mCallback; - private final CameraProxy mCamera; - - /** - * Returns a new instance of {@link PictureCallbackForward}. - * - * @param handler The handler in which the callback will be invoked in. - * @param camera The {@link CameraProxy} which the callback is from. - * @param cb The callback to be invoked. - * @return The instance of the {@link PictureCallbackForward}, - * or null if any parameters is null. - */ - public static PictureCallbackForward getNewInstance( - Handler handler, CameraProxy camera, CameraPictureCallback cb) { - if (handler == null || camera == null || cb == null) return null; - return new PictureCallbackForward(handler, camera, cb); - } - - private PictureCallbackForward( - Handler h, CameraProxy camera, CameraPictureCallback cb) { - mHandler = h; - mCamera = camera; - mCallback = cb; - } - - @Override - public void onPictureTaken( - final byte[] data, android.hardware.Camera camera) { - mHandler.post(new Runnable() { - @Override - public void run() { - mCallback.onPictureTaken(data, mCamera); - } - }); - } - } - - /** - * A helper class to forward PreviewCallback to another thread. - */ - private static class PreviewCallbackForward implements PreviewCallback { - private final Handler mHandler; - private final CameraPreviewDataCallback mCallback; - private final CameraProxy mCamera; - - /** - * Returns a new instance of {@link PreviewCallbackForward}. - * - * @param handler The handler in which the callback will be invoked in. - * @param camera The {@link CameraProxy} which the callback is from. - * @param cb The callback to be invoked. - * @return The instance of the {@link PreviewCallbackForward}, - * or null if any parameters is null. - */ - public static PreviewCallbackForward getNewInstance( - Handler handler, CameraProxy camera, CameraPreviewDataCallback cb) { - if (handler == null || camera == null || cb == null) return null; - return new PreviewCallbackForward(handler, camera, cb); - } - - private PreviewCallbackForward( - Handler h, CameraProxy camera, CameraPreviewDataCallback cb) { - mHandler = h; - mCamera = camera; - mCallback = cb; - } - - @Override - public void onPreviewFrame( - final byte[] data, android.hardware.Camera camera) { - mHandler.post(new Runnable() { - @Override - public void run() { - mCallback.onPreviewFrame(data, mCamera); - } - }); - } - } - - private static class FaceDetectionCallbackForward implements FaceDetectionListener { - private final Handler mHandler; - private final CameraFaceDetectionCallback mCallback; - private final CameraProxy mCamera; - - /** - * Returns a new instance of {@link FaceDetectionCallbackForward}. - * - * @param handler The handler in which the callback will be invoked in. - * @param camera The {@link CameraProxy} which the callback is from. - * @param cb The callback to be invoked. - * @return The instance of the {@link FaceDetectionCallbackForward}, - * or null if any parameter is null. - */ - public static FaceDetectionCallbackForward getNewInstance( - Handler handler, CameraProxy camera, CameraFaceDetectionCallback cb) { - if (handler == null || camera == null || cb == null) return null; - return new FaceDetectionCallbackForward(handler, camera, cb); - } - - private FaceDetectionCallbackForward( - Handler h, CameraProxy camera, CameraFaceDetectionCallback cb) { - mHandler = h; - mCamera = camera; - mCallback = cb; - } - - @Override - public void onFaceDetection( - final Camera.Face[] faces, Camera camera) { - mHandler.post(new Runnable() { - @Override - public void run() { - mCallback.onFaceDetection(faces, mCamera); - } - }); - } - } -} diff --git a/src/com/android/camera/AnimationManager.java b/src/com/android/camera/AnimationManager.java deleted file mode 100644 index 41aa4b862..000000000 --- a/src/com/android/camera/AnimationManager.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2013 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.animation.Animator; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.view.View; - -/** - * Class to handle animations. - */ - -public class AnimationManager { - - public static final float FLASH_ALPHA_START = 0.3f; - public static final float FLASH_ALPHA_END = 0f; - public static final int FLASH_DURATION = 300; - - public static final int SHRINK_DURATION = 400; - public static final int HOLD_DURATION = 2500; - public static final int SLIDE_DURATION = 1100; - - private ObjectAnimator mFlashAnim; - private AnimatorSet mCaptureAnimator; - - /** - * Starts capture animation. - * @param view a thumbnail view that shows a picture captured and gets animated - */ - public void startCaptureAnimation(final View view) { - if (mCaptureAnimator != null && mCaptureAnimator.isStarted()) { - mCaptureAnimator.cancel(); - } - View parentView = (View) view.getParent(); - float slideDistance = (float) (parentView.getWidth() - view.getLeft()); - - float scaleX = ((float) parentView.getWidth()) / ((float) view.getWidth()); - float scaleY = ((float) parentView.getHeight()) / ((float) view.getHeight()); - float scale = scaleX > scaleY ? scaleX : scaleY; - - int centerX = view.getLeft() + view.getWidth() / 2; - int centerY = view.getTop() + view.getHeight() / 2; - - ObjectAnimator slide = ObjectAnimator.ofFloat(view, "translationX", 0f, slideDistance) - .setDuration(AnimationManager.SLIDE_DURATION); - slide.setStartDelay(AnimationManager.SHRINK_DURATION + AnimationManager.HOLD_DURATION); - mCaptureAnimator = new AnimatorSet(); - mCaptureAnimator.playTogether( - ObjectAnimator.ofFloat(view, "scaleX", scale, 1f) - .setDuration(AnimationManager.SHRINK_DURATION), - ObjectAnimator.ofFloat(view, "scaleY", scale, 1f) - .setDuration(AnimationManager.SHRINK_DURATION), - ObjectAnimator.ofFloat(view, "translationX", - parentView.getWidth() / 2 - centerX, 0f) - .setDuration(AnimationManager.SHRINK_DURATION), - ObjectAnimator.ofFloat(view, "translationY", - parentView.getHeight() / 2 - centerY, 0f) - .setDuration(AnimationManager.SHRINK_DURATION), - slide); - mCaptureAnimator.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - view.setVisibility(View.VISIBLE); - } - - @Override - public void onAnimationEnd(Animator animator) { - view.setScaleX(1f); - view.setScaleX(1f); - view.setTranslationX(0f); - view.setTranslationY(0f); - view.setVisibility(View.INVISIBLE); - mCaptureAnimator.removeAllListeners(); - mCaptureAnimator = null; - } - - @Override - public void onAnimationCancel(Animator animator) { - view.setVisibility(View.INVISIBLE); - } - - @Override - public void onAnimationRepeat(Animator animator) { - // Do nothing. - } - }); - mCaptureAnimator.start(); - } - - /** - * Starts flash animation. - * @params flashOverlay the overlay that will animate on alpha to make the flash impression - */ - public void startFlashAnimation(final View flashOverlay) { - // End the previous animation if the previous one is still running - if (mFlashAnim != null && mFlashAnim.isRunning()) { - mFlashAnim.cancel(); - } - // Start new flash animation. - mFlashAnim = ObjectAnimator.ofFloat(flashOverlay, "alpha", - AnimationManager.FLASH_ALPHA_START, AnimationManager.FLASH_ALPHA_END); - mFlashAnim.setDuration(AnimationManager.FLASH_DURATION); - mFlashAnim.addListener(new Animator.AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - flashOverlay.setVisibility(View.VISIBLE); - } - - @Override - public void onAnimationEnd(Animator animator) { - flashOverlay.setAlpha(0f); - flashOverlay.setVisibility(View.GONE); - mFlashAnim.removeAllListeners(); - mFlashAnim = null; - } - - @Override - public void onAnimationCancel(Animator animator) { - // Do nothing. - } - - @Override - public void onAnimationRepeat(Animator animator) { - // Do nothing. - } - }); - mFlashAnim.start(); - } - - /** - * Cancels on-going flash animation and capture animation, if any. - */ - public void cancelAnimations() { - // End the previous animation if the previous one is still running - if (mFlashAnim != null && mFlashAnim.isRunning()) { - mFlashAnim.cancel(); - } - if (mCaptureAnimator != null && mCaptureAnimator.isStarted()) { - mCaptureAnimator.cancel(); - } - } -}
\ No newline at end of file diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java deleted file mode 100644 index d4e7f1865..000000000 --- a/src/com/android/camera/CameraActivity.java +++ /dev/null @@ -1,652 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.ServiceConnection; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.graphics.drawable.ColorDrawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.provider.Settings; -import android.util.Log; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.OrientationEventListener; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ImageView; -import android.widget.ProgressBar; - -import com.android.camera.data.CameraDataAdapter; -import com.android.camera.data.CameraPreviewData; -import com.android.camera.data.FixedFirstDataAdapter; -import com.android.camera.data.FixedLastDataAdapter; -import com.android.camera.data.LocalData; -import com.android.camera.data.LocalDataAdapter; -import com.android.camera.ui.CameraSwitcher; -import com.android.camera.ui.CameraSwitcher.CameraSwitchListener; -import com.android.camera.ui.FilmStripView; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.PanoramaViewHelper; -import com.android.gallery3d.util.RefocusHelper; - -public class CameraActivity extends Activity - implements CameraSwitchListener { - - private static final String TAG = "CAM_Activity"; - - private static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE = - "android.media.action.STILL_IMAGE_CAMERA_SECURE"; - public static final String ACTION_IMAGE_CAPTURE_SECURE = - "android.media.action.IMAGE_CAPTURE_SECURE"; - - // The intent extra for camera from secure lock screen. True if the gallery - // should only show newly captured pictures. sSecureAlbumId does not - // increment. This is used when switching between camera, camcorder, and - // panorama. If the extra is not set, it is in the normal camera mode. - public static final String SECURE_CAMERA_EXTRA = "secure_camera"; - - /** This data adapter is used by FilmStirpView. */ - private LocalDataAdapter mDataAdapter; - /** This data adapter represents the real local camera data. */ - private LocalDataAdapter mWrappedDataAdapter; - - private PanoramaStitchingManager mPanoramaManager; - private int mCurrentModuleIndex; - private CameraModule mCurrentModule; - private View mRootView; - private FilmStripView mFilmStripView; - private ProgressBar mBottomProgress; - private View mPanoStitchingPanel; - private int mResultCodeForTesting; - private Intent mResultDataForTesting; - private OnScreenHint mStorageHint; - private long mStorageSpace = Storage.LOW_STORAGE_THRESHOLD; - private boolean mAutoRotateScreen; - private boolean mSecureCamera; - // This is a hack to speed up the start of SecureCamera. - private static boolean sFirstStartAfterScreenOn = true; - private boolean mShowCameraPreview; - private int mLastRawOrientation; - private MyOrientationEventListener mOrientationListener; - private Handler mMainHandler; - private PanoramaViewHelper mPanoramaViewHelper; - private CameraPreviewData mCameraPreviewData; - - private class MyOrientationEventListener - extends OrientationEventListener { - public MyOrientationEventListener(Context context) { - super(context); - } - - @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 or sky, we still have - // the correct orientation. - if (orientation == ORIENTATION_UNKNOWN) return; - mLastRawOrientation = orientation; - mCurrentModule.onOrientationChanged(orientation); - } - } - - private MediaSaveService mMediaSaveService; - private ServiceConnection mConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName className, IBinder b) { - mMediaSaveService = ((MediaSaveService.LocalBinder) b).getService(); - mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService); - } - @Override - public void onServiceDisconnected(ComponentName className) { - mMediaSaveService = null; - }}; - - // close activity when screen turns off - private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - finish(); - } - }; - - private static BroadcastReceiver sScreenOffReceiver; - private static class ScreenOffReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - sFirstStartAfterScreenOn = true; - } - } - - public static boolean isFirstStartAfterScreenOn() { - return sFirstStartAfterScreenOn; - } - - public static void resetFirstStartAfterScreenOn() { - sFirstStartAfterScreenOn = false; - } - - private FilmStripView.Listener mFilmStripListener = - new FilmStripView.Listener() { - @Override - public void onDataPromoted(int dataID) { - removeData(dataID); - } - - @Override - public void onDataDemoted(int dataID) { - removeData(dataID); - } - - @Override - public void onDataFullScreenChange(int dataID, boolean full) { - } - - @Override - public void onSwitchMode(boolean toCamera) { - mCurrentModule.onSwitchMode(toCamera); - } - - @Override - public void onCurrentDataChanged(int dataID, boolean current) { - if (!current) { - hidePanoStitchingProgress(); - } else { - LocalData currentData = mDataAdapter.getLocalData(dataID); - if (currentData == null) { - Log.w(TAG, "Current data ID not found."); - hidePanoStitchingProgress(); - return; - } - Uri contentUri = currentData.getContentUri(); - if (contentUri == null) { - hidePanoStitchingProgress(); - return; - } - int panoStitchingProgress = mPanoramaManager.getTaskProgress(contentUri); - if (panoStitchingProgress < 0) { - hidePanoStitchingProgress(); - return; - } - showPanoStitchingProgress(); - updateStitchingProgress(panoStitchingProgress); - } - } - }; - - private void hidePanoStitchingProgress() { - mPanoStitchingPanel.setVisibility(View.GONE); - } - - private void showPanoStitchingProgress() { - mPanoStitchingPanel.setVisibility(View.VISIBLE); - } - - private void updateStitchingProgress(int progress) { - mBottomProgress.setProgress(progress); - } - - private Runnable mDeletionRunnable = new Runnable() { - @Override - public void run() { - mDataAdapter.executeDeletion(CameraActivity.this); - } - }; - - private ImageTaskManager.TaskListener mStitchingListener = - new ImageTaskManager.TaskListener() { - @Override - public void onTaskQueued(String filePath, final Uri imageUri) { - mMainHandler.post(new Runnable() { - @Override - public void run() { - notifyNewMedia(imageUri); - } - }); - } - - @Override - public void onTaskDone(String filePath, final Uri imageUri) { - Log.v(TAG, "onTaskDone:" + filePath); - mMainHandler.post(new Runnable() { - @Override - public void run() { - int doneID = mDataAdapter.findDataByContentUri(imageUri); - int currentDataId = mFilmStripView.getCurrentId(); - - if (currentDataId == doneID) { - hidePanoStitchingProgress(); - updateStitchingProgress(0); - } - - mDataAdapter.refresh(getContentResolver(), imageUri); - } - }); - } - - @Override - public void onTaskProgress( - String filePath, final Uri imageUri, final int progress) { - mMainHandler.post(new Runnable() { - @Override - public void run() { - int currentDataId = mFilmStripView.getCurrentId(); - if (currentDataId == -1) { - return; - } - if (imageUri.equals( - mDataAdapter.getLocalData(currentDataId).getContentUri())) { - updateStitchingProgress(progress); - } - } - }); - } - }; - - public MediaSaveService getMediaSaveService() { - return mMediaSaveService; - } - - public void notifyNewMedia(Uri uri) { - ContentResolver cr = getContentResolver(); - String mimeType = cr.getType(uri); - if (mimeType.startsWith("video/")) { - sendBroadcast(new Intent(Util.ACTION_NEW_VIDEO, uri)); - mDataAdapter.addNewVideo(cr, uri); - } else if (mimeType.startsWith("image/")) { - Util.broadcastNewPicture(this, uri); - mDataAdapter.addNewPhoto(cr, uri); - } else if (mimeType.startsWith("application/stitching-preview")) { - mDataAdapter.addNewPhoto(cr, uri); - } else { - android.util.Log.w(TAG, "Unknown new media with MIME type:" - + mimeType + ", uri:" + uri); - } - } - - private void removeData(int dataID) { - mDataAdapter.removeData(CameraActivity.this, dataID); - mMainHandler.removeCallbacks(mDeletionRunnable); - mMainHandler.postDelayed(mDeletionRunnable, 3000); - } - - private void bindMediaSaveService() { - Intent intent = new Intent(this, MediaSaveService.class); - startService(intent); // start service before binding it so the - // service won't be killed if we unbind it. - bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - } - - private void unbindMediaSaveService() { - if (mMediaSaveService != null) { - mMediaSaveService.setListener(null); - } - if (mConnection != null) { - unbindService(mConnection); - } - } - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - setContentView(R.layout.camera_filmstrip); - if (ApiHelper.HAS_ROTATION_ANIMATION) { - setRotationAnimation(); - } - // Check if this is in the secure camera mode. - Intent intent = getIntent(); - String action = intent.getAction(); - if (INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(action) - || ACTION_IMAGE_CAPTURE_SECURE.equals(action)) { - mSecureCamera = true; - } else { - mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false); - } - - if (mSecureCamera) { - // Change the window flags so that secure camera can show when locked - Window win = getWindow(); - WindowManager.LayoutParams params = win.getAttributes(); - params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; - win.setAttributes(params); - - // Filter for screen off so that we can finish secure camera activity - // when screen is off. - IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); - registerReceiver(mScreenOffReceiver, filter); - // TODO: This static screen off event receiver is a workaround to the - // double onResume() invocation (onResume->onPause->onResume). We should - // find a better solution to this. - if (sScreenOffReceiver == null) { - sScreenOffReceiver = new ScreenOffReceiver(); - registerReceiver(sScreenOffReceiver, filter); - } - } - mPanoramaManager = new PanoramaStitchingManager(CameraActivity.this); - mPanoramaManager.addTaskListener(mStitchingListener); - LayoutInflater inflater = getLayoutInflater(); - View rootLayout = inflater.inflate(R.layout.camera, null, false); - mRootView = rootLayout.findViewById(R.id.camera_app_root); - mPanoStitchingPanel = (View) findViewById(R.id.pano_stitching_progress_panel); - mBottomProgress = (ProgressBar) findViewById(R.id.pano_stitching_progress_bar); - mCameraPreviewData = new CameraPreviewData(rootLayout, - FilmStripView.ImageData.SIZE_FULL, - FilmStripView.ImageData.SIZE_FULL); - // Put a CameraPreviewData at the first position. - mWrappedDataAdapter = new FixedFirstDataAdapter( - new CameraDataAdapter(new ColorDrawable( - getResources().getColor(R.color.photo_placeholder))), - mCameraPreviewData); - mFilmStripView = (FilmStripView) findViewById(R.id.filmstrip_view); - mFilmStripView.setViewGap( - getResources().getDimensionPixelSize(R.dimen.camera_film_strip_gap)); - mPanoramaViewHelper = new PanoramaViewHelper(this); - mPanoramaViewHelper.onCreate(); - mFilmStripView.setPanoramaViewHelper(mPanoramaViewHelper); - // Set up the camera preview first so the preview shows up ASAP. - mFilmStripView.setListener(mFilmStripListener); - mCurrentModule = new PhotoModule(); - mCurrentModule.init(this, mRootView); - mOrientationListener = new MyOrientationEventListener(this); - mMainHandler = new Handler(getMainLooper()); - bindMediaSaveService(); - - if (!mSecureCamera) { - mDataAdapter = mWrappedDataAdapter; - mDataAdapter.requestLoad(getContentResolver()); - } else { - // Put a lock placeholder as the last image by setting its date to 0. - ImageView v = (ImageView) getLayoutInflater().inflate( - R.layout.secure_album_placeholder, null); - mDataAdapter = new FixedLastDataAdapter( - mWrappedDataAdapter, - new LocalData.LocalViewData( - v, - v.getDrawable().getIntrinsicWidth(), - v.getDrawable().getIntrinsicHeight(), - 0, 0)); - // Flush out all the original data. - mDataAdapter.flush(); - } - mFilmStripView.setDataAdapter(mDataAdapter); - } - - private void setRotationAnimation() { - int rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; - rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; - Window win = getWindow(); - WindowManager.LayoutParams winParams = win.getAttributes(); - winParams.rotationAnimation = rotationAnimation; - win.setAttributes(winParams); - } - - @Override - public void onUserInteraction() { - super.onUserInteraction(); - mCurrentModule.onUserInteraction(); - } - - @Override - public void onPause() { - mOrientationListener.disable(); - mCurrentModule.onPauseBeforeSuper(); - super.onPause(); - mCurrentModule.onPauseAfterSuper(); - } - - @Override - public void onResume() { - if (Settings.System.getInt(getContentResolver(), - Settings.System.ACCELEROMETER_ROTATION, 0) == 0) {// auto-rotate off - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); - mAutoRotateScreen = false; - } else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); - mAutoRotateScreen = true; - } - mOrientationListener.enable(); - mCurrentModule.onResumeBeforeSuper(); - super.onResume(); - mCurrentModule.onResumeAfterSuper(); - - setSwipingEnabled(true); - } - - @Override - public void onStart() { - super.onStart(); - - mPanoramaViewHelper.onStart(); - } - - @Override - protected void onStop() { - super.onStop(); - mPanoramaViewHelper.onStop(); - } - - @Override - public void onDestroy() { - unbindMediaSaveService(); - if (mSecureCamera) unregisterReceiver(mScreenOffReceiver); - super.onDestroy(); - } - - @Override - public void onConfigurationChanged(Configuration config) { - super.onConfigurationChanged(config); - mCurrentModule.onConfigurationChanged(config); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (mCurrentModule.onKeyDown(keyCode, event)) return true; - // Prevent software keyboard or voice search from showing up. - if (keyCode == KeyEvent.KEYCODE_SEARCH - || keyCode == KeyEvent.KEYCODE_MENU) { - if (event.isLongPress()) return true; - } - if (keyCode == KeyEvent.KEYCODE_MENU && mShowCameraPreview) { - return true; - } - - return super.onKeyDown(keyCode, event); - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - if (mCurrentModule.onKeyUp(keyCode, event)) return true; - if (keyCode == KeyEvent.KEYCODE_MENU && mShowCameraPreview) { - return true; - } - return super.onKeyUp(keyCode, event); - } - - public boolean isAutoRotateScreen() { - return mAutoRotateScreen; - } - - protected void updateStorageSpace() { - mStorageSpace = Storage.getAvailableSpace(); - } - - protected long getStorageSpace() { - return mStorageSpace; - } - - protected void updateStorageSpaceAndHint() { - updateStorageSpace(); - updateStorageHint(mStorageSpace); - } - - protected void updateStorageHint() { - updateStorageHint(mStorageSpace); - } - - protected boolean updateStorageHintOnResume() { - return true; - } - - protected void updateStorageHint(long storageSpace) { - String message = null; - if (storageSpace == Storage.UNAVAILABLE) { - message = getString(R.string.no_storage); - } else if (storageSpace == Storage.PREPARING) { - message = getString(R.string.preparing_sd); - } else if (storageSpace == Storage.UNKNOWN_SIZE) { - message = getString(R.string.access_sd_fail); - } else if (storageSpace <= Storage.LOW_STORAGE_THRESHOLD) { - message = getString(R.string.spaceIsLow_content); - } - - if (message != null) { - if (mStorageHint == null) { - mStorageHint = OnScreenHint.makeText(this, message); - } else { - mStorageHint.setText(message); - } - mStorageHint.show(); - } else if (mStorageHint != null) { - mStorageHint.cancel(); - mStorageHint = null; - } - } - - protected void setResultEx(int resultCode) { - mResultCodeForTesting = resultCode; - setResult(resultCode); - } - - protected void setResultEx(int resultCode, Intent data) { - mResultCodeForTesting = resultCode; - mResultDataForTesting = data; - setResult(resultCode, data); - } - - public int getResultCode() { - return mResultCodeForTesting; - } - - public Intent getResultData() { - return mResultDataForTesting; - } - - public boolean isSecureCamera() { - return mSecureCamera; - } - - @Override - public void onCameraSelected(int i) { - if (mCurrentModuleIndex == i) return; - - CameraHolder.instance().keep(); - closeModule(mCurrentModule); - mCurrentModuleIndex = i; - switch (i) { - case CameraSwitcher.VIDEO_MODULE_INDEX: - mCurrentModule = new VideoModule(); - break; - case CameraSwitcher.PHOTO_MODULE_INDEX: - mCurrentModule = new PhotoModule(); - break; - case CameraSwitcher.LIGHTCYCLE_MODULE_INDEX: - mCurrentModule = LightCycleHelper.createPanoramaModule(); - break; - case CameraSwitcher.REFOCUS_MODULE_INDEX: - mCurrentModule = RefocusHelper.createRefocusModule(); - break; - default: - break; - } - - openModule(mCurrentModule); - mCurrentModule.onOrientationChanged(mLastRawOrientation); - if (mMediaSaveService != null) { - mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService); - } - } - - private void openModule(CameraModule module) { - module.init(this, mRootView); - module.onResumeBeforeSuper(); - module.onResumeAfterSuper(); - } - - private void closeModule(CameraModule module) { - module.onPauseBeforeSuper(); - module.onPauseAfterSuper(); - ((ViewGroup) mRootView).removeAllViews(); - } - - @Override - public void onShowSwitcherPopup() { - } - - public void setSwipingEnabled(boolean enable) { - mCameraPreviewData.lockPreview(!enable); - } - - // Accessor methods for getting latency times used in performance testing - public long getAutoFocusTime() { - return (mCurrentModule instanceof PhotoModule) ? - ((PhotoModule) mCurrentModule).mAutoFocusTime : -1; - } - - public long getShutterLag() { - return (mCurrentModule instanceof PhotoModule) ? - ((PhotoModule) mCurrentModule).mShutterLag : -1; - } - - public long getShutterToPictureDisplayedTime() { - return (mCurrentModule instanceof PhotoModule) ? - ((PhotoModule) mCurrentModule).mShutterToPictureDisplayedTime : -1; - } - - public long getPictureDisplayedToJpegCallbackTime() { - return (mCurrentModule instanceof PhotoModule) ? - ((PhotoModule) mCurrentModule).mPictureDisplayedToJpegCallbackTime : -1; - } - - public long getJpegCallbackFinishTime() { - return (mCurrentModule instanceof PhotoModule) ? - ((PhotoModule) mCurrentModule).mJpegCallbackFinishTime : -1; - } - - public long getCaptureStartTime() { - return (mCurrentModule instanceof PhotoModule) ? - ((PhotoModule) mCurrentModule).mCaptureStartTime : -1; - } - - public boolean isRecording() { - return (mCurrentModule instanceof VideoModule) ? - ((VideoModule) mCurrentModule).isRecording() : false; - } -} diff --git a/src/com/android/camera/CameraBackupAgent.java b/src/com/android/camera/CameraBackupAgent.java deleted file mode 100644 index 30ba212df..000000000 --- a/src/com/android/camera/CameraBackupAgent.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.app.backup.BackupAgentHelper; -import android.app.backup.SharedPreferencesBackupHelper; -import android.content.Context; - -public class CameraBackupAgent extends BackupAgentHelper { - private static final String CAMERA_BACKUP_KEY = "camera_prefs"; - - public void onCreate () { - Context context = getApplicationContext(); - String prefNames[] = ComboPreferences.getSharedPreferencesNames(context); - - addHelper(CAMERA_BACKUP_KEY, new SharedPreferencesBackupHelper(context, prefNames)); - } -} diff --git a/src/com/android/camera/CameraButtonIntentReceiver.java b/src/com/android/camera/CameraButtonIntentReceiver.java deleted file mode 100644 index a65942d57..000000000 --- a/src/com/android/camera/CameraButtonIntentReceiver.java +++ /dev/null @@ -1,53 +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; - -/** - * {@code CameraButtonIntentReceiver} is invoked when the camera button is - * long-pressed. - * - * It is declared in {@code AndroidManifest.xml} to receive the - * {@code android.intent.action.CAMERA_BUTTON} intent. - * - * After making sure we can use the camera hardware, it starts the Camera - * activity. - */ -public class CameraButtonIntentReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - // Try to get the camera hardware - CameraHolder holder = CameraHolder.instance(); - ComboPreferences pref = new ComboPreferences(context); - int cameraId = CameraSettings.readPreferredCameraId(pref); - if (holder.tryOpen(cameraId) == 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, CameraActivity.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/CameraDisabledException.java b/src/com/android/camera/CameraDisabledException.java deleted file mode 100644 index 512809be6..000000000 --- a/src/com/android/camera/CameraDisabledException.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -/** - * This class represents the condition that device policy manager has disabled - * the camera. - */ -public class CameraDisabledException extends Exception { -} diff --git a/src/com/android/camera/CameraErrorCallback.java b/src/com/android/camera/CameraErrorCallback.java deleted file mode 100644 index 22f800ef9..000000000 --- a/src/com/android/camera/CameraErrorCallback.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2010 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.util.Log; - -public class CameraErrorCallback - implements android.hardware.Camera.ErrorCallback { - private static final String TAG = "CameraErrorCallback"; - - @Override - public void onError(int error, android.hardware.Camera camera) { - Log.e(TAG, "Got camera error callback. error=" + error); - if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) { - // We are not sure about the current state of the app (in preview or - // snapshot or recording). Closing the app is better than creating a - // new Camera object. - throw new RuntimeException("Media server died."); - } - } -} diff --git a/src/com/android/camera/CameraHardwareException.java b/src/com/android/camera/CameraHardwareException.java deleted file mode 100644 index 82090554d..000000000 --- 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; - -/** - * This class represents the condition that we cannot open the camera hardware - * successfully. For example, another process is using the camera. - */ -public class CameraHardwareException extends Exception { - - 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 d913df709..000000000 --- a/src/com/android/camera/CameraHolder.java +++ /dev/null @@ -1,299 +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.CameraInfo; -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 com.android.camera.CameraManager.CameraProxy; - -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; - -/** - * The class is used to hold an {@code android.hardware.Camera} instance. - * - * <p>The {@code open()} and {@code release()} calls are similar to the ones - * in {@code android.hardware.Camera}. The difference is if {@code keep()} is - * called before {@code release()}, CameraHolder will try to hold the {@code - * android.hardware.Camera} instance for a while, so if {@code open()} is - * called soon after, we can avoid the cost of {@code open()} in {@code - * android.hardware.Camera}. - * - * <p>This is used in switching between different modules. - */ -public class CameraHolder { - private static final String TAG = "CameraHolder"; - private static final int KEEP_CAMERA_TIMEOUT = 3000; // 3 seconds - private CameraProxy mCameraDevice; - private long mKeepBeforeTime; // Keep the Camera before this time. - private final Handler mHandler; - private boolean mCameraOpened; // true if camera is opened - private final int mNumberOfCameras; - private int mCameraId = -1; // current camera id - private int mBackCameraId = -1; - private int mFrontCameraId = -1; - private final CameraInfo[] mInfo; - private static CameraProxy mMockCamera[]; - private static CameraInfo mMockCameraInfo[]; - - /* Debug double-open issue */ - private static final boolean DEBUG_OPEN_RELEASE = true; - private static class OpenReleaseState { - long time; - int id; - String device; - String[] stack; - } - private static ArrayList<OpenReleaseState> sOpenReleaseStates = - new ArrayList<OpenReleaseState>(); - private static SimpleDateFormat sDateFormat = new SimpleDateFormat( - "yyyy-MM-dd HH:mm:ss.SSS"); - - private static synchronized void collectState(int id, CameraProxy device) { - OpenReleaseState s = new OpenReleaseState(); - s.time = System.currentTimeMillis(); - s.id = id; - if (device == null) { - s.device = "(null)"; - } else { - s.device = device.toString(); - } - - StackTraceElement[] stack = Thread.currentThread().getStackTrace(); - String[] lines = new String[stack.length]; - for (int i = 0; i < stack.length; i++) { - lines[i] = stack[i].toString(); - } - s.stack = lines; - - if (sOpenReleaseStates.size() > 10) { - sOpenReleaseStates.remove(0); - } - sOpenReleaseStates.add(s); - } - - private static synchronized void dumpStates() { - for (int i = sOpenReleaseStates.size() - 1; i >= 0; i--) { - OpenReleaseState s = sOpenReleaseStates.get(i); - String date = sDateFormat.format(new Date(s.time)); - Log.d(TAG, "State " + i + " at " + date); - Log.d(TAG, "mCameraId = " + s.id + ", mCameraDevice = " + s.device); - Log.d(TAG, "Stack:"); - for (int j = 0; j < s.stack.length; j++) { - Log.d(TAG, " " + s.stack[j]); - } - } - } - - // 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 PhotoModule used by VideoModule - // 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: - synchronized (CameraHolder.this) { - // In 'CameraHolder.open', the 'RELEASE_CAMERA' message - // will be removed if it is found in the queue. However, - // there is a chance that this message has been handled - // before being removed. So, we need to add a check - // here: - if (!mCameraOpened) release(); - } - break; - } - } - } - - public static void injectMockCamera(CameraInfo[] info, CameraProxy[] camera) { - mMockCameraInfo = info; - mMockCamera = camera; - sHolder = new CameraHolder(); - } - - private CameraHolder() { - HandlerThread ht = new HandlerThread("CameraHolder"); - ht.start(); - mHandler = new MyHandler(ht.getLooper()); - if (mMockCameraInfo != null) { - mNumberOfCameras = mMockCameraInfo.length; - mInfo = mMockCameraInfo; - } else { - mNumberOfCameras = android.hardware.Camera.getNumberOfCameras(); - mInfo = new CameraInfo[mNumberOfCameras]; - for (int i = 0; i < mNumberOfCameras; i++) { - mInfo[i] = new CameraInfo(); - android.hardware.Camera.getCameraInfo(i, mInfo[i]); - } - } - - // get the first (smallest) back and first front camera id - for (int i = 0; i < mNumberOfCameras; i++) { - if (mBackCameraId == -1 && mInfo[i].facing == CameraInfo.CAMERA_FACING_BACK) { - mBackCameraId = i; - } else if (mFrontCameraId == -1 && mInfo[i].facing == CameraInfo.CAMERA_FACING_FRONT) { - mFrontCameraId = i; - } - } - } - - public int getNumberOfCameras() { - return mNumberOfCameras; - } - - public CameraInfo[] getCameraInfo() { - return mInfo; - } - - public synchronized CameraProxy open(int cameraId) - throws CameraHardwareException { - if (DEBUG_OPEN_RELEASE) { - collectState(cameraId, mCameraDevice); - if (mCameraOpened) { - Log.e(TAG, "double open"); - dumpStates(); - } - } - Assert(!mCameraOpened); - if (mCameraDevice != null && mCameraId != cameraId) { - mCameraDevice.release(); - mCameraDevice = null; - mCameraId = -1; - } - if (mCameraDevice == null) { - try { - Log.v(TAG, "open camera " + cameraId); - if (mMockCameraInfo == null) { - mCameraDevice = CameraManagerFactory - .getAndroidCameraManager().cameraOpen(cameraId); - } else { - if (mMockCamera == null) - throw new RuntimeException(); - mCameraDevice = mMockCamera[cameraId]; - } - mCameraId = cameraId; - } 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); - } - mCameraOpened = true; - 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 CameraProxy tryOpen(int cameraId) { - try { - return !mCameraOpened ? open(cameraId) : 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() { - if (DEBUG_OPEN_RELEASE) { - collectState(mCameraId, mCameraDevice); - } - - if (mCameraDevice == null) return; - - long now = System.currentTimeMillis(); - if (now < mKeepBeforeTime) { - if (mCameraOpened) { - mCameraOpened = false; - mCameraDevice.stopPreview(); - } - mHandler.sendEmptyMessageDelayed(RELEASE_CAMERA, - mKeepBeforeTime - now); - return; - } - mCameraOpened = false; - mCameraDevice.release(); - mCameraDevice = null; - // We must set this to null because it has a reference to Camera. - // Camera has references to the listeners. - mParameters = null; - mCameraId = -1; - } - - public void keep() { - keep(KEEP_CAMERA_TIMEOUT); - } - - public synchronized void keep(int time) { - // We allow mCameraOpened in either state for the convenience of the - // calling activity. The activity may not have a chance to call open() - // before the user switches to another activity. - mKeepBeforeTime = System.currentTimeMillis() + time; - } - - public int getBackCameraId() { - return mBackCameraId; - } - - public int getFrontCameraId() { - return mFrontCameraId; - } -} diff --git a/src/com/android/camera/CameraManager.java b/src/com/android/camera/CameraManager.java deleted file mode 100644 index 90a838ca6..000000000 --- a/src/com/android/camera/CameraManager.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.annotation.TargetApi; -import android.graphics.SurfaceTexture; -import android.hardware.Camera; -import android.hardware.Camera.ErrorCallback; -import android.hardware.Camera.OnZoomChangeListener; -import android.hardware.Camera.Parameters; -import android.os.Handler; -import android.view.SurfaceHolder; - -import com.android.gallery3d.common.ApiHelper; - -import java.io.IOException; - -/** - * An interface which provides possible camera device operations. - * - * The client should call {@code CameraManager.cameraOpen} to get an instance - * of {@link CameraManager.CameraProxy} to control the camera. Classes - * implementing this interface should have its own one unique {@code Thread} - * other than the main thread for camera operations. Camera device callbacks - * are wrapped since the client should not deal with - * {@code android.hardware.Camera} directly. - * - * TODO: provide callback interfaces for: - * {@code android.hardware.Camera.ErrorCallback}, - * {@code android.hardware.Camera.OnZoomChangeListener}, and - * {@code android.hardware.Camera.Parameters}. - */ -public interface CameraManager { - - /** - * An interface which wraps - * {@link android.hardware.Camera.AutoFocusCallback}. - */ - public interface CameraAFCallback { - public void onAutoFocus(boolean focused, CameraProxy camera); - } - - /** - * An interface which wraps - * {@link android.hardware.Camera.AutoFocusMoveCallback}. - */ - public interface CameraAFMoveCallback { - public void onAutoFocusMoving(boolean moving, CameraProxy camera); - } - - /** - * An interface which wraps - * {@link android.hardware.Camera.ShutterCallback}. - */ - public interface CameraShutterCallback { - public void onShutter(CameraProxy camera); - } - - /** - * An interface which wraps - * {@link android.hardware.Camera.PictureCallback}. - */ - public interface CameraPictureCallback { - public void onPictureTaken(byte[] data, CameraProxy camera); - } - - /** - * An interface which wraps - * {@link android.hardware.Camera.PreviewCallback}. - */ - public interface CameraPreviewDataCallback { - public void onPreviewFrame(byte[] data, CameraProxy camera); - } - - /** - * An interface which wraps - * {@link android.hardware.Camera.FaceDetectionListener}. - */ - public interface CameraFaceDetectionCallback { - /** - * Callback for face detection. - * - * @param faces Recognized face in the preview. - * @param camera The camera which the preview image comes from. - */ - public void onFaceDetection(Camera.Face[] faces, CameraProxy camera); - } - - /** - * Opens the camera of the specified ID synchronously. - * - * @param cameraId The camera ID to open. - * @return An instance of {@link CameraProxy} on success. null on failure. - */ - public CameraProxy cameraOpen(int cameraId); - - /** - * An interface that takes camera operation requests and post messages to the - * camera handler thread. All camera operations made through this interface is - * asynchronous by default except those mentioned specifically. - */ - public interface CameraProxy { - - /** - * Returns the underlying {@link android.hardware.Camera} object used - * by this proxy. This method should only be used when handing the - * camera device over to {@link android.media.MediaRecorder} for - * recording. - */ - public android.hardware.Camera getCamera(); - - /** - * Releases the camera device synchronously. - * This function must be synchronous so the caller knows exactly when the camera - * is released and can continue on. - */ - public void release(); - - /** - * Reconnects to the camera device. - * - * @see android.hardware.Camera#reconnect() - */ - public void reconnect() throws IOException; - - /** - * Unlocks the camera device. - * - * @see android.hardware.Camera#unlock() - */ - public void unlock(); - - /** - * Locks the camera device. - * @see android.hardware.Camera#lock() - */ - public void lock(); - - /** - * Sets the {@link android.graphics.SurfaceTexture} for preview. - * - * @param surfaceTexture The {@link SurfaceTexture} for preview. - */ - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - public void setPreviewTexture(final SurfaceTexture surfaceTexture); - - /** - * Sets the {@link android.view.SurfaceHolder} for preview. - * - * @param surfaceHolder The {@link SurfaceHolder} for preview. - */ - public void setPreviewDisplay(final SurfaceHolder surfaceHolder); - - /** - * Starts the camera preview. - */ - public void startPreview(); - - /** - * Stops the camera preview synchronously. - * {@code stopPreview()} must be synchronous to ensure that the caller can - * continues to release resources related to camera preview. - */ - public void stopPreview(); - - /** - * Sets the callback for preview data. - * - * @param handler handler in which the callback was handled. - * @param cb The callback to be invoked when the preview data is available. - * @see android.hardware.Camera#setPreviewCallback(android.hardware.Camera.PreviewCallback) - */ - public void setPreviewDataCallback(Handler handler, CameraPreviewDataCallback cb); - - /** - * Sets the callback for preview data. - * - * @param handler The handler in which the callback will be invoked. - * @param cb The callback to be invoked when the preview data is available. - * @see android.hardware.Camera#setPreviewCallbackWithBuffer(android.hardware.Camera.PreviewCallback) - */ - public void setPreviewDataCallbackWithBuffer(Handler handler, CameraPreviewDataCallback cb); - - /** - * Adds buffer for the preview callback. - * - * @param callbackBuffer The buffer allocated for the preview data. - */ - public void addCallbackBuffer(byte[] callbackBuffer); - - /** - * Starts the auto-focus process. The result will be returned through the callback. - * - * @param handler The handler in which the callback will be invoked. - * @param cb The auto-focus callback. - */ - public void autoFocus(Handler handler, CameraAFCallback cb); - - /** - * Cancels the auto-focus process. - */ - public void cancelAutoFocus(); - - /** - * Sets the auto-focus callback - * - * @param handler The handler in which the callback will be invoked. - * @param cb The callback to be invoked when the preview data is available. - */ - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - public void setAutoFocusMoveCallback(Handler handler, CameraAFMoveCallback cb); - - /** - * Instrument the camera to take a picture. - * - * @param handler The handler in which the callback will be invoked. - * @param shutter The callback for shutter action, may be null. - * @param raw The callback for uncompressed data, may be null. - * @param postview The callback for postview image data, may be null. - * @param jpeg The callback for jpeg image data, may be null. - * @see android.hardware.Camera#takePicture( - * android.hardware.Camera.ShutterCallback, - * android.hardware.Camera.PictureCallback, - * android.hardware.Camera.PictureCallback) - */ - public void takePicture( - Handler handler, - CameraShutterCallback shutter, - CameraPictureCallback raw, - CameraPictureCallback postview, - CameraPictureCallback jpeg); - - /** - * Sets the display orientation for camera to adjust the preview orientation. - * - * @param degrees The rotation in degrees. Should be 0, 90, 180 or 270. - */ - public void setDisplayOrientation(int degrees); - - /** - * Sets the listener for zoom change. - * - * @param listener The listener. - */ - public void setZoomChangeListener(OnZoomChangeListener listener); - - /** - * Sets the face detection listener. - * - * @param handler The handler in which the callback will be invoked. - * @param callback The callback for face detection results. - */ - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - public void setFaceDetectionCallback(Handler handler, CameraFaceDetectionCallback callback); - - /** - * Starts the face detection. - */ - public void startFaceDetection(); - - /** - * Stops the face detection. - */ - public void stopFaceDetection(); - - /** - * Registers an error callback. - * - * @param cb The error callback. - * @see android.hardware.Camera#setErrorCallback(android.hardware.Camera.ErrorCallback) - */ - public void setErrorCallback(ErrorCallback cb); - - /** - * Sets the camera parameters. - * - * @param params The camera parameters to use. - */ - public void setParameters(Parameters params); - - /** - * Gets the current camera parameters synchronously. This method is - * synchronous since the caller has to wait for the camera to return - * the parameters. If the parameters are already cached, it returns - * immediately. - */ - public Parameters getParameters(); - - /** - * Forces {@code CameraProxy} to update the cached version of the camera - * parameters regardless of the dirty bit. - */ - public void refreshParameters(); - - /** - * Enables/Disables the camera shutter sound. - * - * @param enable {@code true} to enable the shutter sound, - * {@code false} to disable it. - */ - public void enableShutterSound(boolean enable); - } -} diff --git a/src/com/android/camera/CameraManagerFactory.java b/src/com/android/camera/CameraManagerFactory.java deleted file mode 100644 index 914ebb265..000000000 --- a/src/com/android/camera/CameraManagerFactory.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 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; - -/** - * A factory class for {@link CameraManager}. - */ -public class CameraManagerFactory { - - private static AndroidCameraManagerImpl sAndroidCameraManager; - - /** - * Returns the android camera implementation of {@link CameraManager}. - * - * @return The {@link CameraManager} to control the camera device. - */ - public static synchronized CameraManager getAndroidCameraManager() { - if (sAndroidCameraManager == null) { - sAndroidCameraManager = new AndroidCameraManagerImpl(); - } - return sAndroidCameraManager; - } -} diff --git a/src/com/android/camera/CameraModule.java b/src/com/android/camera/CameraModule.java deleted file mode 100644 index bcfe98d65..000000000 --- a/src/com/android/camera/CameraModule.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.content.Intent; -import android.content.res.Configuration; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; - -public interface CameraModule { - - public void init(CameraActivity activity, View frame); - - public void onSwitchMode(boolean toCamera); - - public void onPauseBeforeSuper(); - - public void onPauseAfterSuper(); - - public void onResumeBeforeSuper(); - - public void onResumeAfterSuper(); - - public void onConfigurationChanged(Configuration config); - - public void onStop(); - - public void installIntentFilter(); - - public void onActivityResult(int requestCode, int resultCode, Intent data); - - public boolean onBackPressed(); - - public boolean onKeyDown(int keyCode, KeyEvent event); - - public boolean onKeyUp(int keyCode, KeyEvent event); - - public void onSingleTapUp(View view, int x, int y); - - public void onPreviewTextureCopied(); - - public void onCaptureTextureCopied(); - - public void onUserInteraction(); - - public boolean updateStorageHintOnResume(); - - public void updateCameraAppView(); - - public void onOrientationChanged(int orientation); - - public void onShowSwitcherPopup(); - - public void onMediaSaveServiceConnected(MediaSaveService s); -} diff --git a/src/com/android/camera/CameraPreference.java b/src/com/android/camera/CameraPreference.java deleted file mode 100644 index 5ddd86dbc..000000000 --- a/src/com/android/camera/CameraPreference.java +++ /dev/null @@ -1,63 +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.content.SharedPreferences; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -import com.android.gallery3d.R; - -/** - * The base class of all Preferences used in Camera. The preferences can be - * loaded from XML resource by <code>PreferenceInflater</code>. - */ -public abstract class CameraPreference { - - private final String mTitle; - private SharedPreferences mSharedPreferences; - private final Context mContext; - - static public interface OnPreferenceChangedListener { - public void onSharedPreferenceChanged(); - public void onRestorePreferencesClicked(); - public void onOverriddenPreferencesClicked(); - public void onCameraPickerClicked(int cameraId); - } - - public CameraPreference(Context context, AttributeSet attrs) { - mContext = context; - TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.CameraPreference, 0, 0); - mTitle = a.getString(R.styleable.CameraPreference_title); - a.recycle(); - } - - public String getTitle() { - return mTitle; - } - - public SharedPreferences getSharedPreferences() { - if (mSharedPreferences == null) { - mSharedPreferences = ComboPreferences.get(mContext); - } - return mSharedPreferences; - } - - public abstract void reloadValue(); -} diff --git a/src/com/android/camera/CameraScreenNail.java b/src/com/android/camera/CameraScreenNail.java deleted file mode 100644 index 993a7d336..000000000 --- a/src/com/android/camera/CameraScreenNail.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.SurfaceTexture; -import android.opengl.Matrix; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.ui.SurfaceTextureScreenNail; - -/* - * This is a ScreenNail which can display camera's preview. - */ -@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) -public class CameraScreenNail extends SurfaceTextureScreenNail { - private static final String TAG = "CAM_ScreenNail"; - private static final int ANIM_NONE = 0; - // Capture animation is about to start. - private static final int ANIM_CAPTURE_START = 1; - // Capture animation is running. - private static final int ANIM_CAPTURE_RUNNING = 2; - // Switch camera animation needs to copy texture. - private static final int ANIM_SWITCH_COPY_TEXTURE = 3; - // Switch camera animation shows the initial feedback by darkening the - // preview. - private static final int ANIM_SWITCH_DARK_PREVIEW = 4; - // Switch camera animation is waiting for the first frame. - private static final int ANIM_SWITCH_WAITING_FIRST_FRAME = 5; - // Switch camera animation is about to start. - private static final int ANIM_SWITCH_START = 6; - // Switch camera animation is running. - private static final int ANIM_SWITCH_RUNNING = 7; - - private boolean mVisible; - // True if first onFrameAvailable has been called. If screen nail is drawn - // too early, it will be all white. - private boolean mFirstFrameArrived; - private Listener mListener; - private final float[] mTextureTransformMatrix = new float[16]; - - // Animation. - private CaptureAnimManager mCaptureAnimManager; - private SwitchAnimManager mSwitchAnimManager = new SwitchAnimManager(); - private int mAnimState = ANIM_NONE; - private RawTexture mAnimTexture; - // Some methods are called by GL thread and some are called by main thread. - // This protects mAnimState, mVisible, and surface texture. This also makes - // sure some code are atomic. For example, requestRender and setting - // mAnimState. - private Object mLock = new Object(); - - private OnFrameDrawnListener mOneTimeFrameDrawnListener; - private int mRenderWidth; - private int mRenderHeight; - // This represents the scaled, uncropped size of the texture - // Needed for FaceView - private int mUncroppedRenderWidth; - private int mUncroppedRenderHeight; - private float mScaleX = 1f, mScaleY = 1f; - private boolean mFullScreen; - private boolean mEnableAspectRatioClamping = false; - private boolean mAcquireTexture = false; - private final DrawClient mDefaultDraw = new DrawClient() { - @Override - public void onDraw(GLCanvas canvas, int x, int y, int width, int height) { - CameraScreenNail.super.draw(canvas, x, y, width, height); - } - - @Override - public boolean requiresSurfaceTexture() { - return true; - } - - @Override - public RawTexture copyToTexture(GLCanvas c, RawTexture texture, int w, int h) { - // We shouldn't be here since requireSurfaceTexture() returns true. - return null; - } - }; - private DrawClient mDraw = mDefaultDraw; - private float mAlpha = 1f; - private Runnable mOnFrameDrawnListener; - - public interface Listener { - void requestRender(); - // Preview has been copied to a texture. - void onPreviewTextureCopied(); - - void onCaptureTextureCopied(); - } - - public interface OnFrameDrawnListener { - void onFrameDrawn(CameraScreenNail c); - } - - public interface DrawClient { - void onDraw(GLCanvas canvas, int x, int y, int width, int height); - - boolean requiresSurfaceTexture(); - // The client should implement this if requiresSurfaceTexture() is false; - RawTexture copyToTexture(GLCanvas c, RawTexture texture, int width, int height); - } - - public CameraScreenNail(Listener listener, Context ctx) { - mListener = listener; - mCaptureAnimManager = new CaptureAnimManager(ctx); - } - - public void setFullScreen(boolean full) { - synchronized (mLock) { - mFullScreen = full; - } - } - - /** - * returns the uncropped, but scaled, width of the rendered texture - */ - public int getUncroppedRenderWidth() { - return mUncroppedRenderWidth; - } - - /** - * returns the uncropped, but scaled, width of the rendered texture - */ - public int getUncroppedRenderHeight() { - return mUncroppedRenderHeight; - } - - @Override - public int getWidth() { - return mEnableAspectRatioClamping ? mRenderWidth : getTextureWidth(); - } - - @Override - public int getHeight() { - return mEnableAspectRatioClamping ? mRenderHeight : getTextureHeight(); - } - - private int getTextureWidth() { - return super.getWidth(); - } - - private int getTextureHeight() { - return super.getHeight(); - } - - @Override - public void setSize(int w, int h) { - super.setSize(w, h); - mEnableAspectRatioClamping = false; - if (mRenderWidth == 0) { - mRenderWidth = w; - mRenderHeight = h; - } - updateRenderSize(); - } - - /** - * Tells the ScreenNail to override the default aspect ratio scaling - * and instead perform custom scaling to basically do a centerCrop instead - * of the default centerInside - * - * Note that calls to setSize will disable this - */ - public void enableAspectRatioClamping() { - mEnableAspectRatioClamping = true; - updateRenderSize(); - } - - private void setPreviewLayoutSize(int w, int h) { - Log.i(TAG, "preview layout size: "+w+"/"+h); - mRenderWidth = w; - mRenderHeight = h; - updateRenderSize(); - } - - private void updateRenderSize() { - if (!mEnableAspectRatioClamping) { - mScaleX = mScaleY = 1f; - mUncroppedRenderWidth = getTextureWidth(); - mUncroppedRenderHeight = getTextureHeight(); - Log.i(TAG, "aspect ratio clamping disabled"); - return; - } - - float aspectRatio; - if (getTextureWidth() > getTextureHeight()) { - aspectRatio = (float) getTextureWidth() / (float) getTextureHeight(); - } else { - aspectRatio = (float) getTextureHeight() / (float) getTextureWidth(); - } - float scaledTextureWidth, scaledTextureHeight; - if (mRenderWidth > mRenderHeight) { - scaledTextureWidth = Math.max(mRenderWidth, - (int) (mRenderHeight * aspectRatio)); - scaledTextureHeight = Math.max(mRenderHeight, - (int)(mRenderWidth / aspectRatio)); - } else { - scaledTextureWidth = Math.max(mRenderWidth, - (int) (mRenderHeight / aspectRatio)); - scaledTextureHeight = Math.max(mRenderHeight, - (int) (mRenderWidth * aspectRatio)); - } - mScaleX = mRenderWidth / scaledTextureWidth; - mScaleY = mRenderHeight / scaledTextureHeight; - mUncroppedRenderWidth = Math.round(scaledTextureWidth); - mUncroppedRenderHeight = Math.round(scaledTextureHeight); - Log.i(TAG, "aspect ratio clamping enabled, surfaceTexture scale: " + mScaleX + ", " + mScaleY); - } - - public void acquireSurfaceTexture() { - synchronized (mLock) { - mFirstFrameArrived = false; - mAnimTexture = new RawTexture(getTextureWidth(), getTextureHeight(), true); - mAcquireTexture = true; - } - mListener.requestRender(); - } - - @Override - public void releaseSurfaceTexture() { - synchronized (mLock) { - if (mAcquireTexture) { - mAcquireTexture = false; - mLock.notifyAll(); - } else { - if (super.getSurfaceTexture() != null) { - super.releaseSurfaceTexture(); - } - mAnimState = ANIM_NONE; // stop the animation - } - } - } - - public void copyTexture() { - synchronized (mLock) { - mListener.requestRender(); - mAnimState = ANIM_SWITCH_COPY_TEXTURE; - } - } - - public void animateSwitchCamera() { - Log.v(TAG, "animateSwitchCamera"); - synchronized (mLock) { - if (mAnimState == ANIM_SWITCH_DARK_PREVIEW) { - // Do not request render here because camera has been just - // started. We do not want to draw black frames. - mAnimState = ANIM_SWITCH_WAITING_FIRST_FRAME; - } - } - } - - public void animateCapture(int displayRotation) { - synchronized (mLock) { - mCaptureAnimManager.setOrientation(displayRotation); - mCaptureAnimManager.animateFlashAndSlide(); - mListener.requestRender(); - mAnimState = ANIM_CAPTURE_START; - } - } - - public RawTexture getAnimationTexture() { - return mAnimTexture; - } - - public void animateFlash(int displayRotation) { - synchronized (mLock) { - mCaptureAnimManager.setOrientation(displayRotation); - mCaptureAnimManager.animateFlash(); - mListener.requestRender(); - mAnimState = ANIM_CAPTURE_START; - } - } - - public void animateSlide() { - synchronized (mLock) { - mCaptureAnimManager.animateSlide(); - mListener.requestRender(); - } - } - - private void callbackIfNeeded() { - if (mOneTimeFrameDrawnListener != null) { - mOneTimeFrameDrawnListener.onFrameDrawn(this); - mOneTimeFrameDrawnListener = null; - } - } - - @Override - protected void updateTransformMatrix(float[] matrix) { - super.updateTransformMatrix(matrix); - Matrix.translateM(matrix, 0, .5f, .5f, 0); - Matrix.scaleM(matrix, 0, mScaleX, mScaleY, 1f); - Matrix.translateM(matrix, 0, -.5f, -.5f, 0); - } - - public void directDraw(GLCanvas canvas, int x, int y, int width, int height) { - DrawClient draw; - synchronized (mLock) { - draw = mDraw; - } - draw.onDraw(canvas, x, y, width, height); - } - - public void setDraw(DrawClient draw) { - synchronized (mLock) { - if (draw == null) { - mDraw = mDefaultDraw; - } else { - mDraw = draw; - } - } - mListener.requestRender(); - } - - @Override - public void draw(GLCanvas canvas, int x, int y, int width, int height) { - synchronized (mLock) { - allocateTextureIfRequested(canvas); - if (!mVisible) mVisible = true; - SurfaceTexture surfaceTexture = getSurfaceTexture(); - if (mDraw.requiresSurfaceTexture() && (surfaceTexture == null || !mFirstFrameArrived)) { - return; - } - if (mOnFrameDrawnListener != null) { - mOnFrameDrawnListener.run(); - mOnFrameDrawnListener = null; - } - float oldAlpha = canvas.getAlpha(); - canvas.setAlpha(mAlpha); - - switch (mAnimState) { - case ANIM_NONE: - directDraw(canvas, x, y, width, height); - break; - case ANIM_SWITCH_COPY_TEXTURE: - copyPreviewTexture(canvas); - mSwitchAnimManager.setReviewDrawingSize(width, height); - mListener.onPreviewTextureCopied(); - mAnimState = ANIM_SWITCH_DARK_PREVIEW; - // The texture is ready. Fall through to draw darkened - // preview. - case ANIM_SWITCH_DARK_PREVIEW: - case ANIM_SWITCH_WAITING_FIRST_FRAME: - // Consume the frame. If the buffers are full, - // onFrameAvailable will not be called. Animation state - // relies on onFrameAvailable. - surfaceTexture.updateTexImage(); - mSwitchAnimManager.drawDarkPreview(canvas, x, y, width, - height, mAnimTexture); - break; - case ANIM_SWITCH_START: - mSwitchAnimManager.startAnimation(); - mAnimState = ANIM_SWITCH_RUNNING; - break; - case ANIM_CAPTURE_START: - copyPreviewTexture(canvas); - mListener.onCaptureTextureCopied(); - mCaptureAnimManager.startAnimation(); - mAnimState = ANIM_CAPTURE_RUNNING; - break; - } - - if (mAnimState == ANIM_CAPTURE_RUNNING || mAnimState == ANIM_SWITCH_RUNNING) { - boolean drawn; - if (mAnimState == ANIM_CAPTURE_RUNNING) { - if (!mFullScreen) { - // Skip the animation if no longer in full screen mode - drawn = false; - } else { - drawn = mCaptureAnimManager.drawAnimation(canvas, this, mAnimTexture, - x, y, width, height); - } - } else { - drawn = mSwitchAnimManager.drawAnimation(canvas, x, y, - width, height, this, mAnimTexture); - } - if (drawn) { - mListener.requestRender(); - } else { - // Continue to the normal draw procedure if the animation is - // not drawn. - mAnimState = ANIM_NONE; - directDraw(canvas, x, y, width, height); - } - } - canvas.setAlpha(oldAlpha); - callbackIfNeeded(); - } // mLock - } - - private void copyPreviewTexture(GLCanvas canvas) { - if (!mDraw.requiresSurfaceTexture()) { - mAnimTexture = mDraw.copyToTexture( - canvas, mAnimTexture, getTextureWidth(), getTextureHeight()); - } else { - int width = mAnimTexture.getWidth(); - int height = mAnimTexture.getHeight(); - canvas.beginRenderTarget(mAnimTexture); - // Flip preview texture vertically. OpenGL uses bottom left point - // as the origin (0, 0). - canvas.translate(0, height); - canvas.scale(1, -1, 1); - getSurfaceTexture().getTransformMatrix(mTextureTransformMatrix); - updateTransformMatrix(mTextureTransformMatrix); - canvas.drawTexture(mExtTexture, mTextureTransformMatrix, 0, 0, width, height); - canvas.endRenderTarget(); - } - } - - @Override - public void noDraw() { - synchronized (mLock) { - mVisible = false; - } - } - - @Override - public void recycle() { - synchronized (mLock) { - mVisible = false; - } - } - - @Override - public void onFrameAvailable(SurfaceTexture surfaceTexture) { - synchronized (mLock) { - if (getSurfaceTexture() != surfaceTexture) { - return; - } - mFirstFrameArrived = true; - if (mVisible) { - if (mAnimState == ANIM_SWITCH_WAITING_FIRST_FRAME) { - mAnimState = ANIM_SWITCH_START; - } - // We need to ask for re-render if the SurfaceTexture receives a new - // frame. - mListener.requestRender(); - } - } - } - - // We need to keep track of the size of preview frame on the screen because - // it's needed when we do switch-camera animation. See comments in - // SwitchAnimManager.java. This is based on the natural orientation, not the - // view system orientation. - public void setPreviewFrameLayoutSize(int width, int height) { - synchronized (mLock) { - mSwitchAnimManager.setPreviewFrameLayoutSize(width, height); - setPreviewLayoutSize(width, height); - } - } - - public void setOneTimeOnFrameDrawnListener(OnFrameDrawnListener l) { - synchronized (mLock) { - mFirstFrameArrived = false; - mOneTimeFrameDrawnListener = l; - } - } - - @Override - public SurfaceTexture getSurfaceTexture() { - synchronized (mLock) { - SurfaceTexture surfaceTexture = super.getSurfaceTexture(); - if (surfaceTexture == null && mAcquireTexture) { - try { - mLock.wait(); - surfaceTexture = super.getSurfaceTexture(); - } catch (InterruptedException e) { - Log.w(TAG, "unexpected interruption"); - } - } - return surfaceTexture; - } - } - - private void allocateTextureIfRequested(GLCanvas canvas) { - synchronized (mLock) { - if (mAcquireTexture) { - super.acquireSurfaceTexture(canvas); - mAcquireTexture = false; - mLock.notifyAll(); - } - } - } - - public void setOnFrameDrawnOneShot(Runnable run) { - synchronized (mLock) { - mOnFrameDrawnListener = run; - } - } - - public float getAlpha() { - synchronized (mLock) { - return mAlpha; - } - } - - public void setAlpha(float alpha) { - synchronized (mLock) { - mAlpha = alpha; - mListener.requestRender(); - } - } -} diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java deleted file mode 100644 index 3558014cc..000000000 --- a/src/com/android/camera/CameraSettings.java +++ /dev/null @@ -1,570 +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.annotation.TargetApi; -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.hardware.Camera.CameraInfo; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.Size; -import android.media.CamcorderProfile; -import android.util.FloatMath; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -/** - * Provides utilities and keys for Camera settings. - */ -public class CameraSettings { - private static final int NOT_FOUND = -1; - - public static final String KEY_VERSION = "pref_version_key"; - public static final String KEY_LOCAL_VERSION = "pref_local_version_key"; - public static final String KEY_RECORD_LOCATION = "pref_camera_recordlocation_key"; - public static final String KEY_VIDEO_QUALITY = "pref_video_quality_key"; - public static final String KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL = "pref_video_time_lapse_frame_interval_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_VIDEOCAMERA_FLASH_MODE = "pref_camera_video_flashmode_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 String KEY_EXPOSURE = "pref_camera_exposure_key"; - public static final String KEY_TIMER = "pref_camera_timer_key"; - public static final String KEY_TIMER_SOUND_EFFECTS = "pref_camera_timer_sound_key"; - public static final String KEY_VIDEO_EFFECT = "pref_video_effect_key"; - public static final String KEY_CAMERA_ID = "pref_camera_id_key"; - public static final String KEY_CAMERA_HDR = "pref_camera_hdr_key"; - public static final String KEY_CAMERA_FIRST_USE_HINT_SHOWN = "pref_camera_first_use_hint_shown_key"; - public static final String KEY_VIDEO_FIRST_USE_HINT_SHOWN = "pref_video_first_use_hint_shown_key"; - public static final String KEY_PHOTOSPHERE_PICTURESIZE = "pref_photosphere_picturesize_key"; - - public static final String EXPOSURE_DEFAULT_VALUE = "0"; - - public static final int CURRENT_VERSION = 5; - public static final int CURRENT_LOCAL_VERSION = 2; - - private static final String TAG = "CameraSettings"; - - private final Context mContext; - private final Parameters mParameters; - private final CameraInfo[] mCameraInfo; - private final int mCameraId; - - public CameraSettings(Activity activity, Parameters parameters, - int cameraId, CameraInfo[] cameraInfo) { - mContext = activity; - mParameters = parameters; - mCameraId = cameraId; - mCameraInfo = cameraInfo; - } - - public PreferenceGroup getPreferenceGroup(int preferenceRes) { - PreferenceInflater inflater = new PreferenceInflater(mContext); - PreferenceGroup group = - (PreferenceGroup) inflater.inflate(preferenceRes); - if (mParameters != null) initPreference(group); - return group; - } - - public static String getSupportedHighestVideoQuality(int cameraId, - String defaultQuality) { - // When launching the camera app first time, we will set the video quality - // to the first one (i.e. highest quality) in the supported list - List<String> supported = getSupportedVideoQuality(cameraId); - if (supported == null) { - Log.e(TAG, "No supported video quality is found"); - return defaultQuality; - } - return supported.get(0); - } - - 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 = ComboPreferences - .get(context).edit(); - editor.putString(KEY_PICTURE_SIZE, candidate); - editor.apply(); - return; - } - } - Log.e(TAG, "No supported picture size found"); - } - - public static void removePreferenceFromScreen( - PreferenceGroup group, String key) { - removePreference(group, key); - } - - 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; - } - - public static int getMaxVideoDuration(Context context) { - int duration = 0; // in milliseconds, 0 means unlimited. - try { - duration = context.getResources().getInteger(R.integer.max_video_recording_length); - } catch (Resources.NotFoundException ex) { - } - return duration; - } - - private void initPreference(PreferenceGroup group) { - ListPreference videoQuality = group.findPreference(KEY_VIDEO_QUALITY); - ListPreference timeLapseInterval = group.findPreference(KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL); - ListPreference pictureSize = group.findPreference(KEY_PICTURE_SIZE); - ListPreference whiteBalance = group.findPreference(KEY_WHITE_BALANCE); - ListPreference sceneMode = group.findPreference(KEY_SCENE_MODE); - ListPreference flashMode = group.findPreference(KEY_FLASH_MODE); - ListPreference focusMode = group.findPreference(KEY_FOCUS_MODE); - IconListPreference exposure = - (IconListPreference) group.findPreference(KEY_EXPOSURE); - CountDownTimerPreference timer = - (CountDownTimerPreference) group.findPreference(KEY_TIMER); - ListPreference countDownSoundEffects = group.findPreference(KEY_TIMER_SOUND_EFFECTS); - IconListPreference cameraIdPref = - (IconListPreference) group.findPreference(KEY_CAMERA_ID); - ListPreference videoFlashMode = - group.findPreference(KEY_VIDEOCAMERA_FLASH_MODE); - ListPreference videoEffect = group.findPreference(KEY_VIDEO_EFFECT); - ListPreference cameraHdr = group.findPreference(KEY_CAMERA_HDR); - - // Since the screen could be loaded from different resources, we need - // to check if the preference is available here - if (videoQuality != null) { - filterUnsupportedOptions(group, videoQuality, getSupportedVideoQuality(mCameraId)); - } - - if (pictureSize != null) { - filterUnsupportedOptions(group, pictureSize, sizeListToStringList( - mParameters.getSupportedPictureSizes())); - filterSimilarPictureSize(group, pictureSize); - } - if (whiteBalance != null) { - filterUnsupportedOptions(group, - whiteBalance, mParameters.getSupportedWhiteBalance()); - } - if (sceneMode != null) { - filterUnsupportedOptions(group, - sceneMode, mParameters.getSupportedSceneModes()); - } - if (flashMode != null) { - filterUnsupportedOptions(group, - flashMode, mParameters.getSupportedFlashModes()); - } - if (focusMode != null) { - if (!Util.isFocusAreaSupported(mParameters)) { - filterUnsupportedOptions(group, - focusMode, mParameters.getSupportedFocusModes()); - } else { - // Remove the focus mode if we can use tap-to-focus. - removePreference(group, focusMode.getKey()); - } - } - if (videoFlashMode != null) { - filterUnsupportedOptions(group, - videoFlashMode, mParameters.getSupportedFlashModes()); - } - if (exposure != null) buildExposureCompensation(group, exposure); - if (cameraIdPref != null) buildCameraId(group, cameraIdPref); - - if (timeLapseInterval != null) { - if (ApiHelper.HAS_TIME_LAPSE_RECORDING) { - resetIfInvalid(timeLapseInterval); - } else { - removePreference(group, timeLapseInterval.getKey()); - } - } - if (videoEffect != null) { - if (ApiHelper.HAS_EFFECTS_RECORDING) { - initVideoEffect(group, videoEffect); - resetIfInvalid(videoEffect); - } else { - filterUnsupportedOptions(group, videoEffect, null); - } - } - if (cameraHdr != null && (!ApiHelper.HAS_CAMERA_HDR - || !Util.isCameraHdrSupported(mParameters))) { - removePreference(group, cameraHdr.getKey()); - } - } - - private void buildExposureCompensation( - PreferenceGroup group, IconListPreference exposure) { - int max = mParameters.getMaxExposureCompensation(); - int min = mParameters.getMinExposureCompensation(); - if (max == 0 && min == 0) { - removePreference(group, exposure.getKey()); - return; - } - float step = mParameters.getExposureCompensationStep(); - - // show only integer values for exposure compensation - int maxValue = Math.min(3, (int) FloatMath.floor(max * step)); - int minValue = Math.max(-3, (int) FloatMath.ceil(min * step)); - String explabel = mContext.getResources().getString(R.string.pref_exposure_label); - CharSequence entries[] = new CharSequence[maxValue - minValue + 1]; - CharSequence entryValues[] = new CharSequence[maxValue - minValue + 1]; - CharSequence labels[] = new CharSequence[maxValue - minValue + 1]; - int[] icons = new int[maxValue - minValue + 1]; - TypedArray iconIds = mContext.getResources().obtainTypedArray( - R.array.pref_camera_exposure_icons); - for (int i = minValue; i <= maxValue; ++i) { - entryValues[i - minValue] = Integer.toString(Math.round(i / step)); - StringBuilder builder = new StringBuilder(); - if (i > 0) builder.append('+'); - entries[i - minValue] = builder.append(i).toString(); - labels[i - minValue] = explabel + " " + builder.toString(); - icons[i - minValue] = iconIds.getResourceId(3 + i, 0); - } - exposure.setUseSingleIcon(true); - exposure.setEntries(entries); - exposure.setLabels(labels); - exposure.setEntryValues(entryValues); - exposure.setLargeIconIds(icons); - } - - private void buildCameraId( - PreferenceGroup group, IconListPreference preference) { - int numOfCameras = mCameraInfo.length; - if (numOfCameras < 2) { - removePreference(group, preference.getKey()); - return; - } - - CharSequence[] entryValues = new CharSequence[numOfCameras]; - for (int i = 0; i < numOfCameras; ++i) { - entryValues[i] = "" + i; - } - preference.setEntryValues(entryValues); - } - - private static boolean removePreference(PreferenceGroup group, String key) { - for (int i = 0, n = group.size(); i < n; i++) { - CameraPreference child = group.get(i); - if (child instanceof PreferenceGroup) { - if (removePreference((PreferenceGroup) child, key)) { - return true; - } - } - if (child instanceof ListPreference && - ((ListPreference) child).getKey().equals(key)) { - group.removePreference(i); - return true; - } - } - return false; - } - - private void filterUnsupportedOptions(PreferenceGroup group, - ListPreference pref, List<String> supported) { - - // 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(group, pref.getKey()); - return; - } - - pref.filterUnsupported(supported); - if (pref.getEntries().length <= 1) { - removePreference(group, pref.getKey()); - return; - } - - resetIfInvalid(pref); - } - - private void filterSimilarPictureSize(PreferenceGroup group, - ListPreference pref) { - pref.filterDuplicated(); - if (pref.getEntries().length <= 1) { - removePreference(group, pref.getKey()); - return; - } - resetIfInvalid(pref); - } - - private void resetIfInvalid(ListPreference pref) { - // 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(Locale.ENGLISH, "%dx%d", size.width, size.height)); - } - return list; - } - - public static void upgradeLocalPreferences(SharedPreferences pref) { - int version; - try { - version = pref.getInt(KEY_LOCAL_VERSION, 0); - } catch (Exception ex) { - version = 0; - } - if (version == CURRENT_LOCAL_VERSION) return; - - SharedPreferences.Editor editor = pref.edit(); - if (version == 1) { - // We use numbers to represent the quality now. The quality definition is identical to - // that of CamcorderProfile.java. - editor.remove("pref_video_quality_key"); - } - editor.putInt(KEY_LOCAL_VERSION, CURRENT_LOCAL_VERSION); - editor.apply(); - } - - public static void upgradeGlobalPreferences(SharedPreferences pref) { - upgradeOldVersion(pref); - upgradeCameraId(pref); - } - - private static void upgradeOldVersion(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) { - // We won't use the preference which change in version 1. - // So, just upgrade to version 1 directly - version = 1; - } - if (version == 1) { - // Change jpeg quality {65,75,85} to {normal,fine,superfine} - String quality = pref.getString(KEY_JPEG_QUALITY, "85"); - if (quality.equals("65")) { - quality = "normal"; - } else if (quality.equals("75")) { - quality = "fine"; - } else { - quality = "superfine"; - } - editor.putString(KEY_JPEG_QUALITY, quality); - version = 2; - } - if (version == 2) { - editor.putString(KEY_RECORD_LOCATION, - pref.getBoolean(KEY_RECORD_LOCATION, false) - ? RecordLocationPreference.VALUE_ON - : RecordLocationPreference.VALUE_NONE); - version = 3; - } - if (version == 3) { - // Just use video quality to replace it and - // ignore the current settings. - editor.remove("pref_camera_videoquality_key"); - editor.remove("pref_camera_video_duration_key"); - } - - editor.putInt(KEY_VERSION, CURRENT_VERSION); - editor.apply(); - } - - private static void upgradeCameraId(SharedPreferences pref) { - // The id stored in the preference may be out of range if we are running - // inside the emulator and a webcam is removed. - // Note: This method accesses the global preferences directly, not the - // combo preferences. - int cameraId = readPreferredCameraId(pref); - if (cameraId == 0) return; // fast path - - int n = CameraHolder.instance().getNumberOfCameras(); - if (cameraId < 0 || cameraId >= n) { - writePreferredCameraId(pref, 0); - } - } - - public static int readPreferredCameraId(SharedPreferences pref) { - return Integer.parseInt(pref.getString(KEY_CAMERA_ID, "0")); - } - - public static void writePreferredCameraId(SharedPreferences pref, - int cameraId) { - Editor editor = pref.edit(); - editor.putString(KEY_CAMERA_ID, Integer.toString(cameraId)); - editor.apply(); - } - - public static int readExposure(ComboPreferences preferences) { - String exposure = preferences.getString( - CameraSettings.KEY_EXPOSURE, - EXPOSURE_DEFAULT_VALUE); - try { - return Integer.parseInt(exposure); - } catch (Exception ex) { - Log.e(TAG, "Invalid exposure: " + exposure); - } - return 0; - } - - public static int readEffectType(SharedPreferences pref) { - String effectSelection = pref.getString(KEY_VIDEO_EFFECT, "none"); - if (effectSelection.equals("none")) { - return EffectsRecorder.EFFECT_NONE; - } else if (effectSelection.startsWith("goofy_face")) { - return EffectsRecorder.EFFECT_GOOFY_FACE; - } else if (effectSelection.startsWith("backdropper")) { - return EffectsRecorder.EFFECT_BACKDROPPER; - } - Log.e(TAG, "Invalid effect selection: " + effectSelection); - return EffectsRecorder.EFFECT_NONE; - } - - public static Object readEffectParameter(SharedPreferences pref) { - String effectSelection = pref.getString(KEY_VIDEO_EFFECT, "none"); - if (effectSelection.equals("none")) { - return null; - } - int separatorIndex = effectSelection.indexOf('/'); - String effectParameter = - effectSelection.substring(separatorIndex + 1); - if (effectSelection.startsWith("goofy_face")) { - if (effectParameter.equals("squeeze")) { - return EffectsRecorder.EFFECT_GF_SQUEEZE; - } else if (effectParameter.equals("big_eyes")) { - return EffectsRecorder.EFFECT_GF_BIG_EYES; - } else if (effectParameter.equals("big_mouth")) { - return EffectsRecorder.EFFECT_GF_BIG_MOUTH; - } else if (effectParameter.equals("small_mouth")) { - return EffectsRecorder.EFFECT_GF_SMALL_MOUTH; - } else if (effectParameter.equals("big_nose")) { - return EffectsRecorder.EFFECT_GF_BIG_NOSE; - } else if (effectParameter.equals("small_eyes")) { - return EffectsRecorder.EFFECT_GF_SMALL_EYES; - } - } else if (effectSelection.startsWith("backdropper")) { - // Parameter is a string that either encodes the URI to use, - // or specifies 'gallery'. - return effectParameter; - } - - Log.e(TAG, "Invalid effect selection: " + effectSelection); - return null; - } - - public static void restorePreferences(Context context, - ComboPreferences preferences, Parameters parameters) { - int currentCameraId = readPreferredCameraId(preferences); - - // Clear the preferences of both cameras. - int backCameraId = CameraHolder.instance().getBackCameraId(); - if (backCameraId != -1) { - preferences.setLocalId(context, backCameraId); - Editor editor = preferences.edit(); - editor.clear(); - editor.apply(); - } - int frontCameraId = CameraHolder.instance().getFrontCameraId(); - if (frontCameraId != -1) { - preferences.setLocalId(context, frontCameraId); - Editor editor = preferences.edit(); - editor.clear(); - editor.apply(); - } - - // Switch back to the preferences of the current camera. Otherwise, - // we may write the preference to wrong camera later. - preferences.setLocalId(context, currentCameraId); - - upgradeGlobalPreferences(preferences.getGlobal()); - upgradeLocalPreferences(preferences.getLocal()); - - // Write back the current camera id because parameters are related to - // the camera. Otherwise, we may switch to the front camera but the - // initial picture size is that of the back camera. - initialCameraPictureSize(context, parameters); - writePreferredCameraId(preferences, currentCameraId); - } - - private static ArrayList<String> getSupportedVideoQuality(int cameraId) { - ArrayList<String> supported = new ArrayList<String>(); - // Check for supported quality - if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_1080P)) { - supported.add(Integer.toString(CamcorderProfile.QUALITY_1080P)); - } - if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_720P)) { - supported.add(Integer.toString(CamcorderProfile.QUALITY_720P)); - } - if (CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_480P)) { - supported.add(Integer.toString(CamcorderProfile.QUALITY_480P)); - } - return supported; - } - - private void initVideoEffect(PreferenceGroup group, ListPreference videoEffect) { - CharSequence[] values = videoEffect.getEntryValues(); - - boolean goofyFaceSupported = - EffectsRecorder.isEffectSupported(EffectsRecorder.EFFECT_GOOFY_FACE); - boolean backdropperSupported = - EffectsRecorder.isEffectSupported(EffectsRecorder.EFFECT_BACKDROPPER) && - Util.isAutoExposureLockSupported(mParameters) && - Util.isAutoWhiteBalanceLockSupported(mParameters); - - ArrayList<String> supported = new ArrayList<String>(); - for (CharSequence value : values) { - String effectSelection = value.toString(); - if (!goofyFaceSupported && effectSelection.startsWith("goofy_face")) continue; - if (!backdropperSupported && effectSelection.startsWith("backdropper")) continue; - supported.add(effectSelection); - } - - filterUnsupportedOptions(group, videoEffect, supported); - } -} diff --git a/src/com/android/camera/CaptureAnimManager.java b/src/com/android/camera/CaptureAnimManager.java deleted file mode 100644 index 6e8092566..000000000 --- a/src/com/android/camera/CaptureAnimManager.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Color; -import android.os.SystemClock; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; - -import com.android.gallery3d.R; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.NinePatchTexture; -import com.android.gallery3d.glrenderer.RawTexture; - -/** - * Class to handle the capture animation. - */ -public class CaptureAnimManager { - @SuppressWarnings("unused") - private static final String TAG = "CAM_Capture"; - // times mark endpoint of animation phase - private static final int TIME_FLASH = 200; - private static final int TIME_HOLD = 400; - private static final int TIME_SLIDE = 800; - private static final int TIME_HOLD2 = 3300; - private static final int TIME_SLIDE2 = 4100; - - private static final int ANIM_BOTH = 0; - private static final int ANIM_FLASH = 1; - private static final int ANIM_SLIDE = 2; - private static final int ANIM_HOLD2 = 3; - private static final int ANIM_SLIDE2 = 4; - - private final Interpolator mSlideInterpolator = new DecelerateInterpolator(); - - private volatile int mAnimOrientation; // Could be 0, 90, 180 or 270 degrees. - private long mAnimStartTime; // milliseconds. - private float mX; // The center of the whole view including preview and review. - private float mY; - private int mDrawWidth; - private int mDrawHeight; - private int mAnimType; - - private int mHoldX; - private int mHoldY; - private int mHoldW; - private int mHoldH; - - private int mOffset; - - private int mMarginRight; - private int mMarginTop; - private int mSize; - private Resources mResources; - private NinePatchTexture mBorder; - private int mShadowSize; - - public static int getAnimationDuration() { - return TIME_SLIDE2; - } - - /* preview: camera preview view. - * review: view of picture just taken. - */ - public CaptureAnimManager(Context ctx) { - mBorder = new NinePatchTexture(ctx, R.drawable.capture_thumbnail_shadow); - mResources = ctx.getResources(); - } - - public void setOrientation(int displayRotation) { - mAnimOrientation = (360 - displayRotation) % 360; - } - - public void animateSlide() { - if (mAnimType != ANIM_FLASH) { - return; - } - mAnimType = ANIM_SLIDE; - mAnimStartTime = SystemClock.uptimeMillis(); - } - - public void animateFlash() { - mAnimType = ANIM_FLASH; - } - - public void animateFlashAndSlide() { - mAnimType = ANIM_BOTH; - } - - public void startAnimation() { - mAnimStartTime = SystemClock.uptimeMillis(); - } - - private void setAnimationGeometry(int x, int y, int w, int h) { - mMarginRight = mResources.getDimensionPixelSize(R.dimen.capture_margin_right); - mMarginTop = mResources.getDimensionPixelSize(R.dimen.capture_margin_top); - mSize = mResources.getDimensionPixelSize(R.dimen.capture_size); - mShadowSize = mResources.getDimensionPixelSize(R.dimen.capture_border); - mOffset = mMarginRight + mSize; - // Set the views to the initial positions. - mDrawWidth = w; - mDrawHeight = h; - mX = x; - mY = y; - mHoldW = mSize; - mHoldH = mSize; - switch (mAnimOrientation) { - case 0: // Preview is on the left. - mHoldX = x + w - mMarginRight - mSize; - mHoldY = y + mMarginTop; - break; - case 90: // Preview is below. - mHoldX = x + mMarginTop; - mHoldY = y + mMarginRight; - break; - case 180: // Preview on the right. - mHoldX = x + mMarginRight; - mHoldY = y + h - mMarginTop - mSize; - break; - case 270: // Preview is above. - mHoldX = x + w - mMarginTop - mSize; - mHoldY = y + h - mMarginRight - mSize; - break; - } - } - - // Returns true if the animation has been drawn. - public boolean drawAnimation(GLCanvas canvas, CameraScreenNail preview, - RawTexture review, int lx, int ly, int lw, int lh) { - setAnimationGeometry(lx, ly, lw, lh); - long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime; - // Check if the animation is over - if (mAnimType == ANIM_SLIDE && timeDiff > TIME_SLIDE2 - TIME_HOLD) return false; - if (mAnimType == ANIM_BOTH && timeDiff > TIME_SLIDE2) return false; - - // determine phase and time in phase - int animStep = mAnimType; - if (mAnimType == ANIM_SLIDE) { - timeDiff += TIME_HOLD; - } - if (mAnimType == ANIM_SLIDE || mAnimType == ANIM_BOTH) { - if (timeDiff < TIME_HOLD) { - animStep = ANIM_FLASH; - } else if (timeDiff < TIME_SLIDE) { - animStep = ANIM_SLIDE; - timeDiff -= TIME_HOLD; - } else if (timeDiff < TIME_HOLD2) { - animStep = ANIM_HOLD2; - timeDiff -= TIME_SLIDE; - } else { - // SLIDE2 - animStep = ANIM_SLIDE2; - timeDiff -= TIME_HOLD2; - } - } - - if (animStep == ANIM_FLASH) { - review.draw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight); - if (timeDiff < TIME_FLASH) { - float f = 0.3f - 0.3f * timeDiff / TIME_FLASH; - int color = Color.argb((int) (255 * f), 255, 255, 255); - canvas.fillRect(mX, mY, mDrawWidth, mDrawHeight, color); - } - } else if (animStep == ANIM_SLIDE) { - float fraction = mSlideInterpolator.getInterpolation((float) (timeDiff) / (TIME_SLIDE - TIME_HOLD)); - float x = mX; - float y = mY; - float w = 0; - float h = 0; - x = interpolate(mX, mHoldX, fraction); - y = interpolate(mY, mHoldY, fraction); - w = interpolate(mDrawWidth, mHoldW, fraction); - h = interpolate(mDrawHeight, mHoldH, fraction); - preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight); - review.draw(canvas, (int) x, (int) y, (int) w, (int) h); - } else if (animStep == ANIM_HOLD2) { - preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight); - review.draw(canvas, mHoldX, mHoldY, mHoldW, mHoldH); - mBorder.draw(canvas, (int) mHoldX - mShadowSize, (int) mHoldY - mShadowSize, - (int) mHoldW + 2 * mShadowSize, (int) mHoldH + 2 * mShadowSize); - } else if (animStep == ANIM_SLIDE2) { - float fraction = (float)(timeDiff) / (TIME_SLIDE2 - TIME_HOLD2); - float x = mHoldX; - float y = mHoldY; - float d = mOffset * fraction; - switch (mAnimOrientation) { - case 0: - x = mHoldX + d; - break; - case 180: - x = mHoldX - d; - break; - case 90: - y = mHoldY - d; - break; - case 270: - y = mHoldY + d; - break; - } - preview.directDraw(canvas, (int) mX, (int) mY, mDrawWidth, mDrawHeight); - mBorder.draw(canvas, (int) x - mShadowSize, (int) y - mShadowSize, - (int) mHoldW + 2 * mShadowSize, (int) mHoldH + 2 * mShadowSize); - review.draw(canvas, (int) x, (int) y, mHoldW, mHoldH); - } - return true; - } - - private static float interpolate(float start, float end, float fraction) { - return start + (end - start) * fraction; - } - -} diff --git a/src/com/android/camera/ComboPreferences.java b/src/com/android/camera/ComboPreferences.java deleted file mode 100644 index e17e47aa8..000000000 --- a/src/com/android/camera/ComboPreferences.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2010 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.app.backup.BackupManager; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.preference.PreferenceManager; - -import com.android.gallery3d.util.UsageStatistics; - -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.CopyOnWriteArrayList; - -public class ComboPreferences implements - SharedPreferences, - OnSharedPreferenceChangeListener { - private SharedPreferences mPrefGlobal; // global preferences - private SharedPreferences mPrefLocal; // per-camera preferences - private String mPackageName; - private CopyOnWriteArrayList<OnSharedPreferenceChangeListener> mListeners; - // TODO: Remove this WeakHashMap in the camera code refactoring - private static WeakHashMap<Context, ComboPreferences> sMap = - new WeakHashMap<Context, ComboPreferences>(); - - public ComboPreferences(Context context) { - mPackageName = context.getPackageName(); - mPrefGlobal = context.getSharedPreferences( - getGlobalSharedPreferencesName(context), Context.MODE_PRIVATE); - mPrefGlobal.registerOnSharedPreferenceChangeListener(this); - - synchronized (sMap) { - sMap.put(context, this); - } - mListeners = new CopyOnWriteArrayList<OnSharedPreferenceChangeListener>(); - - // The global preferences was previously stored in the default - // shared preferences file. They should be stored in the camera-specific - // shared preferences file so we can backup them solely. - SharedPreferences oldprefs = - PreferenceManager.getDefaultSharedPreferences(context); - if (!mPrefGlobal.contains(CameraSettings.KEY_VERSION) - && oldprefs.contains(CameraSettings.KEY_VERSION)) { - moveGlobalPrefsFrom(oldprefs); - } - } - - public static ComboPreferences get(Context context) { - synchronized (sMap) { - return sMap.get(context); - } - } - - private static String getLocalSharedPreferencesName( - Context context, int cameraId) { - return context.getPackageName() + "_preferences_" + cameraId; - } - - private static String getGlobalSharedPreferencesName(Context context) { - return context.getPackageName() + "_preferences_camera"; - } - - private void movePrefFrom( - Map<String, ?> m, String key, SharedPreferences src) { - if (m.containsKey(key)) { - Object v = m.get(key); - if (v instanceof String) { - mPrefGlobal.edit().putString(key, (String) v).apply(); - } else if (v instanceof Integer) { - mPrefGlobal.edit().putInt(key, (Integer) v).apply(); - } else if (v instanceof Long) { - mPrefGlobal.edit().putLong(key, (Long) v).apply(); - } else if (v instanceof Float) { - mPrefGlobal.edit().putFloat(key, (Float) v).apply(); - } else if (v instanceof Boolean) { - mPrefGlobal.edit().putBoolean(key, (Boolean) v).apply(); - } - src.edit().remove(key).apply(); - } - } - - private void moveGlobalPrefsFrom(SharedPreferences src) { - Map<String, ?> prefMap = src.getAll(); - movePrefFrom(prefMap, CameraSettings.KEY_VERSION, src); - movePrefFrom(prefMap, CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL, src); - movePrefFrom(prefMap, CameraSettings.KEY_CAMERA_ID, src); - movePrefFrom(prefMap, CameraSettings.KEY_RECORD_LOCATION, src); - movePrefFrom(prefMap, CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, src); - movePrefFrom(prefMap, CameraSettings.KEY_VIDEO_FIRST_USE_HINT_SHOWN, src); - movePrefFrom(prefMap, CameraSettings.KEY_VIDEO_EFFECT, src); - } - - public static String[] getSharedPreferencesNames(Context context) { - int numOfCameras = CameraHolder.instance().getNumberOfCameras(); - String prefNames[] = new String[numOfCameras + 1]; - prefNames[0] = getGlobalSharedPreferencesName(context); - for (int i = 0; i < numOfCameras; i++) { - prefNames[i + 1] = getLocalSharedPreferencesName(context, i); - } - return prefNames; - } - - // Sets the camera id and reads its preferences. Each camera has its own - // preferences. - public void setLocalId(Context context, int cameraId) { - String prefName = getLocalSharedPreferencesName(context, cameraId); - if (mPrefLocal != null) { - mPrefLocal.unregisterOnSharedPreferenceChangeListener(this); - } - mPrefLocal = context.getSharedPreferences( - prefName, Context.MODE_PRIVATE); - mPrefLocal.registerOnSharedPreferenceChangeListener(this); - } - - public SharedPreferences getGlobal() { - return mPrefGlobal; - } - - public SharedPreferences getLocal() { - return mPrefLocal; - } - - @Override - public Map<String, ?> getAll() { - throw new UnsupportedOperationException(); // Can be implemented if needed. - } - - private static boolean isGlobal(String key) { - return key.equals(CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL) - || key.equals(CameraSettings.KEY_CAMERA_ID) - || key.equals(CameraSettings.KEY_RECORD_LOCATION) - || key.equals(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN) - || key.equals(CameraSettings.KEY_VIDEO_FIRST_USE_HINT_SHOWN) - || key.equals(CameraSettings.KEY_VIDEO_EFFECT) - || key.equals(CameraSettings.KEY_TIMER) - || key.equals(CameraSettings.KEY_TIMER_SOUND_EFFECTS) - || key.equals(CameraSettings.KEY_PHOTOSPHERE_PICTURESIZE); - } - - @Override - public String getString(String key, String defValue) { - if (isGlobal(key) || !mPrefLocal.contains(key)) { - return mPrefGlobal.getString(key, defValue); - } else { - return mPrefLocal.getString(key, defValue); - } - } - - @Override - public int getInt(String key, int defValue) { - if (isGlobal(key) || !mPrefLocal.contains(key)) { - return mPrefGlobal.getInt(key, defValue); - } else { - return mPrefLocal.getInt(key, defValue); - } - } - - @Override - public long getLong(String key, long defValue) { - if (isGlobal(key) || !mPrefLocal.contains(key)) { - return mPrefGlobal.getLong(key, defValue); - } else { - return mPrefLocal.getLong(key, defValue); - } - } - - @Override - public float getFloat(String key, float defValue) { - if (isGlobal(key) || !mPrefLocal.contains(key)) { - return mPrefGlobal.getFloat(key, defValue); - } else { - return mPrefLocal.getFloat(key, defValue); - } - } - - @Override - public boolean getBoolean(String key, boolean defValue) { - if (isGlobal(key) || !mPrefLocal.contains(key)) { - return mPrefGlobal.getBoolean(key, defValue); - } else { - return mPrefLocal.getBoolean(key, defValue); - } - } - - // This method is not used. - @Override - public Set<String> getStringSet(String key, Set<String> defValues) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean contains(String key) { - return mPrefLocal.contains(key) || mPrefGlobal.contains(key); - } - - private class MyEditor implements Editor { - private Editor mEditorGlobal; - private Editor mEditorLocal; - - MyEditor() { - mEditorGlobal = mPrefGlobal.edit(); - mEditorLocal = mPrefLocal.edit(); - } - - @Override - public boolean commit() { - boolean result1 = mEditorGlobal.commit(); - boolean result2 = mEditorLocal.commit(); - return result1 && result2; - } - - @Override - public void apply() { - mEditorGlobal.apply(); - mEditorLocal.apply(); - } - - // Note: clear() and remove() affects both local and global preferences. - @Override - public Editor clear() { - mEditorGlobal.clear(); - mEditorLocal.clear(); - return this; - } - - @Override - public Editor remove(String key) { - mEditorGlobal.remove(key); - mEditorLocal.remove(key); - return this; - } - - @Override - public Editor putString(String key, String value) { - if (isGlobal(key)) { - mEditorGlobal.putString(key, value); - } else { - mEditorLocal.putString(key, value); - } - return this; - } - - @Override - public Editor putInt(String key, int value) { - if (isGlobal(key)) { - mEditorGlobal.putInt(key, value); - } else { - mEditorLocal.putInt(key, value); - } - return this; - } - - @Override - public Editor putLong(String key, long value) { - if (isGlobal(key)) { - mEditorGlobal.putLong(key, value); - } else { - mEditorLocal.putLong(key, value); - } - return this; - } - - @Override - public Editor putFloat(String key, float value) { - if (isGlobal(key)) { - mEditorGlobal.putFloat(key, value); - } else { - mEditorLocal.putFloat(key, value); - } - return this; - } - - @Override - public Editor putBoolean(String key, boolean value) { - if (isGlobal(key)) { - mEditorGlobal.putBoolean(key, value); - } else { - mEditorLocal.putBoolean(key, value); - } - return this; - } - - // This method is not used. - @Override - public Editor putStringSet(String key, Set<String> values) { - throw new UnsupportedOperationException(); - } - } - - // Note the remove() and clear() of the returned Editor may not work as - // expected because it doesn't touch the global preferences at all. - @Override - public Editor edit() { - return new MyEditor(); - } - - @Override - public void registerOnSharedPreferenceChangeListener( - OnSharedPreferenceChangeListener listener) { - mListeners.add(listener); - } - - @Override - public void unregisterOnSharedPreferenceChangeListener( - OnSharedPreferenceChangeListener listener) { - mListeners.remove(listener); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - for (OnSharedPreferenceChangeListener listener : mListeners) { - listener.onSharedPreferenceChanged(this, key); - } - BackupManager.dataChanged(mPackageName); - UsageStatistics.onEvent("CameraSettingsChange", null, key); - } -} diff --git a/src/com/android/camera/CountDownTimerPreference.java b/src/com/android/camera/CountDownTimerPreference.java deleted file mode 100644 index 9c66dda8c..000000000 --- a/src/com/android/camera/CountDownTimerPreference.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 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 com.android.gallery3d.R; - -public class CountDownTimerPreference extends ListPreference { - private static final int[] DURATIONS = { - 0, 1, 2, 3, 4, 5, 10, 15, 20, 30, 60 - }; - public CountDownTimerPreference(Context context, AttributeSet attrs) { - super(context, attrs); - initCountDownDurationChoices(context); - } - - private void initCountDownDurationChoices(Context context) { - CharSequence[] entryValues = new CharSequence[DURATIONS.length]; - CharSequence[] entries = new CharSequence[DURATIONS.length]; - for (int i = 0; i < DURATIONS.length; i++) { - entryValues[i] = Integer.toString(DURATIONS[i]); - if (i == 0) { - entries[0] = context.getString(R.string.setting_off); // Off - } else { - entries[i] = context.getResources() - .getQuantityString(R.plurals.pref_camera_timer_entry, i, i); - } - } - setEntries(entries); - setEntryValues(entryValues); - } -} diff --git a/src/com/android/camera/DisableCameraReceiver.java b/src/com/android/camera/DisableCameraReceiver.java deleted file mode 100644 index 351740541..000000000 --- a/src/com/android/camera/DisableCameraReceiver.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.hardware.Camera.CameraInfo; -import android.util.Log; - -// We want to disable camera-related activities if there is no camera. This -// receiver runs when BOOT_COMPLETED intent is received. After running once -// this receiver will be disabled, so it will not run again. -public class DisableCameraReceiver extends BroadcastReceiver { - private static final String TAG = "DisableCameraReceiver"; - private static final boolean CHECK_BACK_CAMERA_ONLY = true; - private static final String ACTIVITIES[] = { - "com.android.camera.CameraLauncher", - }; - - @Override - public void onReceive(Context context, Intent intent) { - // Disable camera-related activities if there is no camera. - boolean needCameraActivity = CHECK_BACK_CAMERA_ONLY - ? hasBackCamera() - : hasCamera(); - - if (!needCameraActivity) { - Log.i(TAG, "disable all camera activities"); - for (int i = 0; i < ACTIVITIES.length; i++) { - disableComponent(context, ACTIVITIES[i]); - } - } - - // Disable this receiver so it won't run again. - disableComponent(context, "com.android.camera.DisableCameraReceiver"); - } - - private boolean hasCamera() { - int n = android.hardware.Camera.getNumberOfCameras(); - Log.i(TAG, "number of camera: " + n); - return (n > 0); - } - - private boolean hasBackCamera() { - int n = android.hardware.Camera.getNumberOfCameras(); - CameraInfo info = new CameraInfo(); - for (int i = 0; i < n; i++) { - android.hardware.Camera.getCameraInfo(i, info); - if (info.facing == CameraInfo.CAMERA_FACING_BACK) { - Log.i(TAG, "back camera found: " + i); - return true; - } - } - Log.i(TAG, "no back camera"); - return false; - } - - private void disableComponent(Context context, String klass) { - ComponentName name = new ComponentName(context, klass); - PackageManager pm = context.getPackageManager(); - - // We need the DONT_KILL_APP flag, otherwise we will be killed - // immediately because we are in the same app. - pm.setComponentEnabledSetting(name, - PackageManager.COMPONENT_ENABLED_STATE_DISABLED, - PackageManager.DONT_KILL_APP); - } -} diff --git a/src/com/android/camera/EffectsRecorder.java b/src/com/android/camera/EffectsRecorder.java deleted file mode 100644 index 4bf8d411e..000000000 --- a/src/com/android/camera/EffectsRecorder.java +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.camera; - -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.SurfaceTexture; -import android.hardware.Camera; -import android.media.CamcorderProfile; -import android.media.MediaRecorder; -import android.os.Handler; -import android.os.Looper; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.io.FileDescriptor; -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - - -/** - * Encapsulates the mobile filter framework components needed to record video - * with effects applied. Modeled after MediaRecorder. - */ -@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) // uses SurfaceTexture -public class EffectsRecorder { - private static final String TAG = "EffectsRecorder"; - - private static Class<?> sClassFilter; - private static Method sFilterIsAvailable; - private static EffectsRecorder sEffectsRecorder; - // The index of the current effects recorder. - private static int sEffectsRecorderIndex; - - private static boolean sReflectionInited = false; - - private static Class<?> sClsLearningDoneListener; - private static Class<?> sClsOnRunnerDoneListener; - private static Class<?> sClsOnRecordingDoneListener; - private static Class<?> sClsSurfaceTextureSourceListener; - - private static Method sFilterSetInputValue; - - private static Constructor<?> sCtPoint; - private static Constructor<?> sCtQuad; - - private static Method sLearningDoneListenerOnLearningDone; - - private static Method sObjectEquals; - private static Method sObjectToString; - - private static Class<?> sClsGraphRunner; - private static Method sGraphRunnerGetGraph; - private static Method sGraphRunnerSetDoneCallback; - private static Method sGraphRunnerRun; - private static Method sGraphRunnerGetError; - private static Method sGraphRunnerStop; - - private static Method sFilterGraphGetFilter; - private static Method sFilterGraphTearDown; - - private static Method sOnRunnerDoneListenerOnRunnerDone; - - private static Class<?> sClsGraphEnvironment; - private static Constructor<?> sCtGraphEnvironment; - private static Method sGraphEnvironmentCreateGLEnvironment; - private static Method sGraphEnvironmentGetRunner; - private static Method sGraphEnvironmentAddReferences; - private static Method sGraphEnvironmentLoadGraph; - private static Method sGraphEnvironmentGetContext; - - private static Method sFilterContextGetGLEnvironment; - private static Method sGLEnvironmentIsActive; - private static Method sGLEnvironmentActivate; - private static Method sGLEnvironmentDeactivate; - private static Method sSurfaceTextureTargetDisconnect; - private static Method sOnRecordingDoneListenerOnRecordingDone; - private static Method sSurfaceTextureSourceListenerOnSurfaceTextureSourceReady; - - private Object mLearningDoneListener; - private Object mRunnerDoneCallback; - private Object mSourceReadyCallback; - // A callback to finalize the media after the recording is done. - private Object mRecordingDoneListener; - - static { - try { - sClassFilter = Class.forName("android.filterfw.core.Filter"); - sFilterIsAvailable = sClassFilter.getMethod("isAvailable", - String.class); - } catch (ClassNotFoundException ex) { - Log.v(TAG, "Can't find the class android.filterfw.core.Filter"); - } catch (NoSuchMethodException e) { - Log.v(TAG, "Can't find the method Filter.isAvailable"); - } - } - - public static final int EFFECT_NONE = 0; - public static final int EFFECT_GOOFY_FACE = 1; - public static final int EFFECT_BACKDROPPER = 2; - - public static final int EFFECT_GF_SQUEEZE = 0; - public static final int EFFECT_GF_BIG_EYES = 1; - public static final int EFFECT_GF_BIG_MOUTH = 2; - public static final int EFFECT_GF_SMALL_MOUTH = 3; - public static final int EFFECT_GF_BIG_NOSE = 4; - public static final int EFFECT_GF_SMALL_EYES = 5; - public static final int NUM_OF_GF_EFFECTS = EFFECT_GF_SMALL_EYES + 1; - - public static final int EFFECT_MSG_STARTED_LEARNING = 0; - public static final int EFFECT_MSG_DONE_LEARNING = 1; - public static final int EFFECT_MSG_SWITCHING_EFFECT = 2; - public static final int EFFECT_MSG_EFFECTS_STOPPED = 3; - public static final int EFFECT_MSG_RECORDING_DONE = 4; - public static final int EFFECT_MSG_PREVIEW_RUNNING = 5; - - private Context mContext; - private Handler mHandler; - - private CameraManager.CameraProxy mCameraDevice; - private CamcorderProfile mProfile; - private double mCaptureRate = 0; - private SurfaceTexture mPreviewSurfaceTexture; - private int mPreviewWidth; - private int mPreviewHeight; - private MediaRecorder.OnInfoListener mInfoListener; - private MediaRecorder.OnErrorListener mErrorListener; - - private String mOutputFile; - private FileDescriptor mFd; - private int mOrientationHint = 0; - private long mMaxFileSize = 0; - private int mMaxDurationMs = 0; - private int mCameraFacing = Camera.CameraInfo.CAMERA_FACING_BACK; - private int mCameraDisplayOrientation; - - private int mEffect = EFFECT_NONE; - private int mCurrentEffect = EFFECT_NONE; - private EffectsListener mEffectsListener; - - private Object mEffectParameter; - - private Object mGraphEnv; - private int mGraphId; - private Object mRunner = null; - private Object mOldRunner = null; - - private SurfaceTexture mTextureSource; - - private static final int STATE_CONFIGURE = 0; - private static final int STATE_WAITING_FOR_SURFACE = 1; - private static final int STATE_STARTING_PREVIEW = 2; - private static final int STATE_PREVIEW = 3; - private static final int STATE_RECORD = 4; - private static final int STATE_RELEASED = 5; - private int mState = STATE_CONFIGURE; - - private boolean mLogVerbose = Log.isLoggable(TAG, Log.VERBOSE); - private SoundClips.Player mSoundPlayer; - - /** Determine if a given effect is supported at runtime - * Some effects require libraries not available on all devices - */ - public static boolean isEffectSupported(int effectId) { - if (sFilterIsAvailable == null) return false; - - try { - switch (effectId) { - case EFFECT_GOOFY_FACE: - return (Boolean) sFilterIsAvailable.invoke(null, - "com.google.android.filterpacks.facedetect.GoofyRenderFilter"); - case EFFECT_BACKDROPPER: - return (Boolean) sFilterIsAvailable.invoke(null, - "android.filterpacks.videoproc.BackDropperFilter"); - default: - return false; - } - } catch (Exception ex) { - Log.e(TAG, "Fail to check filter", ex); - } - return false; - } - - public EffectsRecorder(Context context) { - if (mLogVerbose) Log.v(TAG, "EffectsRecorder created (" + this + ")"); - - if (!sReflectionInited) { - try { - sFilterSetInputValue = sClassFilter.getMethod("setInputValue", - new Class[] {String.class, Object.class}); - - Class<?> clsPoint = Class.forName("android.filterfw.geometry.Point"); - sCtPoint = clsPoint.getConstructor(new Class[] {float.class, - float.class}); - - Class<?> clsQuad = Class.forName("android.filterfw.geometry.Quad"); - sCtQuad = clsQuad.getConstructor(new Class[] {clsPoint, clsPoint, - clsPoint, clsPoint}); - - Class<?> clsBackDropperFilter = Class.forName( - "android.filterpacks.videoproc.BackDropperFilter"); - sClsLearningDoneListener = Class.forName( - "android.filterpacks.videoproc.BackDropperFilter$LearningDoneListener"); - sLearningDoneListenerOnLearningDone = sClsLearningDoneListener - .getMethod("onLearningDone", new Class[] {clsBackDropperFilter}); - - sObjectEquals = Object.class.getMethod("equals", new Class[] {Object.class}); - sObjectToString = Object.class.getMethod("toString"); - - sClsOnRunnerDoneListener = Class.forName( - "android.filterfw.core.GraphRunner$OnRunnerDoneListener"); - sOnRunnerDoneListenerOnRunnerDone = sClsOnRunnerDoneListener.getMethod( - "onRunnerDone", new Class[] {int.class}); - - sClsGraphRunner = Class.forName("android.filterfw.core.GraphRunner"); - sGraphRunnerGetGraph = sClsGraphRunner.getMethod("getGraph"); - sGraphRunnerSetDoneCallback = sClsGraphRunner.getMethod( - "setDoneCallback", new Class[] {sClsOnRunnerDoneListener}); - sGraphRunnerRun = sClsGraphRunner.getMethod("run"); - sGraphRunnerGetError = sClsGraphRunner.getMethod("getError"); - sGraphRunnerStop = sClsGraphRunner.getMethod("stop"); - - Class<?> clsFilterContext = Class.forName("android.filterfw.core.FilterContext"); - sFilterContextGetGLEnvironment = clsFilterContext.getMethod( - "getGLEnvironment"); - - Class<?> clsFilterGraph = Class.forName("android.filterfw.core.FilterGraph"); - sFilterGraphGetFilter = clsFilterGraph.getMethod("getFilter", - new Class[] {String.class}); - sFilterGraphTearDown = clsFilterGraph.getMethod("tearDown", - new Class[] {clsFilterContext}); - - sClsGraphEnvironment = Class.forName("android.filterfw.GraphEnvironment"); - sCtGraphEnvironment = sClsGraphEnvironment.getConstructor(); - sGraphEnvironmentCreateGLEnvironment = sClsGraphEnvironment.getMethod( - "createGLEnvironment"); - sGraphEnvironmentGetRunner = sClsGraphEnvironment.getMethod( - "getRunner", new Class[] {int.class, int.class}); - sGraphEnvironmentAddReferences = sClsGraphEnvironment.getMethod( - "addReferences", new Class[] {Object[].class}); - sGraphEnvironmentLoadGraph = sClsGraphEnvironment.getMethod( - "loadGraph", new Class[] {Context.class, int.class}); - sGraphEnvironmentGetContext = sClsGraphEnvironment.getMethod( - "getContext"); - - Class<?> clsGLEnvironment = Class.forName("android.filterfw.core.GLEnvironment"); - sGLEnvironmentIsActive = clsGLEnvironment.getMethod("isActive"); - sGLEnvironmentActivate = clsGLEnvironment.getMethod("activate"); - sGLEnvironmentDeactivate = clsGLEnvironment.getMethod("deactivate"); - - Class<?> clsSurfaceTextureTarget = Class.forName( - "android.filterpacks.videosrc.SurfaceTextureTarget"); - sSurfaceTextureTargetDisconnect = clsSurfaceTextureTarget.getMethod( - "disconnect", new Class[] {clsFilterContext}); - - sClsOnRecordingDoneListener = Class.forName( - "android.filterpacks.videosink.MediaEncoderFilter$OnRecordingDoneListener"); - sOnRecordingDoneListenerOnRecordingDone = - sClsOnRecordingDoneListener.getMethod("onRecordingDone"); - - sClsSurfaceTextureSourceListener = Class.forName( - "android.filterpacks.videosrc.SurfaceTextureSource$SurfaceTextureSourceListener"); - sSurfaceTextureSourceListenerOnSurfaceTextureSourceReady = - sClsSurfaceTextureSourceListener.getMethod( - "onSurfaceTextureSourceReady", - new Class[] {SurfaceTexture.class}); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - - sReflectionInited = true; - } - - sEffectsRecorderIndex++; - Log.v(TAG, "Current effects recorder index is " + sEffectsRecorderIndex); - sEffectsRecorder = this; - SerializableInvocationHandler sih = new SerializableInvocationHandler( - sEffectsRecorderIndex); - mLearningDoneListener = Proxy.newProxyInstance( - sClsLearningDoneListener.getClassLoader(), - new Class[] {sClsLearningDoneListener}, sih); - mRunnerDoneCallback = Proxy.newProxyInstance( - sClsOnRunnerDoneListener.getClassLoader(), - new Class[] {sClsOnRunnerDoneListener}, sih); - mSourceReadyCallback = Proxy.newProxyInstance( - sClsSurfaceTextureSourceListener.getClassLoader(), - new Class[] {sClsSurfaceTextureSourceListener}, sih); - mRecordingDoneListener = Proxy.newProxyInstance( - sClsOnRecordingDoneListener.getClassLoader(), - new Class[] {sClsOnRecordingDoneListener}, sih); - - mContext = context; - mHandler = new Handler(Looper.getMainLooper()); - mSoundPlayer = SoundClips.getPlayer(context); - } - - public synchronized void setCamera(CameraManager.CameraProxy cameraDevice) { - switch (mState) { - case STATE_PREVIEW: - throw new RuntimeException("setCamera cannot be called while previewing!"); - case STATE_RECORD: - throw new RuntimeException("setCamera cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException("setCamera called on an already released recorder!"); - default: - break; - } - - mCameraDevice = cameraDevice; - } - - public void setProfile(CamcorderProfile profile) { - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setProfile cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException("setProfile called on an already released recorder!"); - default: - break; - } - mProfile = profile; - } - - public void setOutputFile(String outputFile) { - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setOutputFile cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException("setOutputFile called on an already released recorder!"); - default: - break; - } - - mOutputFile = outputFile; - mFd = null; - } - - public void setOutputFile(FileDescriptor fd) { - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setOutputFile cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException("setOutputFile called on an already released recorder!"); - default: - break; - } - - mOutputFile = null; - mFd = fd; - } - - /** - * Sets the maximum filesize (in bytes) of the recording session. - * This will be passed on to the MediaEncoderFilter and then to the - * MediaRecorder ultimately. If zero or negative, the MediaRecorder will - * disable the limit - */ - public synchronized void setMaxFileSize(long maxFileSize) { - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setMaxFileSize cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException( - "setMaxFileSize called on an already released recorder!"); - default: - break; - } - mMaxFileSize = maxFileSize; - } - - /** - * Sets the maximum recording duration (in ms) for the next recording session - * Setting it to zero (the default) disables the limit. - */ - public synchronized void setMaxDuration(int maxDurationMs) { - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setMaxDuration cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException( - "setMaxDuration called on an already released recorder!"); - default: - break; - } - mMaxDurationMs = maxDurationMs; - } - - - public void setCaptureRate(double fps) { - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setCaptureRate cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException( - "setCaptureRate called on an already released recorder!"); - default: - break; - } - - if (mLogVerbose) Log.v(TAG, "Setting time lapse capture rate to " + fps + " fps"); - mCaptureRate = fps; - } - - public void setPreviewSurfaceTexture(SurfaceTexture previewSurfaceTexture, - int previewWidth, - int previewHeight) { - if (mLogVerbose) Log.v(TAG, "setPreviewSurfaceTexture(" + this + ")"); - switch (mState) { - case STATE_RECORD: - throw new RuntimeException( - "setPreviewSurfaceTexture cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException( - "setPreviewSurfaceTexture called on an already released recorder!"); - default: - break; - } - - mPreviewSurfaceTexture = previewSurfaceTexture; - mPreviewWidth = previewWidth; - mPreviewHeight = previewHeight; - - switch (mState) { - case STATE_WAITING_FOR_SURFACE: - startPreview(); - break; - case STATE_STARTING_PREVIEW: - case STATE_PREVIEW: - initializeEffect(true); - break; - } - } - - public void setEffect(int effect, Object effectParameter) { - if (mLogVerbose) Log.v(TAG, - "setEffect: effect ID " + effect + - ", parameter " + effectParameter.toString()); - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setEffect cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException("setEffect called on an already released recorder!"); - default: - break; - } - - mEffect = effect; - mEffectParameter = effectParameter; - - if (mState == STATE_PREVIEW || - mState == STATE_STARTING_PREVIEW) { - initializeEffect(false); - } - } - - public interface EffectsListener { - public void onEffectsUpdate(int effectId, int effectMsg); - public void onEffectsError(Exception exception, String filePath); - } - - public void setEffectsListener(EffectsListener listener) { - mEffectsListener = listener; - } - - private void setFaceDetectOrientation() { - if (mCurrentEffect == EFFECT_GOOFY_FACE) { - Object rotateFilter = getGraphFilter(mRunner, "rotate"); - Object metaRotateFilter = getGraphFilter(mRunner, "metarotate"); - setInputValue(rotateFilter, "rotation", mOrientationHint); - int reverseDegrees = (360 - mOrientationHint) % 360; - setInputValue(metaRotateFilter, "rotation", reverseDegrees); - } - } - - private void setRecordingOrientation() { - if (mState != STATE_RECORD && mRunner != null) { - Object bl = newInstance(sCtPoint, new Object[] {0, 0}); - Object br = newInstance(sCtPoint, new Object[] {1, 0}); - Object tl = newInstance(sCtPoint, new Object[] {0, 1}); - Object tr = newInstance(sCtPoint, new Object[] {1, 1}); - Object recordingRegion; - if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_BACK) { - // The back camera is not mirrored, so use a identity transform - recordingRegion = newInstance(sCtQuad, new Object[] {bl, br, tl, tr}); - } else { - // Recording region needs to be tweaked for front cameras, since they - // mirror their preview - if (mOrientationHint == 0 || mOrientationHint == 180) { - // Horizontal flip in landscape - recordingRegion = newInstance(sCtQuad, new Object[] {br, bl, tr, tl}); - } else { - // Horizontal flip in portrait - recordingRegion = newInstance(sCtQuad, new Object[] {tl, tr, bl, br}); - } - } - Object recorder = getGraphFilter(mRunner, "recorder"); - setInputValue(recorder, "inputRegion", recordingRegion); - } - } - public void setOrientationHint(int degrees) { - switch (mState) { - case STATE_RELEASED: - throw new RuntimeException( - "setOrientationHint called on an already released recorder!"); - default: - break; - } - if (mLogVerbose) Log.v(TAG, "Setting orientation hint to: " + degrees); - mOrientationHint = degrees; - setFaceDetectOrientation(); - setRecordingOrientation(); - } - - public void setCameraDisplayOrientation(int orientation) { - if (mState != STATE_CONFIGURE) { - throw new RuntimeException( - "setCameraDisplayOrientation called after configuration!"); - } - mCameraDisplayOrientation = orientation; - } - - public void setCameraFacing(int facing) { - switch (mState) { - case STATE_RELEASED: - throw new RuntimeException( - "setCameraFacing called on alrady released recorder!"); - default: - break; - } - mCameraFacing = facing; - setRecordingOrientation(); - } - - public void setOnInfoListener(MediaRecorder.OnInfoListener infoListener) { - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setInfoListener cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException( - "setInfoListener called on an already released recorder!"); - default: - break; - } - mInfoListener = infoListener; - } - - public void setOnErrorListener(MediaRecorder.OnErrorListener errorListener) { - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("setErrorListener cannot be called while recording!"); - case STATE_RELEASED: - throw new RuntimeException( - "setErrorListener called on an already released recorder!"); - default: - break; - } - mErrorListener = errorListener; - } - - private void initializeFilterFramework() { - mGraphEnv = newInstance(sCtGraphEnvironment); - invoke(mGraphEnv, sGraphEnvironmentCreateGLEnvironment); - - int videoFrameWidth = mProfile.videoFrameWidth; - int videoFrameHeight = mProfile.videoFrameHeight; - if (mCameraDisplayOrientation == 90 || mCameraDisplayOrientation == 270) { - int tmp = videoFrameWidth; - videoFrameWidth = videoFrameHeight; - videoFrameHeight = tmp; - } - - invoke(mGraphEnv, sGraphEnvironmentAddReferences, - new Object[] {new Object[] { - "textureSourceCallback", mSourceReadyCallback, - "recordingWidth", videoFrameWidth, - "recordingHeight", videoFrameHeight, - "recordingProfile", mProfile, - "learningDoneListener", mLearningDoneListener, - "recordingDoneListener", mRecordingDoneListener}}); - mRunner = null; - mGraphId = -1; - mCurrentEffect = EFFECT_NONE; - } - - private synchronized void initializeEffect(boolean forceReset) { - if (forceReset || - mCurrentEffect != mEffect || - mCurrentEffect == EFFECT_BACKDROPPER) { - - invoke(mGraphEnv, sGraphEnvironmentAddReferences, - new Object[] {new Object[] { - "previewSurfaceTexture", mPreviewSurfaceTexture, - "previewWidth", mPreviewWidth, - "previewHeight", mPreviewHeight, - "orientation", mOrientationHint}}); - if (mState == STATE_PREVIEW || - mState == STATE_STARTING_PREVIEW) { - // Switching effects while running. Inform video camera. - sendMessage(mCurrentEffect, EFFECT_MSG_SWITCHING_EFFECT); - } - - switch (mEffect) { - case EFFECT_GOOFY_FACE: - mGraphId = (Integer) invoke(mGraphEnv, - sGraphEnvironmentLoadGraph, - new Object[] {mContext, R.raw.goofy_face}); - break; - case EFFECT_BACKDROPPER: - sendMessage(EFFECT_BACKDROPPER, EFFECT_MSG_STARTED_LEARNING); - mGraphId = (Integer) invoke(mGraphEnv, - sGraphEnvironmentLoadGraph, - new Object[] {mContext, R.raw.backdropper}); - break; - default: - throw new RuntimeException("Unknown effect ID" + mEffect + "!"); - } - mCurrentEffect = mEffect; - - mOldRunner = mRunner; - mRunner = invoke(mGraphEnv, sGraphEnvironmentGetRunner, - new Object[] {mGraphId, - getConstant(sClsGraphEnvironment, "MODE_ASYNCHRONOUS")}); - invoke(mRunner, sGraphRunnerSetDoneCallback, new Object[] {mRunnerDoneCallback}); - if (mLogVerbose) { - Log.v(TAG, "New runner: " + mRunner - + ". Old runner: " + mOldRunner); - } - if (mState == STATE_PREVIEW || - mState == STATE_STARTING_PREVIEW) { - // Switching effects while running. Stop existing runner. - // The stop callback will take care of starting new runner. - mCameraDevice.stopPreview(); - mCameraDevice.setPreviewTexture(null); - invoke(mOldRunner, sGraphRunnerStop); - } - } - - switch (mCurrentEffect) { - case EFFECT_GOOFY_FACE: - tryEnableVideoStabilization(true); - Object goofyFilter = getGraphFilter(mRunner, "goofyrenderer"); - setInputValue(goofyFilter, "currentEffect", - ((Integer) mEffectParameter).intValue()); - break; - case EFFECT_BACKDROPPER: - tryEnableVideoStabilization(false); - Object backgroundSrc = getGraphFilter(mRunner, "background"); - if (ApiHelper.HAS_EFFECTS_RECORDING_CONTEXT_INPUT) { - // Set the context first before setting sourceUrl to - // guarantee the content URI get resolved properly. - setInputValue(backgroundSrc, "context", mContext); - } - setInputValue(backgroundSrc, "sourceUrl", mEffectParameter); - // For front camera, the background video needs to be mirrored in the - // backdropper filter - if (mCameraFacing == Camera.CameraInfo.CAMERA_FACING_FRONT) { - Object replacer = getGraphFilter(mRunner, "replacer"); - setInputValue(replacer, "mirrorBg", true); - if (mLogVerbose) Log.v(TAG, "Setting the background to be mirrored"); - } - break; - default: - break; - } - setFaceDetectOrientation(); - setRecordingOrientation(); - } - - public synchronized void startPreview() { - if (mLogVerbose) Log.v(TAG, "Starting preview (" + this + ")"); - - switch (mState) { - case STATE_STARTING_PREVIEW: - case STATE_PREVIEW: - // Already running preview - Log.w(TAG, "startPreview called when already running preview"); - return; - case STATE_RECORD: - throw new RuntimeException("Cannot start preview when already recording!"); - case STATE_RELEASED: - throw new RuntimeException("setEffect called on an already released recorder!"); - default: - break; - } - - if (mEffect == EFFECT_NONE) { - throw new RuntimeException("No effect selected!"); - } - if (mEffectParameter == null) { - throw new RuntimeException("No effect parameter provided!"); - } - if (mProfile == null) { - throw new RuntimeException("No recording profile provided!"); - } - if (mPreviewSurfaceTexture == null) { - if (mLogVerbose) Log.v(TAG, "Passed a null surface; waiting for valid one"); - mState = STATE_WAITING_FOR_SURFACE; - return; - } - if (mCameraDevice == null) { - throw new RuntimeException("No camera to record from!"); - } - - if (mLogVerbose) Log.v(TAG, "Initializing filter framework and running the graph."); - initializeFilterFramework(); - - initializeEffect(true); - - mState = STATE_STARTING_PREVIEW; - invoke(mRunner, sGraphRunnerRun); - // Rest of preview startup handled in mSourceReadyCallback - } - - private Object invokeObjectEquals(Object proxy, Object[] args) { - return Boolean.valueOf(proxy == args[0]); - } - - private Object invokeObjectToString() { - return "Proxy-" + toString(); - } - - private void invokeOnLearningDone() { - if (mLogVerbose) Log.v(TAG, "Learning done callback triggered"); - // Called in a processing thread, so have to post message back to UI - // thread - sendMessage(EFFECT_BACKDROPPER, EFFECT_MSG_DONE_LEARNING); - enable3ALocks(true); - } - - private void invokeOnRunnerDone(Object[] args) { - int runnerDoneResult = (Integer) args[0]; - synchronized (EffectsRecorder.this) { - if (mLogVerbose) { - Log.v(TAG, - "Graph runner done (" + EffectsRecorder.this - + ", mRunner " + mRunner - + ", mOldRunner " + mOldRunner + ")"); - } - if (runnerDoneResult == - (Integer) getConstant(sClsGraphRunner, "RESULT_ERROR")) { - // Handle error case - Log.e(TAG, "Error running filter graph!"); - Exception e = null; - if (mRunner != null) { - e = (Exception) invoke(mRunner, sGraphRunnerGetError); - } else if (mOldRunner != null) { - e = (Exception) invoke(mOldRunner, sGraphRunnerGetError); - } - raiseError(e); - } - if (mOldRunner != null) { - // Tear down old graph if available - if (mLogVerbose) Log.v(TAG, "Tearing down old graph."); - Object glEnv = getContextGLEnvironment(mGraphEnv); - if (glEnv != null && !(Boolean) invoke(glEnv, sGLEnvironmentIsActive)) { - invoke(glEnv, sGLEnvironmentActivate); - } - getGraphTearDown(mOldRunner, - invoke(mGraphEnv, sGraphEnvironmentGetContext)); - if (glEnv != null && (Boolean) invoke(glEnv, sGLEnvironmentIsActive)) { - invoke(glEnv, sGLEnvironmentDeactivate); - } - mOldRunner = null; - } - if (mState == STATE_PREVIEW || - mState == STATE_STARTING_PREVIEW) { - // Switching effects, start up the new runner - if (mLogVerbose) { - Log.v(TAG, "Previous effect halted. Running graph again. state: " - + mState); - } - tryEnable3ALocks(false); - // In case of an error, the graph restarts from beginning and in case - // of the BACKDROPPER effect, the learner re-learns the background. - // Hence, we need to show the learning dialogue to the user - // to avoid recording before the learning is done. Else, the user - // could start recording before the learning is done and the new - // background comes up later leading to an end result video - // with a heterogeneous background. - // For BACKDROPPER effect, this path is also executed sometimes at - // the end of a normal recording session. In such a case, the graph - // does not restart and hence the learner does not re-learn. So we - // do not want to show the learning dialogue then. - if (runnerDoneResult == (Integer) getConstant( - sClsGraphRunner, "RESULT_ERROR") - && mCurrentEffect == EFFECT_BACKDROPPER) { - sendMessage(EFFECT_BACKDROPPER, EFFECT_MSG_STARTED_LEARNING); - } - invoke(mRunner, sGraphRunnerRun); - } else if (mState != STATE_RELEASED) { - // Shutting down effects - if (mLogVerbose) Log.v(TAG, "Runner halted, restoring direct preview"); - tryEnable3ALocks(false); - sendMessage(EFFECT_NONE, EFFECT_MSG_EFFECTS_STOPPED); - } else { - // STATE_RELEASED - camera will be/has been released as well, do nothing. - } - } - } - - private void invokeOnSurfaceTextureSourceReady(Object[] args) { - SurfaceTexture source = (SurfaceTexture) args[0]; - if (mLogVerbose) Log.v(TAG, "SurfaceTexture ready callback received"); - synchronized (EffectsRecorder.this) { - mTextureSource = source; - - if (mState == STATE_CONFIGURE) { - // Stop preview happened while the runner was doing startup tasks - // Since we haven't started anything up, don't do anything - // Rest of cleanup will happen in onRunnerDone - if (mLogVerbose) Log.v(TAG, "Ready callback: Already stopped, skipping."); - return; - } - if (mState == STATE_RELEASED) { - // EffectsRecorder has been released, so don't touch the camera device - // or anything else - if (mLogVerbose) Log.v(TAG, "Ready callback: Already released, skipping."); - return; - } - if (source == null) { - if (mLogVerbose) { - Log.v(TAG, "Ready callback: source null! Looks like graph was closed!"); - } - if (mState == STATE_PREVIEW || - mState == STATE_STARTING_PREVIEW || - mState == STATE_RECORD) { - // A null source here means the graph is shutting down - // unexpectedly, so we need to turn off preview before - // the surface texture goes away. - if (mLogVerbose) { - Log.v(TAG, "Ready callback: State: " + mState - + ". stopCameraPreview"); - } - - stopCameraPreview(); - } - return; - } - - // Lock AE/AWB to reduce transition flicker - tryEnable3ALocks(true); - - mCameraDevice.stopPreview(); - if (mLogVerbose) Log.v(TAG, "Runner active, connecting effects preview"); - mCameraDevice.setPreviewTexture(mTextureSource); - - mCameraDevice.startPreview(); - - // Unlock AE/AWB after preview started - tryEnable3ALocks(false); - - mState = STATE_PREVIEW; - - if (mLogVerbose) Log.v(TAG, "Start preview/effect switch complete"); - - // Sending a message to listener that preview is complete - sendMessage(mCurrentEffect, EFFECT_MSG_PREVIEW_RUNNING); - } - } - - private void invokeOnRecordingDone() { - // Forward the callback to the VideoModule object (as an asynchronous event). - if (mLogVerbose) Log.v(TAG, "Recording done callback triggered"); - sendMessage(EFFECT_NONE, EFFECT_MSG_RECORDING_DONE); - } - - public synchronized void startRecording() { - if (mLogVerbose) Log.v(TAG, "Starting recording (" + this + ")"); - - switch (mState) { - case STATE_RECORD: - throw new RuntimeException("Already recording, cannot begin anew!"); - case STATE_RELEASED: - throw new RuntimeException( - "startRecording called on an already released recorder!"); - default: - break; - } - - if ((mOutputFile == null) && (mFd == null)) { - throw new RuntimeException("No output file name or descriptor provided!"); - } - - if (mState == STATE_CONFIGURE) { - startPreview(); - } - - Object recorder = getGraphFilter(mRunner, "recorder"); - if (mFd != null) { - setInputValue(recorder, "outputFileDescriptor", mFd); - } else { - setInputValue(recorder, "outputFile", mOutputFile); - } - // It is ok to set the audiosource without checking for timelapse here - // since that check will be done in the MediaEncoderFilter itself - setInputValue(recorder, "audioSource", MediaRecorder.AudioSource.CAMCORDER); - setInputValue(recorder, "recordingProfile", mProfile); - setInputValue(recorder, "orientationHint", mOrientationHint); - // Important to set the timelapseinterval to 0 if the capture rate is not >0 - // since the recorder does not get created every time the recording starts. - // The recorder infers whether the capture is timelapsed based on the value of - // this interval - boolean captureTimeLapse = mCaptureRate > 0; - if (captureTimeLapse) { - double timeBetweenFrameCapture = 1 / mCaptureRate; - setInputValue(recorder, "timelapseRecordingIntervalUs", - (long) (1000000 * timeBetweenFrameCapture)); - - } else { - setInputValue(recorder, "timelapseRecordingIntervalUs", 0L); - } - - if (mInfoListener != null) { - setInputValue(recorder, "infoListener", mInfoListener); - } - if (mErrorListener != null) { - setInputValue(recorder, "errorListener", mErrorListener); - } - setInputValue(recorder, "maxFileSize", mMaxFileSize); - setInputValue(recorder, "maxDurationMs", mMaxDurationMs); - setInputValue(recorder, "recording", true); - mSoundPlayer.play(SoundClips.START_VIDEO_RECORDING); - mState = STATE_RECORD; - } - - public synchronized void stopRecording() { - if (mLogVerbose) Log.v(TAG, "Stop recording (" + this + ")"); - - switch (mState) { - case STATE_CONFIGURE: - case STATE_STARTING_PREVIEW: - case STATE_PREVIEW: - Log.w(TAG, "StopRecording called when recording not active!"); - return; - case STATE_RELEASED: - throw new RuntimeException("stopRecording called on released EffectsRecorder!"); - default: - break; - } - Object recorder = getGraphFilter(mRunner, "recorder"); - setInputValue(recorder, "recording", false); - mSoundPlayer.play(SoundClips.STOP_VIDEO_RECORDING); - mState = STATE_PREVIEW; - } - - // Called to tell the filter graph that the display surfacetexture is not valid anymore. - // So the filter graph should not hold any reference to the surface created with that. - public synchronized void disconnectDisplay() { - if (mLogVerbose) Log.v(TAG, "Disconnecting the graph from the " + - "SurfaceTexture"); - Object display = getGraphFilter(mRunner, "display"); - invoke(display, sSurfaceTextureTargetDisconnect, new Object[] { - invoke(mGraphEnv, sGraphEnvironmentGetContext)}); - } - - // The VideoModule will call this to notify that the camera is being - // released to the outside world. This call should happen after the - // stopRecording call. Else, the effects may throw an exception. - // With the recording stopped, the stopPreview call will not try to - // release the camera again. - // This must be called in onPause() if the effects are ON. - public synchronized void disconnectCamera() { - if (mLogVerbose) Log.v(TAG, "Disconnecting the effects from Camera"); - stopCameraPreview(); - mCameraDevice = null; - } - - // In a normal case, when the disconnect is not called, we should not - // set the camera device to null, since on return callback, we try to - // enable 3A locks, which need the cameradevice. - public synchronized void stopCameraPreview() { - if (mLogVerbose) Log.v(TAG, "Stopping camera preview."); - if (mCameraDevice == null) { - Log.d(TAG, "Camera already null. Nothing to disconnect"); - return; - } - mCameraDevice.stopPreview(); - mCameraDevice.setPreviewTexture(null); - } - - // Stop and release effect resources - public synchronized void stopPreview() { - if (mLogVerbose) Log.v(TAG, "Stopping preview (" + this + ")"); - switch (mState) { - case STATE_CONFIGURE: - Log.w(TAG, "StopPreview called when preview not active!"); - return; - case STATE_RELEASED: - throw new RuntimeException("stopPreview called on released EffectsRecorder!"); - default: - break; - } - - if (mState == STATE_RECORD) { - stopRecording(); - } - - mCurrentEffect = EFFECT_NONE; - - // This will not do anything if the camera has already been disconnected. - stopCameraPreview(); - - mState = STATE_CONFIGURE; - mOldRunner = mRunner; - invoke(mRunner, sGraphRunnerStop); - mRunner = null; - // Rest of stop and release handled in mRunnerDoneCallback - } - - // Try to enable/disable video stabilization if supported; otherwise return false - // It is called from a synchronized block. - boolean tryEnableVideoStabilization(boolean toggle) { - if (mLogVerbose) Log.v(TAG, "tryEnableVideoStabilization."); - if (mCameraDevice == null) { - Log.d(TAG, "Camera already null. Not enabling video stabilization."); - return false; - } - Camera.Parameters params = mCameraDevice.getParameters(); - - String vstabSupported = params.get("video-stabilization-supported"); - if ("true".equals(vstabSupported)) { - if (mLogVerbose) Log.v(TAG, "Setting video stabilization to " + toggle); - params.set("video-stabilization", toggle ? "true" : "false"); - mCameraDevice.setParameters(params); - return true; - } - if (mLogVerbose) Log.v(TAG, "Video stabilization not supported"); - return false; - } - - // Try to enable/disable 3A locks if supported; otherwise return false - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - synchronized boolean tryEnable3ALocks(boolean toggle) { - if (mLogVerbose) Log.v(TAG, "tryEnable3ALocks"); - if (mCameraDevice == null) { - Log.d(TAG, "Camera already null. Not tryenabling 3A locks."); - return false; - } - Camera.Parameters params = mCameraDevice.getParameters(); - if (Util.isAutoExposureLockSupported(params) && - Util.isAutoWhiteBalanceLockSupported(params)) { - params.setAutoExposureLock(toggle); - params.setAutoWhiteBalanceLock(toggle); - mCameraDevice.setParameters(params); - return true; - } - return false; - } - - // Try to enable/disable 3A locks if supported; otherwise, throw error - // Use this when locks are essential to success - synchronized void enable3ALocks(boolean toggle) { - if (mLogVerbose) Log.v(TAG, "Enable3ALocks"); - if (mCameraDevice == null) { - Log.d(TAG, "Camera already null. Not enabling 3A locks."); - return; - } - Camera.Parameters params = mCameraDevice.getParameters(); - if (!tryEnable3ALocks(toggle)) { - throw new RuntimeException("Attempt to lock 3A on camera with no locking support!"); - } - } - - static class SerializableInvocationHandler - implements InvocationHandler, Serializable { - private final int mEffectsRecorderIndex; - public SerializableInvocationHandler(int index) { - mEffectsRecorderIndex = index; - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if (sEffectsRecorder == null) return null; - if (mEffectsRecorderIndex != sEffectsRecorderIndex) { - Log.v(TAG, "Ignore old callback " + mEffectsRecorderIndex); - return null; - } - if (method.equals(sObjectEquals)) { - return sEffectsRecorder.invokeObjectEquals(proxy, args); - } else if (method.equals(sObjectToString)) { - return sEffectsRecorder.invokeObjectToString(); - } else if (method.equals(sLearningDoneListenerOnLearningDone)) { - sEffectsRecorder.invokeOnLearningDone(); - } else if (method.equals(sOnRunnerDoneListenerOnRunnerDone)) { - sEffectsRecorder.invokeOnRunnerDone(args); - } else if (method.equals( - sSurfaceTextureSourceListenerOnSurfaceTextureSourceReady)) { - sEffectsRecorder.invokeOnSurfaceTextureSourceReady(args); - } else if (method.equals(sOnRecordingDoneListenerOnRecordingDone)) { - sEffectsRecorder.invokeOnRecordingDone(); - } - return null; - } - } - - // Indicates that all camera/recording activity needs to halt - public synchronized void release() { - if (mLogVerbose) Log.v(TAG, "Releasing (" + this + ")"); - - switch (mState) { - case STATE_RECORD: - case STATE_STARTING_PREVIEW: - case STATE_PREVIEW: - stopPreview(); - // Fall-through - default: - if (mSoundPlayer != null) { - mSoundPlayer.release(); - mSoundPlayer = null; - } - mState = STATE_RELEASED; - break; - } - sEffectsRecorder = null; - } - - private void sendMessage(final int effect, final int msg) { - if (mEffectsListener != null) { - mHandler.post(new Runnable() { - @Override - public void run() { - mEffectsListener.onEffectsUpdate(effect, msg); - } - }); - } - } - - private void raiseError(final Exception exception) { - if (mEffectsListener != null) { - mHandler.post(new Runnable() { - @Override - public void run() { - if (mFd != null) { - mEffectsListener.onEffectsError(exception, null); - } else { - mEffectsListener.onEffectsError(exception, mOutputFile); - } - } - }); - } - } - - // invoke method on receiver with no arguments - private Object invoke(Object receiver, Method method) { - try { - return method.invoke(receiver); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - // invoke method on receiver with arguments - private Object invoke(Object receiver, Method method, Object[] args) { - try { - return method.invoke(receiver, args); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private void setInputValue(Object receiver, String key, Object value) { - try { - sFilterSetInputValue.invoke(receiver, new Object[] {key, value}); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private Object newInstance(Constructor<?> ct, Object[] initArgs) { - try { - return ct.newInstance(initArgs); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private Object newInstance(Constructor<?> ct) { - try { - return ct.newInstance(); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private Object getGraphFilter(Object receiver, String name) { - try { - return sFilterGraphGetFilter.invoke(sGraphRunnerGetGraph - .invoke(receiver), new Object[] {name}); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private Object getContextGLEnvironment(Object receiver) { - try { - return sFilterContextGetGLEnvironment - .invoke(sGraphEnvironmentGetContext.invoke(receiver)); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private void getGraphTearDown(Object receiver, Object filterContext) { - try { - sFilterGraphTearDown.invoke(sGraphRunnerGetGraph.invoke(receiver), - new Object[]{filterContext}); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private Object getConstant(Class<?> cls, String name) { - try { - return cls.getDeclaredField(name).get(null); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } -} diff --git a/src/com/android/camera/Exif.java b/src/com/android/camera/Exif.java deleted file mode 100644 index c6ec6af50..000000000 --- a/src/com/android/camera/Exif.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2010 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.util.Log; - -import com.android.gallery3d.exif.ExifInterface; - -import java.io.IOException; - -public class Exif { - private static final String TAG = "CameraExif"; - - public static ExifInterface getExif(byte[] jpegData) { - ExifInterface exif = new ExifInterface(); - try { - exif.readExif(jpegData); - } catch (IOException e) { - Log.w(TAG, "Failed to read EXIF data", e); - } - return exif; - } - - // Returns the degrees in clockwise. Values are 0, 90, 180, or 270. - public static int getOrientation(ExifInterface exif) { - Integer val = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION); - if (val == null) { - return 0; - } else { - return ExifInterface.getRotationForOrientationValue(val.shortValue()); - } - } - - public static int getOrientation(byte[] jpegData) { - if (jpegData == null) return 0; - - ExifInterface exif = getExif(jpegData); - return getOrientation(exif); - } -} diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java deleted file mode 100644 index 8bcb52fe5..000000000 --- a/src/com/android/camera/FocusOverlayManager.java +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.annotation.TargetApi; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.graphics.RectF; -import android.hardware.Camera.Area; -import android.hardware.Camera.Parameters; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; -import java.util.List; - -/* A class that handles everything about focus in still picture mode. - * This also handles the metering area because it is the same as focus area. - * - * The test cases: - * (1) The camera has continuous autofocus. Move the camera. Take a picture when - * CAF is not in progress. - * (2) The camera has continuous autofocus. Move the camera. Take a picture when - * CAF is in progress. - * (3) The camera has face detection. Point the camera at some faces. Hold the - * shutter. Release to take a picture. - * (4) The camera has face detection. Point the camera at some faces. Single tap - * the shutter to take a picture. - * (5) The camera has autofocus. Single tap the shutter to take a picture. - * (6) The camera has autofocus. Hold the shutter. Release to take a picture. - * (7) The camera has no autofocus. Single tap the shutter and take a picture. - * (8) The camera has autofocus and supports focus area. Touch the screen to - * trigger autofocus. Take a picture. - * (9) The camera has autofocus and supports focus area. Touch the screen to - * trigger autofocus. Wait until it times out. - * (10) The camera has no autofocus and supports metering area. Touch the screen - * to change metering area. - */ -public class FocusOverlayManager { - private static final String TAG = "CAM_FocusManager"; - - private static final int RESET_TOUCH_FOCUS = 0; - private static final int RESET_TOUCH_FOCUS_DELAY = 3000; - - private int mState = STATE_IDLE; - private static final int STATE_IDLE = 0; // Focus is not active. - private static final int STATE_FOCUSING = 1; // Focus is in progress. - // Focus is in progress and the camera should take a picture after focus finishes. - private static final int STATE_FOCUSING_SNAP_ON_FINISH = 2; - private static final int STATE_SUCCESS = 3; // Focus finishes and succeeds. - private static final int STATE_FAIL = 4; // Focus finishes and fails. - - private boolean mInitialized; - private boolean mFocusAreaSupported; - private boolean mMeteringAreaSupported; - private boolean mLockAeAwbNeeded; - private boolean mAeAwbLock; - private Matrix mMatrix; - - private int mPreviewWidth; // The width of the preview frame layout. - private int mPreviewHeight; // The height of the preview frame layout. - private boolean mMirror; // true if the camera is front-facing. - private int mDisplayOrientation; - private List<Object> mFocusArea; // focus area in driver format - private List<Object> mMeteringArea; // metering area in driver format - private String mFocusMode; - private String[] mDefaultFocusModes; - private String mOverrideFocusMode; - private Parameters mParameters; - private ComboPreferences mPreferences; - private Handler mHandler; - Listener mListener; - private boolean mPreviousMoving; - private boolean mFocusDefault; - - private FocusUI mUI; - - public interface FocusUI { - public boolean hasFaces(); - public void clearFocus(); - public void setFocusPosition(int x, int y); - public void onFocusStarted(); - public void onFocusSucceeded(boolean timeOut); - public void onFocusFailed(boolean timeOut); - public void pauseFaceDetection(); - public void resumeFaceDetection(); - } - - public interface Listener { - public void autoFocus(); - public void cancelAutoFocus(); - public boolean capture(); - public void startFaceDetection(); - public void stopFaceDetection(); - public void setFocusParameters(); - } - - private class MainHandler extends Handler { - public MainHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case RESET_TOUCH_FOCUS: { - cancelAutoFocus(); - mListener.startFaceDetection(); - break; - } - } - } - } - - public FocusOverlayManager(ComboPreferences preferences, String[] defaultFocusModes, - Parameters parameters, Listener listener, - boolean mirror, Looper looper, FocusUI ui) { - mHandler = new MainHandler(looper); - mMatrix = new Matrix(); - mPreferences = preferences; - mDefaultFocusModes = defaultFocusModes; - setParameters(parameters); - mListener = listener; - setMirror(mirror); - mFocusDefault = true; - mUI = ui; - } - - public void setParameters(Parameters parameters) { - // parameters can only be null when onConfigurationChanged is called - // before camera is open. We will just return in this case, because - // parameters will be set again later with the right parameters after - // camera is open. - if (parameters == null) return; - mParameters = parameters; - mFocusAreaSupported = Util.isFocusAreaSupported(parameters); - mMeteringAreaSupported = Util.isMeteringAreaSupported(parameters); - mLockAeAwbNeeded = (Util.isAutoExposureLockSupported(mParameters) || - Util.isAutoWhiteBalanceLockSupported(mParameters)); - } - - public void setPreviewSize(int previewWidth, int previewHeight) { - if (mPreviewWidth != previewWidth || mPreviewHeight != previewHeight) { - mPreviewWidth = previewWidth; - mPreviewHeight = previewHeight; - setMatrix(); - } - } - - public void setMirror(boolean mirror) { - mMirror = mirror; - setMatrix(); - } - - public void setDisplayOrientation(int displayOrientation) { - mDisplayOrientation = displayOrientation; - setMatrix(); - } - - private void setMatrix() { - if (mPreviewWidth != 0 && mPreviewHeight != 0) { - Matrix matrix = new Matrix(); - Util.prepareMatrix(matrix, mMirror, mDisplayOrientation, - mPreviewWidth, mPreviewHeight); - // In face detection, the matrix converts the driver coordinates to UI - // coordinates. In tap focus, the inverted matrix converts the UI - // coordinates to driver coordinates. - matrix.invert(mMatrix); - mInitialized = true; - } - } - - private void lockAeAwbIfNeeded() { - if (mLockAeAwbNeeded && !mAeAwbLock) { - mAeAwbLock = true; - mListener.setFocusParameters(); - } - } - - private void unlockAeAwbIfNeeded() { - if (mLockAeAwbNeeded && mAeAwbLock && (mState != STATE_FOCUSING_SNAP_ON_FINISH)) { - mAeAwbLock = false; - mListener.setFocusParameters(); - } - } - - public void onShutterDown() { - if (!mInitialized) return; - - boolean autoFocusCalled = false; - if (needAutoFocusCall()) { - // Do not focus if touch focus has been triggered. - if (mState != STATE_SUCCESS && mState != STATE_FAIL) { - autoFocus(); - autoFocusCalled = true; - } - } - - if (!autoFocusCalled) lockAeAwbIfNeeded(); - } - - public void onShutterUp() { - if (!mInitialized) return; - - if (needAutoFocusCall()) { - // User releases half-pressed focus key. - if (mState == STATE_FOCUSING || mState == STATE_SUCCESS - || mState == STATE_FAIL) { - cancelAutoFocus(); - } - } - - // Unlock AE and AWB after cancelAutoFocus. Camera API does not - // guarantee setParameters can be called during autofocus. - unlockAeAwbIfNeeded(); - } - - public void doSnap() { - if (!mInitialized) return; - - // 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 (!needAutoFocusCall() || (mState == STATE_SUCCESS || mState == STATE_FAIL)) { - capture(); - } else if (mState == STATE_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. - mState = STATE_FOCUSING_SNAP_ON_FINISH; - } else if (mState == STATE_IDLE) { - // We didn't do focus. This can happen if the user press focus key - // while the snapshot is still in progress. The user probably wants - // the next snapshot as soon as possible, so we just do a snapshot - // without focusing again. - capture(); - } - } - - public void onAutoFocus(boolean focused, boolean shutterButtonPressed) { - if (mState == STATE_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) { - mState = STATE_SUCCESS; - } else { - mState = STATE_FAIL; - } - updateFocusUI(); - capture(); - } else if (mState == STATE_FOCUSING) { - // This happens when (1) user is half-pressing the focus key or - // (2) touch focus is triggered. Play the focus tone. Do not - // take the picture now. - if (focused) { - mState = STATE_SUCCESS; - } else { - mState = STATE_FAIL; - } - updateFocusUI(); - // If this is triggered by touch focus, cancel focus after a - // while. - if (!mFocusDefault) { - mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY); - } - if (shutterButtonPressed) { - // Lock AE & AWB so users can half-press shutter and recompose. - lockAeAwbIfNeeded(); - } - } else if (mState == STATE_IDLE) { - // User has released the focus key before focus completes. - // Do nothing. - } - } - - public void onAutoFocusMoving(boolean moving) { - if (!mInitialized) return; - - - // Ignore if the camera has detected some faces. - if (mUI.hasFaces()) { - mUI.clearFocus(); - return; - } - - // Ignore if we have requested autofocus. This method only handles - // continuous autofocus. - if (mState != STATE_IDLE) return; - - // animate on false->true trasition only b/8219520 - if (moving && !mPreviousMoving) { - mUI.onFocusStarted(); - } else if (!moving) { - mUI.onFocusSucceeded(true); - } - mPreviousMoving = moving; - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void initializeFocusAreas(int x, int y) { - if (mFocusArea == null) { - mFocusArea = new ArrayList<Object>(); - mFocusArea.add(new Area(new Rect(), 1)); - } - - // Convert the coordinates to driver format. - calculateTapArea(x, y, 1f, ((Area) mFocusArea.get(0)).rect); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void initializeMeteringAreas(int x, int y) { - if (mMeteringArea == null) { - mMeteringArea = new ArrayList<Object>(); - mMeteringArea.add(new Area(new Rect(), 1)); - } - - // Convert the coordinates to driver format. - // AE area is bigger because exposure is sensitive and - // easy to over- or underexposure if area is too small. - calculateTapArea(x, y, 1.5f, ((Area) mMeteringArea.get(0)).rect); - } - - public void onSingleTapUp(int x, int y) { - if (!mInitialized || mState == STATE_FOCUSING_SNAP_ON_FINISH) return; - - // Let users be able to cancel previous touch focus. - if ((!mFocusDefault) && (mState == STATE_FOCUSING || - mState == STATE_SUCCESS || mState == STATE_FAIL)) { - cancelAutoFocus(); - } - if (mPreviewWidth == 0 || mPreviewHeight == 0) return; - mFocusDefault = false; - // Initialize mFocusArea. - if (mFocusAreaSupported) { - initializeFocusAreas(x, y); - } - // Initialize mMeteringArea. - if (mMeteringAreaSupported) { - initializeMeteringAreas(x, y); - } - - // Use margin to set the focus indicator to the touched area. - mUI.setFocusPosition(x, y); - - // Stop face detection because we want to specify focus and metering area. - mListener.stopFaceDetection(); - - // Set the focus area and metering area. - mListener.setFocusParameters(); - if (mFocusAreaSupported) { - autoFocus(); - } else { // Just show the indicator in all other cases. - updateFocusUI(); - // Reset the metering area in 3 seconds. - mHandler.removeMessages(RESET_TOUCH_FOCUS); - mHandler.sendEmptyMessageDelayed(RESET_TOUCH_FOCUS, RESET_TOUCH_FOCUS_DELAY); - } - } - - public void onPreviewStarted() { - mState = STATE_IDLE; - } - - public void onPreviewStopped() { - // If auto focus was in progress, it would have been stopped. - mState = STATE_IDLE; - resetTouchFocus(); - updateFocusUI(); - } - - public void onCameraReleased() { - onPreviewStopped(); - } - - private void autoFocus() { - Log.v(TAG, "Start autofocus."); - mListener.autoFocus(); - mState = STATE_FOCUSING; - // Pause the face view because the driver will keep sending face - // callbacks after the focus completes. - mUI.pauseFaceDetection(); - updateFocusUI(); - mHandler.removeMessages(RESET_TOUCH_FOCUS); - } - - private void cancelAutoFocus() { - Log.v(TAG, "Cancel autofocus."); - - // Reset the tap area before calling mListener.cancelAutofocus. - // Otherwise, focus mode stays at auto and the tap area passed to the - // driver is not reset. - resetTouchFocus(); - mListener.cancelAutoFocus(); - mUI.resumeFaceDetection(); - mState = STATE_IDLE; - updateFocusUI(); - mHandler.removeMessages(RESET_TOUCH_FOCUS); - } - - private void capture() { - if (mListener.capture()) { - mState = STATE_IDLE; - mHandler.removeMessages(RESET_TOUCH_FOCUS); - } - } - - public String getFocusMode() { - if (mOverrideFocusMode != null) return mOverrideFocusMode; - if (mParameters == null) return Parameters.FOCUS_MODE_AUTO; - List<String> supportedFocusModes = mParameters.getSupportedFocusModes(); - - if (mFocusAreaSupported && !mFocusDefault) { - // Always use autofocus in tap-to-focus. - mFocusMode = Parameters.FOCUS_MODE_AUTO; - } else { - // The default is continuous autofocus. - mFocusMode = mPreferences.getString( - CameraSettings.KEY_FOCUS_MODE, null); - - // Try to find a supported focus mode from the default list. - if (mFocusMode == null) { - for (int i = 0; i < mDefaultFocusModes.length; i++) { - String mode = mDefaultFocusModes[i]; - if (Util.isSupported(mode, supportedFocusModes)) { - mFocusMode = mode; - break; - } - } - } - } - if (!Util.isSupported(mFocusMode, supportedFocusModes)) { - // For some reasons, the driver does not support the current - // focus mode. Fall back to auto. - if (Util.isSupported(Parameters.FOCUS_MODE_AUTO, - mParameters.getSupportedFocusModes())) { - mFocusMode = Parameters.FOCUS_MODE_AUTO; - } else { - mFocusMode = mParameters.getFocusMode(); - } - } - return mFocusMode; - } - - public List getFocusAreas() { - return mFocusArea; - } - - public List getMeteringAreas() { - return mMeteringArea; - } - - public void updateFocusUI() { - if (!mInitialized) return; - // Show only focus indicator or face indicator. - - if (mState == STATE_IDLE) { - if (mFocusDefault) { - mUI.clearFocus(); - } else { - // Users touch on the preview and the indicator represents the - // metering area. Either focus area is not supported or - // autoFocus call is not required. - mUI.onFocusStarted(); - } - } else if (mState == STATE_FOCUSING || mState == STATE_FOCUSING_SNAP_ON_FINISH) { - mUI.onFocusStarted(); - } else { - if (Util.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusMode)) { - // TODO: check HAL behavior and decide if this can be removed. - mUI.onFocusSucceeded(false); - } else if (mState == STATE_SUCCESS) { - mUI.onFocusSucceeded(false); - } else if (mState == STATE_FAIL) { - mUI.onFocusFailed(false); - } - } - } - - public void resetTouchFocus() { - if (!mInitialized) return; - - // Put focus indicator to the center. clear reset position - mUI.clearFocus(); - // Initialize mFocusArea. - if (mFocusAreaSupported) { - initializeFocusAreas(mPreviewWidth / 2, mPreviewHeight / 2); - } - // Initialize mMeteringArea. - if (mMeteringAreaSupported) { - initializeMeteringAreas(mPreviewWidth / 2, mPreviewHeight / 2); - } - mFocusDefault = true; - } - - private void calculateTapArea(int x, int y, float areaMultiple, Rect rect) { - int areaSize = (int) (Math.min(mPreviewWidth, mPreviewHeight) * areaMultiple / 20); - int left = Util.clamp(x - areaSize, 0, mPreviewWidth - 2 * areaSize); - int top = Util.clamp(y - areaSize, 0, mPreviewHeight - 2 * areaSize); - - RectF rectF = new RectF(left, top, left + 2 * areaSize, top + 2 * areaSize); - mMatrix.mapRect(rectF); - Util.rectFToRect(rectF, rect); - } - - /* package */ int getFocusState() { - return mState; - } - - public boolean isFocusCompleted() { - return mState == STATE_SUCCESS || mState == STATE_FAIL; - } - - public boolean isFocusingSnapOnFinish() { - return mState == STATE_FOCUSING_SNAP_ON_FINISH; - } - - public void removeMessages() { - mHandler.removeMessages(RESET_TOUCH_FOCUS); - } - - public void overrideFocusMode(String focusMode) { - mOverrideFocusMode = focusMode; - } - - public void setAeAwbLock(boolean lock) { - mAeAwbLock = lock; - } - - public boolean getAeAwbLock() { - return mAeAwbLock; - } - - private boolean needAutoFocusCall() { - String focusMode = getFocusMode(); - return !(focusMode.equals(Parameters.FOCUS_MODE_INFINITY) - || focusMode.equals(Parameters.FOCUS_MODE_FIXED) - || focusMode.equals(Parameters.FOCUS_MODE_EDOF)); - } -} diff --git a/src/com/android/camera/IconListPreference.java b/src/com/android/camera/IconListPreference.java deleted file mode 100644 index e5f75d3a5..000000000 --- a/src/com/android/camera/IconListPreference.java +++ /dev/null @@ -1,117 +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.content.res.Resources; -import android.content.res.TypedArray; -import android.util.AttributeSet; - -import com.android.gallery3d.R; - -import java.util.List; - -/** A {@code ListPreference} where each entry has a corresponding icon. */ -public class IconListPreference extends ListPreference { - private int mSingleIconId; - private int mIconIds[]; - private int mLargeIconIds[]; - private int mImageIds[]; - private boolean mUseSingleIcon; - - public IconListPreference(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.IconListPreference, 0, 0); - Resources res = context.getResources(); - mSingleIconId = a.getResourceId( - R.styleable.IconListPreference_singleIcon, 0); - mIconIds = getIds(res, a.getResourceId( - R.styleable.IconListPreference_icons, 0)); - mLargeIconIds = getIds(res, a.getResourceId( - R.styleable.IconListPreference_largeIcons, 0)); - mImageIds = getIds(res, a.getResourceId( - R.styleable.IconListPreference_images, 0)); - a.recycle(); - } - - public int getSingleIcon() { - return mSingleIconId; - } - - public int[] getIconIds() { - return mIconIds; - } - - public int[] getLargeIconIds() { - return mLargeIconIds; - } - - public int[] getImageIds() { - return mImageIds; - } - - public boolean getUseSingleIcon() { - return mUseSingleIcon; - } - - public void setIconIds(int[] iconIds) { - mIconIds = iconIds; - } - - public void setLargeIconIds(int[] largeIconIds) { - mLargeIconIds = largeIconIds; - } - - public void setUseSingleIcon(boolean useSingle) { - mUseSingleIcon = useSingle; - } - - private int[] getIds(Resources res, int iconsRes) { - if (iconsRes == 0) return null; - TypedArray array = res.obtainTypedArray(iconsRes); - int n = array.length(); - int ids[] = new int[n]; - for (int i = 0; i < n; ++i) { - ids[i] = array.getResourceId(i, 0); - } - array.recycle(); - return ids; - } - - @Override - public void filterUnsupported(List<String> supported) { - CharSequence entryValues[] = getEntryValues(); - IntArray iconIds = new IntArray(); - IntArray largeIconIds = new IntArray(); - IntArray imageIds = new IntArray(); - - for (int i = 0, len = entryValues.length; i < len; i++) { - if (supported.indexOf(entryValues[i].toString()) >= 0) { - if (mIconIds != null) iconIds.add(mIconIds[i]); - if (mLargeIconIds != null) largeIconIds.add(mLargeIconIds[i]); - if (mImageIds != null) imageIds.add(mImageIds[i]); - } - } - if (mIconIds != null) mIconIds = iconIds.toArray(new int[iconIds.size()]); - if (mLargeIconIds != null) { - mLargeIconIds = largeIconIds.toArray(new int[largeIconIds.size()]); - } - if (mImageIds != null) mImageIds = imageIds.toArray(new int[imageIds.size()]); - super.filterUnsupported(supported); - } -} diff --git a/src/com/android/camera/ImageTaskManager.java b/src/com/android/camera/ImageTaskManager.java deleted file mode 100644 index 601de4c50..000000000 --- a/src/com/android/camera/ImageTaskManager.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 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.net.Uri; - -/** - * The interface for background image processing task manager. - */ -public interface ImageTaskManager { - - /** - * Callback interface for task events. - */ - public interface TaskListener { - public void onTaskQueued(String filePath, Uri imageUri); - public void onTaskDone(String filePath, Uri imageUri); - public void onTaskProgress( - String filePath, Uri imageUri, int progress); - } - - public void addTaskListener(TaskListener l); - - public void removeTaskListener(TaskListener l); - - /** - * Get task progress by Uri. - * - * @param uri The Uri of the final image file to identify the task. - * @return Integer from 0 to 100, or -1. The percentage of the task done - * so far. -1 means not found. - */ - public int getTaskProgress(Uri uri); -} diff --git a/src/com/android/camera/IntArray.java b/src/com/android/camera/IntArray.java deleted file mode 100644 index a2550dbd8..000000000 --- a/src/com/android/camera/IntArray.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2010 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 IntArray { - private static final int INIT_CAPACITY = 8; - - private int mData[] = new int[INIT_CAPACITY]; - private int mSize = 0; - - public void add(int value) { - if (mData.length == mSize) { - int temp[] = new int[mSize + mSize]; - System.arraycopy(mData, 0, temp, 0, mSize); - mData = temp; - } - mData[mSize++] = value; - } - - public int size() { - return mSize; - } - - public int[] toArray(int[] result) { - if (result == null || result.length < mSize) { - result = new int[mSize]; - } - System.arraycopy(mData, 0, result, 0, mSize); - return result; - } -} diff --git a/src/com/android/camera/ListPreference.java b/src/com/android/camera/ListPreference.java deleted file mode 100644 index 38866de9d..000000000 --- a/src/com/android/camera/ListPreference.java +++ /dev/null @@ -1,202 +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.content.SharedPreferences; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.util.Log; -import android.util.TypedValue; - -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.List; - -/** - * A type of <code>CameraPreference</code> whose number of possible values - * is limited. - */ -public class ListPreference extends CameraPreference { - private static final String TAG = "ListPreference"; - private final String mKey; - private String mValue; - private final CharSequence[] mDefaultValues; - - private CharSequence[] mEntries; - private CharSequence[] mEntryValues; - private CharSequence[] mLabels; - private boolean mLoaded = false; - - public ListPreference(Context context, AttributeSet attrs) { - super(context, attrs); - - TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.ListPreference, 0, 0); - - mKey = Util.checkNotNull( - a.getString(R.styleable.ListPreference_key)); - - // We allow the defaultValue attribute to be a string or an array of - // strings. The reason we need multiple default values is that some - // of them may be unsupported on a specific platform (for example, - // continuous auto-focus). In that case the first supported value - // in the array will be used. - int attrDefaultValue = R.styleable.ListPreference_defaultValue; - TypedValue tv = a.peekValue(attrDefaultValue); - if (tv != null && tv.type == TypedValue.TYPE_REFERENCE) { - mDefaultValues = a.getTextArray(attrDefaultValue); - } else { - mDefaultValues = new CharSequence[1]; - mDefaultValues[0] = a.getString(attrDefaultValue); - } - - setEntries(a.getTextArray(R.styleable.ListPreference_entries)); - setEntryValues(a.getTextArray( - R.styleable.ListPreference_entryValues)); - setLabels(a.getTextArray( - R.styleable.ListPreference_labelList)); - a.recycle(); - } - - public String getKey() { - return mKey; - } - - public CharSequence[] getEntries() { - return mEntries; - } - - public CharSequence[] getEntryValues() { - return mEntryValues; - } - - public CharSequence[] getLabels() { - return mLabels; - } - - public void setEntries(CharSequence entries[]) { - mEntries = entries == null ? new CharSequence[0] : entries; - } - - public void setEntryValues(CharSequence values[]) { - mEntryValues = values == null ? new CharSequence[0] : values; - } - - public void setLabels(CharSequence labels[]) { - mLabels = labels == null ? new CharSequence[0] : labels; - } - - public String getValue() { - if (!mLoaded) { - mValue = getSharedPreferences().getString(mKey, - findSupportedDefaultValue()); - mLoaded = true; - } - return mValue; - } - - // Find the first value in mDefaultValues which is supported. - private String findSupportedDefaultValue() { - for (int i = 0; i < mDefaultValues.length; i++) { - for (int j = 0; j < mEntryValues.length; j++) { - // Note that mDefaultValues[i] may be null (if unspecified - // in the xml file). - if (mEntryValues[j].equals(mDefaultValues[i])) { - return mDefaultValues[i].toString(); - } - } - } - return null; - } - - public void setValue(String value) { - if (findIndexOfValue(value) < 0) throw new IllegalArgumentException(); - mValue = value; - persistStringValue(value); - } - - public void setValueIndex(int index) { - setValue(mEntryValues[index].toString()); - } - - public int findIndexOfValue(String value) { - for (int i = 0, n = mEntryValues.length; i < n; ++i) { - if (Util.equals(mEntryValues[i], value)) return i; - } - return -1; - } - - public int getCurrentIndex() { - return findIndexOfValue(getValue()); - } - - public String getEntry() { - return mEntries[findIndexOfValue(getValue())].toString(); - } - - public String getLabel() { - return mLabels[findIndexOfValue(getValue())].toString(); - } - - protected void persistStringValue(String value) { - SharedPreferences.Editor editor = getSharedPreferences().edit(); - editor.putString(mKey, value); - editor.apply(); - } - - @Override - public void reloadValue() { - this.mLoaded = false; - } - - public void filterUnsupported(List<String> supported) { - ArrayList<CharSequence> entries = new ArrayList<CharSequence>(); - ArrayList<CharSequence> entryValues = new ArrayList<CharSequence>(); - for (int i = 0, len = mEntryValues.length; i < len; i++) { - if (supported.indexOf(mEntryValues[i].toString()) >= 0) { - entries.add(mEntries[i]); - entryValues.add(mEntryValues[i]); - } - } - int size = entries.size(); - mEntries = entries.toArray(new CharSequence[size]); - mEntryValues = entryValues.toArray(new CharSequence[size]); - } - - public void filterDuplicated() { - ArrayList<CharSequence> entries = new ArrayList<CharSequence>(); - ArrayList<CharSequence> entryValues = new ArrayList<CharSequence>(); - for (int i = 0, len = mEntryValues.length; i < len; i++) { - if (!entries.contains(mEntries[i])) { - entries.add(mEntries[i]); - entryValues.add(mEntryValues[i]); - } - } - int size = entries.size(); - mEntries = entries.toArray(new CharSequence[size]); - mEntryValues = entryValues.toArray(new CharSequence[size]); - } - - public void print() { - Log.v(TAG, "Preference key=" + getKey() + ". value=" + getValue()); - for (int i = 0; i < mEntryValues.length; i++) { - Log.v(TAG, "entryValues[" + i + "]=" + mEntryValues[i]); - } - } -} diff --git a/src/com/android/camera/LocationManager.java b/src/com/android/camera/LocationManager.java deleted file mode 100644 index fcf21b60f..000000000 --- a/src/com/android/camera/LocationManager.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.content.Context; -import android.location.Location; -import android.location.LocationProvider; -import android.os.Bundle; -import android.util.Log; - -/** - * A class that handles everything about location. - */ -public class LocationManager { - private static final String TAG = "LocationManager"; - - private Context mContext; - private Listener mListener; - private android.location.LocationManager mLocationManager; - private boolean mRecordLocation; - - LocationListener [] mLocationListeners = new LocationListener[] { - new LocationListener(android.location.LocationManager.GPS_PROVIDER), - new LocationListener(android.location.LocationManager.NETWORK_PROVIDER) - }; - - public interface Listener { - public void showGpsOnScreenIndicator(boolean hasSignal); - public void hideGpsOnScreenIndicator(); - } - - public LocationManager(Context context, Listener listener) { - mContext = context; - mListener = listener; - } - - public Location getCurrentLocation() { - if (!mRecordLocation) return null; - - // go in best to worst order - for (int i = 0; i < mLocationListeners.length; i++) { - Location l = mLocationListeners[i].current(); - if (l != null) return l; - } - Log.d(TAG, "No location received yet."); - return null; - } - - public void recordLocation(boolean recordLocation) { - if (mRecordLocation != recordLocation) { - mRecordLocation = recordLocation; - if (recordLocation) { - startReceivingLocationUpdates(); - } else { - stopReceivingLocationUpdates(); - } - } - } - - private void startReceivingLocationUpdates() { - if (mLocationManager == null) { - mLocationManager = (android.location.LocationManager) - mContext.getSystemService(Context.LOCATION_SERVICE); - } - if (mLocationManager != null) { - try { - mLocationManager.requestLocationUpdates( - android.location.LocationManager.NETWORK_PROVIDER, - 1000, - 0F, - mLocationListeners[1]); - } catch (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( - android.location.LocationManager.GPS_PROVIDER, - 1000, - 0F, - mLocationListeners[0]); - if (mListener != null) mListener.showGpsOnScreenIndicator(false); - } catch (SecurityException ex) { - Log.i(TAG, "fail to request location update, ignore", ex); - } catch (IllegalArgumentException ex) { - Log.d(TAG, "provider does not exist " + ex.getMessage()); - } - Log.d(TAG, "startReceivingLocationUpdates"); - } - } - - 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); - } - } - Log.d(TAG, "stopReceivingLocationUpdates"); - } - if (mListener != null) mListener.hideGpsOnScreenIndicator(); - } - - private class LocationListener - implements android.location.LocationListener { - Location mLastLocation; - boolean mValid = false; - String mProvider; - - public LocationListener(String provider) { - mProvider = provider; - mLastLocation = new Location(mProvider); - } - - @Override - 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 (mListener != null && mRecordLocation && - android.location.LocationManager.GPS_PROVIDER.equals(mProvider)) { - mListener.showGpsOnScreenIndicator(true); - } - if (!mValid) { - Log.d(TAG, "Got first location."); - } - mLastLocation.set(newLocation); - mValid = true; - } - - @Override - public void onProviderEnabled(String provider) { - } - - @Override - public void onProviderDisabled(String provider) { - mValid = false; - } - - @Override - public void onStatusChanged( - String provider, int status, Bundle extras) { - switch(status) { - case LocationProvider.OUT_OF_SERVICE: - case LocationProvider.TEMPORARILY_UNAVAILABLE: { - mValid = false; - if (mListener != null && mRecordLocation && - android.location.LocationManager.GPS_PROVIDER.equals(provider)) { - mListener.showGpsOnScreenIndicator(false); - } - break; - } - } - } - - public Location current() { - return mValid ? mLastLocation : null; - } - } -} diff --git a/src/com/android/camera/MediaSaveService.java b/src/com/android/camera/MediaSaveService.java deleted file mode 100644 index 40675b8c0..000000000 --- a/src/com/android/camera/MediaSaveService.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2013 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.app.Service; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Intent; -import android.location.Location; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Binder; -import android.os.IBinder; -import android.provider.MediaStore.Video; -import android.util.Log; - -import com.android.gallery3d.exif.ExifInterface; - -import java.io.File; - -/* - * Service for saving images in the background thread. - */ -public class MediaSaveService extends Service { - // The memory limit for unsaved image is 20MB. - private static final int SAVE_TASK_MEMORY_LIMIT = 20 * 1024 * 1024; - private static final String TAG = "CAM_" + MediaSaveService.class.getSimpleName(); - - private final IBinder mBinder = new LocalBinder(); - private Listener mListener; - // Memory used by the total queued save request, in bytes. - private long mMemoryUse; - - interface Listener { - public void onQueueStatus(boolean full); - } - - interface OnMediaSavedListener { - public void onMediaSaved(Uri uri); - } - - class LocalBinder extends Binder { - public MediaSaveService getService() { - return MediaSaveService.this; - } - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - @Override - public int onStartCommand(Intent intent, int flag, int startId) { - return START_STICKY; - } - - @Override - public void onDestroy() { - } - - @Override - public void onCreate() { - mMemoryUse = 0; - } - - public boolean isQueueFull() { - return (mMemoryUse >= SAVE_TASK_MEMORY_LIMIT); - } - - public void addImage(final byte[] data, String title, long date, Location loc, - int width, int height, int orientation, ExifInterface exif, - OnMediaSavedListener l, ContentResolver resolver) { - if (isQueueFull()) { - Log.e(TAG, "Cannot add image when the queue is full"); - return; - } - ImageSaveTask t = new ImageSaveTask(data, title, date, - (loc == null) ? null : new Location(loc), - width, height, orientation, exif, resolver, l); - - mMemoryUse += data.length; - if (isQueueFull()) { - onQueueFull(); - } - t.execute(); - } - - public void addImage(final byte[] data, String title, Location loc, - int width, int height, int orientation, ExifInterface exif, - OnMediaSavedListener l, ContentResolver resolver) { - addImage(data, title, System.currentTimeMillis(), loc, width, height, - orientation, exif, l, resolver); - } - - public void addVideo(String path, long duration, ContentValues values, - OnMediaSavedListener l, ContentResolver resolver) { - // We don't set a queue limit for video saving because the file - // is already in the storage. Only updating the database. - new VideoSaveTask(path, duration, values, l, resolver).execute(); - } - - public void setListener(Listener l) { - mListener = l; - if (l == null) return; - l.onQueueStatus(isQueueFull()); - } - - private void onQueueFull() { - if (mListener != null) mListener.onQueueStatus(true); - } - - private void onQueueAvailable() { - if (mListener != null) mListener.onQueueStatus(false); - } - - private class ImageSaveTask extends AsyncTask <Void, Void, Uri> { - private byte[] data; - private String title; - private long date; - private Location loc; - private int width, height; - private int orientation; - private ExifInterface exif; - private ContentResolver resolver; - private OnMediaSavedListener listener; - - public ImageSaveTask(byte[] data, String title, long date, Location loc, - int width, int height, int orientation, ExifInterface exif, - ContentResolver resolver, OnMediaSavedListener listener) { - this.data = data; - this.title = title; - this.date = date; - this.loc = loc; - this.width = width; - this.height = height; - this.orientation = orientation; - this.exif = exif; - this.resolver = resolver; - this.listener = listener; - } - - @Override - protected void onPreExecute() { - // do nothing. - } - - @Override - protected Uri doInBackground(Void... v) { - return Storage.addImage( - resolver, title, date, loc, orientation, exif, data, width, height); - } - - @Override - protected void onPostExecute(Uri uri) { - if (listener != null) listener.onMediaSaved(uri); - boolean previouslyFull = isQueueFull(); - mMemoryUse -= data.length; - if (isQueueFull() != previouslyFull) onQueueAvailable(); - } - } - - private class VideoSaveTask extends AsyncTask <Void, Void, Uri> { - private String path; - private long duration; - private ContentValues values; - private OnMediaSavedListener listener; - private ContentResolver resolver; - - public VideoSaveTask(String path, long duration, ContentValues values, - OnMediaSavedListener l, ContentResolver r) { - this.path = path; - this.duration = duration; - this.values = new ContentValues(values); - this.listener = l; - this.resolver = r; - } - - @Override - protected void onPreExecute() { - // do nothing. - } - - @Override - protected Uri doInBackground(Void... v) { - values.put(Video.Media.SIZE, new File(path).length()); - values.put(Video.Media.DURATION, duration); - Uri uri = null; - try { - Uri videoTable = Uri.parse("content://media/external/video/media"); - uri = resolver.insert(videoTable, values); - - // Rename the video file to the final name. This avoids other - // apps reading incomplete data. We need to do it after we are - // certain that the previous insert to MediaProvider is completed. - String finalName = values.getAsString( - Video.Media.DATA); - if (new File(path).renameTo(new File(finalName))) { - path = finalName; - } - - resolver.update(uri, values, null, null); - } catch (Exception e) { - // We failed to insert into the database. This can happen if - // the SD card is unmounted. - Log.e(TAG, "failed to add video to media store", e); - uri = null; - } finally { - Log.v(TAG, "Current video URI: " + uri); - } - return uri; - } - - @Override - protected void onPostExecute(Uri uri) { - if (listener != null) listener.onMediaSaved(uri); - } - } -} diff --git a/src/com/android/camera/OnClickAttr.java b/src/com/android/camera/OnClickAttr.java deleted file mode 100644 index 07a10635b..000000000 --- a/src/com/android/camera/OnClickAttr.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - - -/** - * Interface for OnClickAttr annotation. - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface OnClickAttr { -} diff --git a/src/com/android/camera/OnScreenHint.java b/src/com/android/camera/OnScreenHint.java deleted file mode 100644 index 4d7fa7088..000000000 --- a/src/com/android/camera/OnScreenHint.java +++ /dev/null @@ -1,190 +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.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; - -import com.android.gallery3d.R; - -/** - * 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 {@code OnScreenHint} object. - */ -public class OnScreenHint { - static final String TAG = "OnScreenHint"; - - 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. - * - * @param context The context to use. Usually your - * {@link android.app.Application} or - * {@link android.app.Activity} object. - */ - private OnScreenHint(Context 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("View is not initialized"); - } - 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() { - @Override - public void run() { - handleShow(); - } - }; - - private final Runnable mHide = new Runnable() { - @Override - public void run() { - handleHide(); - } - }; -} - diff --git a/src/com/android/camera/OnScreenIndicators.java b/src/com/android/camera/OnScreenIndicators.java deleted file mode 100644 index 77c8fafc0..000000000 --- a/src/com/android/camera/OnScreenIndicators.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2013 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.content.res.TypedArray; -import android.hardware.Camera; -import android.hardware.Camera.Parameters; -import android.view.View; -import android.widget.ImageView; - -import com.android.gallery3d.R; - -/** - * The on-screen indicators of the pie menu button. They show the camera - * settings in the viewfinder. - */ -public class OnScreenIndicators { - private final int[] mWBArray; - private final View mOnScreenIndicators; - private final ImageView mExposureIndicator; - private final ImageView mFlashIndicator; - private final ImageView mSceneIndicator; - private final ImageView mLocationIndicator; - private final ImageView mTimerIndicator; - private final ImageView mWBIndicator; - - public OnScreenIndicators(Context ctx, View onScreenIndicatorsView) { - TypedArray iconIds = ctx.getResources().obtainTypedArray( - R.array.camera_wb_indicators); - final int n = iconIds.length(); - mWBArray = new int[n]; - for (int i = 0; i < n; i++) { - mWBArray[i] = iconIds.getResourceId(i, R.drawable.ic_indicator_wb_off); - } - mOnScreenIndicators = onScreenIndicatorsView; - mExposureIndicator = (ImageView) onScreenIndicatorsView.findViewById( - R.id.menu_exposure_indicator); - mFlashIndicator = (ImageView) onScreenIndicatorsView.findViewById( - R.id.menu_flash_indicator); - mSceneIndicator = (ImageView) onScreenIndicatorsView.findViewById( - R.id.menu_scenemode_indicator); - mLocationIndicator = (ImageView) onScreenIndicatorsView.findViewById( - R.id.menu_location_indicator); - mTimerIndicator = (ImageView) onScreenIndicatorsView.findViewById( - R.id.menu_timer_indicator); - mWBIndicator = (ImageView) onScreenIndicatorsView.findViewById( - R.id.menu_wb_indicator); - } - - /** - * Resets all indicators to show the default values. - */ - public void resetToDefault() { - updateExposureOnScreenIndicator(0); - updateFlashOnScreenIndicator(Parameters.FLASH_MODE_OFF); - updateSceneOnScreenIndicator(Parameters.SCENE_MODE_AUTO); - updateWBIndicator(2); - updateTimerIndicator(false); - updateLocationIndicator(false); - } - - /** - * Sets the exposure indicator using exposure compensations step rounding. - */ - public void updateExposureOnScreenIndicator(Camera.Parameters params, int value) { - if (mExposureIndicator == null) { - return; - } - float step = params.getExposureCompensationStep(); - value = Math.round(value * step); - updateExposureOnScreenIndicator(value); - } - - /** - * Set the exposure indicator to the given value. - * - * @param value Value between -3 and 3. If outside this range, 0 is used by - * default. - */ - public void updateExposureOnScreenIndicator(int value) { - int id = 0; - switch(value) { - case -3: - id = R.drawable.ic_indicator_ev_n3; - break; - case -2: - id = R.drawable.ic_indicator_ev_n2; - break; - case -1: - id = R.drawable.ic_indicator_ev_n1; - break; - case 0: - id = R.drawable.ic_indicator_ev_0; - break; - case 1: - id = R.drawable.ic_indicator_ev_p1; - break; - case 2: - id = R.drawable.ic_indicator_ev_p2; - break; - case 3: - id = R.drawable.ic_indicator_ev_p3; - break; - } - mExposureIndicator.setImageResource(id); - } - - public void updateWBIndicator(int wbIndex) { - if (mWBIndicator == null) return; - mWBIndicator.setImageResource(mWBArray[wbIndex]); - } - - public void updateTimerIndicator(boolean on) { - if (mTimerIndicator == null) return; - mTimerIndicator.setImageResource(on ? R.drawable.ic_indicator_timer_on - : R.drawable.ic_indicator_timer_off); - } - - public void updateLocationIndicator(boolean on) { - if (mLocationIndicator == null) return; - mLocationIndicator.setImageResource(on ? R.drawable.ic_indicator_loc_on - : R.drawable.ic_indicator_loc_off); - } - - /** - * Set the flash indicator to the given value. - * - * @param value One of Parameters.FLASH_MODE_OFF, - * Parameters.FLASH_MODE_AUTO, Parameters.FLASH_MODE_ON. - */ - public void updateFlashOnScreenIndicator(String value) { - if (mFlashIndicator == null) { - return; - } - if (value == null || Parameters.FLASH_MODE_OFF.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off); - } else { - if (Parameters.FLASH_MODE_AUTO.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_auto); - } else if (Parameters.FLASH_MODE_ON.equals(value) - || Parameters.FLASH_MODE_TORCH.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_on); - } else { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off); - } - } - } - - /** - * Set the scene indicator depending on the given scene mode. - * - * @param value the current Parameters.SCENE_MODE_* value. - */ - public void updateSceneOnScreenIndicator(String value) { - if (mSceneIndicator == null) { - return; - } - if ((value == null) || Parameters.SCENE_MODE_AUTO.equals(value)) { - mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_off); - } else if (Parameters.SCENE_MODE_HDR.equals(value)) { - mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_hdr); - } else { - mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_on); - } - } - - /** - * Sets the visibility of all indicators. - * - * @param visibility View.VISIBLE, View.GONE etc. - */ - public void setVisibility(int visibility) { - mOnScreenIndicators.setVisibility(visibility); - } -} diff --git a/src/com/android/camera/PhotoController.java b/src/com/android/camera/PhotoController.java deleted file mode 100644 index bc824d917..000000000 --- a/src/com/android/camera/PhotoController.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2013 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.view.SurfaceHolder; -import android.view.View; - -import com.android.camera.ShutterButton.OnShutterButtonListener; - - -public interface PhotoController extends OnShutterButtonListener { - - public static final int PREVIEW_STOPPED = 0; - public static final int IDLE = 1; // preview is active - // Focus is in progress. The exact focus state is in Focus.java. - public static final int FOCUSING = 2; - public static final int SNAPSHOT_IN_PROGRESS = 3; - // Switching between cameras. - public static final int SWITCHING_CAMERA = 4; - - // returns the actual set zoom value - public int onZoomChanged(int requestedZoom); - - public boolean isImageCaptureIntent(); - - public boolean isCameraIdle(); - - public void onCaptureDone(); - - public void onCaptureCancelled(); - - public void onCaptureRetake(); - - public void cancelAutoFocus(); - - public void stopPreview(); - - public int getCameraState(); - - public void onSingleTapUp(View view, int x, int y); - - public void onSurfaceCreated(SurfaceHolder holder); - - public void onCountDownFinished(); - - public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight); - - public void updateCameraOrientation(); - - public void enableRecordingLocation(boolean enable); -} diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java deleted file mode 100644 index 6c1e2d085..000000000 --- a/src/com/android/camera/PhotoMenu.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.content.res.Resources; -import android.hardware.Camera.Parameters; - -import com.android.camera.ui.AbstractSettingPopup; -import com.android.camera.ui.CountdownTimerPopup; -import com.android.camera.ui.ListPrefSettingPopup; -import com.android.camera.ui.PieItem; -import com.android.camera.ui.PieItem.OnClickListener; -import com.android.camera.ui.PieRenderer; -import com.android.gallery3d.R; - -import java.util.Locale; - -public class PhotoMenu extends PieController - implements CountdownTimerPopup.Listener, - ListPrefSettingPopup.Listener { - private static String TAG = "CAM_photomenu"; - - private final String mSettingOff; - - private PhotoUI mUI; - private AbstractSettingPopup mPopup; - private CameraActivity mActivity; - - public PhotoMenu(CameraActivity activity, PhotoUI ui, PieRenderer pie) { - super(activity, pie); - mUI = ui; - mSettingOff = activity.getString(R.string.setting_off_value); - mActivity = activity; - } - - public void initialize(PreferenceGroup group) { - super.initialize(group); - mPopup = null; - PieItem item = null; - final Resources res = mActivity.getResources(); - Locale locale = res.getConfiguration().locale; - // the order is from left to right in the menu - - // hdr - if (group.findPreference(CameraSettings.KEY_CAMERA_HDR) != null) { - item = makeSwitchItem(CameraSettings.KEY_CAMERA_HDR, true); - mRenderer.addItem(item); - } - // exposure compensation - if (group.findPreference(CameraSettings.KEY_EXPOSURE) != null) { - item = makeItem(CameraSettings.KEY_EXPOSURE); - item.setLabel(res.getString(R.string.pref_exposure_label)); - mRenderer.addItem(item); - } - // more settings - PieItem more = makeItem(R.drawable.ic_settings_holo_light); - more.setLabel(res.getString(R.string.camera_menu_more_label)); - mRenderer.addItem(more); - // flash - if (group.findPreference(CameraSettings.KEY_FLASH_MODE) != null) { - item = makeItem(CameraSettings.KEY_FLASH_MODE); - item.setLabel(res.getString(R.string.pref_camera_flashmode_label)); - mRenderer.addItem(item); - } - // camera switcher - if (group.findPreference(CameraSettings.KEY_CAMERA_ID) != null) { - item = makeSwitchItem(CameraSettings.KEY_CAMERA_ID, false); - final PieItem fitem = item; - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - // Find the index of next camera. - ListPreference pref = mPreferenceGroup - .findPreference(CameraSettings.KEY_CAMERA_ID); - if (pref != null) { - int index = pref.findIndexOfValue(pref.getValue()); - CharSequence[] values = pref.getEntryValues(); - index = (index + 1) % values.length; - pref.setValueIndex(index); - mListener.onCameraPickerClicked(index); - } - updateItem(fitem, CameraSettings.KEY_CAMERA_ID); - } - }); - mRenderer.addItem(item); - } - // location - if (group.findPreference(CameraSettings.KEY_RECORD_LOCATION) != null) { - item = makeSwitchItem(CameraSettings.KEY_RECORD_LOCATION, true); - more.addItem(item); - if (mActivity.isSecureCamera()) { - // Prevent location preference from getting changed in secure camera mode - item.setEnabled(false); - } - } - // countdown timer - final ListPreference ctpref = group.findPreference(CameraSettings.KEY_TIMER); - final ListPreference beeppref = group.findPreference(CameraSettings.KEY_TIMER_SOUND_EFFECTS); - item = makeItem(R.drawable.ic_timer); - item.setLabel(res.getString(R.string.pref_camera_timer_title).toUpperCase(locale)); - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - CountdownTimerPopup timerPopup = (CountdownTimerPopup) mActivity.getLayoutInflater().inflate( - R.layout.countdown_setting_popup, null, false); - timerPopup.initialize(ctpref, beeppref); - timerPopup.setSettingChangedListener(PhotoMenu.this); - mUI.dismissPopup(); - mPopup = timerPopup; - mUI.showPopup(mPopup); - } - }); - more.addItem(item); - // image size - item = makeItem(R.drawable.ic_imagesize); - final ListPreference sizePref = group.findPreference(CameraSettings.KEY_PICTURE_SIZE); - item.setLabel(res.getString(R.string.pref_camera_picturesize_title).toUpperCase(locale)); - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - ListPrefSettingPopup popup = (ListPrefSettingPopup) mActivity.getLayoutInflater().inflate( - R.layout.list_pref_setting_popup, null, false); - popup.initialize(sizePref); - popup.setSettingChangedListener(PhotoMenu.this); - mUI.dismissPopup(); - mPopup = popup; - mUI.showPopup(mPopup); - } - }); - more.addItem(item); - // white balance - if (group.findPreference(CameraSettings.KEY_WHITE_BALANCE) != null) { - item = makeItem(CameraSettings.KEY_WHITE_BALANCE); - item.setLabel(res.getString(R.string.pref_camera_whitebalance_label)); - more.addItem(item); - } - // scene mode - if (group.findPreference(CameraSettings.KEY_SCENE_MODE) != null) { - IconListPreference pref = (IconListPreference) group.findPreference( - CameraSettings.KEY_SCENE_MODE); - pref.setUseSingleIcon(true); - item = makeItem(CameraSettings.KEY_SCENE_MODE); - more.addItem(item); - } - } - - @Override - // Hit when an item in a popup gets selected - public void onListPrefChanged(ListPreference pref) { - if (mPopup != null) { - mUI.dismissPopup(); - } - onSettingChanged(pref); - } - - public void popupDismissed() { - if (mPopup != null) { - mPopup = null; - } - } - - // Return true if the preference has the specified key but not the value. - private static boolean notSame(ListPreference pref, String key, String value) { - return (key.equals(pref.getKey()) && !value.equals(pref.getValue())); - } - - private void setPreference(String key, String value) { - ListPreference pref = mPreferenceGroup.findPreference(key); - if (pref != null && !value.equals(pref.getValue())) { - pref.setValue(value); - reloadPreferences(); - } - } - - @Override - public void onSettingChanged(ListPreference pref) { - // Reset the scene mode if HDR is set to on. Reset HDR if scene mode is - // set to non-auto. - if (notSame(pref, CameraSettings.KEY_CAMERA_HDR, mSettingOff)) { - setPreference(CameraSettings.KEY_SCENE_MODE, Parameters.SCENE_MODE_AUTO); - } else if (notSame(pref, CameraSettings.KEY_SCENE_MODE, Parameters.SCENE_MODE_AUTO)) { - setPreference(CameraSettings.KEY_CAMERA_HDR, mSettingOff); - } - super.onSettingChanged(pref); - } -} diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java deleted file mode 100644 index d09c081a1..000000000 --- a/src/com/android/camera/PhotoModule.java +++ /dev/null @@ -1,1985 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.ContentProviderClient; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences.Editor; -import android.content.res.Configuration; -import android.graphics.Bitmap; -import android.graphics.SurfaceTexture; -import android.hardware.Camera.CameraInfo; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.Size; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; -import android.location.Location; -import android.media.CameraProfile; -import android.net.Uri; -import android.os.Bundle; -import android.os.ConditionVariable; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.MessageQueue; -import android.os.SystemClock; -import android.provider.MediaStore; -import android.util.Log; -import android.view.KeyEvent; -import android.view.OrientationEventListener; -import android.view.SurfaceHolder; -import android.view.View; -import android.view.WindowManager; - -import com.android.camera.CameraManager.CameraAFCallback; -import com.android.camera.CameraManager.CameraAFMoveCallback; -import com.android.camera.CameraManager.CameraPictureCallback; -import com.android.camera.CameraManager.CameraProxy; -import com.android.camera.CameraManager.CameraShutterCallback; -import com.android.camera.ui.CountDownView.OnCountDownFinishedListener; -import com.android.camera.ui.PopupManager; -import com.android.camera.ui.RotateTextToast; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.exif.ExifTag; -import com.android.gallery3d.exif.Rational; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.filtershow.crop.CropExtras; -import com.android.gallery3d.util.UsageStatistics; - -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.Formatter; -import java.util.List; - -public class PhotoModule - implements CameraModule, - PhotoController, - FocusOverlayManager.Listener, - CameraPreference.OnPreferenceChangedListener, - ShutterButton.OnShutterButtonListener, - MediaSaveService.Listener, - OnCountDownFinishedListener, - SensorEventListener { - - private static final String TAG = "CAM_PhotoModule"; - - // We number the request code from 1000 to avoid collision with Gallery. - private static final int REQUEST_CROP = 1000; - - private static final int SETUP_PREVIEW = 1; - private static final int FIRST_TIME_INIT = 2; - private static final int CLEAR_SCREEN_DELAY = 3; - private static final int SET_CAMERA_PARAMETERS_WHEN_IDLE = 4; - private static final int CHECK_DISPLAY_ROTATION = 5; - private static final int SHOW_TAP_TO_FOCUS_TOAST = 6; - private static final int SWITCH_CAMERA = 7; - private static final int SWITCH_CAMERA_START_ANIMATION = 8; - private static final int CAMERA_OPEN_DONE = 9; - private static final int START_PREVIEW_DONE = 10; - private static final int OPEN_CAMERA_FAIL = 11; - private static final int CAMERA_DISABLED = 12; - - // The subset of parameters we need to update in setCameraParameters(). - private static final int UPDATE_PARAM_INITIALIZE = 1; - private static final int UPDATE_PARAM_ZOOM = 2; - private static final int UPDATE_PARAM_PREFERENCE = 4; - private static final int UPDATE_PARAM_ALL = -1; - - // This is the timeout to keep the camera in onPause for the first time - // after screen on if the activity is started from secure lock screen. - private static final int KEEP_CAMERA_TIMEOUT = 1000; // ms - - // copied from Camera hierarchy - private CameraActivity mActivity; - private CameraProxy mCameraDevice; - private int mCameraId; - private Parameters mParameters; - private boolean mPaused; - - private PhotoUI mUI; - - // The activity is going to switch to the specified camera id. This is - // needed because texture copy is done in GL thread. -1 means camera is not - // switching. - protected int mPendingSwitchCameraId = -1; - private boolean mOpenCameraFail; - private boolean mCameraDisabled; - - // When setCameraParametersWhenIdle() is called, we accumulate the subsets - // needed to be updated in mUpdateSet. - private int mUpdateSet; - - private static final int SCREEN_DELAY = 2 * 60 * 1000; - - private int mZoomValue; // The current zoom value. - - private Parameters mInitialParams; - private boolean mFocusAreaSupported; - private boolean mMeteringAreaSupported; - private boolean mAeLockSupported; - private boolean mAwbLockSupported; - private boolean mContinousFocusSupported; - - // The degrees of the device rotated clockwise from its natural orientation. - private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; - private ComboPreferences mPreferences; - - private static final String sTempCropFilename = "crop-temp"; - - private ContentProviderClient mMediaProviderClient; - private boolean mFaceDetectionStarted = false; - - // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true. - private String mCropValue; - private Uri mSaveUri; - - // We use a queue to generated names of the images to be used later - // when the image is ready to be saved. - private NamedImages mNamedImages; - - private Runnable mDoSnapRunnable = new Runnable() { - @Override - public void run() { - onShutterButtonClick(); - } - }; - - private final StringBuilder mBuilder = new StringBuilder(); - private final Formatter mFormatter = new Formatter(mBuilder); - private final Object[] mFormatterArgs = new Object[1]; - - /** - * An unpublished intent flag requesting to return as soon as capturing - * is completed. - * - * TODO: consider publishing by moving into MediaStore. - */ - private static final String EXTRA_QUICK_CAPTURE = - "android.intent.extra.quickCapture"; - - // The display rotation in degrees. This is only valid when mCameraState is - // not PREVIEW_STOPPED. - private int mDisplayRotation; - // The value for android.hardware.Camera.setDisplayOrientation. - private int mCameraDisplayOrientation; - // The value for UI components like indicators. - private int mDisplayOrientation; - // The value for android.hardware.Camera.Parameters.setRotation. - private int mJpegRotation; - private boolean mFirstTimeInitialized; - private boolean mIsImageCaptureIntent; - - private int mCameraState = PREVIEW_STOPPED; - private boolean mSnapshotOnIdle = false; - - private ContentResolver mContentResolver; - - private LocationManager mLocationManager; - - private final PostViewPictureCallback mPostViewPictureCallback = - new PostViewPictureCallback(); - private final RawPictureCallback mRawPictureCallback = - new RawPictureCallback(); - private final AutoFocusCallback mAutoFocusCallback = - new AutoFocusCallback(); - private final Object mAutoFocusMoveCallback = - ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK - ? new AutoFocusMoveCallback() - : null; - - private final CameraErrorCallback mErrorCallback = new CameraErrorCallback(); - - private long mFocusStartTime; - private long mShutterCallbackTime; - private long mPostViewPictureCallbackTime; - private long mRawPictureCallbackTime; - private long mJpegPictureCallbackTime; - private long mOnResumeTime; - private byte[] mJpegImageData; - - // These latency time are for the CameraLatency test. - public long mAutoFocusTime; - public long mShutterLag; - public long mShutterToPictureDisplayedTime; - public long mPictureDisplayedToJpegCallbackTime; - public long mJpegCallbackFinishTime; - public long mCaptureStartTime; - - // This handles everything about focus. - private FocusOverlayManager mFocusManager; - - private String mSceneMode; - - private final Handler mHandler = new MainHandler(); - private PreferenceGroup mPreferenceGroup; - - private boolean mQuickCapture; - private SensorManager mSensorManager; - private float[] mGData = new float[3]; - private float[] mMData = new float[3]; - private float[] mR = new float[16]; - private int mHeading = -1; - - CameraStartUpThread mCameraStartUpThread; - ConditionVariable mStartPreviewPrerequisiteReady = new ConditionVariable(); - - private MediaSaveService.OnMediaSavedListener mOnMediaSavedListener = - new MediaSaveService.OnMediaSavedListener() { - @Override - public void onMediaSaved(Uri uri) { - if (uri != null) { - mActivity.notifyNewMedia(uri); - } - } - }; - - // The purpose is not to block the main thread in onCreate and onResume. - private class CameraStartUpThread extends Thread { - private volatile boolean mCancelled; - - public void cancel() { - mCancelled = true; - interrupt(); - } - - public boolean isCanceled() { - return mCancelled; - } - - @Override - public void run() { - try { - // We need to check whether the activity is paused before long - // operations to ensure that onPause() can be done ASAP. - if (mCancelled) return; - mCameraDevice = Util.openCamera(mActivity, mCameraId); - mParameters = mCameraDevice.getParameters(); - // Wait until all the initialization needed by startPreview are - // done. - mStartPreviewPrerequisiteReady.block(); - - initializeCapabilities(); - if (mFocusManager == null) initializeFocusManager(); - if (mCancelled) return; - setCameraParameters(UPDATE_PARAM_ALL); - mHandler.sendEmptyMessage(CAMERA_OPEN_DONE); - if (mCancelled) return; - startPreview(); - mHandler.sendEmptyMessage(START_PREVIEW_DONE); - mOnResumeTime = SystemClock.uptimeMillis(); - mHandler.sendEmptyMessage(CHECK_DISPLAY_ROTATION); - } catch (CameraHardwareException e) { - mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL); - } catch (CameraDisabledException e) { - mHandler.sendEmptyMessage(CAMERA_DISABLED); - } - } - } - - /** - * 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 SETUP_PREVIEW: { - setupPreview(); - break; - } - - case CLEAR_SCREEN_DELAY: { - mActivity.getWindow().clearFlags( - WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - break; - } - - case FIRST_TIME_INIT: { - initializeFirstTime(); - break; - } - - case SET_CAMERA_PARAMETERS_WHEN_IDLE: { - setCameraParametersWhenIdle(0); - break; - } - - case CHECK_DISPLAY_ROTATION: { - // Set the display orientation if display rotation has changed. - // Sometimes this happens when the device is held upside - // down and camera app is opened. Rotation animation will - // take some time and the rotation value we have got may be - // wrong. Framework does not have a callback for this now. - if (Util.getDisplayRotation(mActivity) != mDisplayRotation) { - setDisplayOrientation(); - } - if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) { - mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100); - } - break; - } - - case SHOW_TAP_TO_FOCUS_TOAST: { - showTapToFocusToast(); - break; - } - - case SWITCH_CAMERA: { - switchCamera(); - break; - } - - case SWITCH_CAMERA_START_ANIMATION: { - // TODO: Need to revisit - // ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera(); - break; - } - - case CAMERA_OPEN_DONE: { - onCameraOpened(); - break; - } - - case START_PREVIEW_DONE: { - onPreviewStarted(); - break; - } - - case OPEN_CAMERA_FAIL: { - mCameraStartUpThread = null; - mOpenCameraFail = true; - Util.showErrorAndFinish(mActivity, - R.string.cannot_connect_camera); - break; - } - - case CAMERA_DISABLED: { - mCameraStartUpThread = null; - mCameraDisabled = true; - Util.showErrorAndFinish(mActivity, - R.string.camera_disabled); - break; - } - } - } - } - - @Override - public void init(CameraActivity activity, View parent) { - mActivity = activity; - mUI = new PhotoUI(activity, this, parent); - mPreferences = new ComboPreferences(mActivity); - CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal()); - mCameraId = getPreferredCameraId(mPreferences); - - mContentResolver = mActivity.getContentResolver(); - - // To reduce startup time, open the camera and start the preview in - // another thread. - mCameraStartUpThread = new CameraStartUpThread(); - mCameraStartUpThread.start(); - - // Surface texture is from camera screen nail and startPreview needs it. - // This must be done before startPreview. - mIsImageCaptureIntent = isImageCaptureIntent(); - - mPreferences.setLocalId(mActivity, mCameraId); - CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); - // we need to reset exposure for the preview - resetExposureCompensation(); - // Starting the preview needs preferences, camera screen nail, and - // focus area indicator. - mStartPreviewPrerequisiteReady.open(); - - initializeControlByIntent(); - mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false); - mLocationManager = new LocationManager(mActivity, mUI); - mSensorManager = (SensorManager)(mActivity.getSystemService(Context.SENSOR_SERVICE)); - } - - private void initializeControlByIntent() { - mUI.initializeControlByIntent(); - if (mIsImageCaptureIntent) { - setupCaptureParams(); - } - } - - private void onPreviewStarted() { - mCameraStartUpThread = null; - setCameraState(IDLE); - startFaceDetection(); - locationFirstRun(); - } - - // Prompt the user to pick to record location for the very first run of - // camera only - private void locationFirstRun() { - if (RecordLocationPreference.isSet(mPreferences)) { - return; - } - if (mActivity.isSecureCamera()) return; - // Check if the back camera exists - int backCameraId = CameraHolder.instance().getBackCameraId(); - if (backCameraId == -1) { - // If there is no back camera, do not show the prompt. - return; - } - mUI.showLocationDialog(); - } - - public void enableRecordingLocation(boolean enable) { - setLocationPreference(enable ? RecordLocationPreference.VALUE_ON - : RecordLocationPreference.VALUE_OFF); - } - - private void setLocationPreference(String value) { - mPreferences.edit() - .putString(CameraSettings.KEY_RECORD_LOCATION, value) - .apply(); - // TODO: Fix this to use the actual onSharedPreferencesChanged listener - // instead of invoking manually - onSharedPreferenceChanged(); - } - - private void onCameraOpened() { - View root = mUI.getRootView(); - // These depend on camera parameters. - - int width = root.getWidth(); - int height = root.getHeight(); - mFocusManager.setPreviewSize(width, height); - openCameraCommon(); - } - - private void switchCamera() { - if (mPaused) return; - - Log.v(TAG, "Start to switch camera. id=" + mPendingSwitchCameraId); - mCameraId = mPendingSwitchCameraId; - mPendingSwitchCameraId = -1; - setCameraId(mCameraId); - - // from onPause - closeCamera(); - mUI.collapseCameraControls(); - mUI.clearFaces(); - if (mFocusManager != null) mFocusManager.removeMessages(); - - // Restart the camera and initialize the UI. From onCreate. - mPreferences.setLocalId(mActivity, mCameraId); - CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); - try { - mCameraDevice = Util.openCamera(mActivity, mCameraId); - mParameters = mCameraDevice.getParameters(); - } catch (CameraHardwareException e) { - Util.showErrorAndFinish(mActivity, R.string.cannot_connect_camera); - return; - } catch (CameraDisabledException e) { - Util.showErrorAndFinish(mActivity, R.string.camera_disabled); - return; - } - initializeCapabilities(); - CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; - boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); - mFocusManager.setMirror(mirror); - mFocusManager.setParameters(mInitialParams); - setupPreview(); - - // reset zoom value index - mZoomValue = 0; - openCameraCommon(); - - if (ApiHelper.HAS_SURFACE_TEXTURE) { - // Start switch camera animation. Post a message because - // onFrameAvailable from the old camera may already exist. - mHandler.sendEmptyMessage(SWITCH_CAMERA_START_ANIMATION); - } - } - - protected void setCameraId(int cameraId) { - ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_ID); - pref.setValue("" + cameraId); - } - - // either open a new camera or switch cameras - private void openCameraCommon() { - loadCameraPreferences(); - - mUI.onCameraOpened(mPreferenceGroup, mPreferences, mParameters, this); - updateSceneMode(); - showTapToFocusToastIfNeeded(); - - - } - - public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight) { - if (mFocusManager != null) mFocusManager.setPreviewSize(width, height); - } - - private void resetExposureCompensation() { - String value = mPreferences.getString(CameraSettings.KEY_EXPOSURE, - CameraSettings.EXPOSURE_DEFAULT_VALUE); - if (!CameraSettings.EXPOSURE_DEFAULT_VALUE.equals(value)) { - Editor editor = mPreferences.edit(); - editor.putString(CameraSettings.KEY_EXPOSURE, "0"); - editor.apply(); - } - } - - private void keepMediaProviderInstance() { - // We want to keep a reference to MediaProvider in camera's lifecycle. - // TODO: Utilize mMediaProviderClient instance to replace - // ContentResolver calls. - if (mMediaProviderClient == null) { - mMediaProviderClient = mContentResolver - .acquireContentProviderClient(MediaStore.AUTHORITY); - } - } - - // 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; - - // Initialize location service. - boolean recordLocation = RecordLocationPreference.get( - mPreferences, mContentResolver); - mLocationManager.recordLocation(recordLocation); - - keepMediaProviderInstance(); - - mUI.initializeFirstTime(); - MediaSaveService s = mActivity.getMediaSaveService(); - // We set the listener only when both service and shutterbutton - // are initialized. - if (s != null) { - s.setListener(this); - } - - mNamedImages = new NamedImages(); - - mFirstTimeInitialized = true; - addIdleHandler(); - - mActivity.updateStorageSpaceAndHint(); - } - - // If the activity is paused and resumed, this method will be called in - // onResume. - private void initializeSecondTime() { - // Start location update if needed. - boolean recordLocation = RecordLocationPreference.get( - mPreferences, mContentResolver); - mLocationManager.recordLocation(recordLocation); - MediaSaveService s = mActivity.getMediaSaveService(); - if (s != null) { - s.setListener(this); - } - mNamedImages = new NamedImages(); - mUI.initializeSecondTime(mParameters); - keepMediaProviderInstance(); - } - - @Override - public void onSurfaceCreated(SurfaceHolder holder) { - // Do not access the camera if camera start up thread is not finished. - if (mCameraDevice == null || mCameraStartUpThread != null) - return; - - mCameraDevice.setPreviewDisplay(holder); - // This happens when onConfigurationChanged arrives, surface has been - // destroyed, and there is no onFullScreenChanged. - if (mCameraState == PREVIEW_STOPPED) { - setupPreview(); - } - } - - private void showTapToFocusToastIfNeeded() { - // Show the tap to focus toast if this is the first start. - if (mFocusAreaSupported && - mPreferences.getBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, true)) { - // Delay the toast for one second to wait for orientation. - mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_FOCUS_TOAST, 1000); - } - } - - private void addIdleHandler() { - MessageQueue queue = Looper.myQueue(); - queue.addIdleHandler(new MessageQueue.IdleHandler() { - @Override - public boolean queueIdle() { - Storage.ensureOSXCompatible(); - return false; - } - }); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public void startFaceDetection() { - if (!ApiHelper.HAS_FACE_DETECTION) return; - if (mFaceDetectionStarted) return; - if (mParameters.getMaxNumDetectedFaces() > 0) { - mFaceDetectionStarted = true; - CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; - mUI.onStartFaceDetection(mDisplayOrientation, - (info.facing == CameraInfo.CAMERA_FACING_FRONT)); - mCameraDevice.setFaceDetectionCallback(mHandler, mUI); - mCameraDevice.startFaceDetection(); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public void stopFaceDetection() { - if (!ApiHelper.HAS_FACE_DETECTION) return; - if (!mFaceDetectionStarted) return; - if (mParameters.getMaxNumDetectedFaces() > 0) { - mFaceDetectionStarted = false; - mCameraDevice.setFaceDetectionCallback(null, null); - mCameraDevice.stopFaceDetection(); - mUI.clearFaces(); - } - } - - private final class ShutterCallback - implements CameraShutterCallback { - - private boolean mNeedsAnimation; - - public ShutterCallback(boolean needsAnimation) { - mNeedsAnimation = needsAnimation; - } - - @Override - public void onShutter(CameraProxy camera) { - mShutterCallbackTime = System.currentTimeMillis(); - mShutterLag = mShutterCallbackTime - mCaptureStartTime; - Log.v(TAG, "mShutterLag = " + mShutterLag + "ms"); - if (mNeedsAnimation) { - mActivity.runOnUiThread(new Runnable() { - @Override - public void run() { - animateAfterShutter(); - } - }); - } - } - } - - private final class PostViewPictureCallback - implements CameraPictureCallback { - @Override - public void onPictureTaken(byte [] data, CameraProxy camera) { - mPostViewPictureCallbackTime = System.currentTimeMillis(); - Log.v(TAG, "mShutterToPostViewCallbackTime = " - + (mPostViewPictureCallbackTime - mShutterCallbackTime) - + "ms"); - } - } - - private final class RawPictureCallback - implements CameraPictureCallback { - @Override - public void onPictureTaken(byte [] rawData, CameraProxy camera) { - mRawPictureCallbackTime = System.currentTimeMillis(); - Log.v(TAG, "mShutterToRawCallbackTime = " - + (mRawPictureCallbackTime - mShutterCallbackTime) + "ms"); - } - } - - private final class JpegPictureCallback - implements CameraPictureCallback { - Location mLocation; - - public JpegPictureCallback(Location loc) { - mLocation = loc; - } - - @Override - public void onPictureTaken(final byte [] jpegData, CameraProxy camera) { - if (mPaused) { - return; - } - if (mIsImageCaptureIntent) { - stopPreview(); - } else { - // Animate capture with real jpeg data instead of a preview frame. - mUI.animateCapture(jpegData); - } - if (mSceneMode == Util.SCENE_MODE_HDR) { - mUI.showSwitcher(); - mUI.setSwipingEnabled(true); - } - - mJpegPictureCallbackTime = System.currentTimeMillis(); - // If postview callback has arrived, the captured image is displayed - // in postview callback. If not, the captured image is displayed in - // raw picture callback. - if (mPostViewPictureCallbackTime != 0) { - mShutterToPictureDisplayedTime = - mPostViewPictureCallbackTime - mShutterCallbackTime; - mPictureDisplayedToJpegCallbackTime = - mJpegPictureCallbackTime - mPostViewPictureCallbackTime; - } else { - mShutterToPictureDisplayedTime = - mRawPictureCallbackTime - mShutterCallbackTime; - mPictureDisplayedToJpegCallbackTime = - mJpegPictureCallbackTime - mRawPictureCallbackTime; - } - Log.v(TAG, "mPictureDisplayedToJpegCallbackTime = " - + mPictureDisplayedToJpegCallbackTime + "ms"); - - mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden. - if (!mIsImageCaptureIntent) { - if (ApiHelper.CAN_START_PREVIEW_IN_JPEG_CALLBACK) { - setupPreview(); - } else { - // Camera HAL of some devices have a bug. Starting preview - // immediately after taking a picture will fail. Wait some - // time before starting the preview. - mHandler.sendEmptyMessageDelayed(SETUP_PREVIEW, 300); - } - } - - if (!mIsImageCaptureIntent) { - // Calculate the width and the height of the jpeg. - Size s = mParameters.getPictureSize(); - ExifInterface exif = Exif.getExif(jpegData); - int orientation = Exif.getOrientation(exif); - int width, height; - if ((mJpegRotation + orientation) % 180 == 0) { - width = s.width; - height = s.height; - } else { - width = s.height; - height = s.width; - } - String title = mNamedImages.getTitle(); - long date = mNamedImages.getDate(); - if (title == null) { - Log.e(TAG, "Unbalanced name/data pair"); - } else { - if (date == -1) date = mCaptureStartTime; - if (mHeading >= 0) { - // heading direction has been updated by the sensor. - ExifTag directionRefTag = exif.buildTag( - ExifInterface.TAG_GPS_IMG_DIRECTION_REF, - ExifInterface.GpsTrackRef.MAGNETIC_DIRECTION); - ExifTag directionTag = exif.buildTag( - ExifInterface.TAG_GPS_IMG_DIRECTION, - new Rational(mHeading, 1)); - exif.setTag(directionRefTag); - exif.setTag(directionTag); - } - mActivity.getMediaSaveService().addImage( - jpegData, title, date, mLocation, width, height, - orientation, exif, mOnMediaSavedListener, mContentResolver); - } - } else { - mJpegImageData = jpegData; - if (!mQuickCapture) { - mUI.showPostCaptureAlert(); - } else { - onCaptureDone(); - } - } - - // Check 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. - mActivity.updateStorageSpaceAndHint(); - - long now = System.currentTimeMillis(); - mJpegCallbackFinishTime = now - mJpegPictureCallbackTime; - Log.v(TAG, "mJpegCallbackFinishTime = " - + mJpegCallbackFinishTime + "ms"); - mJpegPictureCallbackTime = 0; - } - } - - private final class AutoFocusCallback implements CameraAFCallback { - @Override - public void onAutoFocus( - boolean focused, CameraProxy camera) { - if (mPaused) return; - - mAutoFocusTime = System.currentTimeMillis() - mFocusStartTime; - Log.v(TAG, "mAutoFocusTime = " + mAutoFocusTime + "ms"); - setCameraState(IDLE); - mFocusManager.onAutoFocus(focused, mUI.isShutterPressed()); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private final class AutoFocusMoveCallback - implements CameraAFMoveCallback { - @Override - public void onAutoFocusMoving( - boolean moving, CameraProxy camera) { - mFocusManager.onAutoFocusMoving(moving); - } - } - - private static class NamedImages { - private ArrayList<NamedEntity> mQueue; - private boolean mStop; - private NamedEntity mNamedEntity; - - public NamedImages() { - mQueue = new ArrayList<NamedEntity>(); - } - - public void nameNewImage(ContentResolver resolver, long date) { - NamedEntity r = new NamedEntity(); - r.title = Util.createJpegName(date); - r.date = date; - mQueue.add(r); - } - - public String getTitle() { - if (mQueue.isEmpty()) { - mNamedEntity = null; - return null; - } - mNamedEntity = mQueue.get(0); - mQueue.remove(0); - - return mNamedEntity.title; - } - - // Must be called after getTitle(). - public long getDate() { - if (mNamedEntity == null) return -1; - return mNamedEntity.date; - } - - private static class NamedEntity { - String title; - long date; - } - } - - private void setCameraState(int state) { - mCameraState = state; - switch (state) { - case PhotoController.PREVIEW_STOPPED: - case PhotoController.SNAPSHOT_IN_PROGRESS: - case PhotoController.SWITCHING_CAMERA: - mUI.enableGestures(false); - break; - case PhotoController.IDLE: - mUI.enableGestures(true); - break; - } - } - - private void animateAfterShutter() { - // Only animate when in full screen capture mode - // i.e. If monkey/a user swipes to the gallery during picture taking, - // don't show animation - if (!mIsImageCaptureIntent) { - mUI.animateFlash(); - } - } - - @Override - public boolean capture() { - // If we are already in the middle of taking a snapshot or the image save request - // is full then ignore. - if (mCameraDevice == null || mCameraState == SNAPSHOT_IN_PROGRESS - || mCameraState == SWITCHING_CAMERA - || mActivity.getMediaSaveService().isQueueFull()) { - return false; - } - mCaptureStartTime = System.currentTimeMillis(); - mPostViewPictureCallbackTime = 0; - mJpegImageData = null; - - final boolean animateBefore = (mSceneMode == Util.SCENE_MODE_HDR); - - if (animateBefore) { - animateAfterShutter(); - } - - // Set rotation and gps data. - int orientation; - // We need to be consistent with the framework orientation (i.e. the - // orientation of the UI.) when the auto-rotate screen setting is on. - if (mActivity.isAutoRotateScreen()) { - orientation = (360 - mDisplayRotation) % 360; - } else { - orientation = mOrientation; - } - mJpegRotation = Util.getJpegRotation(mCameraId, orientation); - mParameters.setRotation(mJpegRotation); - Location loc = mLocationManager.getCurrentLocation(); - Util.setGpsParameters(mParameters, loc); - mCameraDevice.setParameters(mParameters); - - mCameraDevice.takePicture(mHandler, - new ShutterCallback(!animateBefore), - mRawPictureCallback, mPostViewPictureCallback, - new JpegPictureCallback(loc)); - - mNamedImages.nameNewImage(mContentResolver, mCaptureStartTime); - - mFaceDetectionStarted = false; - setCameraState(SNAPSHOT_IN_PROGRESS); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA, - UsageStatistics.ACTION_CAPTURE_DONE, "Photo"); - return true; - } - - @Override - public void setFocusParameters() { - setCameraParameters(UPDATE_PARAM_PREFERENCE); - } - - private int getPreferredCameraId(ComboPreferences preferences) { - int intentCameraId = Util.getCameraFacingIntentExtras(mActivity); - if (intentCameraId != -1) { - // Testing purpose. Launch a specific camera through the intent - // extras. - return intentCameraId; - } else { - return CameraSettings.readPreferredCameraId(preferences); - } - } - - private void updateSceneMode() { - // If scene mode is set, we cannot set flash mode, white balance, and - // focus mode, instead, we read it from driver - if (!Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) { - overrideCameraSettings(mParameters.getFlashMode(), - mParameters.getWhiteBalance(), mParameters.getFocusMode()); - } else { - overrideCameraSettings(null, null, null); - } - } - - private void overrideCameraSettings(final String flashMode, - final String whiteBalance, final String focusMode) { - mUI.overrideSettings( - CameraSettings.KEY_FLASH_MODE, flashMode, - CameraSettings.KEY_WHITE_BALANCE, whiteBalance, - CameraSettings.KEY_FOCUS_MODE, focusMode); - } - - private void loadCameraPreferences() { - CameraSettings settings = new CameraSettings(mActivity, mInitialParams, - mCameraId, CameraHolder.instance().getCameraInfo()); - mPreferenceGroup = settings.getPreferenceGroup(R.xml.camera_preferences); - } - - @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 or sky, we still have - // the correct orientation. - if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return; - mOrientation = Util.roundOrientation(orientation, mOrientation); - - // Show the toast after getting the first orientation changed. - if (mHandler.hasMessages(SHOW_TAP_TO_FOCUS_TOAST)) { - mHandler.removeMessages(SHOW_TAP_TO_FOCUS_TOAST); - showTapToFocusToast(); - } - } - - @Override - public void onStop() { - if (mMediaProviderClient != null) { - mMediaProviderClient.release(); - mMediaProviderClient = null; - } - } - - @Override - public void onCaptureCancelled() { - mActivity.setResultEx(Activity.RESULT_CANCELED, new Intent()); - mActivity.finish(); - } - - @Override - public void onCaptureRetake() { - if (mPaused) - return; - mUI.hidePostCaptureAlert(); - setupPreview(); - } - - @Override - public void onCaptureDone() { - if (mPaused) { - return; - } - - byte[] data = mJpegImageData; - - 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 its - // 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(); - - mActivity.setResultEx(Activity.RESULT_OK); - mActivity.finish(); - } catch (IOException ex) { - // ignore exception - } finally { - Util.closeSilently(outputStream); - } - } else { - ExifInterface exif = Exif.getExif(data); - int orientation = Exif.getOrientation(exif); - Bitmap bitmap = Util.makeBitmap(data, 50 * 1024); - bitmap = Util.rotate(bitmap, orientation); - mActivity.setResultEx(Activity.RESULT_OK, - new Intent("inline-data").putExtra("data", bitmap)); - mActivity.finish(); - } - } else { - // Save the image to a temp file and invoke the cropper - Uri tempUri = null; - FileOutputStream tempStream = null; - try { - File path = mActivity.getFileStreamPath(sTempCropFilename); - path.delete(); - tempStream = mActivity.openFileOutput(sTempCropFilename, 0); - tempStream.write(data); - tempStream.close(); - tempUri = Uri.fromFile(path); - } catch (FileNotFoundException ex) { - mActivity.setResultEx(Activity.RESULT_CANCELED); - mActivity.finish(); - return; - } catch (IOException ex) { - mActivity.setResultEx(Activity.RESULT_CANCELED); - mActivity.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(CropExtras.KEY_RETURN_DATA, true); - } - if (mActivity.isSecureCamera()) { - newExtras.putBoolean(CropExtras.KEY_SHOW_WHEN_LOCKED, true); - } - - Intent cropIntent = new Intent(CropActivity.CROP_ACTION); - - cropIntent.setData(tempUri); - cropIntent.putExtras(newExtras); - - mActivity.startActivityForResult(cropIntent, REQUEST_CROP); - } - } - - @Override - public void onShutterButtonFocus(boolean pressed) { - if (mPaused || mUI.collapseCameraControls() - || (mCameraState == SNAPSHOT_IN_PROGRESS) - || (mCameraState == PREVIEW_STOPPED)) return; - - // Do not do focus if there is not enough storage. - if (pressed && !canTakePicture()) return; - - if (pressed) { - mFocusManager.onShutterDown(); - } else { - // for countdown mode, we need to postpone the shutter release - // i.e. lock the focus during countdown. - if (!mUI.isCountingDown()) { - mFocusManager.onShutterUp(); - } - } - } - - @Override - public void onShutterButtonClick() { - if (mPaused || mUI.collapseCameraControls() - || (mCameraState == SWITCHING_CAMERA) - || (mCameraState == PREVIEW_STOPPED)) return; - - // Do not take the picture if there is not enough storage. - if (mActivity.getStorageSpace() <= Storage.LOW_STORAGE_THRESHOLD) { - Log.i(TAG, "Not enough space or storage not ready. remaining=" - + mActivity.getStorageSpace()); - return; - } - Log.v(TAG, "onShutterButtonClick: mCameraState=" + mCameraState); - - if (mSceneMode == Util.SCENE_MODE_HDR) { - mUI.hideSwitcher(); - mUI.setSwipingEnabled(false); - } - // If the user wants to do a snapshot while the previous one is still - // in progress, remember the fact and do it after we finish the previous - // one and re-start the preview. Snapshot in progress also includes the - // state that autofocus is focusing and a picture will be taken when - // focus callback arrives. - if ((mFocusManager.isFocusingSnapOnFinish() || mCameraState == SNAPSHOT_IN_PROGRESS) - && !mIsImageCaptureIntent) { - mSnapshotOnIdle = true; - return; - } - - String timer = mPreferences.getString( - CameraSettings.KEY_TIMER, - mActivity.getString(R.string.pref_camera_timer_default)); - boolean playSound = mPreferences.getString(CameraSettings.KEY_TIMER_SOUND_EFFECTS, - mActivity.getString(R.string.pref_camera_timer_sound_default)) - .equals(mActivity.getString(R.string.setting_on_value)); - - int seconds = Integer.parseInt(timer); - // When shutter button is pressed, check whether the previous countdown is - // finished. If not, cancel the previous countdown and start a new one. - if (mUI.isCountingDown()) { - mUI.cancelCountDown(); - } - if (seconds > 0) { - mUI.startCountDown(seconds, playSound); - } else { - mSnapshotOnIdle = false; - mFocusManager.doSnap(); - } - } - - @Override - public void installIntentFilter() { - } - - @Override - public boolean updateStorageHintOnResume() { - return mFirstTimeInitialized; - } - - @Override - public void updateCameraAppView() { - } - - @Override - public void onResumeBeforeSuper() { - mPaused = false; - } - - @Override - public void onResumeAfterSuper() { - if (mOpenCameraFail || mCameraDisabled) return; - - mJpegPictureCallbackTime = 0; - mZoomValue = 0; - // Start the preview if it is not started. - if (mCameraState == PREVIEW_STOPPED && mCameraStartUpThread == null) { - resetExposureCompensation(); - mCameraStartUpThread = new CameraStartUpThread(); - mCameraStartUpThread.start(); - } - - // If first time initialization is not finished, put it in the - // message queue. - if (!mFirstTimeInitialized) { - mHandler.sendEmptyMessage(FIRST_TIME_INIT); - } else { - initializeSecondTime(); - } - keepScreenOnAwhile(); - - // Dismiss open menu if exists. - PopupManager.getInstance(mActivity).notifyShowPopup(null); - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_CAMERA, "PhotoModule"); - - Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - if (gsensor != null) { - mSensorManager.registerListener(this, gsensor, SensorManager.SENSOR_DELAY_NORMAL); - } - - Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); - if (msensor != null) { - mSensorManager.registerListener(this, msensor, SensorManager.SENSOR_DELAY_NORMAL); - } - } - - void waitCameraStartUpThread() { - try { - if (mCameraStartUpThread != null) { - mCameraStartUpThread.cancel(); - mCameraStartUpThread.join(); - mCameraStartUpThread = null; - setCameraState(IDLE); - } - } catch (InterruptedException e) { - // ignore - } - } - - @Override - public void onPauseBeforeSuper() { - mPaused = true; - Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - if (gsensor != null) { - mSensorManager.unregisterListener(this, gsensor); - } - - Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); - if (msensor != null) { - mSensorManager.unregisterListener(this, msensor); - } - } - - @Override - public void onPauseAfterSuper() { - // Wait the camera start up thread to finish. - waitCameraStartUpThread(); - - // When camera is started from secure lock screen for the first time - // after screen on, the activity gets onCreate->onResume->onPause->onResume. - // To reduce the latency, keep the camera for a short time so it does - // not need to be opened again. - if (mCameraDevice != null && mActivity.isSecureCamera() - && CameraActivity.isFirstStartAfterScreenOn()) { - CameraActivity.resetFirstStartAfterScreenOn(); - CameraHolder.instance().keep(KEEP_CAMERA_TIMEOUT); - } - // Reset the focus first. Camera CTS does not guarantee that - // cancelAutoFocus is allowed after preview stops. - if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { - mCameraDevice.cancelAutoFocus(); - } - stopPreview(); - - mNamedImages = null; - - if (mLocationManager != null) mLocationManager.recordLocation(false); - - // If we are in an image capture intent and has taken - // a picture, we just clear it in onPause. - mJpegImageData = null; - - // Remove the messages in the event queue. - mHandler.removeMessages(SETUP_PREVIEW); - mHandler.removeMessages(FIRST_TIME_INIT); - mHandler.removeMessages(CHECK_DISPLAY_ROTATION); - mHandler.removeMessages(SWITCH_CAMERA); - mHandler.removeMessages(SWITCH_CAMERA_START_ANIMATION); - mHandler.removeMessages(CAMERA_OPEN_DONE); - mHandler.removeMessages(START_PREVIEW_DONE); - mHandler.removeMessages(OPEN_CAMERA_FAIL); - mHandler.removeMessages(CAMERA_DISABLED); - - closeCamera(); - - resetScreenOn(); - mUI.onPause(); - - mPendingSwitchCameraId = -1; - if (mFocusManager != null) mFocusManager.removeMessages(); - MediaSaveService s = mActivity.getMediaSaveService(); - if (s != null) { - s.setListener(null); - } - } - - /** - * The focus manager is the first UI related element to get initialized, - * and it requires the RenderOverlay, so initialize it here - */ - private void initializeFocusManager() { - // Create FocusManager object. startPreview needs it. - // if mFocusManager not null, reuse it - // otherwise create a new instance - if (mFocusManager != null) { - mFocusManager.removeMessages(); - } else { - CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; - boolean mirror = (info.facing == CameraInfo.CAMERA_FACING_FRONT); - String[] defaultFocusModes = mActivity.getResources().getStringArray( - R.array.pref_camera_focusmode_default_array); - mFocusManager = new FocusOverlayManager(mPreferences, defaultFocusModes, - mInitialParams, this, mirror, - mActivity.getMainLooper(), mUI); - } - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - Log.v(TAG, "onConfigurationChanged"); - setDisplayOrientation(); - } - - @Override - public void updateCameraOrientation() { - if (mDisplayRotation != Util.getDisplayRotation(mActivity)) { - setDisplayOrientation(); - } - } - - @Override - public void onActivityResult( - int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case REQUEST_CROP: { - Intent intent = new Intent(); - if (data != null) { - Bundle extras = data.getExtras(); - if (extras != null) { - intent.putExtras(extras); - } - } - mActivity.setResultEx(resultCode, intent); - mActivity.finish(); - - File path = mActivity.getFileStreamPath(sTempCropFilename); - path.delete(); - - break; - } - } - } - - private boolean canTakePicture() { - return isCameraIdle() && (mActivity.getStorageSpace() > Storage.LOW_STORAGE_THRESHOLD); - } - - @Override - public void autoFocus() { - mFocusStartTime = System.currentTimeMillis(); - mCameraDevice.autoFocus(mHandler, mAutoFocusCallback); - setCameraState(FOCUSING); - } - - @Override - public void cancelAutoFocus() { - mCameraDevice.cancelAutoFocus(); - setCameraState(IDLE); - setCameraParameters(UPDATE_PARAM_PREFERENCE); - } - - // Preview area is touched. Handle touch focus. - @Override - public void onSingleTapUp(View view, int x, int y) { - if (mPaused || mCameraDevice == null || !mFirstTimeInitialized - || mCameraState == SNAPSHOT_IN_PROGRESS - || mCameraState == SWITCHING_CAMERA - || mCameraState == PREVIEW_STOPPED) { - return; - } - - // Do not trigger touch focus if popup window is opened. - if (mUI.removeTopLevelPopup()) return; - - // Check if metering area or focus area is supported. - if (!mFocusAreaSupported && !mMeteringAreaSupported) return; - mFocusManager.onSingleTapUp(x, y); - } - - @Override - public boolean onBackPressed() { - return mUI.onBackPressed(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_VOLUME_UP: - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_FOCUS: - if (/*TODO: mActivity.isInCameraApp() &&*/ mFirstTimeInitialized) { - if (event.getRepeatCount() == 0) { - onShutterButtonFocus(true); - } - return true; - } - return false; - case KeyEvent.KEYCODE_CAMERA: - if (mFirstTimeInitialized && event.getRepeatCount() == 0) { - onShutterButtonClick(); - } - 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, onShutterButtonFocus() - // will be called again but it is fine. - if (mUI.removeTopLevelPopup()) return true; - onShutterButtonFocus(true); - mUI.pressShutterButton(); - } - return true; - } - return false; - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_VOLUME_UP: - case KeyEvent.KEYCODE_VOLUME_DOWN: - if (/*mActivity.isInCameraApp() && */ mFirstTimeInitialized) { - onShutterButtonClick(); - return true; - } - return false; - case KeyEvent.KEYCODE_FOCUS: - if (mFirstTimeInitialized) { - onShutterButtonFocus(false); - } - return true; - } - return false; - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void closeCamera() { - if (mCameraDevice != null) { - mCameraDevice.setZoomChangeListener(null); - if(ApiHelper.HAS_FACE_DETECTION) { - mCameraDevice.setFaceDetectionCallback(null, null); - } - mCameraDevice.setErrorCallback(null); - CameraHolder.instance().release(); - mFaceDetectionStarted = false; - mCameraDevice = null; - setCameraState(PREVIEW_STOPPED); - mFocusManager.onCameraReleased(); - } - } - - private void setDisplayOrientation() { - mDisplayRotation = Util.getDisplayRotation(mActivity); - mDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, mCameraId); - mCameraDisplayOrientation = mDisplayOrientation; - mUI.setDisplayOrientation(mDisplayOrientation); - if (mFocusManager != null) { - mFocusManager.setDisplayOrientation(mDisplayOrientation); - } - // Change the camera display orientation - if (mCameraDevice != null) { - mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation); - } - } - - // Only called by UI thread. - private void setupPreview() { - mFocusManager.resetTouchFocus(); - startPreview(); - setCameraState(IDLE); - startFaceDetection(); - } - - // This can be called by UI Thread or CameraStartUpThread. So this should - // not modify the views. - private void startPreview() { - mCameraDevice.setErrorCallback(mErrorCallback); - - // ICS camera frameworks has a bug. Face detection state is not cleared - // after taking a picture. Stop the preview to work around it. The bug - // was fixed in JB. - if (mCameraState != PREVIEW_STOPPED) stopPreview(); - - setDisplayOrientation(); - - if (!mSnapshotOnIdle) { - // If the focus mode is continuous autofocus, call cancelAutoFocus to - // resume it because it may have been paused by autoFocus call. - if (Util.FOCUS_MODE_CONTINUOUS_PICTURE.equals(mFocusManager.getFocusMode())) { - mCameraDevice.cancelAutoFocus(); - } - mFocusManager.setAeAwbLock(false); // Unlock AE and AWB. - } - setCameraParameters(UPDATE_PARAM_ALL); - // Let UI set its expected aspect ratio - mUI.setPreviewSize(mParameters.getPreviewSize()); - Object st = mUI.getSurfaceTexture(); - if (st != null) { - mCameraDevice.setPreviewTexture((SurfaceTexture) st); - } - - Log.v(TAG, "startPreview"); - mCameraDevice.startPreview(); - mFocusManager.onPreviewStarted(); - - if (mSnapshotOnIdle) { - mHandler.post(mDoSnapRunnable); - } - } - - @Override - public void stopPreview() { - if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { - Log.v(TAG, "stopPreview"); - mCameraDevice.stopPreview(); - mFaceDetectionStarted = false; - } - setCameraState(PREVIEW_STOPPED); - if (mFocusManager != null) mFocusManager.onPreviewStopped(); - } - - @SuppressWarnings("deprecation") - private void updateCameraParametersInitialize() { - // Reset preview frame rate to the maximum because it may be lowered by - // video camera application. - int[] fpsRange = Util.getMaxPreviewFpsRange(mParameters); - if (fpsRange.length > 0) { - mParameters.setPreviewFpsRange( - fpsRange[Parameters.PREVIEW_FPS_MIN_INDEX], - fpsRange[Parameters.PREVIEW_FPS_MAX_INDEX]); - } - - mParameters.set(Util.RECORDING_HINT, Util.FALSE); - - // Disable video stabilization. Convenience methods not available in API - // level <= 14 - String vstabSupported = mParameters.get("video-stabilization-supported"); - if ("true".equals(vstabSupported)) { - mParameters.set("video-stabilization", "false"); - } - } - - private void updateCameraParametersZoom() { - // Set zoom. - if (mParameters.isZoomSupported()) { - mParameters.setZoom(mZoomValue); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private void setAutoExposureLockIfSupported() { - if (mAeLockSupported) { - mParameters.setAutoExposureLock(mFocusManager.getAeAwbLock()); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private void setAutoWhiteBalanceLockIfSupported() { - if (mAwbLockSupported) { - mParameters.setAutoWhiteBalanceLock(mFocusManager.getAeAwbLock()); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void setFocusAreasIfSupported() { - if (mFocusAreaSupported) { - mParameters.setFocusAreas(mFocusManager.getFocusAreas()); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void setMeteringAreasIfSupported() { - if (mMeteringAreaSupported) { - // Use the same area for focus and metering. - mParameters.setMeteringAreas(mFocusManager.getMeteringAreas()); - } - } - - private void updateCameraParametersPreference() { - setAutoExposureLockIfSupported(); - setAutoWhiteBalanceLockIfSupported(); - setFocusAreasIfSupported(); - setMeteringAreasIfSupported(); - - // Set picture size. - String pictureSize = mPreferences.getString( - CameraSettings.KEY_PICTURE_SIZE, null); - if (pictureSize == null) { - CameraSettings.initialCameraPictureSize(mActivity, mParameters); - } else { - List<Size> supported = mParameters.getSupportedPictureSizes(); - CameraSettings.setCameraPictureSize( - pictureSize, supported, mParameters); - } - Size size = mParameters.getPictureSize(); - - // Set a preview size that is closest to the viewfinder height and has - // the right aspect ratio. - List<Size> sizes = mParameters.getSupportedPreviewSizes(); - Size optimalSize = Util.getOptimalPreviewSize(mActivity, sizes, - (double) size.width / size.height); - Size original = mParameters.getPreviewSize(); - if (!original.equals(optimalSize)) { - mParameters.setPreviewSize(optimalSize.width, optimalSize.height); - - // Zoom related settings will be changed for different preview - // sizes, so set and read the parameters to get latest values - if (mHandler.getLooper() == Looper.myLooper()) { - // On UI thread only, not when camera starts up - setupPreview(); - } else { - mCameraDevice.setParameters(mParameters); - } - mParameters = mCameraDevice.getParameters(); - } - Log.v(TAG, "Preview size is " + optimalSize.width + "x" + optimalSize.height); - - // Since changing scene mode may change supported values, set scene mode - // first. HDR is a scene mode. To promote it in UI, it is stored in a - // separate preference. - String hdr = mPreferences.getString(CameraSettings.KEY_CAMERA_HDR, - mActivity.getString(R.string.pref_camera_hdr_default)); - if (mActivity.getString(R.string.setting_on_value).equals(hdr)) { - mSceneMode = Util.SCENE_MODE_HDR; - } else { - mSceneMode = mPreferences.getString( - CameraSettings.KEY_SCENE_MODE, - mActivity.getString(R.string.pref_camera_scenemode_default)); - } - if (Util.isSupported(mSceneMode, mParameters.getSupportedSceneModes())) { - if (!mParameters.getSceneMode().equals(mSceneMode)) { - mParameters.setSceneMode(mSceneMode); - - // Setting scene mode will change the settings of flash mode, - // white balance, and focus mode. Here we read back the - // parameters, so we can know those settings. - mCameraDevice.setParameters(mParameters); - mParameters = mCameraDevice.getParameters(); - } - } else { - mSceneMode = mParameters.getSceneMode(); - if (mSceneMode == null) { - mSceneMode = Parameters.SCENE_MODE_AUTO; - } - } - - // Set JPEG quality. - int jpegQuality = CameraProfile.getJpegEncodingQualityParameter(mCameraId, - CameraProfile.QUALITY_HIGH); - mParameters.setJpegQuality(jpegQuality); - - // For the following settings, we need to check if the settings are - // still supported by latest driver, if not, ignore the settings. - - // Set exposure compensation - int value = CameraSettings.readExposure(mPreferences); - int max = mParameters.getMaxExposureCompensation(); - int min = mParameters.getMinExposureCompensation(); - if (value >= min && value <= max) { - mParameters.setExposureCompensation(value); - } else { - Log.w(TAG, "invalid exposure range: " + value); - } - - if (Parameters.SCENE_MODE_AUTO.equals(mSceneMode)) { - // Set flash mode. - String flashMode = mPreferences.getString( - CameraSettings.KEY_FLASH_MODE, - mActivity.getString(R.string.pref_camera_flashmode_default)); - List<String> supportedFlash = mParameters.getSupportedFlashModes(); - if (Util.isSupported(flashMode, supportedFlash)) { - mParameters.setFlashMode(flashMode); - } else { - flashMode = mParameters.getFlashMode(); - if (flashMode == null) { - flashMode = mActivity.getString( - R.string.pref_camera_flashmode_no_flash); - } - } - - // Set white balance parameter. - String whiteBalance = mPreferences.getString( - CameraSettings.KEY_WHITE_BALANCE, - mActivity.getString(R.string.pref_camera_whitebalance_default)); - if (Util.isSupported(whiteBalance, - mParameters.getSupportedWhiteBalance())) { - mParameters.setWhiteBalance(whiteBalance); - } else { - whiteBalance = mParameters.getWhiteBalance(); - if (whiteBalance == null) { - whiteBalance = Parameters.WHITE_BALANCE_AUTO; - } - } - - // Set focus mode. - mFocusManager.overrideFocusMode(null); - mParameters.setFocusMode(mFocusManager.getFocusMode()); - } else { - mFocusManager.overrideFocusMode(mParameters.getFocusMode()); - } - - if (mContinousFocusSupported && ApiHelper.HAS_AUTO_FOCUS_MOVE_CALLBACK) { - updateAutoFocusMoveCallback(); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private void updateAutoFocusMoveCallback() { - if (mParameters.getFocusMode().equals(Util.FOCUS_MODE_CONTINUOUS_PICTURE)) { - mCameraDevice.setAutoFocusMoveCallback(mHandler, - (CameraManager.CameraAFMoveCallback) mAutoFocusMoveCallback); - } else { - mCameraDevice.setAutoFocusMoveCallback(null, null); - } - } - - // We separate the parameters into several subsets, so we can update only - // the subsets actually need updating. The PREFERENCE set needs extra - // locking because the preference can be changed from GLThread as well. - private void setCameraParameters(int updateSet) { - if ((updateSet & UPDATE_PARAM_INITIALIZE) != 0) { - updateCameraParametersInitialize(); - } - - if ((updateSet & UPDATE_PARAM_ZOOM) != 0) { - updateCameraParametersZoom(); - } - - if ((updateSet & UPDATE_PARAM_PREFERENCE) != 0) { - updateCameraParametersPreference(); - } - - mCameraDevice.setParameters(mParameters); - } - - // If the Camera is idle, update the parameters immediately, otherwise - // accumulate them in mUpdateSet and update later. - private void setCameraParametersWhenIdle(int additionalUpdateSet) { - mUpdateSet |= additionalUpdateSet; - if (mCameraDevice == null) { - // We will update all the parameters when we open the device, so - // we don't need to do anything now. - mUpdateSet = 0; - return; - } else if (isCameraIdle()) { - setCameraParameters(mUpdateSet); - updateSceneMode(); - mUpdateSet = 0; - } else { - if (!mHandler.hasMessages(SET_CAMERA_PARAMETERS_WHEN_IDLE)) { - mHandler.sendEmptyMessageDelayed( - SET_CAMERA_PARAMETERS_WHEN_IDLE, 1000); - } - } - } - - public boolean isCameraIdle() { - return (mCameraState == IDLE) || - (mCameraState == PREVIEW_STOPPED) || - ((mFocusManager != null) && mFocusManager.isFocusCompleted() - && (mCameraState != SWITCHING_CAMERA)); - } - - public boolean isImageCaptureIntent() { - String action = mActivity.getIntent().getAction(); - return (MediaStore.ACTION_IMAGE_CAPTURE.equals(action) - || CameraActivity.ACTION_IMAGE_CAPTURE_SECURE.equals(action)); - } - - private void setupCaptureParams() { - Bundle myExtras = mActivity.getIntent().getExtras(); - if (myExtras != null) { - mSaveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); - mCropValue = myExtras.getString("crop"); - } - } - - @Override - public void onSharedPreferenceChanged() { - // ignore the events after "onPause()" - if (mPaused) return; - - boolean recordLocation = RecordLocationPreference.get( - mPreferences, mContentResolver); - mLocationManager.recordLocation(recordLocation); - - setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE); - mUI.updateOnScreenIndicators(mParameters, mPreferenceGroup, mPreferences); - } - - @Override - public void onCameraPickerClicked(int cameraId) { - if (mPaused || mPendingSwitchCameraId != -1) return; - - mPendingSwitchCameraId = cameraId; - - Log.v(TAG, "Start to switch camera. cameraId=" + cameraId); - // We need to keep a preview frame for the animation before - // releasing the camera. This will trigger onPreviewTextureCopied. - //TODO: Need to animate the camera switch - switchCamera(); - } - - // Preview texture has been copied. Now camera can be released and the - // animation can be started. - @Override - public void onPreviewTextureCopied() { - mHandler.sendEmptyMessage(SWITCH_CAMERA); - } - - @Override - public void onCaptureTextureCopied() { - } - - @Override - public void onUserInteraction() { - if (!mActivity.isFinishing()) keepScreenOnAwhile(); - } - - private void resetScreenOn() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - - private void keepScreenOnAwhile() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); - } - - @Override - public void onOverriddenPreferencesClicked() { - if (mPaused) return; - mUI.showPreferencesToast(); - } - - private void showTapToFocusToast() { - // TODO: Use a toast? - new RotateTextToast(mActivity, R.string.tap_to_focus, 0).show(); - // Clear the preference. - Editor editor = mPreferences.edit(); - editor.putBoolean(CameraSettings.KEY_CAMERA_FIRST_USE_HINT_SHOWN, false); - editor.apply(); - } - - private void initializeCapabilities() { - mInitialParams = mCameraDevice.getParameters(); - mFocusAreaSupported = Util.isFocusAreaSupported(mInitialParams); - mMeteringAreaSupported = Util.isMeteringAreaSupported(mInitialParams); - mAeLockSupported = Util.isAutoExposureLockSupported(mInitialParams); - mAwbLockSupported = Util.isAutoWhiteBalanceLockSupported(mInitialParams); - mContinousFocusSupported = mInitialParams.getSupportedFocusModes().contains( - Util.FOCUS_MODE_CONTINUOUS_PICTURE); - } - - @Override - public void onCountDownFinished() { - mSnapshotOnIdle = false; - mFocusManager.doSnap(); - mFocusManager.onShutterUp(); - } - - @Override - public void onShowSwitcherPopup() { - mUI.onShowSwitcherPopup(); - } - - @Override - public int onZoomChanged(int index) { - // Not useful to change zoom value when the activity is paused. - if (mPaused) return index; - mZoomValue = index; - if (mParameters == null || mCameraDevice == null) return index; - // Set zoom parameters asynchronously - mParameters.setZoom(mZoomValue); - mCameraDevice.setParameters(mParameters); - Parameters p = mCameraDevice.getParameters(); - if (p != null) return p.getZoom(); - return index; - } - - @Override - public int getCameraState() { - return mCameraState; - } - - @Override - public void onQueueStatus(boolean full) { - mUI.enableShutter(!full); - } - - @Override - public void onMediaSaveServiceConnected(MediaSaveService s) { - // We set the listener only when both service and shutterbutton - // are initialized. - if (mFirstTimeInitialized) { - s.setListener(this); - } - } - - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - } - - @Override - public void onSensorChanged(SensorEvent event) { - int type = event.sensor.getType(); - float[] data; - if (type == Sensor.TYPE_ACCELEROMETER) { - data = mGData; - } else if (type == Sensor.TYPE_MAGNETIC_FIELD) { - data = mMData; - } else { - // we should not be here. - return; - } - for (int i = 0; i < 3 ; i++) { - data[i] = event.values[i]; - } - float[] orientation = new float[3]; - SensorManager.getRotationMatrix(mR, null, mGData, mMData); - SensorManager.getOrientation(mR, orientation); - mHeading = (int) (orientation[0] * 180f / Math.PI) % 360; - if (mHeading < 0) { - mHeading += 360; - } - } - - @Override - public void onSwitchMode(boolean toCamera) { - mUI.onSwitchMode(toCamera); - } - -/* Below is no longer needed, except to get rid of compile error - * TODO: Remove these - */ - - // TODO: Delete this function after old camera code is removed - @Override - public void onRestorePreferencesClicked() {} - -} diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java deleted file mode 100644 index ef2722438..000000000 --- a/src/com/android/camera/PhotoUI.java +++ /dev/null @@ -1,854 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.android.camera; - -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.graphics.SurfaceTexture; -import android.hardware.Camera; -import android.hardware.Camera.Face; -import android.hardware.Camera.Size; -import android.os.AsyncTask; -import android.os.Handler; -import android.os.Message; -import android.util.Log; -import android.view.Gravity; -import android.view.TextureView; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnLayoutChangeListener; -import android.view.ViewGroup; -import android.view.ViewStub; -import android.widget.FrameLayout; -import android.widget.FrameLayout.LayoutParams; -import android.widget.ImageView; -import android.widget.Toast; - -import com.android.camera.CameraPreference.OnPreferenceChangedListener; -import com.android.camera.FocusOverlayManager.FocusUI; -import com.android.camera.ui.AbstractSettingPopup; -import com.android.camera.ui.CameraControls; -import com.android.camera.ui.CameraRootView; -import com.android.camera.ui.CameraSwitcher; -import com.android.camera.ui.CameraSwitcher.CameraSwitchListener; -import com.android.camera.ui.CountDownView; -import com.android.camera.ui.CountDownView.OnCountDownFinishedListener; -import com.android.camera.ui.FaceView; -import com.android.camera.ui.FocusIndicator; -import com.android.camera.ui.PieRenderer; -import com.android.camera.ui.PieRenderer.PieListener; -import com.android.camera.ui.RenderOverlay; -import com.android.camera.ui.ZoomRenderer; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.List; - -public class PhotoUI implements PieListener, - PreviewGestures.SingleTapListener, - FocusUI, TextureView.SurfaceTextureListener, - LocationManager.Listener, CameraRootView.MyDisplayListener, - CameraManager.CameraFaceDetectionCallback { - - private static final String TAG = "CAM_UI"; - private static final int UPDATE_TRANSFORM_MATRIX = 1; - private static final int DOWN_SAMPLE_FACTOR = 4; - private final AnimationManager mAnimationManager; - private CameraActivity mActivity; - private PhotoController mController; - private PreviewGestures mGestures; - - private View mRootView; - private Object mSurfaceTexture; - - private AbstractSettingPopup mPopup; - private ShutterButton mShutterButton; - private CountDownView mCountDownView; - - private FaceView mFaceView; - private RenderOverlay mRenderOverlay; - private View mReviewCancelButton; - private View mReviewDoneButton; - private View mReviewRetakeButton; - - private View mMenuButton; - private View mBlocker; - private PhotoMenu mMenu; - private CameraSwitcher mSwitcher; - private CameraControls mCameraControls; - private AlertDialog mLocationDialog; - - // Small indicators which show the camera settings in the viewfinder. - private OnScreenIndicators mOnScreenIndicators; - - private PieRenderer mPieRenderer; - private ZoomRenderer mZoomRenderer; - private Toast mNotSelectableToast; - - private int mZoomMax; - private List<Integer> mZoomRatios; - - private int mPreviewWidth = 0; - private int mPreviewHeight = 0; - private float mSurfaceTextureUncroppedWidth; - private float mSurfaceTextureUncroppedHeight; - - private ImageView mPreviewThumb; - private View mFlashOverlay; - - private SurfaceTextureSizeChangedListener mSurfaceTextureSizeListener; - private TextureView mTextureView; - private Matrix mMatrix = null; - private float mAspectRatio = 4f / 3f; - private final Object mLock = new Object(); - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case UPDATE_TRANSFORM_MATRIX: - setTransformMatrix(mPreviewWidth, mPreviewHeight); - break; - default: - break; - } - } - }; - - public interface SurfaceTextureSizeChangedListener { - public void onSurfaceTextureSizeChanged(int uncroppedWidth, int uncroppedHeight); - } - - private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, - int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - int width = right - left; - int height = bottom - top; - // Full-screen screennail - int w = width; - int h = height; - if (Util.getDisplayRotation(mActivity) % 180 != 0) { - w = height; - h = width; - } - if (mPreviewWidth != width || mPreviewHeight != height) { - mPreviewWidth = width; - mPreviewHeight = height; - onScreenSizeChanged(width, height, w, h); - mController.onScreenSizeChanged(width, height, w, h); - } - } - }; - - private class DecodeTask extends AsyncTask<Integer, Void, Bitmap> { - private final byte [] mData; - - public DecodeTask(byte[] data) { - mData = data; - } - - @Override - protected Bitmap doInBackground(Integer... params) { - // Decode image in background. - return Util.downSample(mData, DOWN_SAMPLE_FACTOR); - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - mPreviewThumb.setImageBitmap(bitmap); - mAnimationManager.startCaptureAnimation(mPreviewThumb); - } - } - - public PhotoUI(CameraActivity activity, PhotoController controller, View parent) { - mActivity = activity; - mController = controller; - mRootView = parent; - - mActivity.getLayoutInflater().inflate(R.layout.photo_module, - (ViewGroup) mRootView, true); - mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay); - mFlashOverlay = mRootView.findViewById(R.id.flash_overlay); - // display the view - mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content); - mTextureView.setSurfaceTextureListener(this); - mTextureView.addOnLayoutChangeListener(mLayoutListener); - initIndicators(); - - mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button); - mSwitcher = (CameraSwitcher) mRootView.findViewById(R.id.camera_switcher); - mSwitcher.setCurrentIndex(CameraSwitcher.PHOTO_MODULE_INDEX); - mSwitcher.setSwitchListener((CameraSwitchListener) mActivity); - mMenuButton = mRootView.findViewById(R.id.menu); - if (ApiHelper.HAS_FACE_DETECTION) { - ViewStub faceViewStub = (ViewStub) mRootView - .findViewById(R.id.face_view_stub); - if (faceViewStub != null) { - faceViewStub.inflate(); - mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); - setSurfaceTextureSizeChangedListener( - (SurfaceTextureSizeChangedListener) mFaceView); - } - } - mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls); - ((CameraRootView) mRootView).setDisplayChangeListener(this); - mAnimationManager = new AnimationManager(); - } - - public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight) { - setTransformMatrix(width, height); - } - - public void setSurfaceTextureSizeChangedListener(SurfaceTextureSizeChangedListener listener) { - mSurfaceTextureSizeListener = listener; - } - - public void setPreviewSize(Size size) { - int width = size.width; - int height = size.height; - if (width == 0 || height == 0) { - Log.w(TAG, "Preview size should not be 0."); - return; - } - if (width > height) { - mAspectRatio = (float) width / height; - } else { - mAspectRatio = (float) height / width; - } - mHandler.sendEmptyMessage(UPDATE_TRANSFORM_MATRIX); - } - - private void setTransformMatrix(int width, int height) { - mMatrix = mTextureView.getTransform(mMatrix); - int orientation = Util.getDisplayRotation(mActivity); - float scaleX = 1f, scaleY = 1f; - float scaledTextureWidth, scaledTextureHeight; - if (width > height) { - scaledTextureWidth = Math.max(width, - (int) (height * mAspectRatio)); - scaledTextureHeight = Math.max(height, - (int)(width / mAspectRatio)); - } else { - scaledTextureWidth = Math.max(width, - (int) (height / mAspectRatio)); - scaledTextureHeight = Math.max(height, - (int) (width * mAspectRatio)); - } - - if (mSurfaceTextureUncroppedWidth != scaledTextureWidth || - mSurfaceTextureUncroppedHeight != scaledTextureHeight) { - mSurfaceTextureUncroppedWidth = scaledTextureWidth; - mSurfaceTextureUncroppedHeight = scaledTextureHeight; - if (mSurfaceTextureSizeListener != null) { - mSurfaceTextureSizeListener.onSurfaceTextureSizeChanged( - (int) mSurfaceTextureUncroppedWidth, (int) mSurfaceTextureUncroppedHeight); - } - } - scaleX = scaledTextureWidth / width; - scaleY = scaledTextureHeight / height; - mMatrix.setScale(scaleX, scaleY, (float) width / 2, (float) height / 2); - mTextureView.setTransform(mMatrix); - } - - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - synchronized (mLock) { - mSurfaceTexture = surface; - mLock.notifyAll(); - } - } - - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - // Ignored, Camera does all the work for us - } - - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - mSurfaceTexture = null; - mController.stopPreview(); - Log.w(TAG, "surfaceTexture is destroyed"); - return true; - } - - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - // Invoked every time there's a new Camera preview frame - } - - public View getRootView() { - return mRootView; - } - - private void initIndicators() { - mOnScreenIndicators = new OnScreenIndicators(mActivity, - mRootView.findViewById(R.id.on_screen_indicators)); - } - - public void onCameraOpened(PreferenceGroup prefGroup, ComboPreferences prefs, - Camera.Parameters params, OnPreferenceChangedListener listener) { - if (mPieRenderer == null) { - mPieRenderer = new PieRenderer(mActivity); - mPieRenderer.setPieListener(this); - mRenderOverlay.addRenderer(mPieRenderer); - } - - if (mMenu == null) { - mMenu = new PhotoMenu(mActivity, this, mPieRenderer); - mMenu.setListener(listener); - } - mMenu.initialize(prefGroup); - - if (mZoomRenderer == null) { - mZoomRenderer = new ZoomRenderer(mActivity); - mRenderOverlay.addRenderer(mZoomRenderer); - } - - if (mGestures == null) { - // this will handle gesture disambiguation and dispatching - mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer); - mRenderOverlay.setGestures(mGestures); - } - mGestures.setZoomEnabled(params.isZoomSupported()); - mGestures.setRenderOverlay(mRenderOverlay); - mRenderOverlay.requestLayout(); - - initializeZoom(params); - updateOnScreenIndicators(params, prefGroup, prefs); - } - - public void animateCapture(final byte[] jpegData) { - // Decode jpeg byte array and then animate the jpeg - DecodeTask task = new DecodeTask(jpegData); - task.execute(); - } - - private void openMenu() { - if (mPieRenderer != null) { - // If autofocus is not finished, cancel autofocus so that the - // subsequent touch can be handled by PreviewGestures - if (mController.getCameraState() == PhotoController.FOCUSING) { - mController.cancelAutoFocus(); - } - mPieRenderer.showInCenter(); - } - } - - public void initializeControlByIntent() { - mBlocker = mRootView.findViewById(R.id.blocker); - mPreviewThumb = (ImageView) mRootView.findViewById(R.id.preview_thumb); - mPreviewThumb.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - // TODO: go to filmstrip - // mActivity.gotoGallery(); - } - }); - mMenuButton = mRootView.findViewById(R.id.menu); - mMenuButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - openMenu(); - } - }); - if (mController.isImageCaptureIntent()) { - hideSwitcher(); - ViewGroup cameraControls = (ViewGroup) mRootView.findViewById(R.id.camera_controls); - mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls); - - mReviewDoneButton = mRootView.findViewById(R.id.btn_done); - mReviewCancelButton = mRootView.findViewById(R.id.btn_cancel); - mReviewRetakeButton = mRootView.findViewById(R.id.btn_retake); - mReviewCancelButton.setVisibility(View.VISIBLE); - - mReviewDoneButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mController.onCaptureDone(); - } - }); - mReviewCancelButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mController.onCaptureCancelled(); - } - }); - - mReviewRetakeButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mController.onCaptureRetake(); - } - }); - } - } - - public void hideUI() { - mCameraControls.setVisibility(View.INVISIBLE); - mSwitcher.closePopup(); - } - - public void showUI() { - mCameraControls.setVisibility(View.VISIBLE); - } - - public void hideSwitcher() { - mSwitcher.closePopup(); - mSwitcher.setVisibility(View.INVISIBLE); - } - - public void showSwitcher() { - mSwitcher.setVisibility(View.VISIBLE); - } - // called from onResume but only the first time - public void initializeFirstTime() { - // Initialize shutter button. - mShutterButton.setImageResource(R.drawable.btn_new_shutter); - mShutterButton.setOnShutterButtonListener(mController); - mShutterButton.setVisibility(View.VISIBLE); - } - - // called from onResume every other time - public void initializeSecondTime(Camera.Parameters params) { - initializeZoom(params); - if (mController.isImageCaptureIntent()) { - hidePostCaptureAlert(); - } - if (mMenu != null) { - mMenu.reloadPreferences(); - } - } - - public void showLocationDialog() { - mLocationDialog = new AlertDialog.Builder(mActivity) - .setTitle(R.string.remember_location_title) - .setMessage(R.string.remember_location_prompt) - .setPositiveButton(R.string.remember_location_yes, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int arg1) { - mController.enableRecordingLocation(true); - mLocationDialog = null; - } - }) - .setNegativeButton(R.string.remember_location_no, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int arg1) { - dialog.cancel(); - } - }) - .setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - mController.enableRecordingLocation(false); - mLocationDialog = null; - } - }) - .show(); - } - - public void initializeZoom(Camera.Parameters params) { - if ((params == null) || !params.isZoomSupported() - || (mZoomRenderer == null)) return; - mZoomMax = params.getMaxZoom(); - mZoomRatios = params.getZoomRatios(); - // Currently we use immediate zoom for fast zooming to get better UX and - // there is no plan to take advantage of the smooth zoom. - if (mZoomRenderer != null) { - mZoomRenderer.setZoomMax(mZoomMax); - mZoomRenderer.setZoom(params.getZoom()); - mZoomRenderer.setZoomValue(mZoomRatios.get(params.getZoom())); - mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener()); - } - } - - public void showGpsOnScreenIndicator(boolean hasSignal) { } - - public void hideGpsOnScreenIndicator() { } - - public void overrideSettings(final String ... keyvalues) { - mMenu.overrideSettings(keyvalues); - } - - public void updateOnScreenIndicators(Camera.Parameters params, - PreferenceGroup group, ComboPreferences prefs) { - if (params == null) return; - mOnScreenIndicators.updateSceneOnScreenIndicator(params.getSceneMode()); - mOnScreenIndicators.updateExposureOnScreenIndicator(params, - CameraSettings.readExposure(prefs)); - mOnScreenIndicators.updateFlashOnScreenIndicator(params.getFlashMode()); - int wbIndex = 2; - ListPreference pref = group.findPreference(CameraSettings.KEY_WHITE_BALANCE); - if (pref != null) { - wbIndex = pref.getCurrentIndex(); - } - mOnScreenIndicators.updateWBIndicator(wbIndex); - boolean location = RecordLocationPreference.get( - prefs, mActivity.getContentResolver()); - mOnScreenIndicators.updateLocationIndicator(location); - } - - public void setCameraState(int state) { - } - - public void animateFlash() { - mAnimationManager.startFlashAnimation(mFlashOverlay); - } - - public void enableGestures(boolean enable) { - if (mGestures != null) { - mGestures.setEnabled(enable); - } - } - - // forward from preview gestures to controller - @Override - public void onSingleTapUp(View view, int x, int y) { - mController.onSingleTapUp(view, x, y); - } - - public boolean onBackPressed() { - if (mPieRenderer != null && mPieRenderer.showsItems()) { - mPieRenderer.hide(); - return true; - } - // In image capture mode, back button should: - // 1) if there is any popup, dismiss them, 2) otherwise, get out of - // image capture - if (mController.isImageCaptureIntent()) { - if (!removeTopLevelPopup()) { - // no popup to dismiss, cancel image capture - mController.onCaptureCancelled(); - } - return true; - } else if (!mController.isCameraIdle()) { - // ignore backs while we're taking a picture - return true; - } else { - return removeTopLevelPopup(); - } - } - - public void onSwitchMode(boolean toCamera) { - if (toCamera) { - showUI(); - } else { - hideUI(); - } - if (mFaceView != null) { - mFaceView.setBlockDraw(!toCamera); - } - if (mPopup != null) { - dismissPopup(toCamera); - } - if (mGestures != null) { - mGestures.setEnabled(toCamera); - } - if (mRenderOverlay != null) { - // this can not happen in capture mode - mRenderOverlay.setVisibility(toCamera ? View.VISIBLE : View.GONE); - } - if (mPieRenderer != null) { - mPieRenderer.setBlockFocus(!toCamera); - } - setShowMenu(toCamera); - if (!toCamera && mCountDownView != null) mCountDownView.cancelCountDown(); - } - - public boolean removeTopLevelPopup() { - // Remove the top level popup or dialog box and return true if there's any - if (mPopup != null) { - dismissPopup(); - return true; - } - return false; - } - - public void showPopup(AbstractSettingPopup popup) { - hideUI(); - mBlocker.setVisibility(View.INVISIBLE); - setShowMenu(false); - mPopup = popup; - mPopup.setVisibility(View.VISIBLE); - FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - lp.gravity = Gravity.CENTER; - ((FrameLayout) mRootView).addView(mPopup, lp); - } - - public void dismissPopup() { - dismissPopup(true); - } - - private void dismissPopup(boolean fullScreen) { - if (fullScreen) { - showUI(); - mBlocker.setVisibility(View.VISIBLE); - } - setShowMenu(fullScreen); - if (mPopup != null) { - ((FrameLayout) mRootView).removeView(mPopup); - mPopup = null; - } - mMenu.popupDismissed(); - } - - public void onShowSwitcherPopup() { - if (mPieRenderer != null && mPieRenderer.showsItems()) { - mPieRenderer.hide(); - } - } - - private void setShowMenu(boolean show) { - if (mOnScreenIndicators != null) { - mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE); - } - if (mMenuButton != null) { - mMenuButton.setVisibility(show ? View.VISIBLE : View.GONE); - } - } - - public boolean collapseCameraControls() { - // Remove all the popups/dialog boxes - boolean ret = false; - if (mPopup != null) { - dismissPopup(); - ret = true; - } - onShowSwitcherPopup(); - return ret; - } - - protected void showPostCaptureAlert() { - mOnScreenIndicators.setVisibility(View.GONE); - mMenuButton.setVisibility(View.GONE); - Util.fadeIn(mReviewDoneButton); - mShutterButton.setVisibility(View.INVISIBLE); - Util.fadeIn(mReviewRetakeButton); - pauseFaceDetection(); - } - - protected void hidePostCaptureAlert() { - mOnScreenIndicators.setVisibility(View.VISIBLE); - mMenuButton.setVisibility(View.VISIBLE); - Util.fadeOut(mReviewDoneButton); - mShutterButton.setVisibility(View.VISIBLE); - Util.fadeOut(mReviewRetakeButton); - resumeFaceDetection(); - } - - public void setDisplayOrientation(int orientation) { - if (mFaceView != null) { - mFaceView.setDisplayOrientation(orientation); - } - } - - // shutter button handling - - public boolean isShutterPressed() { - return mShutterButton.isPressed(); - } - - public void enableShutter(boolean enabled) { - if (mShutterButton != null) { - mShutterButton.setEnabled(enabled); - } - } - - public void pressShutterButton() { - if (mShutterButton.isInTouchMode()) { - mShutterButton.requestFocusFromTouch(); - } else { - mShutterButton.requestFocus(); - } - mShutterButton.setPressed(true); - } - - private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener { - @Override - public void onZoomValueChanged(int index) { - int newZoom = mController.onZoomChanged(index); - if (mZoomRenderer != null) { - mZoomRenderer.setZoomValue(mZoomRatios.get(newZoom)); - } - } - - @Override - public void onZoomStart() { - if (mPieRenderer != null) { - mPieRenderer.setBlockFocus(true); - } - } - - @Override - public void onZoomEnd() { - if (mPieRenderer != null) { - mPieRenderer.setBlockFocus(false); - } - } - } - - @Override - public void onPieOpened(int centerX, int centerY) { - setSwipingEnabled(false); - dismissPopup(); - if (mFaceView != null) { - mFaceView.setBlockDraw(true); - } - } - - @Override - public void onPieClosed() { - setSwipingEnabled(true); - if (mFaceView != null) { - mFaceView.setBlockDraw(false); - } - } - - public void setSwipingEnabled(boolean enable) { - mActivity.setSwipingEnabled(enable); - } - - public Object getSurfaceTexture() { - synchronized (mLock) { - if (mSurfaceTexture == null) { - try { - mLock.wait(); - } catch (InterruptedException e) { - Log.w(TAG, "Unexpected interruption when waiting to get surface texture"); - } - } - } - return mSurfaceTexture; - } - - // Countdown timer - - private void initializeCountDown() { - mActivity.getLayoutInflater().inflate(R.layout.count_down_to_capture, - (ViewGroup) mRootView, true); - mCountDownView = (CountDownView) (mRootView.findViewById(R.id.count_down_to_capture)); - mCountDownView.setCountDownFinishedListener((OnCountDownFinishedListener) mController); - } - - public boolean isCountingDown() { - return mCountDownView != null && mCountDownView.isCountingDown(); - } - - public void cancelCountDown() { - if (mCountDownView == null) return; - mCountDownView.cancelCountDown(); - } - - public void startCountDown(int sec, boolean playSound) { - if (mCountDownView == null) initializeCountDown(); - mCountDownView.startCountDown(sec, playSound); - } - - public void showPreferencesToast() { - if (mNotSelectableToast == null) { - String str = mActivity.getResources().getString(R.string.not_selectable_in_scene_mode); - mNotSelectableToast = Toast.makeText(mActivity, str, Toast.LENGTH_SHORT); - } - mNotSelectableToast.show(); - } - - public void onPause() { - cancelCountDown(); - - // Clear UI. - collapseCameraControls(); - if (mFaceView != null) mFaceView.clear(); - - if (mLocationDialog != null && mLocationDialog.isShowing()) { - mLocationDialog.dismiss(); - } - mLocationDialog = null; - mPreviewWidth = 0; - mPreviewHeight = 0; - } - - // focus UI implementation - - private FocusIndicator getFocusIndicator() { - return (mFaceView != null && mFaceView.faceExists()) ? mFaceView : mPieRenderer; - } - - @Override - public boolean hasFaces() { - return (mFaceView != null && mFaceView.faceExists()); - } - - public void clearFaces() { - if (mFaceView != null) mFaceView.clear(); - } - - @Override - public void clearFocus() { - FocusIndicator indicator = getFocusIndicator(); - if (indicator != null) indicator.clear(); - } - - @Override - public void setFocusPosition(int x, int y) { - mPieRenderer.setFocus(x, y); - } - - @Override - public void onFocusStarted() { - getFocusIndicator().showStart(); - } - - @Override - public void onFocusSucceeded(boolean timeout) { - getFocusIndicator().showSuccess(timeout); - } - - @Override - public void onFocusFailed(boolean timeout) { - getFocusIndicator().showFail(timeout); - } - - @Override - public void pauseFaceDetection() { - if (mFaceView != null) mFaceView.pause(); - } - - @Override - public void resumeFaceDetection() { - if (mFaceView != null) mFaceView.resume(); - } - - public void onStartFaceDetection(int orientation, boolean mirror) { - mFaceView.clear(); - mFaceView.setVisibility(View.VISIBLE); - mFaceView.setDisplayOrientation(orientation); - mFaceView.setMirror(mirror); - mFaceView.resume(); - } - - @Override - public void onFaceDetection(Face[] faces, CameraManager.CameraProxy camera) { - mFaceView.setFaces(faces); - } - - public void onDisplayChanged() { - mCameraControls.checkLayoutFlip(); - mController.updateCameraOrientation(); - } - -} diff --git a/src/com/android/camera/PieController.java b/src/com/android/camera/PieController.java deleted file mode 100644 index 3cbcb4bf5..000000000 --- a/src/com/android/camera/PieController.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.app.Activity; -import android.graphics.drawable.Drawable; -import android.util.Log; - -import com.android.camera.CameraPreference.OnPreferenceChangedListener; -import com.android.camera.drawable.TextDrawable; -import com.android.camera.ui.PieItem; -import com.android.camera.ui.PieItem.OnClickListener; -import com.android.camera.ui.PieRenderer; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class PieController { - - private static String TAG = "CAM_piecontrol"; - - protected static final int MODE_PHOTO = 0; - protected static final int MODE_VIDEO = 1; - - protected static float CENTER = (float) Math.PI / 2; - protected static final float SWEEP = 0.06f; - - protected Activity mActivity; - protected PreferenceGroup mPreferenceGroup; - protected OnPreferenceChangedListener mListener; - protected PieRenderer mRenderer; - private List<IconListPreference> mPreferences; - private Map<IconListPreference, PieItem> mPreferenceMap; - private Map<IconListPreference, String> mOverrides; - - public void setListener(OnPreferenceChangedListener listener) { - mListener = listener; - } - - public PieController(Activity activity, PieRenderer pie) { - mActivity = activity; - mRenderer = pie; - mPreferences = new ArrayList<IconListPreference>(); - mPreferenceMap = new HashMap<IconListPreference, PieItem>(); - mOverrides = new HashMap<IconListPreference, String>(); - } - - public void initialize(PreferenceGroup group) { - mRenderer.clearItems(); - mPreferenceMap.clear(); - setPreferenceGroup(group); - } - - public void onSettingChanged(ListPreference pref) { - if (mListener != null) { - mListener.onSharedPreferenceChanged(); - } - } - - protected void setCameraId(int cameraId) { - ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_ID); - pref.setValue("" + cameraId); - } - - protected PieItem makeItem(int resId) { - // We need a mutable version as we change the alpha - Drawable d = mActivity.getResources().getDrawable(resId).mutate(); - return new PieItem(d, 0); - } - - protected PieItem makeItem(CharSequence value) { - TextDrawable drawable = new TextDrawable(mActivity.getResources(), value); - return new PieItem(drawable, 0); - } - - public PieItem makeItem(String prefKey) { - final IconListPreference pref = - (IconListPreference) mPreferenceGroup.findPreference(prefKey); - if (pref == null) return null; - int[] iconIds = pref.getLargeIconIds(); - int resid = -1; - if (!pref.getUseSingleIcon() && iconIds != null) { - // Each entry has a corresponding icon. - int index = pref.findIndexOfValue(pref.getValue()); - resid = iconIds[index]; - } else { - // The preference only has a single icon to represent it. - resid = pref.getSingleIcon(); - } - PieItem item = makeItem(resid); - item.setLabel(pref.getTitle().toUpperCase()); - mPreferences.add(pref); - mPreferenceMap.put(pref, item); - int nOfEntries = pref.getEntries().length; - if (nOfEntries > 1) { - for (int i = 0; i < nOfEntries; i++) { - PieItem inner = null; - if (iconIds != null) { - inner = makeItem(iconIds[i]); - } else { - inner = makeItem(pref.getEntries()[i]); - } - inner.setLabel(pref.getLabels()[i]); - item.addItem(inner); - final int index = i; - inner.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - pref.setValueIndex(index); - reloadPreference(pref); - onSettingChanged(pref); - } - }); - } - } - return item; - } - - public PieItem makeSwitchItem(final String prefKey, boolean addListener) { - final IconListPreference pref = - (IconListPreference) mPreferenceGroup.findPreference(prefKey); - if (pref == null) return null; - int[] iconIds = pref.getLargeIconIds(); - int resid = -1; - int index = pref.findIndexOfValue(pref.getValue()); - if (!pref.getUseSingleIcon() && iconIds != null) { - // Each entry has a corresponding icon. - resid = iconIds[index]; - } else { - // The preference only has a single icon to represent it. - resid = pref.getSingleIcon(); - } - PieItem item = makeItem(resid); - item.setLabel(pref.getLabels()[index]); - item.setImageResource(mActivity, resid); - mPreferences.add(pref); - mPreferenceMap.put(pref, item); - if (addListener) { - final PieItem fitem = item; - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - IconListPreference pref = (IconListPreference) mPreferenceGroup - .findPreference(prefKey); - int index = pref.findIndexOfValue(pref.getValue()); - CharSequence[] values = pref.getEntryValues(); - index = (index + 1) % values.length; - pref.setValueIndex(index); - fitem.setLabel(pref.getLabels()[index]); - fitem.setImageResource(mActivity, - ((IconListPreference) pref).getLargeIconIds()[index]); - reloadPreference(pref); - onSettingChanged(pref); - } - }); - } - return item; - } - - - public PieItem makeDialItem(ListPreference pref, int iconId, float center, float sweep) { - PieItem item = makeItem(iconId); - return item; - } - - public void addItem(String prefKey) { - PieItem item = makeItem(prefKey); - mRenderer.addItem(item); - } - - public void updateItem(PieItem item, String prefKey) { - IconListPreference pref = (IconListPreference) mPreferenceGroup - .findPreference(prefKey); - if (pref != null) { - int index = pref.findIndexOfValue(pref.getValue()); - item.setLabel(pref.getLabels()[index]); - item.setImageResource(mActivity, - ((IconListPreference) pref).getLargeIconIds()[index]); - } - } - - public void setPreferenceGroup(PreferenceGroup group) { - mPreferenceGroup = group; - } - - public void reloadPreferences() { - mPreferenceGroup.reloadValue(); - for (IconListPreference pref : mPreferenceMap.keySet()) { - reloadPreference(pref); - } - } - - private void reloadPreference(IconListPreference pref) { - if (pref.getUseSingleIcon()) return; - PieItem item = mPreferenceMap.get(pref); - String overrideValue = mOverrides.get(pref); - int[] iconIds = pref.getLargeIconIds(); - if (iconIds != null) { - // Each entry has a corresponding icon. - int index; - if (overrideValue == null) { - index = pref.findIndexOfValue(pref.getValue()); - } else { - index = pref.findIndexOfValue(overrideValue); - if (index == -1) { - // Avoid the crash if camera driver has bugs. - Log.e(TAG, "Fail to find override value=" + overrideValue); - pref.print(); - return; - } - } - item.setImageResource(mActivity, iconIds[index]); - } else { - // The preference only has a single icon to represent it. - item.setImageResource(mActivity, pref.getSingleIcon()); - } - } - - // Scene mode may override other camera settings (ex: flash mode). - public void overrideSettings(final String ... keyvalues) { - if (keyvalues.length % 2 != 0) { - throw new IllegalArgumentException(); - } - for (IconListPreference pref : mPreferenceMap.keySet()) { - override(pref, keyvalues); - } - } - - private void override(IconListPreference pref, final String ... keyvalues) { - mOverrides.remove(pref); - for (int i = 0; i < keyvalues.length; i += 2) { - String key = keyvalues[i]; - String value = keyvalues[i + 1]; - if (key.equals(pref.getKey())) { - mOverrides.put(pref, value); - PieItem item = mPreferenceMap.get(pref); - item.setEnabled(value == null); - break; - } - } - reloadPreference(pref); - } -} diff --git a/src/com/android/camera/PreferenceGroup.java b/src/com/android/camera/PreferenceGroup.java deleted file mode 100644 index 4d0519f4e..000000000 --- a/src/com/android/camera/PreferenceGroup.java +++ /dev/null @@ -1,79 +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.util.AttributeSet; - -import java.util.ArrayList; - -/** - * A collection of <code>CameraPreference</code>s. It may contain other - * <code>PreferenceGroup</code> and form a tree structure. - */ -public class PreferenceGroup extends CameraPreference { - private ArrayList<CameraPreference> list = - new ArrayList<CameraPreference>(); - - public PreferenceGroup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void addChild(CameraPreference child) { - list.add(child); - } - - public void removePreference(int index) { - list.remove(index); - } - - public CameraPreference get(int index) { - return list.get(index); - } - - public int size() { - return list.size(); - } - - @Override - public void reloadValue() { - for (CameraPreference pref : list) { - pref.reloadValue(); - } - } - - /** - * Finds the preference with the given key recursively. Returns - * <code>null</code> if cannot find. - */ - public ListPreference findPreference(String key) { - // Find a leaf preference with the given key. Currently, the base - // type of all "leaf" preference is "ListPreference". If we add some - // other types later, we need to change the code. - for (CameraPreference pref : list) { - if (pref instanceof ListPreference) { - ListPreference listPref = (ListPreference) pref; - if(listPref.getKey().equals(key)) return listPref; - } else if(pref instanceof PreferenceGroup) { - ListPreference listPref = - ((PreferenceGroup) pref).findPreference(key); - if (listPref != null) return listPref; - } - } - return null; - } -} diff --git a/src/com/android/camera/PreferenceInflater.java b/src/com/android/camera/PreferenceInflater.java deleted file mode 100644 index 231c9833b..000000000 --- a/src/com/android/camera/PreferenceInflater.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2010 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.util.Xml; -import android.view.InflateException; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Inflate <code>CameraPreference</code> from XML resource. - */ -public class PreferenceInflater { - private static final String PACKAGE_NAME = - PreferenceInflater.class.getPackage().getName(); - - private static final Class<?>[] CTOR_SIGNATURE = - new Class[] {Context.class, AttributeSet.class}; - private static final HashMap<String, Constructor<?>> sConstructorMap = - new HashMap<String, Constructor<?>>(); - - private Context mContext; - - public PreferenceInflater(Context context) { - mContext = context; - } - - public CameraPreference inflate(int resId) { - return inflate(mContext.getResources().getXml(resId)); - } - - private CameraPreference newPreference(String tagName, Object[] args) { - String name = PACKAGE_NAME + "." + tagName; - Constructor<?> constructor = sConstructorMap.get(name); - try { - if (constructor == null) { - // Class not found in the cache, see if it's real, and try to - // add it - Class<?> clazz = mContext.getClassLoader().loadClass(name); - constructor = clazz.getConstructor(CTOR_SIGNATURE); - sConstructorMap.put(name, constructor); - } - return (CameraPreference) constructor.newInstance(args); - } catch (NoSuchMethodException e) { - throw new InflateException("Error inflating class " + name, e); - } catch (ClassNotFoundException e) { - throw new InflateException("No such class: " + name, e); - } catch (Exception e) { - throw new InflateException("While create instance of" + name, e); - } - } - - private CameraPreference inflate(XmlPullParser parser) { - - AttributeSet attrs = Xml.asAttributeSet(parser); - ArrayList<CameraPreference> list = new ArrayList<CameraPreference>(); - Object args[] = new Object[]{mContext, attrs}; - - try { - for (int type = parser.next(); - type != XmlPullParser.END_DOCUMENT; type = parser.next()) { - if (type != XmlPullParser.START_TAG) continue; - CameraPreference pref = newPreference(parser.getName(), args); - - int depth = parser.getDepth(); - if (depth > list.size()) { - list.add(pref); - } else { - list.set(depth - 1, pref); - } - if (depth > 1) { - ((PreferenceGroup) list.get(depth - 2)).addChild(pref); - } - } - - if (list.size() == 0) { - throw new InflateException("No root element found"); - } - return list.get(0); - } catch (XmlPullParserException e) { - throw new InflateException(e); - } catch (IOException e) { - throw new InflateException(parser.getPositionDescription(), e); - } - } -} diff --git a/src/com/android/camera/PreviewFrameLayout.java b/src/com/android/camera/PreviewFrameLayout.java deleted file mode 100644 index 03ef91c60..000000000 --- a/src/com/android/camera/PreviewFrameLayout.java +++ /dev/null @@ -1,136 +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.content.res.Configuration; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewStub; -import android.widget.RelativeLayout; - -import com.android.camera.ui.LayoutChangeHelper; -import com.android.camera.ui.LayoutChangeNotifier; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -/** - * A layout which handles the preview aspect ratio. - */ -public class PreviewFrameLayout extends RelativeLayout implements LayoutChangeNotifier { - - private static final String TAG = "CAM_preview"; - - /** A callback to be invoked when the preview frame's size changes. */ - public interface OnSizeChangedListener { - public void onSizeChanged(int width, int height); - } - - private double mAspectRatio; - private View mBorder; - private OnSizeChangedListener mListener; - private LayoutChangeHelper mLayoutChangeHelper; - - public PreviewFrameLayout(Context context, AttributeSet attrs) { - super(context, attrs); - setAspectRatio(4.0 / 3.0); - mLayoutChangeHelper = new LayoutChangeHelper(this); - } - - @Override - protected void onFinishInflate() { - mBorder = findViewById(R.id.preview_border); - } - - public void setAspectRatio(double ratio) { - if (ratio <= 0.0) throw new IllegalArgumentException(); - - if (mAspectRatio != ratio) { - mAspectRatio = ratio; - requestLayout(); - } - } - - public void showBorder(boolean enabled) { - mBorder.setVisibility(enabled ? View.VISIBLE : View.INVISIBLE); - } - - public void fadeOutBorder() { - Util.fadeOut(mBorder); - } - - @Override - protected void onMeasure(int widthSpec, int heightSpec) { - int previewWidth = MeasureSpec.getSize(widthSpec); - int previewHeight = MeasureSpec.getSize(heightSpec); - - if (!ApiHelper.HAS_SURFACE_TEXTURE) { - // Get the padding of the border background. - int hPadding = getPaddingLeft() + getPaddingRight(); - int vPadding = getPaddingTop() + getPaddingBottom(); - - // Resize the preview frame with correct aspect ratio. - previewWidth -= hPadding; - previewHeight -= vPadding; - - boolean widthLonger = previewWidth > previewHeight; - int longSide = (widthLonger ? previewWidth : previewHeight); - int shortSide = (widthLonger ? previewHeight : previewWidth); - if (longSide > shortSide * mAspectRatio) { - longSide = (int) ((double) shortSide * mAspectRatio); - } else { - shortSide = (int) ((double) longSide / mAspectRatio); - } - if (widthLonger) { - previewWidth = longSide; - previewHeight = shortSide; - } else { - previewWidth = shortSide; - previewHeight = longSide; - } - - // Add the padding of the border. - previewWidth += hPadding; - previewHeight += vPadding; - } - - // Ask children to follow the new preview dimension. - super.onMeasure(MeasureSpec.makeMeasureSpec(previewWidth, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(previewHeight, MeasureSpec.EXACTLY)); - } - - public void setOnSizeChangedListener(OnSizeChangedListener listener) { - mListener = listener; - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - if (mListener != null) mListener.onSizeChanged(w, h); - } - - @Override - public void setOnLayoutChangeListener( - LayoutChangeNotifier.Listener listener) { - mLayoutChangeHelper.setOnLayoutChangeListener(listener); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - mLayoutChangeHelper.onLayout(changed, l, t, r, b); - } -} diff --git a/src/com/android/camera/PreviewGestures.java b/src/com/android/camera/PreviewGestures.java deleted file mode 100644 index 466172b7c..000000000 --- a/src/com/android/camera/PreviewGestures.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2013 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.view.GestureDetector; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; -import android.view.View; - -import com.android.camera.ui.PieRenderer; -import com.android.camera.ui.RenderOverlay; -import com.android.camera.ui.ZoomRenderer; - -/* PreviewGestures disambiguates touch events received on RenderOverlay - * and dispatch them to the proper recipient (i.e. zoom renderer or pie renderer). - * Touch events on CameraControls will be handled by framework. - * */ -public class PreviewGestures - implements ScaleGestureDetector.OnScaleGestureListener { - - private static final String TAG = "CAM_gestures"; - - private static final int MODE_NONE = 0; - private static final int MODE_ZOOM = 2; - - public static final int DIR_UP = 0; - public static final int DIR_DOWN = 1; - public static final int DIR_LEFT = 2; - public static final int DIR_RIGHT = 3; - - private SingleTapListener mTapListener; - private RenderOverlay mOverlay; - private PieRenderer mPie; - private ZoomRenderer mZoom; - private MotionEvent mDown; - private MotionEvent mCurrent; - private ScaleGestureDetector mScale; - private int mMode; - private boolean mZoomEnabled; - private boolean mEnabled; - private boolean mZoomOnly; - private GestureDetector mGestureDetector; - - private GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() { - @Override - public void onLongPress (MotionEvent e) { - // Open pie - if (!mZoomOnly && mPie != null && !mPie.showsItems()) { - openPie(); - } - } - - @Override - public boolean onSingleTapUp (MotionEvent e) { - // Tap to focus when pie is not open - if (mPie == null || !mPie.showsItems()) { - mTapListener.onSingleTapUp(null, (int) e.getX(), (int) e.getY()); - return true; - } - return false; - } - - @Override - public boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - if (mZoomOnly || mMode == MODE_ZOOM) return false; - int deltaX = (int) (e1.getX() - e2.getX()); - int deltaY = (int) (e1.getY() - e2.getY()); - if (deltaY > 2 * deltaX && deltaY > -2 * deltaX) { - // Open pie on swipe up - if (mPie != null && !mPie.showsItems()) { - openPie(); - return true; - } - } - return false; - } - }; - - public interface SingleTapListener { - public void onSingleTapUp(View v, int x, int y); - } - - public PreviewGestures(CameraActivity ctx, SingleTapListener tapListener, - ZoomRenderer zoom, PieRenderer pie) { - mTapListener = tapListener; - mPie = pie; - mZoom = zoom; - mMode = MODE_NONE; - mScale = new ScaleGestureDetector(ctx, this); - mEnabled = true; - mGestureDetector = new GestureDetector(mGestureListener); - } - - public void setRenderOverlay(RenderOverlay overlay) { - mOverlay = overlay; - } - - public void setEnabled(boolean enabled) { - mEnabled = enabled; - } - - public void setZoomEnabled(boolean enable) { - mZoomEnabled = enable; - } - - public void setZoomOnly(boolean zoom) { - mZoomOnly = zoom; - } - - public boolean isEnabled() { - return mEnabled; - } - - public boolean dispatchTouch(MotionEvent m) { - if (!mEnabled) { - return false; - } - mCurrent = m; - if (MotionEvent.ACTION_DOWN == m.getActionMasked()) { - mMode = MODE_NONE; - mDown = MotionEvent.obtain(m); - } - - // If pie is open, redirects all the touch events to pie. - if (mPie != null && mPie.isOpen()) { - return sendToPie(m); - } - - // If pie is not open, send touch events to gesture detector and scale - // listener to recognize the gesture. - mGestureDetector.onTouchEvent(m); - if (mZoom != null) { - mScale.onTouchEvent(m); - if (MotionEvent.ACTION_POINTER_DOWN == m.getActionMasked()) { - mMode = MODE_ZOOM; - if (mZoomEnabled) { - // Start showing zoom UI as soon as there is a second finger down - mZoom.onScaleBegin(mScale); - } - } else if (MotionEvent.ACTION_POINTER_UP == m.getActionMasked()) { - mZoom.onScaleEnd(mScale); - } - } - return true; - } - - private MotionEvent makeCancelEvent(MotionEvent m) { - MotionEvent c = MotionEvent.obtain(m); - c.setAction(MotionEvent.ACTION_CANCEL); - return c; - } - - private void openPie() { - mGestureDetector.onTouchEvent(makeCancelEvent(mDown)); - mScale.onTouchEvent(makeCancelEvent(mDown)); - mOverlay.directDispatchTouch(mDown, mPie); - } - - private boolean sendToPie(MotionEvent m) { - return mOverlay.directDispatchTouch(m, mPie); - } - - // OnScaleGestureListener implementation - @Override - public boolean onScale(ScaleGestureDetector detector) { - return mZoom.onScale(detector); - } - - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - if (mPie == null || !mPie.isOpen()) { - mMode = MODE_ZOOM; - mGestureDetector.onTouchEvent(makeCancelEvent(mCurrent)); - if (!mZoomEnabled) return false; - return mZoom.onScaleBegin(detector); - } - return false; - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - mZoom.onScaleEnd(detector); - } -} - diff --git a/src/com/android/camera/ProxyLauncher.java b/src/com/android/camera/ProxyLauncher.java deleted file mode 100644 index 8c566214c..000000000 --- a/src/com/android/camera/ProxyLauncher.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; - -public class ProxyLauncher extends Activity { - - public static final int RESULT_USER_CANCELED = -2; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - if (savedInstanceState == null) { - Intent intent = getIntent().getParcelableExtra(Intent.EXTRA_INTENT); - startActivityForResult(intent, 0); - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - if (resultCode == RESULT_CANCELED) { - resultCode = RESULT_USER_CANCELED; - } - setResult(resultCode, data); - finish(); - } - -} diff --git a/src/com/android/camera/RecordLocationPreference.java b/src/com/android/camera/RecordLocationPreference.java deleted file mode 100644 index 9992afabb..000000000 --- a/src/com/android/camera/RecordLocationPreference.java +++ /dev/null @@ -1,58 +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.Context; -import android.content.SharedPreferences; -import android.util.AttributeSet; - -/** - * {@code RecordLocationPreference} is used to keep the "store locaiton" - * option in {@code SharedPreference}. - */ -public class RecordLocationPreference extends IconListPreference { - - public static final String VALUE_NONE = "none"; - public static final String VALUE_ON = "on"; - public static final String VALUE_OFF = "off"; - - private final ContentResolver mResolver; - - public RecordLocationPreference(Context context, AttributeSet attrs) { - super(context, attrs); - mResolver = context.getContentResolver(); - } - - @Override - public String getValue() { - return get(getSharedPreferences(), mResolver) ? VALUE_ON : VALUE_OFF; - } - - public static boolean get( - SharedPreferences pref, ContentResolver resolver) { - String value = pref.getString( - CameraSettings.KEY_RECORD_LOCATION, VALUE_NONE); - return VALUE_ON.equals(value); - } - - public static boolean isSet(SharedPreferences pref) { - String value = pref.getString( - CameraSettings.KEY_RECORD_LOCATION, VALUE_NONE); - return !VALUE_NONE.equals(value); - } -} diff --git a/src/com/android/camera/RotateDialogController.java b/src/com/android/camera/RotateDialogController.java deleted file mode 100644 index 5d5e5e70f..000000000 --- a/src/com/android/camera/RotateDialogController.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.app.Activity; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.widget.Button; -import android.widget.ProgressBar; -import android.widget.TextView; - -import com.android.camera.ui.Rotatable; -import com.android.camera.ui.RotateLayout; -import com.android.gallery3d.R; - -public class RotateDialogController implements Rotatable { - - @SuppressWarnings("unused") - private static final String TAG = "RotateDialogController"; - private static final long ANIM_DURATION = 150; // millis - - private Activity mActivity; - private int mLayoutResourceID; - private View mDialogRootLayout; - private RotateLayout mRotateDialog; - private View mRotateDialogTitleLayout; - private View mRotateDialogButtonLayout; - private TextView mRotateDialogTitle; - private ProgressBar mRotateDialogSpinner; - private TextView mRotateDialogText; - private TextView mRotateDialogButton1; - private TextView mRotateDialogButton2; - - private Animation mFadeInAnim, mFadeOutAnim; - - public RotateDialogController(Activity a, int layoutResource) { - mActivity = a; - mLayoutResourceID = layoutResource; - } - - private void inflateDialogLayout() { - if (mDialogRootLayout == null) { - ViewGroup layoutRoot = (ViewGroup) mActivity.getWindow().getDecorView(); - LayoutInflater inflater = mActivity.getLayoutInflater(); - View v = inflater.inflate(mLayoutResourceID, layoutRoot); - mDialogRootLayout = v.findViewById(R.id.rotate_dialog_root_layout); - mRotateDialog = (RotateLayout) v.findViewById(R.id.rotate_dialog_layout); - mRotateDialogTitleLayout = v.findViewById(R.id.rotate_dialog_title_layout); - mRotateDialogButtonLayout = v.findViewById(R.id.rotate_dialog_button_layout); - mRotateDialogTitle = (TextView) v.findViewById(R.id.rotate_dialog_title); - mRotateDialogSpinner = (ProgressBar) v.findViewById(R.id.rotate_dialog_spinner); - mRotateDialogText = (TextView) v.findViewById(R.id.rotate_dialog_text); - mRotateDialogButton1 = (Button) v.findViewById(R.id.rotate_dialog_button1); - mRotateDialogButton2 = (Button) v.findViewById(R.id.rotate_dialog_button2); - - mFadeInAnim = AnimationUtils.loadAnimation( - mActivity, android.R.anim.fade_in); - mFadeOutAnim = AnimationUtils.loadAnimation( - mActivity, android.R.anim.fade_out); - mFadeInAnim.setDuration(ANIM_DURATION); - mFadeOutAnim.setDuration(ANIM_DURATION); - } - } - - @Override - public void setOrientation(int orientation, boolean animation) { - inflateDialogLayout(); - mRotateDialog.setOrientation(orientation, animation); - } - - public void resetRotateDialog() { - inflateDialogLayout(); - mRotateDialogTitleLayout.setVisibility(View.GONE); - mRotateDialogSpinner.setVisibility(View.GONE); - mRotateDialogButton1.setVisibility(View.GONE); - mRotateDialogButton2.setVisibility(View.GONE); - mRotateDialogButtonLayout.setVisibility(View.GONE); - } - - private void fadeOutDialog() { - mDialogRootLayout.startAnimation(mFadeOutAnim); - mDialogRootLayout.setVisibility(View.GONE); - } - - private void fadeInDialog() { - mDialogRootLayout.startAnimation(mFadeInAnim); - mDialogRootLayout.setVisibility(View.VISIBLE); - } - - public void dismissDialog() { - if (mDialogRootLayout != null && mDialogRootLayout.getVisibility() != View.GONE) { - fadeOutDialog(); - } - } - - public void showAlertDialog(String title, String msg, String button1Text, - final Runnable r1, String button2Text, final Runnable r2) { - resetRotateDialog(); - - if (title != null) { - mRotateDialogTitle.setText(title); - mRotateDialogTitleLayout.setVisibility(View.VISIBLE); - } - - mRotateDialogText.setText(msg); - - if (button1Text != null) { - mRotateDialogButton1.setText(button1Text); - mRotateDialogButton1.setContentDescription(button1Text); - mRotateDialogButton1.setVisibility(View.VISIBLE); - mRotateDialogButton1.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (r1 != null) r1.run(); - dismissDialog(); - } - }); - mRotateDialogButtonLayout.setVisibility(View.VISIBLE); - } - if (button2Text != null) { - mRotateDialogButton2.setText(button2Text); - mRotateDialogButton2.setContentDescription(button2Text); - mRotateDialogButton2.setVisibility(View.VISIBLE); - mRotateDialogButton2.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (r2 != null) r2.run(); - dismissDialog(); - } - }); - mRotateDialogButtonLayout.setVisibility(View.VISIBLE); - } - - fadeInDialog(); - } - - public void showWaitingDialog(String msg) { - resetRotateDialog(); - - mRotateDialogText.setText(msg); - mRotateDialogSpinner.setVisibility(View.VISIBLE); - - fadeInDialog(); - } - - public int getVisibility() { - if (mDialogRootLayout != null) { - return mDialogRootLayout.getVisibility(); - } - return View.INVISIBLE; - } -} diff --git a/src/com/android/camera/SecureCameraActivity.java b/src/com/android/camera/SecureCameraActivity.java deleted file mode 100644 index 2fa68f8e6..000000000 --- a/src/com/android/camera/SecureCameraActivity.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -// Use a different activity for secure camera only. So it can have a different -// task affinity from others. This makes sure non-secure camera activity is not -// started in secure lock screen. -public class SecureCameraActivity extends CameraActivity { -} diff --git a/src/com/android/camera/ShutterButton.java b/src/com/android/camera/ShutterButton.java deleted file mode 100755 index a1bbb1a0d..000000000 --- a/src/com/android/camera/ShutterButton.java +++ /dev/null @@ -1,130 +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.view.MotionEvent; -import android.view.View; -import android.widget.ImageView; - -/** - * A button designed to be used for the on-screen shutter button. - * It's currently an {@code ImageView} that can call a delegate when the - * pressed state changes. - */ -public class ShutterButton extends ImageView { - - private boolean mTouchEnabled = true; - - /** - * A callback to be invoked when a ShutterButton's pressed state changes. - */ - public interface OnShutterButtonListener { - /** - * Called when a ShutterButton has been pressed. - * - * @param pressed The ShutterButton that was pressed. - */ - void onShutterButtonFocus(boolean pressed); - void onShutterButtonClick(); - } - - private OnShutterButtonListener mListener; - private boolean mOldPressed; - - public ShutterButton(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void setOnShutterButtonListener(OnShutterButtonListener listener) { - mListener = listener; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent m) { - if (mTouchEnabled) { - return super.dispatchTouchEvent(m); - } else { - return false; - } - } - - public void enableTouch(boolean enable) { - mTouchEnabled = enable; - } - - /** - * 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 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() { - @Override - public void run() { - callShutterButtonFocus(pressed); - } - }); - } else { - callShutterButtonFocus(pressed); - } - mOldPressed = pressed; - } - } - - private void callShutterButtonFocus(boolean pressed) { - if (mListener != null) { - mListener.onShutterButtonFocus(pressed); - } - } - - @Override - public boolean performClick() { - boolean result = super.performClick(); - if (mListener != null && getVisibility() == View.VISIBLE) { - mListener.onShutterButtonClick(); - } - return result; - } -} diff --git a/src/com/android/camera/SoundClips.java b/src/com/android/camera/SoundClips.java deleted file mode 100644 index 8155c03dc..000000000 --- a/src/com/android/camera/SoundClips.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.annotation.TargetApi; -import android.content.Context; -import android.media.AudioManager; -import android.media.MediaActionSound; -import android.media.SoundPool; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -/* - * This class controls the sound playback according to the API level. - */ -public class SoundClips { - // Sound actions. - public static final int FOCUS_COMPLETE = 0; - public static final int START_VIDEO_RECORDING = 1; - public static final int STOP_VIDEO_RECORDING = 2; - - public interface Player { - public void release(); - public void play(int action); - } - - public static Player getPlayer(Context context) { - if (ApiHelper.HAS_MEDIA_ACTION_SOUND) { - return new MediaActionSoundPlayer(); - } else { - return new SoundPoolPlayer(context); - } - } - - public static int getAudioTypeForSoundPool() { - return ApiHelper.getIntFieldIfExists(AudioManager.class, - "STREAM_SYSTEM_ENFORCED", null, AudioManager.STREAM_RING); - } - - /** - * This class implements SoundClips.Player using MediaActionSound, - * which exists since API level 16. - */ - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private static class MediaActionSoundPlayer implements Player { - private static final String TAG = "MediaActionSoundPlayer"; - private MediaActionSound mSound; - - @Override - public void release() { - if (mSound != null) { - mSound.release(); - mSound = null; - } - } - - public MediaActionSoundPlayer() { - mSound = new MediaActionSound(); - mSound.load(MediaActionSound.START_VIDEO_RECORDING); - mSound.load(MediaActionSound.STOP_VIDEO_RECORDING); - mSound.load(MediaActionSound.FOCUS_COMPLETE); - } - - @Override - public synchronized void play(int action) { - switch(action) { - case FOCUS_COMPLETE: - mSound.play(MediaActionSound.FOCUS_COMPLETE); - break; - case START_VIDEO_RECORDING: - mSound.play(MediaActionSound.START_VIDEO_RECORDING); - break; - case STOP_VIDEO_RECORDING: - mSound.play(MediaActionSound.STOP_VIDEO_RECORDING); - break; - default: - Log.w(TAG, "Unrecognized action:" + action); - } - } - } - - /** - * This class implements SoundClips.Player using SoundPool, which - * exists since API level 1. - */ - private static class SoundPoolPlayer implements - Player, SoundPool.OnLoadCompleteListener { - - private static final String TAG = "SoundPoolPlayer"; - private static final int NUM_SOUND_STREAMS = 1; - private static final int[] SOUND_RES = { // Soundtrack res IDs. - R.raw.focus_complete, - R.raw.video_record - }; - - // ID returned by load() should be non-zero. - private static final int ID_NOT_LOADED = 0; - - // Maps a sound action to the id; - private final int[] mSoundRes = {0, 1, 1}; - // Store the context for lazy loading. - private Context mContext; - // mSoundPool is created every time load() is called and cleared every - // time release() is called. - private SoundPool mSoundPool; - // Sound ID of each sound resources. Given when the sound is loaded. - private final int[] mSoundIDs; - private final boolean[] mSoundIDReady; - private int mSoundIDToPlay; - - public SoundPoolPlayer(Context context) { - mContext = context; - - mSoundIDToPlay = ID_NOT_LOADED; - - mSoundPool = new SoundPool(NUM_SOUND_STREAMS, getAudioTypeForSoundPool(), 0); - mSoundPool.setOnLoadCompleteListener(this); - - mSoundIDs = new int[SOUND_RES.length]; - mSoundIDReady = new boolean[SOUND_RES.length]; - for (int i = 0; i < SOUND_RES.length; i++) { - mSoundIDs[i] = mSoundPool.load(mContext, SOUND_RES[i], 1); - mSoundIDReady[i] = false; - } - } - - @Override - public synchronized void release() { - if (mSoundPool != null) { - mSoundPool.release(); - mSoundPool = null; - } - } - - @Override - public synchronized void play(int action) { - if (action < 0 || action >= mSoundRes.length) { - Log.e(TAG, "Resource ID not found for action:" + action + " in play()."); - return; - } - - int index = mSoundRes[action]; - if (mSoundIDs[index] == ID_NOT_LOADED) { - // Not loaded yet, load first and then play when the loading is complete. - mSoundIDs[index] = mSoundPool.load(mContext, SOUND_RES[index], 1); - mSoundIDToPlay = mSoundIDs[index]; - } else if (!mSoundIDReady[index]) { - // Loading and not ready yet. - mSoundIDToPlay = mSoundIDs[index]; - } else { - mSoundPool.play(mSoundIDs[index], 1f, 1f, 0, 0, 1f); - } - } - - @Override - public void onLoadComplete(SoundPool pool, int soundID, int status) { - if (status != 0) { - Log.e(TAG, "loading sound tracks failed (status=" + status + ")"); - for (int i = 0; i < mSoundIDs.length; i++ ) { - if (mSoundIDs[i] == soundID) { - mSoundIDs[i] = ID_NOT_LOADED; - break; - } - } - return; - } - - for (int i = 0; i < mSoundIDs.length; i++ ) { - if (mSoundIDs[i] == soundID) { - mSoundIDReady[i] = true; - break; - } - } - - if (soundID == mSoundIDToPlay) { - mSoundIDToPlay = ID_NOT_LOADED; - mSoundPool.play(soundID, 1f, 1f, 0, 0, 1f); - } - } - } -} diff --git a/src/com/android/camera/StaticBitmapScreenNail.java b/src/com/android/camera/StaticBitmapScreenNail.java deleted file mode 100644 index 10788c0fb..000000000 --- a/src/com/android/camera/StaticBitmapScreenNail.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.graphics.Bitmap; - -import com.android.gallery3d.ui.BitmapScreenNail; - -public class StaticBitmapScreenNail extends BitmapScreenNail { - public StaticBitmapScreenNail(Bitmap bitmap) { - super(bitmap); - } - - @Override - public void recycle() { - // Always keep the bitmap in memory. - } -} diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java deleted file mode 100644 index ba995edef..000000000 --- a/src/com/android/camera/Storage.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2010 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.annotation.TargetApi; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.location.Location; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.os.StatFs; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.provider.MediaStore.MediaColumns; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.exif.ExifInterface; - -import java.io.File; -import java.io.FileOutputStream; - -public class Storage { - private static final String TAG = "CameraStorage"; - - public static final String DCIM = - Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString(); - - public static final String DIRECTORY = DCIM + "/Camera"; - - // Match the code in MediaProvider.computeBucketValues(). - public static final String BUCKET_ID = - String.valueOf(DIRECTORY.toLowerCase().hashCode()); - - public static final long UNAVAILABLE = -1L; - public static final long PREPARING = -2L; - public static final long UNKNOWN_SIZE = -3L; - public static final long LOW_STORAGE_THRESHOLD = 50000000; - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private static void setImageSize(ContentValues values, int width, int height) { - // The two fields are available since ICS but got published in JB - if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) { - values.put(MediaColumns.WIDTH, width); - values.put(MediaColumns.HEIGHT, height); - } - } - - public static void writeFile(String path, byte[] data) { - FileOutputStream out = null; - try { - out = new FileOutputStream(path); - out.write(data); - } catch (Exception e) { - Log.e(TAG, "Failed to write data", e); - } finally { - try { - out.close(); - } catch (Exception e) { - } - } - } - - // Save the image and add it to media store. - public static Uri addImage(ContentResolver resolver, String title, - long date, Location location, int orientation, ExifInterface exif, - byte[] jpeg, int width, int height) { - // Save the image. - String path = generateFilepath(title); - if (exif != null) { - try { - exif.writeExif(jpeg, path); - } catch (Exception e) { - Log.e(TAG, "Failed to write data", e); - } - } else { - writeFile(path, jpeg); - } - return addImage(resolver, title, date, location, orientation, - jpeg.length, path, width, height); - } - - // Add the image to media store. - public static Uri addImage(ContentResolver resolver, String title, - long date, Location location, int orientation, int jpegLength, - String path, int width, int height) { - // Insert into MediaStore. - ContentValues values = new ContentValues(9); - values.put(ImageColumns.TITLE, title); - values.put(ImageColumns.DISPLAY_NAME, title + ".jpg"); - values.put(ImageColumns.DATE_TAKEN, date); - values.put(ImageColumns.MIME_TYPE, "image/jpeg"); - // Clockwise rotation in degrees. 0, 90, 180, or 270. - values.put(ImageColumns.ORIENTATION, orientation); - values.put(ImageColumns.DATA, path); - values.put(ImageColumns.SIZE, jpegLength); - - setImageSize(values, width, height); - - if (location != null) { - values.put(ImageColumns.LATITUDE, location.getLatitude()); - values.put(ImageColumns.LONGITUDE, location.getLongitude()); - } - - Uri uri = null; - try { - uri = resolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values); - } catch (Throwable th) { - // This can happen when the external volume is already mounted, but - // MediaScanner has not notify MediaProvider to add that volume. - // The picture is still safe and MediaScanner will find it and - // insert it into MediaProvider. The only problem is that the user - // cannot click the thumbnail to review the picture. - Log.e(TAG, "Failed to write MediaStore" + th); - } - return uri; - } - - public static void deleteImage(ContentResolver resolver, Uri uri) { - try { - resolver.delete(uri, null, null); - } catch (Throwable th) { - Log.e(TAG, "Failed to delete image: " + uri); - } - } - - public static String generateFilepath(String title) { - return DIRECTORY + '/' + title + ".jpg"; - } - - public static long getAvailableSpace() { - String state = Environment.getExternalStorageState(); - Log.d(TAG, "External storage state=" + state); - if (Environment.MEDIA_CHECKING.equals(state)) { - return PREPARING; - } - if (!Environment.MEDIA_MOUNTED.equals(state)) { - return UNAVAILABLE; - } - - File dir = new File(DIRECTORY); - dir.mkdirs(); - if (!dir.isDirectory() || !dir.canWrite()) { - return UNAVAILABLE; - } - - try { - StatFs stat = new StatFs(DIRECTORY); - return stat.getAvailableBlocks() * (long) stat.getBlockSize(); - } catch (Exception e) { - Log.i(TAG, "Fail to access external storage", e); - } - return UNKNOWN_SIZE; - } - - /** - * OSX requires plugged-in USB storage to have path /DCIM/NNNAAAAA to be - * imported. This is a temporary fix for bug#1655552. - */ - public static void ensureOSXCompatible() { - File nnnAAAAA = new File(DCIM, "100ANDRO"); - if (!(nnnAAAAA.exists() || nnnAAAAA.mkdirs())) { - Log.e(TAG, "Failed to create " + nnnAAAAA.getPath()); - } - } -} diff --git a/src/com/android/camera/SurfaceTextureRenderer.java b/src/com/android/camera/SurfaceTextureRenderer.java deleted file mode 100644 index 66f7aa219..000000000 --- a/src/com/android/camera/SurfaceTextureRenderer.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.graphics.SurfaceTexture; -import android.os.Handler; -import android.util.Log; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL10; - -public class SurfaceTextureRenderer { - - public interface FrameDrawer { - public void onDrawFrame(GL10 gl); - } - - private static final String TAG = "CAM_" + SurfaceTextureRenderer.class.getSimpleName(); - private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - - private EGLConfig mEglConfig; - private EGLDisplay mEglDisplay; - private EGLContext mEglContext; - private EGLSurface mEglSurface; - private EGL10 mEgl; - private GL10 mGl; - - private Handler mEglHandler; - private FrameDrawer mFrameDrawer; - - private Object mRenderLock = new Object(); - private Runnable mRenderTask = new Runnable() { - @Override - public void run() { - synchronized (mRenderLock) { - mFrameDrawer.onDrawFrame(mGl); - mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); - mRenderLock.notifyAll(); - } - } - }; - - public class RenderThread extends Thread { - private Boolean mRenderStopped = false; - - @Override - public void run() { - while (true) { - synchronized (mRenderStopped) { - if (mRenderStopped) return; - } - draw(true); - } - } - - public void stopRender() { - synchronized (mRenderStopped) { - mRenderStopped = true; - } - } - } - - public SurfaceTextureRenderer(SurfaceTexture tex, - Handler handler, FrameDrawer renderer) { - mEglHandler = handler; - mFrameDrawer = renderer; - - initialize(tex); - } - - public RenderThread createRenderThread() { - return new RenderThread(); - } - - public void release() { - mEglHandler.post(new Runnable() { - @Override - public void run() { - mEgl.eglDestroySurface(mEglDisplay, mEglSurface); - mEgl.eglDestroyContext(mEglDisplay, mEglContext); - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_CONTEXT); - mEgl.eglTerminate(mEglDisplay); - mEglSurface = null; - mEglContext = null; - mEglDisplay = null; - } - }); - } - - /** - * Posts a render request to the GL thread. - * @param sync set <code>true</code> if the caller needs it to be - * a synchronous call. - */ - public void draw(boolean sync) { - synchronized (mRenderLock) { - mEglHandler.post(mRenderTask); - if (sync) { - try { - mRenderLock.wait(); - } catch (InterruptedException ex) { - Log.v(TAG, "RenderLock.wait() interrupted"); - } - } - } - } - - private void initialize(final SurfaceTexture target) { - mEglHandler.post(new Runnable() { - @Override - public void run() { - mEgl = (EGL10) EGLContext.getEGL(); - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { - throw new RuntimeException("eglGetDisplay failed"); - } - int[] version = new int[2]; - if (!mEgl.eglInitialize(mEglDisplay, version)) { - throw new RuntimeException("eglInitialize failed"); - } else { - Log.v(TAG, "EGL version: " + version[0] + '.' + version[1]); - } - int[] attribList = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; - mEglConfig = chooseConfig(mEgl, mEglDisplay); - mEglContext = mEgl.eglCreateContext( - mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, attribList); - - if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { - throw new RuntimeException("failed to createContext"); - } - mEglSurface = mEgl.eglCreateWindowSurface( - mEglDisplay, mEglConfig, target, null); - if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { - throw new RuntimeException("failed to createWindowSurface"); - } - - if (!mEgl.eglMakeCurrent( - mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { - throw new RuntimeException("failed to eglMakeCurrent"); - } - - mGl = (GL10) mEglContext.getGL(); - } - }); - waitDone(); - } - - private void waitDone() { - final Object lock = new Object(); - synchronized (lock) { - mEglHandler.post(new Runnable() { - @Override - public void run() { - synchronized (lock) { - lock.notifyAll(); - } - } - }); - try { - lock.wait(); - } catch (InterruptedException ex) { - Log.v(TAG, "waitDone() interrupted"); - } - } - } - - private static void checkEglError(String prompt, EGL10 egl) { - int error; - while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) { - Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error)); - } - } - - private static final int EGL_OPENGL_ES2_BIT = 4; - private static final int[] CONFIG_SPEC = new int[] { - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_RED_SIZE, 8, - EGL10.EGL_GREEN_SIZE, 8, - EGL10.EGL_BLUE_SIZE, 8, - EGL10.EGL_ALPHA_SIZE, 0, - EGL10.EGL_DEPTH_SIZE, 0, - EGL10.EGL_STENCIL_SIZE, 0, - EGL10.EGL_NONE - }; - - private static EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) { - int[] numConfig = new int[1]; - if (!egl.eglChooseConfig(display, CONFIG_SPEC, null, 0, numConfig)) { - throw new IllegalArgumentException("eglChooseConfig failed"); - } - - int numConfigs = numConfig[0]; - if (numConfigs <= 0) { - throw new IllegalArgumentException("No configs match configSpec"); - } - - EGLConfig[] configs = new EGLConfig[numConfigs]; - if (!egl.eglChooseConfig( - display, CONFIG_SPEC, configs, numConfigs, numConfig)) { - throw new IllegalArgumentException("eglChooseConfig#2 failed"); - } - - return configs[0]; - } -} diff --git a/src/com/android/camera/SwitchAnimManager.java b/src/com/android/camera/SwitchAnimManager.java deleted file mode 100644 index 6ec88223e..000000000 --- a/src/com/android/camera/SwitchAnimManager.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.os.SystemClock; -import android.util.Log; - -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; - -/** - * Class to handle the animation when switching between back and front cameras. - * An image of the previous camera zooms in and fades out. The preview of the - * new camera zooms in and fades in. The image of the previous camera is called - * review in this class. - */ -public class SwitchAnimManager { - private static final String TAG = "SwitchAnimManager"; - // The amount of change for zooming in and out. - private static final float ZOOM_DELTA_PREVIEW = 0.2f; - private static final float ZOOM_DELTA_REVIEW = 0.5f; - private static final float ANIMATION_DURATION = 400; // ms - public static final float INITIAL_DARKEN_ALPHA = 0.8f; - - private long mAnimStartTime; // milliseconds. - // The drawing width and height of the review image. This is saved when the - // texture is copied. - private int mReviewDrawingWidth; - private int mReviewDrawingHeight; - // The maximum width of the camera screen nail width from onDraw. We need to - // know how much the preview is scaled and scale the review the same amount. - // For example, the preview is not full screen in film strip mode. - private int mPreviewFrameLayoutWidth; - - public SwitchAnimManager() { - } - - public void setReviewDrawingSize(int width, int height) { - mReviewDrawingWidth = width; - mReviewDrawingHeight = height; - } - - // width: the width of PreviewFrameLayout view. - // height: the height of PreviewFrameLayout view. Not used. Kept for - // consistency. - public void setPreviewFrameLayoutSize(int width, int height) { - mPreviewFrameLayoutWidth = width; - } - - // w and h: the rectangle area where the animation takes place. - public void startAnimation() { - mAnimStartTime = SystemClock.uptimeMillis(); - } - - // Returns true if the animation has been drawn. - // preview: camera preview view. - // review: snapshot of the preview before switching the camera. - public boolean drawAnimation(GLCanvas canvas, int x, int y, int width, - int height, CameraScreenNail preview, RawTexture review) { - long timeDiff = SystemClock.uptimeMillis() - mAnimStartTime; - if (timeDiff > ANIMATION_DURATION) return false; - float fraction = timeDiff / ANIMATION_DURATION; - - // Calculate the position and the size of the preview. - float centerX = x + width / 2f; - float centerY = y + height / 2f; - float previewAnimScale = 1 - ZOOM_DELTA_PREVIEW * (1 - fraction); - float previewWidth = width * previewAnimScale; - float previewHeight = height * previewAnimScale; - int previewX = Math.round(centerX - previewWidth / 2); - int previewY = Math.round(centerY - previewHeight / 2); - - // Calculate the position and the size of the review. - float reviewAnimScale = 1 + ZOOM_DELTA_REVIEW * fraction; - - // Calculate how much preview is scaled. - // The scaling is done by PhotoView in Gallery so we don't have the - // scaling information but only the width and the height passed to this - // method. The inference of the scale ratio is done by matching the - // current width and the original width we have at first when the camera - // layout is inflated. - float scaleRatio = 1; - if (mPreviewFrameLayoutWidth != 0) { - scaleRatio = (float) width / mPreviewFrameLayoutWidth; - } else { - Log.e(TAG, "mPreviewFrameLayoutWidth is 0."); - } - float reviewWidth = mReviewDrawingWidth * reviewAnimScale * scaleRatio; - float reviewHeight = mReviewDrawingHeight * reviewAnimScale * scaleRatio; - int reviewX = Math.round(centerX - reviewWidth / 2); - int reviewY = Math.round(centerY - reviewHeight / 2); - - // Draw the preview. - float alpha = canvas.getAlpha(); - canvas.setAlpha(fraction); // fade in - preview.directDraw(canvas, previewX, previewY, Math.round(previewWidth), - Math.round(previewHeight)); - - // Draw the review. - canvas.setAlpha((1f - fraction) * INITIAL_DARKEN_ALPHA); // fade out - review.draw(canvas, reviewX, reviewY, Math.round(reviewWidth), - Math.round(reviewHeight)); - canvas.setAlpha(alpha); - return true; - } - - public boolean drawDarkPreview(GLCanvas canvas, int x, int y, int width, - int height, RawTexture review) { - // Calculate the position and the size. - float centerX = x + width / 2f; - float centerY = y + height / 2f; - float scaleRatio = 1; - if (mPreviewFrameLayoutWidth != 0) { - scaleRatio = (float) width / mPreviewFrameLayoutWidth; - } else { - Log.e(TAG, "mPreviewFrameLayoutWidth is 0."); - } - float reviewWidth = mReviewDrawingWidth * scaleRatio; - float reviewHeight = mReviewDrawingHeight * scaleRatio; - int reviewX = Math.round(centerX - reviewWidth / 2); - int reviewY = Math.round(centerY - reviewHeight / 2); - - // Draw the review. - float alpha = canvas.getAlpha(); - canvas.setAlpha(INITIAL_DARKEN_ALPHA); - review.draw(canvas, reviewX, reviewY, Math.round(reviewWidth), - Math.round(reviewHeight)); - canvas.setAlpha(alpha); - return true; - } - -} diff --git a/src/com/android/camera/Thumbnail.java b/src/com/android/camera/Thumbnail.java deleted file mode 100644 index 5f8483d6c..000000000 --- a/src/com/android/camera/Thumbnail.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.graphics.Bitmap; -import android.media.MediaMetadataRetriever; - -import java.io.FileDescriptor; - -public class Thumbnail { - public static Bitmap createVideoThumbnailBitmap(FileDescriptor fd, int targetWidth) { - return createVideoThumbnailBitmap(null, fd, targetWidth); - } - - public static Bitmap createVideoThumbnailBitmap(String filePath, int targetWidth) { - return createVideoThumbnailBitmap(filePath, null, targetWidth); - } - - private static Bitmap createVideoThumbnailBitmap(String filePath, FileDescriptor fd, - int targetWidth) { - Bitmap bitmap = null; - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - try { - if (filePath != null) { - retriever.setDataSource(filePath); - } else { - retriever.setDataSource(fd); - } - bitmap = retriever.getFrameAtTime(-1); - } catch (IllegalArgumentException ex) { - // Assume this is a corrupt video file - } catch (RuntimeException ex) { - // Assume this is a corrupt video file. - } finally { - try { - retriever.release(); - } catch (RuntimeException ex) { - // Ignore failures while cleaning up. - } - } - if (bitmap == null) return null; - - // Scale down the bitmap if it is bigger than we need. - int width = bitmap.getWidth(); - int height = bitmap.getHeight(); - if (width > targetWidth) { - float scale = (float) targetWidth / width; - int w = Math.round(scale * width); - int h = Math.round(scale * height); - bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true); - } - return bitmap; - } -} diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java deleted file mode 100644 index 2c5aa9eab..000000000 --- a/src/com/android/camera/Util.java +++ /dev/null @@ -1,817 +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.annotation.TargetApi; -import android.app.Activity; -import android.app.AlertDialog; -import android.app.admin.DevicePolicyManager; -import android.content.ActivityNotFoundException; -import android.content.ContentResolver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.RectF; -import android.hardware.Camera; -import android.hardware.Camera.CameraInfo; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.Size; -import android.location.Location; -import android.net.Uri; -import android.os.Build; -import android.os.Handler; -import android.os.ParcelFileDescriptor; -import android.telephony.TelephonyManager; -import android.util.DisplayMetrics; -import android.util.FloatMath; -import android.util.Log; -import android.util.TypedValue; -import android.view.Display; -import android.view.OrientationEventListener; -import android.view.Surface; -import android.view.View; -import android.view.WindowManager; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.MovieActivity; -import com.android.gallery3d.common.ApiHelper; - -import java.io.Closeable; -import java.io.IOException; -import java.lang.reflect.Method; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.StringTokenizer; - -/** - * Collection of utility functions used in this package. - */ -public class Util { - private static final String TAG = "Util"; - - // Orientation hysteresis amount used in rounding, in degrees - public static final int ORIENTATION_HYSTERESIS = 5; - - public static final String REVIEW_ACTION = "com.android.camera.action.REVIEW"; - // See android.hardware.Camera.ACTION_NEW_PICTURE. - public static final String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE"; - // See android.hardware.Camera.ACTION_NEW_VIDEO. - public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; - - // Fields from android.hardware.Camera.Parameters - public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture"; - public static final String RECORDING_HINT = "recording-hint"; - private static final String AUTO_EXPOSURE_LOCK_SUPPORTED = "auto-exposure-lock-supported"; - private static final String AUTO_WHITE_BALANCE_LOCK_SUPPORTED = "auto-whitebalance-lock-supported"; - private static final String VIDEO_SNAPSHOT_SUPPORTED = "video-snapshot-supported"; - public static final String SCENE_MODE_HDR = "hdr"; - public static final String TRUE = "true"; - public static final String FALSE = "false"; - - public static boolean isSupported(String value, List<String> supported) { - return supported == null ? false : supported.indexOf(value) >= 0; - } - - public static boolean isAutoExposureLockSupported(Parameters params) { - return TRUE.equals(params.get(AUTO_EXPOSURE_LOCK_SUPPORTED)); - } - - public static boolean isAutoWhiteBalanceLockSupported(Parameters params) { - return TRUE.equals(params.get(AUTO_WHITE_BALANCE_LOCK_SUPPORTED)); - } - - public static boolean isVideoSnapshotSupported(Parameters params) { - return TRUE.equals(params.get(VIDEO_SNAPSHOT_SUPPORTED)); - } - - public static boolean isCameraHdrSupported(Parameters params) { - List<String> supported = params.getSupportedSceneModes(); - return (supported != null) && supported.contains(SCENE_MODE_HDR); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - public static boolean isMeteringAreaSupported(Parameters params) { - if (ApiHelper.HAS_CAMERA_METERING_AREA) { - return params.getMaxNumMeteringAreas() > 0; - } - return false; - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - public static boolean isFocusAreaSupported(Parameters params) { - if (ApiHelper.HAS_CAMERA_FOCUS_AREA) { - return (params.getMaxNumFocusAreas() > 0 - && isSupported(Parameters.FOCUS_MODE_AUTO, - params.getSupportedFocusModes())); - } - return false; - } - - // Private intent extras. Test only. - private static final String EXTRAS_CAMERA_FACING = - "android.intent.extras.CAMERA_FACING"; - - private static float sPixelDensity = 1; - private static ImageFileNamer sImageFileNamer; - - private Util() { - } - - public static void initialize(Context context) { - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) - context.getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(metrics); - sPixelDensity = metrics.density; - sImageFileNamer = new ImageFileNamer( - context.getString(R.string.image_file_name_format)); - } - - public static int dpToPixel(int dp) { - return Math.round(sPixelDensity * dp); - } - - // Rotates the bitmap by the specified degree. - // If a new bitmap is created, the original bitmap is recycled. - public static Bitmap rotate(Bitmap b, int degrees) { - return rotateAndMirror(b, degrees, false); - } - - // Rotates and/or mirrors the bitmap. If a new bitmap is created, the - // original bitmap is recycled. - public static Bitmap rotateAndMirror(Bitmap b, int degrees, boolean mirror) { - if ((degrees != 0 || mirror) && b != null) { - Matrix m = new Matrix(); - // Mirror first. - // horizontal flip + rotation = -rotation + horizontal flip - if (mirror) { - m.postScale(-1, 1); - degrees = (degrees + 360) % 360; - if (degrees == 0 || degrees == 180) { - m.postTranslate(b.getWidth(), 0); - } else if (degrees == 90 || degrees == 270) { - m.postTranslate(b.getHeight(), 0); - } else { - throw new IllegalArgumentException("Invalid degrees=" + degrees); - } - } - if (degrees != 0) { - // clockwise - m.postRotate(degrees, - (float) b.getWidth() / 2, (float) b.getHeight() / 2); - } - - try { - Bitmap b2 = Bitmap.createBitmap( - b, 0, 0, b.getWidth(), b.getHeight(), m, true); - if (b != b2) { - b.recycle(); - b = b2; - } - } catch (OutOfMemoryError ex) { - // We have no memory to rotate. Return the original bitmap. - } - } - return b; - } - - /* - * Compute the sample size as a function of minSideLength - * and maxNumOfPixels. - * minSideLength is used to specify that minimal width or height of a - * bitmap. - * maxNumOfPixels is used to specify the maximal size in pixels that is - * tolerable in terms of memory usage. - * - * The function returns a sample size based on the constraints. - * Both size and minSideLength can be passed in as -1 - * which indicates no care of the corresponding constraint. - * The functions prefers returning a sample size that - * generates a smaller bitmap, unless minSideLength = -1. - * - * Also, the function rounds up the sample size to a power of 2 or multiple - * of 8 because BitmapFactory only honors sample size this way. - * For example, BitmapFactory downsamples an image by 2 even though the - * request is 3. So we round up the sample size to avoid OOM. - */ - public static int computeSampleSize(BitmapFactory.Options options, - int minSideLength, int maxNumOfPixels) { - int initialSize = computeInitialSampleSize(options, minSideLength, - maxNumOfPixels); - - int roundedSize; - if (initialSize <= 8) { - roundedSize = 1; - while (roundedSize < initialSize) { - roundedSize <<= 1; - } - } else { - roundedSize = (initialSize + 7) / 8 * 8; - } - - return roundedSize; - } - - private static int computeInitialSampleSize(BitmapFactory.Options options, - int minSideLength, int maxNumOfPixels) { - double w = options.outWidth; - double h = options.outHeight; - - int lowerBound = (maxNumOfPixels < 0) ? 1 : - (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); - int upperBound = (minSideLength < 0) ? 128 : - (int) Math.min(Math.floor(w / minSideLength), - Math.floor(h / minSideLength)); - - if (upperBound < lowerBound) { - // return the larger one when there is no overlapping zone. - return lowerBound; - } - - if (maxNumOfPixels < 0 && minSideLength < 0) { - return 1; - } else if (minSideLength < 0) { - return lowerBound; - } else { - return upperBound; - } - } - - 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, -1, 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; - } - } - - public static void closeSilently(Closeable c) { - if (c == null) return; - try { - c.close(); - } catch (Throwable t) { - // do nothing - } - } - - public static void Assert(boolean cond) { - if (!cond) { - throw new AssertionError(); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private static void throwIfCameraDisabled(Activity activity) throws CameraDisabledException { - // Check if device policy has disabled the camera. - if (ApiHelper.HAS_GET_CAMERA_DISABLED) { - DevicePolicyManager dpm = (DevicePolicyManager) activity.getSystemService( - Context.DEVICE_POLICY_SERVICE); - if (dpm.getCameraDisabled(null)) { - throw new CameraDisabledException(); - } - } - } - - public static CameraManager.CameraProxy openCamera( - Activity activity, int cameraId) - throws CameraHardwareException, CameraDisabledException { - throwIfCameraDisabled(activity); - - try { - return CameraHolder.instance().open(cameraId); - } 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("openCamera failed", e); - } else { - throw e; - } - } - } - - public static void showErrorAndFinish(final Activity activity, int msgId) { - DialogInterface.OnClickListener buttonListener = - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - activity.finish(); - } - }; - TypedValue out = new TypedValue(); - activity.getTheme().resolveAttribute(android.R.attr.alertDialogIcon, out, true); - new AlertDialog.Builder(activity) - .setCancelable(false) - .setTitle(R.string.camera_error_title) - .setMessage(msgId) - .setNeutralButton(R.string.dialog_ok, buttonListener) - .setIcon(out.resourceId) - .show(); - } - - public static <T> T checkNotNull(T object) { - if (object == null) throw new NullPointerException(); - return object; - } - - public static boolean equals(Object a, Object b) { - return (a == b) || (a == null ? false : a.equals(b)); - } - - public static int nextPowerOf2(int n) { - n -= 1; - n |= n >>> 16; - n |= n >>> 8; - n |= n >>> 4; - n |= n >>> 2; - n |= n >>> 1; - return n + 1; - } - - public static float distance(float x, float y, float sx, float sy) { - float dx = x - sx; - float dy = y - sy; - return FloatMath.sqrt(dx * dx + dy * dy); - } - - public static int clamp(int x, int min, int max) { - if (x > max) return max; - if (x < min) return min; - return x; - } - - public static int getDisplayRotation(Activity activity) { - int rotation = activity.getWindowManager().getDefaultDisplay() - .getRotation(); - switch (rotation) { - case Surface.ROTATION_0: return 0; - case Surface.ROTATION_90: return 90; - case Surface.ROTATION_180: return 180; - case Surface.ROTATION_270: return 270; - } - return 0; - } - - public static int getDisplayOrientation(int degrees, int cameraId) { - // See android.hardware.Camera.setDisplayOrientation for - // documentation. - Camera.CameraInfo info = new Camera.CameraInfo(); - Camera.getCameraInfo(cameraId, info); - int result; - if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { - result = (info.orientation + degrees) % 360; - result = (360 - result) % 360; // compensate the mirror - } else { // back-facing - result = (info.orientation - degrees + 360) % 360; - } - return result; - } - - public static int getCameraOrientation(int cameraId) { - Camera.CameraInfo info = new Camera.CameraInfo(); - Camera.getCameraInfo(cameraId, info); - return info.orientation; - } - - public static int roundOrientation(int orientation, int orientationHistory) { - boolean changeOrientation = false; - if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) { - changeOrientation = true; - } else { - int dist = Math.abs(orientation - orientationHistory); - dist = Math.min( dist, 360 - dist ); - changeOrientation = ( dist >= 45 + ORIENTATION_HYSTERESIS ); - } - if (changeOrientation) { - return ((orientation + 45) / 90 * 90) % 360; - } - return orientationHistory; - } - - @SuppressWarnings("deprecation") - @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) - private static Point getDefaultDisplaySize(Activity activity, Point size) { - Display d = activity.getWindowManager().getDefaultDisplay(); - if (Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.HONEYCOMB_MR2) { - d.getSize(size); - } else { - size.set(d.getWidth(), d.getHeight()); - } - return size; - } - - public static Size getOptimalPreviewSize(Activity currentActivity, - List<Size> sizes, double targetRatio) { - // Use a very small tolerance because we want an exact match. - final double ASPECT_TOLERANCE = 0.001; - 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 preview surface. 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. - Point point = getDefaultDisplaySize(currentActivity, new Point()); - int targetHeight = Math.min(point.x, point.y); - // 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. This should not happen. - // Ignore the requirement. - if (optimalSize == null) { - Log.w(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); - } - } - } - return optimalSize; - } - - // Returns the largest picture size which matches the given aspect ratio. - public static Size getOptimalVideoSnapshotPictureSize( - List<Size> sizes, double targetRatio) { - // Use a very small tolerance because we want an exact match. - final double ASPECT_TOLERANCE = 0.001; - if (sizes == null) return null; - - Size optimalSize = null; - - // Try to find a size matches aspect ratio and has the largest width - for (Size size : sizes) { - double ratio = (double) size.width / size.height; - if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; - if (optimalSize == null || size.width > optimalSize.width) { - optimalSize = size; - } - } - - // Cannot find one that matches the aspect ratio. This should not happen. - // Ignore the requirement. - if (optimalSize == null) { - Log.w(TAG, "No picture size match the aspect ratio"); - for (Size size : sizes) { - if (optimalSize == null || size.width > optimalSize.width) { - optimalSize = size; - } - } - } - return optimalSize; - } - - public static void dumpParameters(Parameters parameters) { - String flattened = parameters.flatten(); - StringTokenizer tokenizer = new StringTokenizer(flattened, ";"); - Log.d(TAG, "Dump all camera parameters:"); - while (tokenizer.hasMoreElements()) { - Log.d(TAG, tokenizer.nextToken()); - } - } - - /** - * Returns whether the device is voice-capable (meaning, it can do MMS). - */ - public static boolean isMmsCapable(Context context) { - TelephonyManager telephonyManager = (TelephonyManager) - context.getSystemService(Context.TELEPHONY_SERVICE); - if (telephonyManager == null) { - return false; - } - - try { - Class<?> partypes[] = new Class[0]; - Method sIsVoiceCapable = TelephonyManager.class.getMethod( - "isVoiceCapable", partypes); - - Object arglist[] = new Object[0]; - Object retobj = sIsVoiceCapable.invoke(telephonyManager, arglist); - return (Boolean) retobj; - } catch (java.lang.reflect.InvocationTargetException ite) { - // Failure, must be another device. - // Assume that it is voice capable. - } catch (IllegalAccessException iae) { - // Failure, must be an other device. - // Assume that it is voice capable. - } catch (NoSuchMethodException nsme) { - } - return true; - } - - // This is for test only. Allow the camera to launch the specific camera. - public static int getCameraFacingIntentExtras(Activity currentActivity) { - int cameraId = -1; - - int intentCameraId = - currentActivity.getIntent().getIntExtra(Util.EXTRAS_CAMERA_FACING, -1); - - if (isFrontCameraIntent(intentCameraId)) { - // Check if the front camera exist - int frontCameraId = CameraHolder.instance().getFrontCameraId(); - if (frontCameraId != -1) { - cameraId = frontCameraId; - } - } else if (isBackCameraIntent(intentCameraId)) { - // Check if the back camera exist - int backCameraId = CameraHolder.instance().getBackCameraId(); - if (backCameraId != -1) { - cameraId = backCameraId; - } - } - return cameraId; - } - - private static boolean isFrontCameraIntent(int intentCameraId) { - return (intentCameraId == android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); - } - - private static boolean isBackCameraIntent(int intentCameraId) { - return (intentCameraId == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); - } - - private static int sLocation[] = new int[2]; - - // This method is not thread-safe. - public static boolean pointInView(float x, float y, View v) { - v.getLocationInWindow(sLocation); - return x >= sLocation[0] && x < (sLocation[0] + v.getWidth()) - && y >= sLocation[1] && y < (sLocation[1] + v.getHeight()); - } - - public static int[] getRelativeLocation(View reference, View view) { - reference.getLocationInWindow(sLocation); - int referenceX = sLocation[0]; - int referenceY = sLocation[1]; - view.getLocationInWindow(sLocation); - sLocation[0] -= referenceX; - sLocation[1] -= referenceY; - return sLocation; - } - - public static boolean isUriValid(Uri uri, ContentResolver resolver) { - if (uri == null) return false; - - try { - ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r"); - if (pfd == null) { - Log.e(TAG, "Fail to open URI. URI=" + uri); - return false; - } - pfd.close(); - } catch (IOException ex) { - return false; - } - return true; - } - - public static void viewUri(Uri uri, Context context) { - if (!isUriValid(uri, context.getContentResolver())) { - Log.e(TAG, "Uri invalid. uri=" + uri); - return; - } - - try { - context.startActivity(new Intent(Util.REVIEW_ACTION, uri)); - } catch (ActivityNotFoundException ex) { - try { - context.startActivity(new Intent(Intent.ACTION_VIEW, uri)); - } catch (ActivityNotFoundException e) { - Log.e(TAG, "review image fail. uri=" + uri, e); - } - } - } - - public static void dumpRect(RectF rect, String msg) { - Log.v(TAG, msg + "=(" + rect.left + "," + rect.top - + "," + rect.right + "," + rect.bottom + ")"); - } - - public static void rectFToRect(RectF rectF, Rect rect) { - rect.left = Math.round(rectF.left); - rect.top = Math.round(rectF.top); - rect.right = Math.round(rectF.right); - rect.bottom = Math.round(rectF.bottom); - } - - public static void prepareMatrix(Matrix matrix, boolean mirror, int displayOrientation, - int viewWidth, int viewHeight) { - // Need mirror for front camera. - matrix.setScale(mirror ? -1 : 1, 1); - // This is the value for android.hardware.Camera.setDisplayOrientation. - matrix.postRotate(displayOrientation); - // Camera driver coordinates range from (-1000, -1000) to (1000, 1000). - // UI coordinates range from (0, 0) to (width, height). - matrix.postScale(viewWidth / 2000f, viewHeight / 2000f); - matrix.postTranslate(viewWidth / 2f, viewHeight / 2f); - } - - public static String createJpegName(long dateTaken) { - synchronized (sImageFileNamer) { - return sImageFileNamer.generateName(dateTaken); - } - } - - public static void broadcastNewPicture(Context context, Uri uri) { - context.sendBroadcast(new Intent(ACTION_NEW_PICTURE, uri)); - // Keep compatibility - context.sendBroadcast(new Intent("com.android.camera.NEW_PICTURE", uri)); - } - - public static void fadeIn(View view, float startAlpha, float endAlpha, long duration) { - if (view.getVisibility() == View.VISIBLE) return; - - view.setVisibility(View.VISIBLE); - Animation animation = new AlphaAnimation(startAlpha, endAlpha); - animation.setDuration(duration); - view.startAnimation(animation); - } - - public static void fadeIn(View view) { - fadeIn(view, 0F, 1F, 400); - - // We disabled the button in fadeOut(), so enable it here. - view.setEnabled(true); - } - - public static void fadeOut(View view) { - if (view.getVisibility() != View.VISIBLE) return; - - // Since the button is still clickable before fade-out animation - // ends, we disable the button first to block click. - view.setEnabled(false); - Animation animation = new AlphaAnimation(1F, 0F); - animation.setDuration(400); - view.startAnimation(animation); - view.setVisibility(View.GONE); - } - - public static int getJpegRotation(int cameraId, int orientation) { - // See android.hardware.Camera.Parameters.setRotation for - // documentation. - int rotation = 0; - if (orientation != OrientationEventListener.ORIENTATION_UNKNOWN) { - CameraInfo info = CameraHolder.instance().getCameraInfo()[cameraId]; - if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { - rotation = (info.orientation - orientation + 360) % 360; - } else { // back-facing camera - rotation = (info.orientation + orientation) % 360; - } - } - return rotation; - } - - /** - * Down-samples a jpeg byte array. - * @param data a byte array of jpeg data - * @param downSampleFactor down-sample factor - * @return decoded and down-sampled bitmap - */ - public static Bitmap downSample(final byte[] data, int downSampleFactor) { - final BitmapFactory.Options opts = new BitmapFactory.Options(); - // Downsample the image - opts.inSampleSize = downSampleFactor; - return BitmapFactory.decodeByteArray(data, 0, data.length, opts); - } - - public static void setGpsParameters(Parameters parameters, Location loc) { - // Clear previous GPS location from the parameters. - parameters.removeGpsData(); - - // We always encode GpsTimeStamp - parameters.setGpsTimestamp(System.currentTimeMillis() / 1000); - - // Set GPS location. - if (loc != null) { - double lat = loc.getLatitude(); - double lon = loc.getLongitude(); - boolean hasLatLon = (lat != 0.0d) || (lon != 0.0d); - - if (hasLatLon) { - Log.d(TAG, "Set gps location"); - parameters.setGpsLatitude(lat); - parameters.setGpsLongitude(lon); - parameters.setGpsProcessingMethod(loc.getProvider().toUpperCase()); - if (loc.hasAltitude()) { - parameters.setGpsAltitude(loc.getAltitude()); - } else { - // for NETWORK_PROVIDER location provider, we may have - // no altitude information, but the driver needs it, so - // we fake one. - parameters.setGpsAltitude(0); - } - if (loc.getTime() != 0) { - // Location.getTime() is UTC in milliseconds. - // gps-timestamp is UTC in seconds. - long utcTimeSeconds = loc.getTime() / 1000; - parameters.setGpsTimestamp(utcTimeSeconds); - } - } else { - loc = null; - } - } - } - - - public static int[] getMaxPreviewFpsRange(Parameters params) { - List<int[]> frameRates = params.getSupportedPreviewFpsRange(); - if (frameRates != null && frameRates.size() > 0) { - // The list is sorted. Return the last element. - return frameRates.get(frameRates.size() - 1); - } - return new int[0]; - } - - private static class ImageFileNamer { - private SimpleDateFormat mFormat; - - // The date (in milliseconds) used to generate the last name. - private long mLastDate; - - // Number of names generated for the same second. - private int mSameSecondCount; - - public ImageFileNamer(String format) { - mFormat = new SimpleDateFormat(format); - } - - public String generateName(long dateTaken) { - Date date = new Date(dateTaken); - String result = mFormat.format(date); - - // If the last name was generated for the same second, - // we append _1, _2, etc to the name. - if (dateTaken / 1000 == mLastDate / 1000) { - mSameSecondCount++; - result += "_" + mSameSecondCount; - } else { - mLastDate = dateTaken; - mSameSecondCount = 0; - } - - return result; - } - } - - public static void playVideo(Context context, Uri uri, String title) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW) - .setDataAndType(uri, "video/*") - .putExtra(Intent.EXTRA_TITLE, title) - .putExtra(MovieActivity.KEY_TREAT_UP_AS_BACK, true); - context.startActivity(intent); - } catch (ActivityNotFoundException e) { - Toast.makeText(context, context.getString(R.string.video_err), - Toast.LENGTH_SHORT).show(); - } - } -} diff --git a/src/com/android/camera/VideoController.java b/src/com/android/camera/VideoController.java deleted file mode 100644 index e84654821..000000000 --- a/src/com/android/camera/VideoController.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 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.view.View; - -import com.android.camera.ShutterButton.OnShutterButtonListener; - -public interface VideoController extends OnShutterButtonListener { - - public void onReviewDoneClicked(View view); - public void onReviewCancelClicked(View viwe); - public void onReviewPlayClicked(View view); - - public boolean isVideoCaptureIntent(); - public boolean isInReviewMode(); - public int onZoomChanged(int index); - - public void onSingleTapUp(View view, int x, int y); - - public void stopPreview(); - - public void updateCameraOrientation(); - - // Callbacks for camera preview UI events. - public void onPreviewUIReady(); - public void onPreviewUIDestroyed(); -} diff --git a/src/com/android/camera/VideoMenu.java b/src/com/android/camera/VideoMenu.java deleted file mode 100644 index da0bde10e..000000000 --- a/src/com/android/camera/VideoMenu.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.app.Activity; -import android.content.Context; -import android.view.LayoutInflater; - -import com.android.camera.ui.AbstractSettingPopup; -import com.android.camera.ui.ListPrefSettingPopup; -import com.android.camera.ui.MoreSettingPopup; -import com.android.camera.ui.PieItem; -import com.android.camera.ui.PieItem.OnClickListener; -import com.android.camera.ui.PieRenderer; -import com.android.camera.ui.TimeIntervalPopup; -import com.android.gallery3d.R; - -public class VideoMenu extends PieController - implements MoreSettingPopup.Listener, - ListPrefSettingPopup.Listener, - TimeIntervalPopup.Listener { - - private static String TAG = "CAM_VideoMenu"; - - private VideoUI mUI; - private String[] mOtherKeys; - private AbstractSettingPopup mPopup; - - private static final int POPUP_NONE = 0; - private static final int POPUP_FIRST_LEVEL = 1; - private static final int POPUP_SECOND_LEVEL = 2; - private int mPopupStatus; - private CameraActivity mActivity; - - public VideoMenu(CameraActivity activity, VideoUI ui, PieRenderer pie) { - super(activity, pie); - mUI = ui; - mActivity = activity; - } - - - public void initialize(PreferenceGroup group) { - super.initialize(group); - mPopup = null; - mPopupStatus = POPUP_NONE; - PieItem item = null; - // white balance - if (group.findPreference(CameraSettings.KEY_WHITE_BALANCE) != null) { - item = makeItem(CameraSettings.KEY_WHITE_BALANCE); - mRenderer.addItem(item); - } - // settings popup - mOtherKeys = new String[] { - CameraSettings.KEY_VIDEO_EFFECT, - CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL, - CameraSettings.KEY_VIDEO_QUALITY, - CameraSettings.KEY_RECORD_LOCATION - }; - item = makeItem(R.drawable.ic_settings_holo_light); - item.setLabel(mActivity.getResources().getString(R.string.camera_menu_settings_label)); - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - if (mPopup == null || mPopupStatus != POPUP_FIRST_LEVEL) { - initializePopup(); - mPopupStatus = POPUP_FIRST_LEVEL; - } - mUI.showPopup(mPopup); - } - }); - mRenderer.addItem(item); - // camera switcher - if (group.findPreference(CameraSettings.KEY_CAMERA_ID) != null) { - item = makeItem(R.drawable.ic_switch_back); - IconListPreference lpref = (IconListPreference) group.findPreference( - CameraSettings.KEY_CAMERA_ID); - item.setLabel(lpref.getLabel()); - item.setImageResource(mActivity, - ((IconListPreference) lpref).getIconIds() - [lpref.findIndexOfValue(lpref.getValue())]); - - final PieItem fitem = item; - item.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(PieItem item) { - // Find the index of next camera. - ListPreference pref = - mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_ID); - if (pref != null) { - int index = pref.findIndexOfValue(pref.getValue()); - CharSequence[] values = pref.getEntryValues(); - index = (index + 1) % values.length; - int newCameraId = Integer.parseInt((String) values[index]); - fitem.setImageResource(mActivity, - ((IconListPreference) pref).getIconIds()[index]); - fitem.setLabel(pref.getLabel()); - mListener.onCameraPickerClicked(newCameraId); - } - } - }); - mRenderer.addItem(item); - } - // flash - if (group.findPreference(CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE) != null) { - item = makeItem(CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE); - mRenderer.addItem(item); - } - } - - @Override - public void reloadPreferences() { - super.reloadPreferences(); - if (mPopup != null) { - mPopup.reloadPreference(); - } - } - - @Override - public void overrideSettings(final String ... keyvalues) { - super.overrideSettings(keyvalues); - if (mPopup == null || mPopupStatus != POPUP_FIRST_LEVEL) { - mPopupStatus = POPUP_FIRST_LEVEL; - initializePopup(); - } - ((MoreSettingPopup) mPopup).overrideSettings(keyvalues); - } - - @Override - // Hit when an item in the second-level popup gets selected - public void onListPrefChanged(ListPreference pref) { - if (mPopup != null) { - if (mPopupStatus == POPUP_SECOND_LEVEL) { - mUI.dismissPopup(true); - } - } - super.onSettingChanged(pref); - } - - protected void initializePopup() { - LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - - MoreSettingPopup popup = (MoreSettingPopup) inflater.inflate( - R.layout.more_setting_popup, null, false); - popup.setSettingChangedListener(this); - popup.initialize(mPreferenceGroup, mOtherKeys); - if (mActivity.isSecureCamera()) { - // Prevent location preference from getting changed in secure camera mode - popup.setPreferenceEnabled(CameraSettings.KEY_RECORD_LOCATION, false); - } - mPopup = popup; - } - - public void popupDismissed(boolean topPopupOnly) { - // if the 2nd level popup gets dismissed - if (mPopupStatus == POPUP_SECOND_LEVEL) { - initializePopup(); - mPopupStatus = POPUP_FIRST_LEVEL; - if (topPopupOnly) mUI.showPopup(mPopup); - } - } - - @Override - // Hit when an item in the first-level popup gets selected, then bring up - // the second-level popup - public void onPreferenceClicked(ListPreference pref) { - if (mPopupStatus != POPUP_FIRST_LEVEL) return; - - LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - - if (CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL.equals(pref.getKey())) { - TimeIntervalPopup timeInterval = (TimeIntervalPopup) inflater.inflate( - R.layout.time_interval_popup, null, false); - timeInterval.initialize((IconListPreference) pref); - timeInterval.setSettingChangedListener(this); - mUI.dismissPopup(true); - mPopup = timeInterval; - } else { - ListPrefSettingPopup basic = (ListPrefSettingPopup) inflater.inflate( - R.layout.list_pref_setting_popup, null, false); - basic.initialize(pref); - basic.setSettingChangedListener(this); - mUI.dismissPopup(true); - mPopup = basic; - } - mUI.showPopup(mPopup); - mPopupStatus = POPUP_SECOND_LEVEL; - } -} diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java deleted file mode 100644 index 3c4d1e57b..000000000 --- a/src/com/android/camera/VideoModule.java +++ /dev/null @@ -1,2225 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.annotation.TargetApi; -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.Editor; -import android.content.res.Configuration; -import android.graphics.Bitmap; -import android.graphics.SurfaceTexture; -import android.hardware.Camera.CameraInfo; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.Size; -import android.location.Location; -import android.media.CamcorderProfile; -import android.media.CameraProfile; -import android.media.MediaRecorder; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.ParcelFileDescriptor; -import android.os.SystemClock; -import android.provider.MediaStore; -import android.provider.MediaStore.MediaColumns; -import android.provider.MediaStore.Video; -import android.util.Log; -import android.view.KeyEvent; -import android.view.OrientationEventListener; -import android.view.Surface; -import android.view.View; -import android.view.WindowManager; -import android.widget.Toast; - -import com.android.camera.CameraManager.CameraPictureCallback; -import com.android.camera.CameraManager.CameraProxy; -import com.android.camera.ui.PopupManager; -import com.android.camera.ui.RotateTextToast; -import com.android.gallery3d.R; -import com.android.gallery3d.app.OrientationManager; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.util.AccessibilityUtils; -import com.android.gallery3d.util.UsageStatistics; - -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -public class VideoModule implements CameraModule, - VideoController, - CameraPreference.OnPreferenceChangedListener, - ShutterButton.OnShutterButtonListener, - MediaRecorder.OnErrorListener, - MediaRecorder.OnInfoListener, - EffectsRecorder.EffectsListener { - - private static final String TAG = "CAM_VideoModule"; - - // We number the request code from 1000 to avoid collision with Gallery. - private static final int REQUEST_EFFECT_BACKDROPPER = 1000; - - private static final int CHECK_DISPLAY_ROTATION = 3; - private static final int CLEAR_SCREEN_DELAY = 4; - private static final int UPDATE_RECORD_TIME = 5; - private static final int ENABLE_SHUTTER_BUTTON = 6; - private static final int SHOW_TAP_TO_SNAPSHOT_TOAST = 7; - private static final int SWITCH_CAMERA = 8; - private static final int SWITCH_CAMERA_START_ANIMATION = 9; - - private static final int SCREEN_DELAY = 2 * 60 * 1000; - - private static final long SHUTTER_BUTTON_TIMEOUT = 500L; // 500ms - - /** - * An unpublished intent flag requesting to start recording straight away - * and return as soon as recording is stopped. - * TODO: consider publishing by moving into MediaStore. - */ - private static final String EXTRA_QUICK_CAPTURE = - "android.intent.extra.quickCapture"; - - // module fields - private CameraActivity mActivity; - private boolean mPaused; - private int mCameraId; - private Parameters mParameters; - - private boolean mIsInReviewMode; - private boolean mSnapshotInProgress = false; - - private static final String EFFECT_BG_FROM_GALLERY = "gallery"; - - private final CameraErrorCallback mErrorCallback = new CameraErrorCallback(); - - private ComboPreferences mPreferences; - private PreferenceGroup mPreferenceGroup; - // Preference must be read before starting preview. We check this before starting - // preview. - private boolean mPreferenceRead; - - private boolean mIsVideoCaptureIntent; - private boolean mQuickCapture; - - private MediaRecorder mMediaRecorder; - private EffectsRecorder mEffectsRecorder; - private boolean mEffectsDisplayResult; - - private int mEffectType = EffectsRecorder.EFFECT_NONE; - private Object mEffectParameter = null; - private String mEffectUriFromGallery = null; - private String mPrefVideoEffectDefault; - private boolean mResetEffect = true; - - private boolean mSwitchingCamera; - private boolean mMediaRecorderRecording = false; - private long mRecordingStartTime; - private boolean mRecordingTimeCountsDown = false; - private long mOnResumeTime; - // The video file that the hardware camera is about to record into - // (or is recording into.) - private String mVideoFilename; - private ParcelFileDescriptor mVideoFileDescriptor; - - // 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 CamcorderProfile mProfile; - - // The video duration limit. 0 menas no limit. - private int mMaxVideoDurationInMs; - - // Time Lapse parameters. - private boolean mCaptureTimeLapse = false; - // Default 0. If it is larger than 0, the camcorder is in time lapse mode. - private int mTimeBetweenTimeLapseFrameCaptureMs = 0; - - boolean mPreviewing = false; // True if preview is started. - // The display rotation in degrees. This is only valid when mPreviewing is - // true. - private int mDisplayRotation; - private int mCameraDisplayOrientation; - - private int mDesiredPreviewWidth; - private int mDesiredPreviewHeight; - private ContentResolver mContentResolver; - - private LocationManager mLocationManager; - private OrientationManager mOrientationManager; - - private Surface mSurface; - private int mPendingSwitchCameraId; - private boolean mOpenCameraFail; - private boolean mCameraDisabled; - private final Handler mHandler = new MainHandler(); - private VideoUI mUI; - private CameraProxy mCameraDevice; - - // The degrees of the device rotated clockwise from its natural orientation. - private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; - - private int mZoomValue; // The current zoom value. - - private boolean mRestoreFlash; // This is used to check if we need to restore the flash - // status when going back from gallery. - - private final MediaSaveService.OnMediaSavedListener mOnVideoSavedListener = - new MediaSaveService.OnMediaSavedListener() { - @Override - public void onMediaSaved(Uri uri) { - if (uri != null) { - mActivity.notifyNewMedia(uri); - } - } - }; - - private final MediaSaveService.OnMediaSavedListener mOnPhotoSavedListener = - new MediaSaveService.OnMediaSavedListener() { - @Override - public void onMediaSaved(Uri uri) { - if (uri != null) { - mActivity.notifyNewMedia(uri); - } - } - }; - - - protected class CameraOpenThread extends Thread { - @Override - public void run() { - openCamera(); - } - } - - private void openCamera() { - try { - if (mCameraDevice == null) { - mCameraDevice = Util.openCamera(mActivity, mCameraId); - } - mParameters = mCameraDevice.getParameters(); - } catch (CameraHardwareException e) { - mOpenCameraFail = true; - } catch (CameraDisabledException e) { - mCameraDisabled = true; - } - } - - // 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 ENABLE_SHUTTER_BUTTON: - mUI.enableShutter(true); - break; - - case CLEAR_SCREEN_DELAY: { - mActivity.getWindow().clearFlags( - WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - break; - } - - case UPDATE_RECORD_TIME: { - updateRecordingTime(); - break; - } - - case CHECK_DISPLAY_ROTATION: { - // Restart the preview if display rotation has changed. - // Sometimes this happens when the device is held upside - // down and camera app is opened. Rotation animation will - // take some time and the rotation value we have got may be - // wrong. Framework does not have a callback for this now. - if ((Util.getDisplayRotation(mActivity) != mDisplayRotation) - && !mMediaRecorderRecording && !mSwitchingCamera) { - startPreview(); - } - if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) { - mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100); - } - break; - } - - case SHOW_TAP_TO_SNAPSHOT_TOAST: { - showTapToSnapshotToast(); - break; - } - - case SWITCH_CAMERA: { - switchCamera(); - break; - } - - case SWITCH_CAMERA_START_ANIMATION: { - //TODO: - //((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera(); - - // Enable all camera controls. - mSwitchingCamera = false; - 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)) { - stopVideoRecording(); - } else if (action.equals(Intent.ACTION_MEDIA_SCANNER_STARTED)) { - Toast.makeText(mActivity, - mActivity.getResources().getString(R.string.wait), Toast.LENGTH_LONG).show(); - } - } - } - - private String createName(long dateTaken) { - Date date = new Date(dateTaken); - SimpleDateFormat dateFormat = new SimpleDateFormat( - mActivity.getString(R.string.video_file_name_format)); - - return dateFormat.format(date); - } - - private int getPreferredCameraId(ComboPreferences preferences) { - int intentCameraId = Util.getCameraFacingIntentExtras(mActivity); - if (intentCameraId != -1) { - // Testing purpose. Launch a specific camera through the intent - // extras. - return intentCameraId; - } else { - return CameraSettings.readPreferredCameraId(preferences); - } - } - - private void initializeSurfaceView() { - if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) { // API level < 16 - mUI.initializeSurfaceView(); - } - } - - @Override - public void init(CameraActivity activity, View root) { - mActivity = activity; - mUI = new VideoUI(activity, this, root); - mPreferences = new ComboPreferences(mActivity); - CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal()); - mCameraId = getPreferredCameraId(mPreferences); - - mPreferences.setLocalId(mActivity, mCameraId); - CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); - - mPrefVideoEffectDefault = mActivity.getString(R.string.pref_video_effect_default); - resetEffect(); - mOrientationManager = new OrientationManager(mActivity); - - /* - * To reduce startup time, we start the preview in another thread. - * We make sure the preview is started at the end of onCreate. - */ - CameraOpenThread cameraOpenThread = new CameraOpenThread(); - cameraOpenThread.start(); - - mContentResolver = mActivity.getContentResolver(); - - // Surface texture is from camera screen nail and startPreview needs it. - // This must be done before startPreview. - mIsVideoCaptureIntent = isVideoCaptureIntent(); - initializeSurfaceView(); - - // Make sure camera device is opened. - try { - cameraOpenThread.join(); - if (mOpenCameraFail) { - Util.showErrorAndFinish(mActivity, R.string.cannot_connect_camera); - return; - } else if (mCameraDisabled) { - Util.showErrorAndFinish(mActivity, R.string.camera_disabled); - return; - } - } catch (InterruptedException ex) { - // ignore - } - - readVideoPreferences(); - mUI.setPrefChangedListener(this); - - mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false); - mLocationManager = new LocationManager(mActivity, null); - - mUI.setOrientationIndicator(0, false); - setDisplayOrientation(); - - mUI.showTimeLapseUI(mCaptureTimeLapse); - initializeVideoSnapshot(); - resizeForPreviewAspectRatio(); - - initializeVideoControl(); - mPendingSwitchCameraId = -1; - mUI.updateOnScreenIndicators(mParameters, mPreferences); - - // Disable the shutter button if effects are ON since it might take - // a little more time for the effects preview to be ready. We do not - // want to allow recording before that happens. The shutter button - // will be enabled when we get the message from effectsrecorder that - // the preview is running. This becomes critical when the camera is - // swapped. - if (effectsActive()) { - mUI.enableShutter(false); - } - } - - // SingleTapListener - // Preview area is touched. Take a picture. - @Override - public void onSingleTapUp(View view, int x, int y) { - if (mMediaRecorderRecording && effectsActive()) { - new RotateTextToast(mActivity, R.string.disable_video_snapshot_hint, - mOrientation).show(); - return; - } - - MediaSaveService s = mActivity.getMediaSaveService(); - if (mPaused || mSnapshotInProgress || effectsActive() || s == null || s.isQueueFull()) { - return; - } - - if (!mMediaRecorderRecording) { - // check for dismissing popup - mUI.dismissPopup(true); - return; - } - - // Set rotation and gps data. - int rotation = Util.getJpegRotation(mCameraId, mOrientation); - mParameters.setRotation(rotation); - Location loc = mLocationManager.getCurrentLocation(); - Util.setGpsParameters(mParameters, loc); - mCameraDevice.setParameters(mParameters); - - Log.v(TAG, "Video snapshot start"); - mCameraDevice.takePicture(mHandler, - null, null, null, new JpegPictureCallback(loc)); - showVideoSnapshotUI(true); - mSnapshotInProgress = true; - UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA, - UsageStatistics.ACTION_CAPTURE_DONE, "VideoSnapshot"); - } - - @Override - public void onStop() {} - - private void loadCameraPreferences() { - CameraSettings settings = new CameraSettings(mActivity, mParameters, - mCameraId, CameraHolder.instance().getCameraInfo()); - // Remove the video quality preference setting when the quality is given in the intent. - mPreferenceGroup = filterPreferenceScreenByIntent( - settings.getPreferenceGroup(R.xml.video_preferences)); - } - - private void initializeVideoControl() { - loadCameraPreferences(); - mUI.initializePopup(mPreferenceGroup); - if (effectsActive()) { - mUI.overrideSettings( - CameraSettings.KEY_VIDEO_QUALITY, - Integer.toString(CamcorderProfile.QUALITY_480P)); - } - } - - @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 or sky, we still have - // the correct orientation. - if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) return; - int newOrientation = Util.roundOrientation(orientation, mOrientation); - - if (mOrientation != newOrientation) { - mOrientation = newOrientation; - // The input of effects recorder is affected by - // android.hardware.Camera.setDisplayOrientation. Its value only - // compensates the camera orientation (no Display.getRotation). - // So the orientation hint here should only consider sensor - // orientation. - if (effectsActive()) { - mEffectsRecorder.setOrientationHint(mOrientation); - } - } - - // Show the toast after getting the first orientation changed. - if (mHandler.hasMessages(SHOW_TAP_TO_SNAPSHOT_TOAST)) { - mHandler.removeMessages(SHOW_TAP_TO_SNAPSHOT_TOAST); - showTapToSnapshotToast(); - } - } - - private void startPlayVideoActivity() { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setDataAndType(mCurrentVideoUri, convertOutputFormatToMimeType(mProfile.fileFormat)); - try { - mActivity.startActivity(intent); - } catch (ActivityNotFoundException ex) { - Log.e(TAG, "Couldn't view video " + mCurrentVideoUri, ex); - } - } - - @OnClickAttr - public void onReviewPlayClicked(View v) { - startPlayVideoActivity(); - } - - @OnClickAttr - public void onReviewDoneClicked(View v) { - mIsInReviewMode = false; - doReturnToCaller(true); - } - - @OnClickAttr - public void onReviewCancelClicked(View v) { - mIsInReviewMode = false; - stopVideoRecording(); - doReturnToCaller(false); - } - - @Override - public boolean isInReviewMode() { - return mIsInReviewMode; - } - - private void onStopVideoRecording() { - mEffectsDisplayResult = true; - boolean recordFail = stopVideoRecording(); - if (mIsVideoCaptureIntent) { - if (!effectsActive()) { - if (mQuickCapture) { - doReturnToCaller(!recordFail); - } else if (!recordFail) { - showCaptureResult(); - } - } - } else if (!recordFail){ - // Start capture animation. - if (!mPaused && ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) { - // The capture animation is disabled on ICS because we use SurfaceView - // for preview during recording. When the recording is done, we switch - // back to use SurfaceTexture for preview and we need to stop then start - // the preview. This will cause the preview flicker since the preview - // will not be continuous for a short period of time. - - mUI.animateFlash(); - Bitmap bitmap = getVideoThumbnail(); - if (bitmap != null) { - mUI.animateCapture(bitmap); - } - } - } - } - - public void onProtectiveCurtainClick(View v) { - // Consume clicks - } - - @Override - public void onShutterButtonClick() { - if (mUI.collapseCameraControls() || mSwitchingCamera) return; - - boolean stop = mMediaRecorderRecording; - - if (stop) { - onStopVideoRecording(); - } else { - startVideoRecording(); - } - mUI.enableShutter(false); - - // Keep the shutter button disabled when in video capture intent - // mode and recording is stopped. It'll be re-enabled when - // re-take button is clicked. - if (!(mIsVideoCaptureIntent && stop)) { - mHandler.sendEmptyMessageDelayed( - ENABLE_SHUTTER_BUTTON, SHUTTER_BUTTON_TIMEOUT); - } - } - - @Override - public void onShutterButtonFocus(boolean pressed) { - mUI.setShutterPressed(pressed); - } - - private void readVideoPreferences() { - // The preference stores values from ListPreference and is thus string type for all values. - // We need to convert it to int manually. - String videoQuality = mPreferences.getString(CameraSettings.KEY_VIDEO_QUALITY, - null); - if (videoQuality == null) { - // check for highest quality before setting default value - videoQuality = CameraSettings.getSupportedHighestVideoQuality(mCameraId, - mActivity.getResources().getString(R.string.pref_video_quality_default)); - mPreferences.edit().putString(CameraSettings.KEY_VIDEO_QUALITY, videoQuality); - } - int quality = Integer.valueOf(videoQuality); - - // Set video quality. - Intent intent = mActivity.getIntent(); - if (intent.hasExtra(MediaStore.EXTRA_VIDEO_QUALITY)) { - int extraVideoQuality = - intent.getIntExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); - if (extraVideoQuality > 0) { - quality = CamcorderProfile.QUALITY_HIGH; - } else { // 0 is mms. - quality = CamcorderProfile.QUALITY_LOW; - } - } - - // 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 { - mMaxVideoDurationInMs = CameraSettings.getMaxVideoDuration(mActivity); - } - - // Set effect - mEffectType = CameraSettings.readEffectType(mPreferences); - if (mEffectType != EffectsRecorder.EFFECT_NONE) { - mEffectParameter = CameraSettings.readEffectParameter(mPreferences); - // Set quality to be no higher than 480p. - CamcorderProfile profile = CamcorderProfile.get(mCameraId, quality); - if (profile.videoFrameHeight > 480) { - quality = CamcorderProfile.QUALITY_480P; - } - } else { - mEffectParameter = null; - } - // Read time lapse recording interval. - if (ApiHelper.HAS_TIME_LAPSE_RECORDING) { - String frameIntervalStr = mPreferences.getString( - CameraSettings.KEY_VIDEO_TIME_LAPSE_FRAME_INTERVAL, - mActivity.getString(R.string.pref_video_time_lapse_frame_interval_default)); - mTimeBetweenTimeLapseFrameCaptureMs = Integer.parseInt(frameIntervalStr); - mCaptureTimeLapse = (mTimeBetweenTimeLapseFrameCaptureMs != 0); - } - // TODO: This should be checked instead directly +1000. - if (mCaptureTimeLapse) quality += 1000; - mProfile = CamcorderProfile.get(mCameraId, quality); - getDesiredPreviewSize(); - mPreferenceRead = true; - } - - private void writeDefaultEffectToPrefs() { - ComboPreferences.Editor editor = mPreferences.edit(); - editor.putString(CameraSettings.KEY_VIDEO_EFFECT, - mActivity.getString(R.string.pref_video_effect_default)); - editor.apply(); - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - private void getDesiredPreviewSize() { - mParameters = mCameraDevice.getParameters(); - if (ApiHelper.HAS_GET_SUPPORTED_VIDEO_SIZE) { - if (mParameters.getSupportedVideoSizes() == null || effectsActive()) { - mDesiredPreviewWidth = mProfile.videoFrameWidth; - mDesiredPreviewHeight = mProfile.videoFrameHeight; - } else { // Driver supports separates outputs for preview and video. - List<Size> sizes = mParameters.getSupportedPreviewSizes(); - Size preferred = mParameters.getPreferredPreviewSizeForVideo(); - int product = preferred.width * preferred.height; - Iterator<Size> it = sizes.iterator(); - // Remove the preview sizes that are not preferred. - while (it.hasNext()) { - Size size = it.next(); - if (size.width * size.height > product) { - it.remove(); - } - } - Size optimalSize = Util.getOptimalPreviewSize(mActivity, sizes, - (double) mProfile.videoFrameWidth / mProfile.videoFrameHeight); - mDesiredPreviewWidth = optimalSize.width; - mDesiredPreviewHeight = optimalSize.height; - } - } else { - mDesiredPreviewWidth = mProfile.videoFrameWidth; - mDesiredPreviewHeight = mProfile.videoFrameHeight; - } - mUI.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight); - Log.v(TAG, "mDesiredPreviewWidth=" + mDesiredPreviewWidth + - ". mDesiredPreviewHeight=" + mDesiredPreviewHeight); - } - - private void resizeForPreviewAspectRatio() { - mUI.setAspectRatio( - (double) mProfile.videoFrameWidth / mProfile.videoFrameHeight); - } - - @Override - public void installIntentFilter() { - // install an intent filter to receive SD card related events. - IntentFilter intentFilter = - new IntentFilter(Intent.ACTION_MEDIA_EJECT); - intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED); - intentFilter.addDataScheme("file"); - mReceiver = new MyBroadcastReceiver(); - mActivity.registerReceiver(mReceiver, intentFilter); - } - - @Override - public void onResumeBeforeSuper() { - mPaused = false; - } - - @Override - public void onResumeAfterSuper() { - if (mOpenCameraFail || mCameraDisabled) - return; - mUI.enableShutter(false); - mZoomValue = 0; - - showVideoSnapshotUI(false); - - if (!mPreviewing) { - resetEffect(); - openCamera(); - if (mOpenCameraFail) { - Util.showErrorAndFinish(mActivity, - R.string.cannot_connect_camera); - return; - } else if (mCameraDisabled) { - Util.showErrorAndFinish(mActivity, R.string.camera_disabled); - return; - } - readVideoPreferences(); - resizeForPreviewAspectRatio(); - startPreview(); - } else { - // preview already started - mUI.enableShutter(true); - } - - // Initializing it here after the preview is started. - mUI.initializeZoom(mParameters); - - keepScreenOnAwhile(); - - // Initialize location service. - boolean recordLocation = RecordLocationPreference.get(mPreferences, - mContentResolver); - mLocationManager.recordLocation(recordLocation); - - if (mPreviewing) { - mOnResumeTime = SystemClock.uptimeMillis(); - mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100); - } - // Dismiss open menu if exists. - PopupManager.getInstance(mActivity).notifyShowPopup(null); - - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_CAMERA, "VideoModule"); - } - - private void setDisplayOrientation() { - mDisplayRotation = Util.getDisplayRotation(mActivity); - mCameraDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, mCameraId); - // Change the camera display orientation - if (mCameraDevice != null) { - mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation); - } - } - - @Override - public void updateCameraOrientation() { - if (mMediaRecorderRecording) return; - if (mDisplayRotation != Util.getDisplayRotation(mActivity)) { - setDisplayOrientation(); - } - } - - @Override - public int onZoomChanged(int index) { - // Not useful to change zoom value when the activity is paused. - if (mPaused) return index; - mZoomValue = index; - if (mParameters == null || mCameraDevice == null) return index; - // Set zoom parameters asynchronously - mParameters.setZoom(mZoomValue); - mCameraDevice.setParameters(mParameters); - Parameters p = mCameraDevice.getParameters(); - if (p != null) return p.getZoom(); - return index; - } - - private void startPreview() { - Log.v(TAG, "startPreview"); - - SurfaceTexture surfaceTexture = mUI.getSurfaceTexture(); - if (!mPreferenceRead || surfaceTexture == null || mPaused == true) return; - - mCameraDevice.setErrorCallback(mErrorCallback); - if (mPreviewing == true) { - stopPreview(); - if (effectsActive() && mEffectsRecorder != null) { - mEffectsRecorder.release(); - mEffectsRecorder = null; - } - } - - setDisplayOrientation(); - mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation); - setCameraParameters(); - - try { - if (!effectsActive()) { - mCameraDevice.setPreviewTexture(surfaceTexture); - mCameraDevice.startPreview(); - mPreviewing = true; - onPreviewStarted(); - } else { - initializeEffectsPreview(); - mEffectsRecorder.startPreview(); - mPreviewing = true; - onPreviewStarted(); - } - } catch (Throwable ex) { - closeCamera(); - throw new RuntimeException("startPreview failed", ex); - } finally { - if (mOpenCameraFail) { - Util.showErrorAndFinish(mActivity, R.string.cannot_connect_camera); - } else if (mCameraDisabled) { - Util.showErrorAndFinish(mActivity, R.string.camera_disabled); - } - } - - } - - private void onPreviewStarted() { - mUI.enableShutter(true); - } - - @Override - public void stopPreview() { - if (!mPreviewing) return; - mCameraDevice.stopPreview(); - mPreviewing = false; - } - - // Closing the effects out. Will shut down the effects graph. - private void closeEffects() { - Log.v(TAG, "Closing effects"); - mEffectType = EffectsRecorder.EFFECT_NONE; - if (mEffectsRecorder == null) { - Log.d(TAG, "Effects are already closed. Nothing to do"); - return; - } - // This call can handle the case where the camera is already released - // after the recording has been stopped. - mEffectsRecorder.release(); - mEffectsRecorder = null; - } - - // By default, we want to close the effects as well with the camera. - private void closeCamera() { - closeCamera(true); - } - - // In certain cases, when the effects are active, we may want to shutdown - // only the camera related parts, and handle closing the effects in the - // effectsUpdate callback. - // For example, in onPause, we want to make the camera available to - // outside world immediately, however, want to wait till the effects - // callback to shut down the effects. In such a case, we just disconnect - // the effects from the camera by calling disconnectCamera. That way - // the effects can handle that when shutting down. - // - // @param closeEffectsAlso - indicates whether we want to close the - // effects also along with the camera. - private void closeCamera(boolean closeEffectsAlso) { - Log.v(TAG, "closeCamera"); - if (mCameraDevice == null) { - Log.d(TAG, "already stopped."); - return; - } - - if (mEffectsRecorder != null) { - // Disconnect the camera from effects so that camera is ready to - // be released to the outside world. - mEffectsRecorder.disconnectCamera(); - } - if (closeEffectsAlso) closeEffects(); - mCameraDevice.setZoomChangeListener(null); - mCameraDevice.setErrorCallback(null); - CameraHolder.instance().release(); - mCameraDevice = null; - mPreviewing = false; - mSnapshotInProgress = false; - } - - private void releasePreviewResources() { - if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) { - mUI.hideSurfaceView(); - } - } - - @Override - public void onPauseBeforeSuper() { - mPaused = true; - - if (mMediaRecorderRecording) { - // Camera will be released in onStopVideoRecording. - onStopVideoRecording(); - } else { - closeCamera(); - if (!effectsActive()) releaseMediaRecorder(); - } - if (effectsActive()) { - // If the effects are active, make sure we tell the graph that the - // surfacetexture is not valid anymore. Disconnect the graph from - // the display. This should be done before releasing the surface - // texture. - mEffectsRecorder.disconnectDisplay(); - } else { - // Close the file descriptor and clear the video namer only if the - // effects are not active. If effects are active, we need to wait - // till we get the callback from the Effects that the graph is done - // recording. That also needs a change in the stopVideoRecording() - // call to not call closeCamera if the effects are active, because - // that will close down the effects are well, thus making this if - // condition invalid. - closeVideoFileDescriptor(); - } - - releasePreviewResources(); - - if (mReceiver != null) { - mActivity.unregisterReceiver(mReceiver); - mReceiver = null; - } - resetScreenOn(); - - if (mLocationManager != null) mLocationManager.recordLocation(false); - - mHandler.removeMessages(CHECK_DISPLAY_ROTATION); - mHandler.removeMessages(SWITCH_CAMERA); - mHandler.removeMessages(SWITCH_CAMERA_START_ANIMATION); - mPendingSwitchCameraId = -1; - mSwitchingCamera = false; - mPreferenceRead = false; - // Call onPause after stopping video recording. So the camera can be - // released as soon as possible. - } - - @Override - public void onPauseAfterSuper() { - } - - @Override - public void onUserInteraction() { - if (!mMediaRecorderRecording && !mActivity.isFinishing()) { - keepScreenOnAwhile(); - } - } - - @Override - public boolean onBackPressed() { - if (mPaused) return true; - if (mMediaRecorderRecording) { - onStopVideoRecording(); - return true; - } else if (mUI.hidePieRenderer()) { - return true; - } else { - return mUI.removeTopLevelPopup(); - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - // Do not handle any key if the activity is paused. - if (mPaused) { - return true; - } - - switch (keyCode) { - case KeyEvent.KEYCODE_CAMERA: - if (event.getRepeatCount() == 0) { - mUI.clickShutter(); - return true; - } - break; - case KeyEvent.KEYCODE_DPAD_CENTER: - if (event.getRepeatCount() == 0) { - mUI.clickShutter(); - return true; - } - break; - case KeyEvent.KEYCODE_MENU: - if (mMediaRecorderRecording) return true; - break; - } - return false; - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_CAMERA: - mUI.pressShutter(false); - return true; - } - return false; - } - - @Override - public boolean isVideoCaptureIntent() { - String action = mActivity.getIntent().getAction(); - return (MediaStore.ACTION_VIDEO_CAPTURE.equals(action)); - } - - private void doReturnToCaller(boolean valid) { - Intent resultIntent = new Intent(); - int resultCode; - if (valid) { - resultCode = Activity.RESULT_OK; - resultIntent.setData(mCurrentVideoUri); - } else { - resultCode = Activity.RESULT_CANCELED; - } - mActivity.setResultEx(resultCode, resultIntent); - mActivity.finish(); - } - - private void cleanupEmptyFile() { - if (mVideoFilename != null) { - File f = new File(mVideoFilename); - if (f.length() == 0 && f.delete()) { - Log.v(TAG, "Empty video file deleted: " + mVideoFilename); - mVideoFilename = null; - } - } - } - - private void setupMediaRecorderPreviewDisplay() { - // Nothing to do here if using SurfaceTexture. - if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) { - // We stop the preview here before unlocking the device because we - // need to change the SurfaceTexture to SurfaceView for preview. - stopPreview(); - mCameraDevice.setPreviewDisplay(mUI.getSurfaceHolder()); - // The orientation for SurfaceTexture is different from that for - // SurfaceView. For SurfaceTexture we don't need to consider the - // display rotation. Just consider the sensor's orientation and we - // will set the orientation correctly when showing the texture. - // Gallery will handle the orientation for the preview. For - // SurfaceView we will have to take everything into account so the - // display rotation is considered. - mCameraDevice.setDisplayOrientation( - Util.getDisplayOrientation(mDisplayRotation, mCameraId)); - mCameraDevice.startPreview(); - mPreviewing = true; - mMediaRecorder.setPreviewDisplay(mUI.getSurfaceHolder().getSurface()); - } - } - - // Prepares media recorder. - private void initializeRecorder() { - Log.v(TAG, "initializeRecorder"); - // If the mCameraDevice is null, then this activity is going to finish - if (mCameraDevice == null) return; - - if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) { - // Set the SurfaceView to visible so the surface gets created. - // surfaceCreated() is called immediately when the visibility is - // changed to visible. Thus, mSurfaceViewReady should become true - // right after calling setVisibility(). - mUI.showSurfaceView(); - } - - Intent intent = mActivity.getIntent(); - Bundle myExtras = intent.getExtras(); - - long requestedSizeLimit = 0; - closeVideoFileDescriptor(); - if (mIsVideoCaptureIntent && myExtras != null) { - Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); - if (saveUri != null) { - try { - mVideoFileDescriptor = - mContentResolver.openFileDescriptor(saveUri, "rw"); - mCurrentVideoUri = saveUri; - } catch (java.io.FileNotFoundException ex) { - // invalid uri - Log.e(TAG, ex.toString()); - } - } - requestedSizeLimit = myExtras.getLong(MediaStore.EXTRA_SIZE_LIMIT); - } - mMediaRecorder = new MediaRecorder(); - - setupMediaRecorderPreviewDisplay(); - // Unlock the camera object before passing it to media recorder. - mCameraDevice.unlock(); - mMediaRecorder.setCamera(mCameraDevice.getCamera()); - if (!mCaptureTimeLapse) { - mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); - } - mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); - mMediaRecorder.setProfile(mProfile); - mMediaRecorder.setMaxDuration(mMaxVideoDurationInMs); - if (mCaptureTimeLapse) { - double fps = 1000 / (double) mTimeBetweenTimeLapseFrameCaptureMs; - setCaptureRate(mMediaRecorder, fps); - } - - setRecordLocation(); - - // Set output file. - // Try Uri in the intent first. If it doesn't exist, use our own - // instead. - if (mVideoFileDescriptor != null) { - mMediaRecorder.setOutputFile(mVideoFileDescriptor.getFileDescriptor()); - } else { - generateVideoFilename(mProfile.fileFormat); - mMediaRecorder.setOutputFile(mVideoFilename); - } - - // Set maximum file size. - long maxFileSize = mActivity.getStorageSpace() - Storage.LOW_STORAGE_THRESHOLD; - 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. - } - - // See android.hardware.Camera.Parameters.setRotation for - // documentation. - // Note that mOrientation here is the device orientation, which is the opposite of - // what activity.getWindowManager().getDefaultDisplay().getRotation() would return, - // which is the orientation the graphics need to rotate in order to render correctly. - int rotation = 0; - if (mOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) { - CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; - if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { - rotation = (info.orientation - mOrientation + 360) % 360; - } else { // back-facing camera - rotation = (info.orientation + mOrientation) % 360; - } - } - mMediaRecorder.setOrientationHint(rotation); - - try { - mMediaRecorder.prepare(); - } catch (IOException e) { - Log.e(TAG, "prepare failed for " + mVideoFilename, e); - releaseMediaRecorder(); - throw new RuntimeException(e); - } - - mMediaRecorder.setOnErrorListener(this); - mMediaRecorder.setOnInfoListener(this); - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - private static void setCaptureRate(MediaRecorder recorder, double fps) { - recorder.setCaptureRate(fps); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void setRecordLocation() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - Location loc = mLocationManager.getCurrentLocation(); - if (loc != null) { - mMediaRecorder.setLocation((float) loc.getLatitude(), - (float) loc.getLongitude()); - } - } - } - - private void initializeEffectsPreview() { - Log.v(TAG, "initializeEffectsPreview"); - // If the mCameraDevice is null, then this activity is going to finish - if (mCameraDevice == null) return; - - boolean inLandscape = (mActivity.getResources().getConfiguration().orientation - == Configuration.ORIENTATION_LANDSCAPE); - - CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; - - mEffectsDisplayResult = false; - mEffectsRecorder = new EffectsRecorder(mActivity); - - // TODO: Confirm none of the following need to go to initializeEffectsRecording() - // and none of these change even when the preview is not refreshed. - mEffectsRecorder.setCameraDisplayOrientation(mCameraDisplayOrientation); - mEffectsRecorder.setCamera(mCameraDevice); - mEffectsRecorder.setCameraFacing(info.facing); - mEffectsRecorder.setProfile(mProfile); - mEffectsRecorder.setEffectsListener(this); - mEffectsRecorder.setOnInfoListener(this); - mEffectsRecorder.setOnErrorListener(this); - - // The input of effects recorder is affected by - // android.hardware.Camera.setDisplayOrientation. Its value only - // compensates the camera orientation (no Display.getRotation). So the - // orientation hint here should only consider sensor orientation. - int orientation = 0; - if (mOrientation != OrientationEventListener.ORIENTATION_UNKNOWN) { - orientation = mOrientation; - } - mEffectsRecorder.setOrientationHint(orientation); - - mEffectsRecorder.setPreviewSurfaceTexture(mUI.getSurfaceTexture(), - mUI.getPreviewWidth(), mUI.getPreviewHeight()); - - if (mEffectType == EffectsRecorder.EFFECT_BACKDROPPER && - ((String) mEffectParameter).equals(EFFECT_BG_FROM_GALLERY)) { - mEffectsRecorder.setEffect(mEffectType, mEffectUriFromGallery); - } else { - mEffectsRecorder.setEffect(mEffectType, mEffectParameter); - } - } - - private void initializeEffectsRecording() { - Log.v(TAG, "initializeEffectsRecording"); - - Intent intent = mActivity.getIntent(); - Bundle myExtras = intent.getExtras(); - - long requestedSizeLimit = 0; - closeVideoFileDescriptor(); - if (mIsVideoCaptureIntent && myExtras != null) { - Uri saveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT); - if (saveUri != null) { - try { - mVideoFileDescriptor = - mContentResolver.openFileDescriptor(saveUri, "rw"); - mCurrentVideoUri = saveUri; - } catch (java.io.FileNotFoundException ex) { - // invalid uri - Log.e(TAG, ex.toString()); - } - } - requestedSizeLimit = myExtras.getLong(MediaStore.EXTRA_SIZE_LIMIT); - } - - mEffectsRecorder.setProfile(mProfile); - // important to set the capture rate to zero if not timelapsed, since the - // effectsrecorder object does not get created again for each recording - // session - if (mCaptureTimeLapse) { - mEffectsRecorder.setCaptureRate((1000 / (double) mTimeBetweenTimeLapseFrameCaptureMs)); - } else { - mEffectsRecorder.setCaptureRate(0); - } - - // Set output file - if (mVideoFileDescriptor != null) { - mEffectsRecorder.setOutputFile(mVideoFileDescriptor.getFileDescriptor()); - } else { - generateVideoFilename(mProfile.fileFormat); - mEffectsRecorder.setOutputFile(mVideoFilename); - } - - // Set maximum file size. - long maxFileSize = mActivity.getStorageSpace() - Storage.LOW_STORAGE_THRESHOLD; - if (requestedSizeLimit > 0 && requestedSizeLimit < maxFileSize) { - maxFileSize = requestedSizeLimit; - } - mEffectsRecorder.setMaxFileSize(maxFileSize); - mEffectsRecorder.setMaxDuration(mMaxVideoDurationInMs); - } - - - private void releaseMediaRecorder() { - Log.v(TAG, "Releasing media recorder."); - if (mMediaRecorder != null) { - cleanupEmptyFile(); - mMediaRecorder.reset(); - mMediaRecorder.release(); - mMediaRecorder = null; - } - mVideoFilename = null; - } - - private void releaseEffectsRecorder() { - Log.v(TAG, "Releasing effects recorder."); - if (mEffectsRecorder != null) { - cleanupEmptyFile(); - mEffectsRecorder.release(); - mEffectsRecorder = null; - } - mEffectType = EffectsRecorder.EFFECT_NONE; - mVideoFilename = null; - } - - private void generateVideoFilename(int outputFileFormat) { - long dateTaken = System.currentTimeMillis(); - String title = createName(dateTaken); - // Used when emailing. - String filename = title + convertOutputFormatToFileExt(outputFileFormat); - String mime = convertOutputFormatToMimeType(outputFileFormat); - String path = Storage.DIRECTORY + '/' + filename; - String tmpPath = path + ".tmp"; - mCurrentVideoValues = new ContentValues(9); - mCurrentVideoValues.put(Video.Media.TITLE, title); - mCurrentVideoValues.put(Video.Media.DISPLAY_NAME, filename); - mCurrentVideoValues.put(Video.Media.DATE_TAKEN, dateTaken); - mCurrentVideoValues.put(MediaColumns.DATE_MODIFIED, dateTaken / 1000); - mCurrentVideoValues.put(Video.Media.MIME_TYPE, mime); - mCurrentVideoValues.put(Video.Media.DATA, path); - mCurrentVideoValues.put(Video.Media.RESOLUTION, - Integer.toString(mProfile.videoFrameWidth) + "x" + - Integer.toString(mProfile.videoFrameHeight)); - Location loc = mLocationManager.getCurrentLocation(); - if (loc != null) { - mCurrentVideoValues.put(Video.Media.LATITUDE, loc.getLatitude()); - mCurrentVideoValues.put(Video.Media.LONGITUDE, loc.getLongitude()); - } - mVideoFilename = tmpPath; - Log.v(TAG, "New video filename: " + mVideoFilename); - } - - private void saveVideo() { - if (mVideoFileDescriptor == null) { - long duration = SystemClock.uptimeMillis() - mRecordingStartTime; - if (duration > 0) { - if (mCaptureTimeLapse) { - duration = getTimeLapseVideoLength(duration); - } - } else { - Log.w(TAG, "Video duration <= 0 : " + duration); - } - mActivity.getMediaSaveService().addVideo(mCurrentVideoFilename, - duration, mCurrentVideoValues, - mOnVideoSavedListener, mContentResolver); - } - mCurrentVideoValues = null; - } - - 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 PreferenceGroup filterPreferenceScreenByIntent( - PreferenceGroup screen) { - Intent intent = mActivity.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_QUALITY); - } - return screen; - } - - // from MediaRecorder.OnErrorListener - @Override - public void onError(MediaRecorder mr, int what, int extra) { - Log.e(TAG, "MediaRecorder error. what=" + what + ". extra=" + extra); - if (what == MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN) { - // We may have run out of space on the sdcard. - stopVideoRecording(); - mActivity.updateStorageSpaceAndHint(); - } - } - - // from MediaRecorder.OnInfoListener - @Override - public void onInfo(MediaRecorder mr, int what, int extra) { - if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { - if (mMediaRecorderRecording) onStopVideoRecording(); - } else if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) { - if (mMediaRecorderRecording) onStopVideoRecording(); - - // Show the toast. - Toast.makeText(mActivity, 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"); - - mActivity.sendBroadcast(i); - } - - // For testing. - public boolean isRecording() { - return mMediaRecorderRecording; - } - - private void startVideoRecording() { - Log.v(TAG, "startVideoRecording"); - mUI.cancelAnimations(); - mUI.setSwipingEnabled(false); - - mActivity.updateStorageSpaceAndHint(); - if (mActivity.getStorageSpace() <= Storage.LOW_STORAGE_THRESHOLD) { - Log.v(TAG, "Storage issue, ignore the start request"); - return; - } - - //?? - //if (!mCameraDevice.waitDone()) return; - mCurrentVideoUri = null; - if (effectsActive()) { - initializeEffectsRecording(); - if (mEffectsRecorder == null) { - Log.e(TAG, "Fail to initialize effect recorder"); - return; - } - } else { - initializeRecorder(); - if (mMediaRecorder == null) { - Log.e(TAG, "Fail to initialize media recorder"); - return; - } - } - - pauseAudioPlayback(); - - if (effectsActive()) { - try { - mEffectsRecorder.startRecording(); - } catch (RuntimeException e) { - Log.e(TAG, "Could not start effects recorder. ", e); - releaseEffectsRecorder(); - return; - } - } else { - try { - mMediaRecorder.start(); // Recording is now started - } catch (RuntimeException e) { - Log.e(TAG, "Could not start media recorder. ", e); - releaseMediaRecorder(); - // If start fails, frameworks will not lock the camera for us. - mCameraDevice.lock(); - return; - } - } - - // Make sure the video recording has started before announcing - // this in accessibility. - AccessibilityUtils.makeAnnouncement(mUI.getShutterButton(), - mActivity.getString(R.string.video_recording_started)); - - // The parameters might have been altered by MediaRecorder already. - // We need to force mCameraDevice to refresh before getting it. - mCameraDevice.refreshParameters(); - // The parameters may have been changed by MediaRecorder upon starting - // recording. We need to alter the parameters if we support camcorder - // zoom. To reduce latency when setting the parameters during zoom, we - // update mParameters here once. - if (ApiHelper.HAS_ZOOM_WHEN_RECORDING) { - mParameters = mCameraDevice.getParameters(); - } - - mUI.enableCameraControls(false); - - mMediaRecorderRecording = true; - mOrientationManager.lockOrientation(); - mRecordingStartTime = SystemClock.uptimeMillis(); - mUI.showRecordingUI(true, mParameters.isZoomSupported()); - - updateRecordingTime(); - keepScreenOn(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA, - UsageStatistics.ACTION_CAPTURE_START, "Video"); - } - - private Bitmap getVideoThumbnail() { - Bitmap bitmap = null; - if (mVideoFileDescriptor != null) { - bitmap = Thumbnail.createVideoThumbnailBitmap(mVideoFileDescriptor.getFileDescriptor(), - mDesiredPreviewWidth); - } else if (mCurrentVideoFilename != null) { - bitmap = Thumbnail.createVideoThumbnailBitmap(mCurrentVideoFilename, - mDesiredPreviewWidth); - } - if (bitmap != null) { - // MetadataRetriever already rotates the thumbnail. We should rotate - // it to match the UI orientation (and mirror if it is front-facing camera). - CameraInfo[] info = CameraHolder.instance().getCameraInfo(); - boolean mirror = (info[mCameraId].facing == CameraInfo.CAMERA_FACING_FRONT); - bitmap = Util.rotateAndMirror(bitmap, 0, mirror); - } - return bitmap; - } - - private void showCaptureResult() { - mIsInReviewMode = true; - Bitmap bitmap = getVideoThumbnail(); - if (bitmap != null) { - mUI.showReviewImage(bitmap); - } - mUI.showReviewControls(); - mUI.enableCameraControls(false); - mUI.showTimeLapseUI(false); - } - - private void hideAlert() { - mUI.enableCameraControls(true); - mUI.hideReviewUI(); - if (mCaptureTimeLapse) { - mUI.showTimeLapseUI(true); - } - } - - private boolean stopVideoRecording() { - Log.v(TAG, "stopVideoRecording"); - mUI.setSwipingEnabled(true); - mUI.showSwitcher(); - - boolean fail = false; - if (mMediaRecorderRecording) { - boolean shouldAddToMediaStoreNow = false; - - try { - if (effectsActive()) { - // This is asynchronous, so we can't add to media store now because thumbnail - // may not be ready. In such case saveVideo() is called later - // through a callback from the MediaEncoderFilter to EffectsRecorder, - // and then to the VideoModule. - mEffectsRecorder.stopRecording(); - } else { - mMediaRecorder.setOnErrorListener(null); - mMediaRecorder.setOnInfoListener(null); - mMediaRecorder.stop(); - shouldAddToMediaStoreNow = true; - } - mCurrentVideoFilename = mVideoFilename; - Log.v(TAG, "stopVideoRecording: Setting current video filename: " - + mCurrentVideoFilename); - AccessibilityUtils.makeAnnouncement(mUI.getShutterButton(), - mActivity.getString(R.string.video_recording_stopped)); - } catch (RuntimeException e) { - Log.e(TAG, "stop fail", e); - if (mVideoFilename != null) deleteVideoFile(mVideoFilename); - fail = true; - } - mMediaRecorderRecording = false; - mOrientationManager.unlockOrientation(); - - // If the activity is paused, this means activity is interrupted - // during recording. Release the camera as soon as possible because - // face unlock or other applications may need to use the camera. - // However, if the effects are active, then we can only release the - // camera and cannot release the effects recorder since that will - // stop the graph. It is possible to separate out the Camera release - // part and the effects release part. However, the effects recorder - // does hold on to the camera, hence, it needs to be "disconnected" - // from the camera in the closeCamera call. - if (mPaused) { - // Closing only the camera part if effects active. Effects will - // be closed in the callback from effects. - boolean closeEffects = !effectsActive(); - closeCamera(closeEffects); - } - - mUI.showRecordingUI(false, mParameters.isZoomSupported()); - if (!mIsVideoCaptureIntent) { - mUI.enableCameraControls(true); - } - // The orientation was fixed during video recording. Now make it - // reflect the device orientation as video recording is stopped. - mUI.setOrientationIndicator(0, true); - keepScreenOnAwhile(); - if (shouldAddToMediaStoreNow) { - saveVideo(); - } - } - // always release media recorder if no effects running - if (!effectsActive()) { - releaseMediaRecorder(); - if (!mPaused) { - mCameraDevice.lock(); - if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) { - stopPreview(); - mUI.hideSurfaceView(); - // Switch back to use SurfaceTexture for preview. - startPreview(); - } - } - } - // Update the parameters here because the parameters might have been altered - // by MediaRecorder. - if (!mPaused) mParameters = mCameraDevice.getParameters(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA, - fail ? UsageStatistics.ACTION_CAPTURE_FAIL : - UsageStatistics.ACTION_CAPTURE_DONE, "Video", - SystemClock.uptimeMillis() - mRecordingStartTime); - return fail; - } - - private void resetScreenOn() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - - private void keepScreenOnAwhile() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY); - } - - private void keepScreenOn() { - mHandler.removeMessages(CLEAR_SCREEN_DELAY); - mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - } - - private static String millisecondToTimeString(long milliSeconds, boolean displayCentiSeconds) { - long seconds = milliSeconds / 1000; // round down to compute seconds - long minutes = seconds / 60; - long hours = minutes / 60; - long remainderMinutes = minutes - (hours * 60); - long remainderSeconds = seconds - (minutes * 60); - - StringBuilder timeStringBuilder = new StringBuilder(); - - // Hours - if (hours > 0) { - if (hours < 10) { - timeStringBuilder.append('0'); - } - timeStringBuilder.append(hours); - - timeStringBuilder.append(':'); - } - - // Minutes - if (remainderMinutes < 10) { - timeStringBuilder.append('0'); - } - timeStringBuilder.append(remainderMinutes); - timeStringBuilder.append(':'); - - // Seconds - if (remainderSeconds < 10) { - timeStringBuilder.append('0'); - } - timeStringBuilder.append(remainderSeconds); - - // Centi seconds - if (displayCentiSeconds) { - timeStringBuilder.append('.'); - long remainderCentiSeconds = (milliSeconds - seconds * 1000) / 10; - if (remainderCentiSeconds < 10) { - timeStringBuilder.append('0'); - } - timeStringBuilder.append(remainderCentiSeconds); - } - - return timeStringBuilder.toString(); - } - - private long getTimeLapseVideoLength(long deltaMs) { - // For better approximation calculate fractional number of frames captured. - // This will update the video time at a higher resolution. - double numberOfFrames = (double) deltaMs / mTimeBetweenTimeLapseFrameCaptureMs; - return (long) (numberOfFrames / mProfile.videoFrameRate * 1000); - } - - 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 deltaAdjusted = delta; - if (countdownRemainingTime) { - deltaAdjusted = Math.max(0, mMaxVideoDurationInMs - deltaAdjusted) + 999; - } - String text; - - long targetNextUpdateDelay; - if (!mCaptureTimeLapse) { - text = millisecondToTimeString(deltaAdjusted, false); - targetNextUpdateDelay = 1000; - } else { - // The length of time lapse video is different from the length - // of the actual wall clock time elapsed. Display the video length - // only in format hh:mm:ss.dd, where dd are the centi seconds. - text = millisecondToTimeString(getTimeLapseVideoLength(delta), true); - targetNextUpdateDelay = mTimeBetweenTimeLapseFrameCaptureMs; - } - - mUI.setRecordingTime(text); - - if (mRecordingTimeCountsDown != countdownRemainingTime) { - // Avoid setting the color on every update, do it only - // when it needs changing. - mRecordingTimeCountsDown = countdownRemainingTime; - - int color = mActivity.getResources().getColor(countdownRemainingTime - ? R.color.recording_time_remaining_text - : R.color.recording_time_elapsed_text); - - mUI.setRecordingTimeTextColor(color); - } - - long actualNextUpdateDelay = targetNextUpdateDelay - (delta % targetNextUpdateDelay); - mHandler.sendEmptyMessageDelayed( - UPDATE_RECORD_TIME, actualNextUpdateDelay); - } - - private static boolean isSupported(String value, List<String> supported) { - return supported == null ? false : supported.indexOf(value) >= 0; - } - - @SuppressWarnings("deprecation") - private void setCameraParameters() { - mParameters.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight); - int[] fpsRange = Util.getMaxPreviewFpsRange(mParameters); - if (fpsRange.length > 0) { - mParameters.setPreviewFpsRange( - fpsRange[Parameters.PREVIEW_FPS_MIN_INDEX], - fpsRange[Parameters.PREVIEW_FPS_MAX_INDEX]); - } else { - mParameters.setPreviewFrameRate(mProfile.videoFrameRate); - } - - // Set flash mode. - String flashMode; - if (mUI.isVisible()) { - flashMode = mPreferences.getString( - CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE, - mActivity.getString(R.string.pref_camera_video_flashmode_default)); - } else { - flashMode = Parameters.FLASH_MODE_OFF; - } - List<String> supportedFlash = mParameters.getSupportedFlashModes(); - if (isSupported(flashMode, supportedFlash)) { - mParameters.setFlashMode(flashMode); - } else { - flashMode = mParameters.getFlashMode(); - if (flashMode == null) { - flashMode = mActivity.getString( - R.string.pref_camera_flashmode_no_flash); - } - } - - // Set white balance parameter. - String whiteBalance = mPreferences.getString( - CameraSettings.KEY_WHITE_BALANCE, - mActivity.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 zoom. - if (mParameters.isZoomSupported()) { - mParameters.setZoom(mZoomValue); - } - - // Set continuous autofocus. - List<String> supportedFocus = mParameters.getSupportedFocusModes(); - if (isSupported(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO, supportedFocus)) { - mParameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); - } - - mParameters.set(Util.RECORDING_HINT, Util.TRUE); - - // Enable video stabilization. Convenience methods not available in API - // level <= 14 - String vstabSupported = mParameters.get("video-stabilization-supported"); - if ("true".equals(vstabSupported)) { - mParameters.set("video-stabilization", "true"); - } - - // Set picture size. - // The logic here is different from the logic in still-mode camera. - // There we determine the preview size based on the picture size, but - // here we determine the picture size based on the preview size. - List<Size> supported = mParameters.getSupportedPictureSizes(); - Size optimalSize = Util.getOptimalVideoSnapshotPictureSize(supported, - (double) mDesiredPreviewWidth / mDesiredPreviewHeight); - Size original = mParameters.getPictureSize(); - if (!original.equals(optimalSize)) { - mParameters.setPictureSize(optimalSize.width, optimalSize.height); - } - Log.v(TAG, "Video snapshot size is " + optimalSize.width + "x" + - optimalSize.height); - - // Set JPEG quality. - int jpegQuality = CameraProfile.getJpegEncodingQualityParameter(mCameraId, - CameraProfile.QUALITY_HIGH); - mParameters.setJpegQuality(jpegQuality); - - mCameraDevice.setParameters(mParameters); - // Keep preview size up to date. - mParameters = mCameraDevice.getParameters(); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - switch (requestCode) { - case REQUEST_EFFECT_BACKDROPPER: - if (resultCode == Activity.RESULT_OK) { - // onActivityResult() runs before onResume(), so this parameter will be - // seen by startPreview from onResume() - mEffectUriFromGallery = data.getData().toString(); - Log.v(TAG, "Received URI from gallery: " + mEffectUriFromGallery); - mResetEffect = false; - } else { - mEffectUriFromGallery = null; - Log.w(TAG, "No URI from gallery"); - mResetEffect = true; - } - break; - } - } - - @Override - public void onEffectsUpdate(int effectId, int effectMsg) { - Log.v(TAG, "onEffectsUpdate. Effect Message = " + effectMsg); - if (effectMsg == EffectsRecorder.EFFECT_MSG_EFFECTS_STOPPED) { - // Effects have shut down. Hide learning message if any, - // and restart regular preview. - checkQualityAndStartPreview(); - } else if (effectMsg == EffectsRecorder.EFFECT_MSG_RECORDING_DONE) { - // This follows the codepath from onStopVideoRecording. - if (mEffectsDisplayResult) { - saveVideo(); - if (mIsVideoCaptureIntent) { - if (mQuickCapture) { - doReturnToCaller(true); - } else { - showCaptureResult(); - } - } - } - mEffectsDisplayResult = false; - // In onPause, these were not called if the effects were active. We - // had to wait till the effects recording is complete to do this. - if (mPaused) { - closeVideoFileDescriptor(); - } - } else if (effectMsg == EffectsRecorder.EFFECT_MSG_PREVIEW_RUNNING) { - // Enable the shutter button once the preview is complete. - mUI.enableShutter(true); - } - // In onPause, this was not called if the effects were active. We had to - // wait till the effects completed to do this. - if (mPaused) { - Log.v(TAG, "OnEffectsUpdate: closing effects if activity paused"); - closeEffects(); - } - } - - public void onCancelBgTraining(View v) { - // Write default effect out to shared prefs - writeDefaultEffectToPrefs(); - // Tell VideoCamer to re-init based on new shared pref values. - onSharedPreferenceChanged(); - } - - @Override - public synchronized void onEffectsError(Exception exception, String fileName) { - // TODO: Eventually we may want to show the user an error dialog, and then restart the - // camera and encoder gracefully. For now, we just delete the file and bail out. - if (fileName != null && new File(fileName).exists()) { - deleteVideoFile(fileName); - } - try { - if (Class.forName("android.filterpacks.videosink.MediaRecorderStopException") - .isInstance(exception)) { - Log.w(TAG, "Problem recoding video file. Removing incomplete file."); - return; - } - } catch (ClassNotFoundException ex) { - Log.w(TAG, ex); - } - throw new RuntimeException("Error during recording!", exception); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - Log.v(TAG, "onConfigurationChanged"); - setDisplayOrientation(); - } - - @Override - public void onOverriddenPreferencesClicked() { - } - - @Override - // TODO: Delete this after old camera code is removed - public void onRestorePreferencesClicked() { - } - - private boolean effectsActive() { - return (mEffectType != EffectsRecorder.EFFECT_NONE); - } - - @Override - public void onSharedPreferenceChanged() { - // ignore the events after "onPause()" or preview has not started yet - if (mPaused) return; - synchronized (mPreferences) { - // If mCameraDevice is not ready then we can set the parameter in - // startPreview(). - if (mCameraDevice == null) return; - - boolean recordLocation = RecordLocationPreference.get( - mPreferences, mContentResolver); - mLocationManager.recordLocation(recordLocation); - - // Check if the current effects selection has changed - if (updateEffectSelection()) return; - - readVideoPreferences(); - mUI.showTimeLapseUI(mCaptureTimeLapse); - // We need to restart the preview if preview size is changed. - Size size = mParameters.getPreviewSize(); - if (size.width != mDesiredPreviewWidth - || size.height != mDesiredPreviewHeight) { - if (!effectsActive()) { - stopPreview(); - } else { - mEffectsRecorder.release(); - mEffectsRecorder = null; - } - resizeForPreviewAspectRatio(); - startPreview(); // Parameters will be set in startPreview(). - } else { - setCameraParameters(); - } - mUI.updateOnScreenIndicators(mParameters, mPreferences); - } - } - - protected void setCameraId(int cameraId) { - ListPreference pref = mPreferenceGroup.findPreference(CameraSettings.KEY_CAMERA_ID); - pref.setValue("" + cameraId); - } - - private void switchCamera() { - if (mPaused) return; - - Log.d(TAG, "Start to switch camera."); - mCameraId = mPendingSwitchCameraId; - mPendingSwitchCameraId = -1; - setCameraId(mCameraId); - - closeCamera(); - mUI.collapseCameraControls(); - // Restart the camera and initialize the UI. From onCreate. - mPreferences.setLocalId(mActivity, mCameraId); - CameraSettings.upgradeLocalPreferences(mPreferences.getLocal()); - openCamera(); - readVideoPreferences(); - startPreview(); - initializeVideoSnapshot(); - resizeForPreviewAspectRatio(); - initializeVideoControl(); - - // From onResume - mZoomValue = 0; - mUI.initializeZoom(mParameters); - mUI.setOrientationIndicator(0, false); - - // Start switch camera animation. Post a message because - // onFrameAvailable from the old camera may already exist. - mHandler.sendEmptyMessage(SWITCH_CAMERA_START_ANIMATION); - mUI.updateOnScreenIndicators(mParameters, mPreferences); - } - - // Preview texture has been copied. Now camera can be released and the - // animation can be started. - @Override - public void onPreviewTextureCopied() { - mHandler.sendEmptyMessage(SWITCH_CAMERA); - } - - @Override - public void onCaptureTextureCopied() { - } - - private boolean updateEffectSelection() { - int previousEffectType = mEffectType; - Object previousEffectParameter = mEffectParameter; - mEffectType = CameraSettings.readEffectType(mPreferences); - mEffectParameter = CameraSettings.readEffectParameter(mPreferences); - - if (mEffectType == previousEffectType) { - if (mEffectType == EffectsRecorder.EFFECT_NONE) return false; - if (mEffectParameter.equals(previousEffectParameter)) return false; - } - Log.v(TAG, "New effect selection: " + mPreferences.getString( - CameraSettings.KEY_VIDEO_EFFECT, "none")); - - if (mEffectType == EffectsRecorder.EFFECT_NONE) { - // Stop effects and return to normal preview - mEffectsRecorder.stopPreview(); - mPreviewing = false; - return true; - } - if (mEffectType == EffectsRecorder.EFFECT_BACKDROPPER && - ((String) mEffectParameter).equals(EFFECT_BG_FROM_GALLERY)) { - // Request video from gallery to use for background - Intent i = new Intent(Intent.ACTION_PICK); - i.setDataAndType(Video.Media.EXTERNAL_CONTENT_URI, - "video/*"); - i.putExtra(Intent.EXTRA_LOCAL_ONLY, true); - mActivity.startActivityForResult(i, REQUEST_EFFECT_BACKDROPPER); - return true; - } - if (previousEffectType == EffectsRecorder.EFFECT_NONE) { - // Stop regular preview and start effects. - stopPreview(); - checkQualityAndStartPreview(); - } else { - // Switch currently running effect - mEffectsRecorder.setEffect(mEffectType, mEffectParameter); - } - return true; - } - - // Verifies that the current preview view size is correct before starting - // preview. If not, resets the surface texture and resizes the view. - private void checkQualityAndStartPreview() { - readVideoPreferences(); - mUI.showTimeLapseUI(mCaptureTimeLapse); - Size size = mParameters.getPreviewSize(); - if (size.width != mDesiredPreviewWidth - || size.height != mDesiredPreviewHeight) { - resizeForPreviewAspectRatio(); - } - // Start up preview again - startPreview(); - } - - private void initializeVideoSnapshot() { - if (mParameters == null) return; - if (Util.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) { - // Show the tap to focus toast if this is the first start. - if (mPreferences.getBoolean( - CameraSettings.KEY_VIDEO_FIRST_USE_HINT_SHOWN, true)) { - // Delay the toast for one second to wait for orientation. - mHandler.sendEmptyMessageDelayed(SHOW_TAP_TO_SNAPSHOT_TOAST, 1000); - } - } - } - - void showVideoSnapshotUI(boolean enabled) { - if (mParameters == null) return; - if (Util.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) { - if (enabled) { - mUI.animateFlash(); - } else { - mUI.showPreviewBorder(enabled); - } - mUI.enableShutter(!enabled); - } - } - - @Override - public void updateCameraAppView() { - if (!mPreviewing || mParameters.getFlashMode() == null) return; - - // When going to and back from gallery, we need to turn off/on the flash. - if (!mUI.isVisible()) { - if (mParameters.getFlashMode().equals(Parameters.FLASH_MODE_OFF)) { - mRestoreFlash = false; - return; - } - mRestoreFlash = true; - setCameraParameters(); - } else if (mRestoreFlash) { - mRestoreFlash = false; - setCameraParameters(); - } - } - - @Override - public void onSwitchMode(boolean toCamera) { - mUI.onSwitchMode(toCamera); - } - - private final class JpegPictureCallback implements CameraPictureCallback { - Location mLocation; - - public JpegPictureCallback(Location loc) { - mLocation = loc; - } - - @Override - public void onPictureTaken(byte [] jpegData, CameraProxy camera) { - Log.v(TAG, "onPictureTaken"); - mSnapshotInProgress = false; - showVideoSnapshotUI(false); - storeImage(jpegData, mLocation); - } - } - - private void storeImage(final byte[] data, Location loc) { - long dateTaken = System.currentTimeMillis(); - String title = Util.createJpegName(dateTaken); - ExifInterface exif = Exif.getExif(data); - int orientation = Exif.getOrientation(exif); - Size s = mParameters.getPictureSize(); - mActivity.getMediaSaveService().addImage( - data, title, dateTaken, loc, s.width, s.height, orientation, - exif, mOnPhotoSavedListener, mContentResolver); - } - - private boolean resetEffect() { - if (mResetEffect) { - String value = mPreferences.getString(CameraSettings.KEY_VIDEO_EFFECT, - mPrefVideoEffectDefault); - if (!mPrefVideoEffectDefault.equals(value)) { - writeDefaultEffectToPrefs(); - return true; - } - } - mResetEffect = true; - return false; - } - - private String convertOutputFormatToMimeType(int outputFileFormat) { - if (outputFileFormat == MediaRecorder.OutputFormat.MPEG_4) { - return "video/mp4"; - } - return "video/3gpp"; - } - - private String convertOutputFormatToFileExt(int outputFileFormat) { - if (outputFileFormat == MediaRecorder.OutputFormat.MPEG_4) { - return ".mp4"; - } - return ".3gp"; - } - - private void closeVideoFileDescriptor() { - if (mVideoFileDescriptor != null) { - try { - mVideoFileDescriptor.close(); - } catch (IOException e) { - Log.e(TAG, "Fail to close fd", e); - } - mVideoFileDescriptor = null; - } - } - - private void showTapToSnapshotToast() { - new RotateTextToast(mActivity, R.string.video_snapshot_hint, 0) - .show(); - // Clear the preference. - Editor editor = mPreferences.edit(); - editor.putBoolean(CameraSettings.KEY_VIDEO_FIRST_USE_HINT_SHOWN, false); - editor.apply(); - } - - @Override - public boolean updateStorageHintOnResume() { - return true; - } - - // required by OnPreferenceChangedListener - @Override - public void onCameraPickerClicked(int cameraId) { - if (mPaused || mPendingSwitchCameraId != -1) return; - - mPendingSwitchCameraId = cameraId; - Log.d(TAG, "Start to copy texture."); - // We need to keep a preview frame for the animation before - // releasing the camera. This will trigger onPreviewTextureCopied. - // TODO: ((CameraScreenNail) mActivity.mCameraScreenNail).copyTexture(); - // Disable all camera controls. - mSwitchingCamera = true; - - } - - @Override - public void onShowSwitcherPopup() { - mUI.onShowSwitcherPopup(); - } - - @Override - public void onMediaSaveServiceConnected(MediaSaveService s) { - // do nothing. - } - - @Override - public void onPreviewUIReady() { - startPreview(); - } - - @Override - public void onPreviewUIDestroyed() { - stopPreview(); - } -} diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java deleted file mode 100644 index 72587381c..000000000 --- a/src/com/android/camera/VideoUI.java +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.animation.Animator; -import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.graphics.SurfaceTexture; -import android.hardware.Camera.Parameters; -import android.os.Handler; -import android.os.Message; -import android.util.Log; -import android.view.Gravity; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.TextureView; -import android.view.TextureView.SurfaceTextureListener; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnLayoutChangeListener; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.FrameLayout.LayoutParams; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.android.camera.CameraPreference.OnPreferenceChangedListener; -import com.android.camera.ui.AbstractSettingPopup; -import com.android.camera.ui.CameraControls; -import com.android.camera.ui.CameraRootView; -import com.android.camera.ui.CameraSwitcher; -import com.android.camera.ui.CameraSwitcher.CameraSwitchListener; -import com.android.camera.ui.PieRenderer; -import com.android.camera.ui.RenderOverlay; -import com.android.camera.ui.RotateLayout; -import com.android.camera.ui.ZoomRenderer; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.List; - -public class VideoUI implements PieRenderer.PieListener, - PreviewGestures.SingleTapListener, - CameraRootView.MyDisplayListener, - SurfaceTextureListener, SurfaceHolder.Callback { - private static final String TAG = "CAM_VideoUI"; - private static final int UPDATE_TRANSFORM_MATRIX = 1; - // module fields - private CameraActivity mActivity; - private View mRootView; - private TextureView mTextureView; - // An review image having same size as preview. It is displayed when - // recording is stopped in capture intent. - private ImageView mReviewImage; - private View mReviewCancelButton; - private View mReviewDoneButton; - private View mReviewPlayButton; - private ShutterButton mShutterButton; - private CameraSwitcher mSwitcher; - private TextView mRecordingTimeView; - private LinearLayout mLabelsLinearLayout; - private View mTimeLapseLabel; - private RenderOverlay mRenderOverlay; - private PieRenderer mPieRenderer; - private VideoMenu mVideoMenu; - private CameraControls mCameraControls; - private AbstractSettingPopup mPopup; - private ZoomRenderer mZoomRenderer; - private PreviewGestures mGestures; - private View mMenuButton; - private View mBlocker; - private OnScreenIndicators mOnScreenIndicators; - private RotateLayout mRecordingTimeRect; - private final Object mLock = new Object(); - private SurfaceTexture mSurfaceTexture; - private VideoController mController; - private int mZoomMax; - private List<Integer> mZoomRatios; - private View mPreviewThumb; - private View mFlashOverlay; - - private SurfaceView mSurfaceView = null; - private int mPreviewWidth = 0; - private int mPreviewHeight = 0; - private float mSurfaceTextureUncroppedWidth; - private float mSurfaceTextureUncroppedHeight; - private float mAspectRatio = 4f / 3f; - private Matrix mMatrix = null; - private final AnimationManager mAnimationManager; - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case UPDATE_TRANSFORM_MATRIX: - setTransformMatrix(mPreviewWidth, mPreviewHeight); - break; - default: - break; - } - } - }; - private OnLayoutChangeListener mLayoutListener = new OnLayoutChangeListener() { - @Override - public void onLayoutChange(View v, int left, int top, int right, - int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - int width = right - left; - int height = bottom - top; - // Full-screen screennail - int w = width; - int h = height; - if (Util.getDisplayRotation(mActivity) % 180 != 0) { - w = height; - h = width; - } - if (mPreviewWidth != width || mPreviewHeight != height) { - mPreviewWidth = width; - mPreviewHeight = height; - onScreenSizeChanged(width, height, w, h); - } - } - }; - - public VideoUI(CameraActivity activity, VideoController controller, View parent) { - mActivity = activity; - mController = controller; - mRootView = parent; - mActivity.getLayoutInflater().inflate(R.layout.video_module, (ViewGroup) mRootView, true); - mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content); - mTextureView.setSurfaceTextureListener(this); - mRootView.addOnLayoutChangeListener(mLayoutListener); - ((CameraRootView) mRootView).setDisplayChangeListener(this); - mFlashOverlay = mRootView.findViewById(R.id.flash_overlay); - mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button); - mSwitcher = (CameraSwitcher) mRootView.findViewById(R.id.camera_switcher); - mSwitcher.setCurrentIndex(CameraSwitcher.VIDEO_MODULE_INDEX); - mSwitcher.setSwitchListener((CameraSwitchListener) mActivity); - initializeMiscControls(); - initializeControlByIntent(); - initializeOverlay(); - mAnimationManager = new AnimationManager(); - } - - - public void initializeSurfaceView() { - mSurfaceView = new SurfaceView(mActivity); - ((ViewGroup) mRootView).addView(mSurfaceView, 0); - mSurfaceView.getHolder().addCallback(this); - } - - private void initializeControlByIntent() { - mBlocker = mActivity.findViewById(R.id.blocker); - mMenuButton = mActivity.findViewById(R.id.menu); - mMenuButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (mPieRenderer != null) { - mPieRenderer.showInCenter(); - } - } - }); - - mCameraControls = (CameraControls) mActivity.findViewById(R.id.camera_controls); - mOnScreenIndicators = new OnScreenIndicators(mActivity, - mActivity.findViewById(R.id.on_screen_indicators)); - mOnScreenIndicators.resetToDefault(); - if (mController.isVideoCaptureIntent()) { - hideSwitcher(); - mActivity.getLayoutInflater().inflate(R.layout.review_module_control, - (ViewGroup) mCameraControls); - // Cannot use RotateImageView for "done" and "cancel" button because - // the tablet layout uses RotateLayout, which cannot be cast to - // RotateImageView. - mReviewDoneButton = mActivity.findViewById(R.id.btn_done); - mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel); - mReviewPlayButton = mActivity.findViewById(R.id.btn_play); - mReviewCancelButton.setVisibility(View.VISIBLE); - mReviewDoneButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mController.onReviewDoneClicked(v); - } - }); - mReviewCancelButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mController.onReviewCancelClicked(v); - } - }); - mReviewPlayButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - mController.onReviewPlayClicked(v); - } - }); - } - } - - public void setPreviewSize(int width, int height) { - if (width == 0 || height == 0) { - Log.w(TAG, "Preview size should not be 0."); - return; - } - if (width > height) { - mAspectRatio = (float) width / height; - } else { - mAspectRatio = (float) height / width; - } - mHandler.sendEmptyMessage(UPDATE_TRANSFORM_MATRIX); - } - - public int getPreviewWidth() { - return mPreviewWidth; - } - - public int getPreviewHeight() { - return mPreviewHeight; - } - - public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight) { - setTransformMatrix(width, height); - } - - private void setTransformMatrix(int width, int height) { - mMatrix = mTextureView.getTransform(mMatrix); - int orientation = Util.getDisplayRotation(mActivity); - float scaleX = 1f, scaleY = 1f; - float scaledTextureWidth, scaledTextureHeight; - if (width > height) { - scaledTextureWidth = Math.max(width, - (int) (height * mAspectRatio)); - scaledTextureHeight = Math.max(height, - (int)(width / mAspectRatio)); - } else { - scaledTextureWidth = Math.max(width, - (int) (height / mAspectRatio)); - scaledTextureHeight = Math.max(height, - (int) (width * mAspectRatio)); - } - - if (mSurfaceTextureUncroppedWidth != scaledTextureWidth || - mSurfaceTextureUncroppedHeight != scaledTextureHeight) { - mSurfaceTextureUncroppedWidth = scaledTextureWidth; - mSurfaceTextureUncroppedHeight = scaledTextureHeight; - } - scaleX = scaledTextureWidth / width; - scaleY = scaledTextureHeight / height; - mMatrix.setScale(scaleX, scaleY, (float) width / 2, (float) height / 2); - mTextureView.setTransform(mMatrix); - - if (mSurfaceView != null && mSurfaceView.getVisibility() == View.VISIBLE) { - LayoutParams lp = (LayoutParams) mSurfaceView.getLayoutParams(); - lp.width = (int) mSurfaceTextureUncroppedWidth; - lp.height = (int) mSurfaceTextureUncroppedHeight; - lp.gravity = Gravity.CENTER; - mSurfaceView.requestLayout(); - } - } - - /** - * Starts a flash animation - */ - public void animateFlash() { - mAnimationManager.startFlashAnimation(mFlashOverlay); - } - - /** - * Starts a capture animation - * @param bitmap the captured image that we shrink and slide in the animation - */ - public void animateCapture(Bitmap bitmap) { - ((ImageView) mPreviewThumb).setImageBitmap(bitmap); - mAnimationManager.startCaptureAnimation(mPreviewThumb); - } - - /** - * Cancels on-going animations - */ - public void cancelAnimations() { - mAnimationManager.cancelAnimations(); - } - - public void hideUI() { - mCameraControls.setVisibility(View.INVISIBLE); - mSwitcher.closePopup(); - } - - public void showUI() { - mCameraControls.setVisibility(View.VISIBLE); - } - - public void hideSwitcher() { - mSwitcher.closePopup(); - mSwitcher.setVisibility(View.INVISIBLE); - } - - public void showSwitcher() { - mSwitcher.setVisibility(View.VISIBLE); - } - - public boolean collapseCameraControls() { - boolean ret = false; - if (mPopup != null) { - dismissPopup(false); - ret = true; - } - return ret; - } - - public boolean removeTopLevelPopup() { - if (mPopup != null) { - dismissPopup(true); - return true; - } - return false; - } - - public void enableCameraControls(boolean enable) { - if (mGestures != null) { - mGestures.setZoomOnly(!enable); - } - if (mPieRenderer != null && mPieRenderer.showsItems()) { - mPieRenderer.hide(); - } - } - - public void overrideSettings(final String... keyvalues) { - mVideoMenu.overrideSettings(keyvalues); - } - - public void setOrientationIndicator(int orientation, boolean animation) { - // We change the orientation of the linearlayout only for phone UI - // because when in portrait the width is not enough. - if (mLabelsLinearLayout != null) { - if (((orientation / 90) & 1) == 0) { - mLabelsLinearLayout.setOrientation(LinearLayout.VERTICAL); - } else { - mLabelsLinearLayout.setOrientation(LinearLayout.HORIZONTAL); - } - } - mRecordingTimeRect.setOrientation(0, animation); - } - - public SurfaceHolder getSurfaceHolder() { - return mSurfaceView.getHolder(); - } - - public void hideSurfaceView() { - mSurfaceView.setVisibility(View.GONE); - mTextureView.setVisibility(View.VISIBLE); - setTransformMatrix(mPreviewWidth, mPreviewHeight); - } - - public void showSurfaceView() { - mSurfaceView.setVisibility(View.VISIBLE); - mTextureView.setVisibility(View.GONE); - setTransformMatrix(mPreviewWidth, mPreviewHeight); - } - - private void initializeOverlay() { - mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay); - if (mPieRenderer == null) { - mPieRenderer = new PieRenderer(mActivity); - mVideoMenu = new VideoMenu(mActivity, this, mPieRenderer); - mPieRenderer.setPieListener(this); - } - mRenderOverlay.addRenderer(mPieRenderer); - if (mZoomRenderer == null) { - mZoomRenderer = new ZoomRenderer(mActivity); - } - mRenderOverlay.addRenderer(mZoomRenderer); - if (mGestures == null) { - mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer); - mRenderOverlay.setGestures(mGestures); - } - mGestures.setRenderOverlay(mRenderOverlay); - - mPreviewThumb = mActivity.findViewById(R.id.preview_thumb); - mPreviewThumb.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - // TODO: Go to filmstrip view - } - }); - } - - public void setPrefChangedListener(OnPreferenceChangedListener listener) { - mVideoMenu.setListener(listener); - } - - private void initializeMiscControls() { - mReviewImage = (ImageView) mRootView.findViewById(R.id.review_image); - mShutterButton.setImageResource(R.drawable.btn_new_shutter_video); - mShutterButton.setOnShutterButtonListener(mController); - mShutterButton.setVisibility(View.VISIBLE); - mShutterButton.requestFocus(); - mShutterButton.enableTouch(true); - mRecordingTimeView = (TextView) mRootView.findViewById(R.id.recording_time); - mRecordingTimeRect = (RotateLayout) mRootView.findViewById(R.id.recording_time_rect); - mTimeLapseLabel = mRootView.findViewById(R.id.time_lapse_label); - // The R.id.labels can only be found in phone layout. - // That is, mLabelsLinearLayout should be null in tablet layout. - mLabelsLinearLayout = (LinearLayout) mRootView.findViewById(R.id.labels); - } - - public void updateOnScreenIndicators(Parameters param, ComboPreferences prefs) { - mOnScreenIndicators.updateFlashOnScreenIndicator(param.getFlashMode()); - boolean location = RecordLocationPreference.get( - prefs, mActivity.getContentResolver()); - mOnScreenIndicators.updateLocationIndicator(location); - - } - - public void setAspectRatio(double ratio) { - // mPreviewFrameLayout.setAspectRatio(ratio); - } - - public void showTimeLapseUI(boolean enable) { - if (mTimeLapseLabel != null) { - mTimeLapseLabel.setVisibility(enable ? View.VISIBLE : View.GONE); - } - } - - private void openMenu() { - if (mPieRenderer != null) { - mPieRenderer.showInCenter(); - } - } - - public void showPopup(AbstractSettingPopup popup) { - hideUI(); - mBlocker.setVisibility(View.INVISIBLE); - setShowMenu(false); - mPopup = popup; - mPopup.setVisibility(View.VISIBLE); - FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, - LayoutParams.WRAP_CONTENT); - lp.gravity = Gravity.CENTER; - ((FrameLayout) mRootView).addView(mPopup, lp); - } - - public void dismissPopup(boolean topLevelOnly) { - dismissPopup(topLevelOnly, true); - } - - public void dismissPopup(boolean topLevelPopupOnly, boolean fullScreen) { - // In review mode, we do not want to bring up the camera UI - if (mController.isInReviewMode()) return; - - if (fullScreen) { - showUI(); - mBlocker.setVisibility(View.VISIBLE); - } - setShowMenu(fullScreen); - if (mPopup != null) { - ((FrameLayout) mRootView).removeView(mPopup); - mPopup = null; - } - mVideoMenu.popupDismissed(topLevelPopupOnly); - } - - public void onShowSwitcherPopup() { - hidePieRenderer(); - } - - public boolean hidePieRenderer() { - if (mPieRenderer != null && mPieRenderer.showsItems()) { - mPieRenderer.hide(); - return true; - } - return false; - } - - // disable preview gestures after shutter is pressed - public void setShutterPressed(boolean pressed) { - if (mGestures == null) return; - mGestures.setEnabled(!pressed); - } - - public void enableShutter(boolean enable) { - if (mShutterButton != null) { - mShutterButton.setEnabled(enable); - } - } - - // PieListener - @Override - public void onPieOpened(int centerX, int centerY) { - setSwipingEnabled(false); - dismissPopup(false, true); - } - - @Override - public void onPieClosed() { - setSwipingEnabled(true); - } - - public void setSwipingEnabled(boolean enable) { - mActivity.setSwipingEnabled(enable); - } - - public void showPreviewBorder(boolean enable) { - // TODO: mPreviewFrameLayout.showBorder(enable); - } - - // SingleTapListener - // Preview area is touched. Take a picture. - @Override - public void onSingleTapUp(View view, int x, int y) { - mController.onSingleTapUp(view, x, y); - } - - public void showRecordingUI(boolean recording, boolean zoomSupported) { - mMenuButton.setVisibility(recording ? View.GONE : View.VISIBLE); - mOnScreenIndicators.setVisibility(recording ? View.GONE : View.VISIBLE); - if (recording) { - mShutterButton.setImageResource(R.drawable.btn_shutter_video_recording); - hideSwitcher(); - mRecordingTimeView.setText(""); - mRecordingTimeView.setVisibility(View.VISIBLE); - // The camera is not allowed to be accessed in older api levels during - // recording. It is therefore necessary to hide the zoom UI on older - // platforms. - // See the documentation of android.media.MediaRecorder.start() for - // further explanation. - if (!ApiHelper.HAS_ZOOM_WHEN_RECORDING && zoomSupported) { - // TODO: disable zoom UI here. - } - } else { - mShutterButton.setImageResource(R.drawable.btn_new_shutter_video); - showSwitcher(); - mRecordingTimeView.setVisibility(View.GONE); - if (!ApiHelper.HAS_ZOOM_WHEN_RECORDING && zoomSupported) { - // TODO: enable zoom UI here. - } - } - } - - public void showReviewImage(Bitmap bitmap) { - mReviewImage.setImageBitmap(bitmap); - mReviewImage.setVisibility(View.VISIBLE); - } - - public void showReviewControls() { - Util.fadeOut(mShutterButton); - Util.fadeIn(mReviewDoneButton); - Util.fadeIn(mReviewPlayButton); - mReviewImage.setVisibility(View.VISIBLE); - mMenuButton.setVisibility(View.GONE); - mOnScreenIndicators.setVisibility(View.GONE); - } - - public void hideReviewUI() { - mReviewImage.setVisibility(View.GONE); - mShutterButton.setEnabled(true); - mMenuButton.setVisibility(View.VISIBLE); - mOnScreenIndicators.setVisibility(View.VISIBLE); - Util.fadeOut(mReviewDoneButton); - Util.fadeOut(mReviewPlayButton); - Util.fadeIn(mShutterButton); - } - - private void setShowMenu(boolean show) { - if (mOnScreenIndicators != null) { - mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE); - } - if (mMenuButton != null) { - mMenuButton.setVisibility(show ? View.VISIBLE : View.GONE); - } - } - - public void onSwitchMode(boolean toCamera) { - if (toCamera) { - showUI(); - } else { - hideUI(); - } - if (mGestures != null) { - mGestures.setEnabled(toCamera); - } - if (mPopup != null) { - dismissPopup(false, toCamera); - } - if (mRenderOverlay != null) { - // this can not happen in capture mode - mRenderOverlay.setVisibility(toCamera ? View.VISIBLE : View.GONE); - } - setShowMenu(toCamera); - } - - public void initializePopup(PreferenceGroup pref) { - mVideoMenu.initialize(pref); - } - - public void initializeZoom(Parameters param) { - if (param == null || !param.isZoomSupported()) { - mGestures.setZoomEnabled(false); - return; - } - mGestures.setZoomEnabled(true); - mZoomMax = param.getMaxZoom(); - mZoomRatios = param.getZoomRatios(); - // Currently we use immediate zoom for fast zooming to get better UX and - // there is no plan to take advantage of the smooth zoom. - mZoomRenderer.setZoomMax(mZoomMax); - mZoomRenderer.setZoom(param.getZoom()); - mZoomRenderer.setZoomValue(mZoomRatios.get(param.getZoom())); - mZoomRenderer.setOnZoomChangeListener(new ZoomChangeListener()); - } - - public void clickShutter() { - mShutterButton.performClick(); - } - - public void pressShutter(boolean pressed) { - mShutterButton.setPressed(pressed); - } - - public View getShutterButton() { - return mShutterButton; - } - - public void setRecordingTime(String text) { - mRecordingTimeView.setText(text); - } - - public void setRecordingTimeTextColor(int color) { - mRecordingTimeView.setTextColor(color); - } - - public boolean isVisible() { - return mTextureView.getVisibility() == View.VISIBLE; - } - - public void onDisplayChanged() { - mCameraControls.checkLayoutFlip(); - mController.updateCameraOrientation(); - } - - private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener { - @Override - public void onZoomValueChanged(int index) { - int newZoom = mController.onZoomChanged(index); - if (mZoomRenderer != null) { - mZoomRenderer.setZoomValue(mZoomRatios.get(newZoom)); - } - } - - @Override - public void onZoomStart() { - } - - @Override - public void onZoomEnd() { - } - } - - public SurfaceTexture getSurfaceTexture() { - return mSurfaceTexture; - } - - // SurfaceTexture callbacks - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - mSurfaceTexture = surface; - mController.onPreviewUIReady(); - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - mSurfaceTexture = null; - mController.onPreviewUIDestroyed(); - Log.d(TAG, "surfaceTexture is destroyed"); - return true; - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - } - - // SurfaceHolder callbacks - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - Log.v(TAG, "Surface changed. width=" + width + ". height=" + height); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - Log.v(TAG, "Surface created"); - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - Log.v(TAG, "Surface destroyed"); - mController.stopPreview(); - } -} diff --git a/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java b/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java deleted file mode 100644 index 5df87f5a8..000000000 --- a/src/com/android/camera/data/AbstractLocalDataAdapterWrapper.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2013 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.data; - -import android.content.ContentResolver; -import android.content.Context; -import android.net.Uri; - -/** - * An abstract {@link LocalDataAdapter} implementation to wrap another - * {@link LocalDataAdapter}. All implementations related to data id is not - * addressed in this abstract class since wrapping another data adapter - * surely makes things different for data id. - * - * @see FixedFirstDataAdapter - * @see FixedLastDataAdapter - */ -public abstract class AbstractLocalDataAdapterWrapper implements LocalDataAdapter { - - protected final LocalDataAdapter mAdapter; - protected int mSuggestedWidth; - protected int mSuggestedHeight; - - /** - * Constructor. - * - * @param wrappedAdapter The {@link LocalDataAdapter} to be wrapped. - */ - AbstractLocalDataAdapterWrapper(LocalDataAdapter wrappedAdapter) { - if (wrappedAdapter == null) { - throw new AssertionError("data adapter is null"); - } - mAdapter = wrappedAdapter; - } - - @Override - public void suggestViewSizeBound(int w, int h) { - mSuggestedWidth = w; - mSuggestedHeight = h; - } - - @Override - public void setListener(Listener listener) { - mAdapter.setListener(listener); - } - - @Override - public void requestLoad(ContentResolver resolver) { - mAdapter.requestLoad(resolver); - } - - @Override - public void addNewVideo(ContentResolver resolver, Uri uri) { - mAdapter.addNewVideo(resolver, uri); - } - - @Override - public void addNewPhoto(ContentResolver resolver, Uri uri) { - mAdapter.addNewPhoto(resolver, uri); - } - - @Override - public void insertData(LocalData data) { - mAdapter.insertData(data); - } - - @Override - public void flush() { - mAdapter.flush(); - } - - @Override - public boolean executeDeletion(Context context) { - return mAdapter.executeDeletion(context); - } - - @Override - public boolean undoDataRemoval() { - return mAdapter.undoDataRemoval(); - } - - @Override - public void refresh(ContentResolver resolver, Uri uri) { - mAdapter.refresh(resolver, uri); - } -} diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java deleted file mode 100644 index aaf5ebe59..000000000 --- a/src/com/android/camera/data/CameraDataAdapter.java +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (C) 2013 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.data; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.Cursor; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.AsyncTask; -import android.provider.MediaStore; -import android.util.Log; -import android.view.View; - -import com.android.camera.Storage; -import com.android.camera.ui.FilmStripView.ImageData; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * A {@link LocalDataAdapter} that provides data in the camera folder. - */ -public class CameraDataAdapter implements LocalDataAdapter { - private static final String TAG = "CAM_CameraDataAdapter"; - - private static final int DEFAULT_DECODE_SIZE = 3000; - private static final String[] CAMERA_PATH = { Storage.DIRECTORY + "%" }; - - private List<LocalData> mImages; - - private Listener mListener; - private Drawable mPlaceHolder; - - private int mSuggestedWidth = DEFAULT_DECODE_SIZE; - private int mSuggestedHeight = DEFAULT_DECODE_SIZE; - - private LocalData mLocalDataToDelete; - - public CameraDataAdapter(Drawable placeHolder) { - mPlaceHolder = placeHolder; - } - - @Override - public void requestLoad(ContentResolver resolver) { - QueryTask qtask = new QueryTask(); - qtask.execute(resolver); - } - - @Override - public LocalData getLocalData(int dataID) { - if (mImages == null || dataID < 0 || dataID >= mImages.size()) { - return null; - } - - return mImages.get(dataID); - } - - @Override - public int getTotalNumber() { - if (mImages == null) { - return 0; - } - return mImages.size(); - } - - @Override - public ImageData getImageData(int id) { - return getLocalData(id); - } - - @Override - public void suggestViewSizeBound(int w, int h) { - if (w <= 0 || h <= 0) { - mSuggestedWidth = mSuggestedHeight = DEFAULT_DECODE_SIZE; - } else { - mSuggestedWidth = (w < DEFAULT_DECODE_SIZE ? w : DEFAULT_DECODE_SIZE); - mSuggestedHeight = (h < DEFAULT_DECODE_SIZE ? h : DEFAULT_DECODE_SIZE); - } - } - - @Override - public View getView(Context c, int dataID) { - if (mImages == null) { - return null; - } - if (dataID >= mImages.size() || dataID < 0) { - return null; - } - - return mImages.get(dataID).getView( - c, mSuggestedWidth, mSuggestedHeight, - mPlaceHolder.getConstantState().newDrawable()); - } - - @Override - public void setListener(Listener listener) { - mListener = listener; - if (mImages != null) { - mListener.onDataLoaded(); - } - } - - @Override - public void onDataFullScreen(int dataID, boolean fullScreen) { - if (dataID < mImages.size() && dataID >= 0) { - mImages.get(dataID).onFullScreen(fullScreen); - } - } - - @Override - public boolean canSwipeInFullScreen(int dataID) { - if (dataID < mImages.size() && dataID > 0) { - return mImages.get(dataID).canSwipeInFullScreen(); - } - return true; - } - - @Override - public void removeData(Context c, int dataID) { - if (dataID >= mImages.size()) return; - LocalData d = mImages.remove(dataID); - // Delete previously removed data first. - executeDeletion(c); - mLocalDataToDelete = d; - mListener.onDataRemoved(dataID, d); - } - - // TODO: put the database query on background thread - @Override - public void addNewVideo(ContentResolver cr, Uri uri) { - Cursor c = cr.query(uri, - LocalData.Video.QUERY_PROJECTION, - MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH, - LocalData.Video.QUERY_ORDER); - if (c == null || !c.moveToFirst()) { - return; - } - int pos = findDataByContentUri(uri); - LocalData.Video newData = LocalData.Video.buildFromCursor(c); - if (pos != -1) { - // A duplicate one, just do a substitute. - updateData(pos, newData); - } else { - // A new data. - insertData(newData); - } - } - - // TODO: put the database query on background thread - @Override - public void addNewPhoto(ContentResolver cr, Uri uri) { - Cursor c = cr.query(uri, - LocalData.Photo.QUERY_PROJECTION, - MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH, - LocalData.Photo.QUERY_ORDER); - if (c == null || !c.moveToFirst()) { - return; - } - int pos = findDataByContentUri(uri); - LocalData.Photo newData = LocalData.Photo.buildFromCursor(c); - if (pos != -1) { - // a duplicate one, just do a substitute. - Log.v(TAG, "found duplicate photo"); - updateData(pos, newData); - } else { - // a new data. - insertData(newData); - } - } - - @Override - public int findDataByContentUri(Uri uri) { - for (int i = 0; i < mImages.size(); i++) { - Uri u = mImages.get(i).getContentUri(); - if (u == null) { - continue; - } - if (u.equals(uri)) { - return i; - } - } - return -1; - } - - @Override - public boolean undoDataRemoval() { - if (mLocalDataToDelete == null) return false; - LocalData d = mLocalDataToDelete; - mLocalDataToDelete = null; - insertData(d); - return true; - } - - @Override - public boolean executeDeletion(Context c) { - if (mLocalDataToDelete == null) return false; - - DeletionTask task = new DeletionTask(c); - task.execute(mLocalDataToDelete); - mLocalDataToDelete = null; - return true; - } - - @Override - public void flush() { - replaceData(null); - } - - @Override - public void refresh(ContentResolver resolver, Uri contentUri) { - int pos = findDataByContentUri(contentUri); - if (pos == -1) { - return; - } - - LocalData data = mImages.get(pos); - if (data.refresh(resolver)) { - updateData(pos, data); - } - } - - @Override - public void updateData(final int pos, LocalData data) { - mImages.set(pos, data); - if (mListener != null) { - mListener.onDataUpdated(new UpdateReporter() { - @Override - public boolean isDataRemoved(int dataID) { - return false; - } - - @Override - public boolean isDataUpdated(int dataID) { - return (dataID == pos); - } - }); - } - } - - @Override - public void insertData(LocalData data) { - if (mImages == null) { - mImages = new ArrayList<LocalData>(); - } - - // Since this function is mostly for adding the newest data, - // a simple linear search should yield the best performance over a - // binary search. - int pos = 0; - Comparator<LocalData> comp = new LocalData.NewestFirstComparator(); - for (; pos < mImages.size() - && comp.compare(data, mImages.get(pos)) > 0; pos++); - mImages.add(pos, data); - if (mListener != null) { - mListener.onDataInserted(pos, data); - } - } - - /** Update all the data */ - private void replaceData(List<LocalData> list) { - boolean changed = (list != mImages); - mImages = list; - if (changed) { - mListener.onDataLoaded(); - } - } - - private class QueryTask extends AsyncTask<ContentResolver, Void, List<LocalData>> { - @Override - protected List<LocalData> doInBackground(ContentResolver... resolver) { - List<LocalData> l = new ArrayList<LocalData>(); - // Photos - Cursor c = resolver[0].query( - LocalData.Photo.CONTENT_URI, - LocalData.Photo.QUERY_PROJECTION, - MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH, - LocalData.Photo.QUERY_ORDER); - if (c != null && c.moveToFirst()) { - // build up the list. - while (true) { - LocalData data = LocalData.Photo.buildFromCursor(c); - if (data != null) { - l.add(data); - } else { - Log.e(TAG, "Error loading data:" - + c.getString(LocalData.Photo.COL_DATA)); - } - if (c.isLast()) { - break; - } - c.moveToNext(); - } - } - if (c != null) { - c.close(); - } - - c = resolver[0].query( - LocalData.Video.CONTENT_URI, - LocalData.Video.QUERY_PROJECTION, - MediaStore.Video.Media.DATA + " like ? ", CAMERA_PATH, - LocalData.Video.QUERY_ORDER); - if (c != null && c.moveToFirst()) { - // build up the list. - c.moveToFirst(); - while (true) { - LocalData data = LocalData.Video.buildFromCursor(c); - if (data != null) { - l.add(data); - } else { - Log.e(TAG, "Error loading data:" - + c.getString(LocalData.Video.COL_DATA)); - } - if (!c.isLast()) { - c.moveToNext(); - } else { - break; - } - } - } - if (c != null) { - c.close(); - } - - if (l.size() == 0) return null; - - Collections.sort(l, new LocalData.NewestFirstComparator()); - return l; - } - - @Override - protected void onPostExecute(List<LocalData> l) { - replaceData(l); - } - } - - private class DeletionTask extends AsyncTask<LocalData, Void, Void> { - Context mContext; - - DeletionTask(Context context) { - mContext = context; - } - - @Override - protected Void doInBackground(LocalData... data) { - for (int i = 0; i < data.length; i++) { - if (!data[i].isDataActionSupported(LocalData.ACTION_DELETE)) { - Log.v(TAG, "Deletion is not supported:" + data[i]); - continue; - } - data[i].delete(mContext); - } - return null; - } - } -} diff --git a/src/com/android/camera/data/CameraPreviewData.java b/src/com/android/camera/data/CameraPreviewData.java deleted file mode 100644 index 8f8e2138d..000000000 --- a/src/com/android/camera/data/CameraPreviewData.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2013 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.data; - -import android.view.View; - -import com.android.camera.ui.FilmStripView.ImageData; - -/** - * A class implementing {@link LocalData} to represent a camera preview. - */ -public class CameraPreviewData extends LocalData.LocalViewData { - - private boolean mPreviewLocked; - - /** - * Constructor. - * - * @param v The {@link android.view.View} for camera preview. - * @param width The width of the camera preview. - * @param height The height of the camera preview. - */ - public CameraPreviewData(View v, int width, int height) { - super(v, width, height, -1, -1); - mPreviewLocked = true; - } - - @Override - public int getType() { - return ImageData.TYPE_CAMERA_PREVIEW; - } - - @Override - public boolean canSwipeInFullScreen() { - return !mPreviewLocked; - } - - /** - * Locks the camera preview. When the camera preview is locked, swipe - * to film strip is not allowed. One case is when the video recording - * is in progress. - * - * @param lock {@code true} if the preview should be locked. {@code false} - * otherwise. - */ - public void lockPreview(boolean lock) { - mPreviewLocked = lock; - } -} diff --git a/src/com/android/camera/data/FixedFirstDataAdapter.java b/src/com/android/camera/data/FixedFirstDataAdapter.java deleted file mode 100644 index 2bff22aa4..000000000 --- a/src/com/android/camera/data/FixedFirstDataAdapter.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2013 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.data; - -import android.content.Context; -import android.net.Uri; -import android.view.View; - -import com.android.camera.ui.FilmStripView; -import com.android.camera.ui.FilmStripView.DataAdapter; -import com.android.camera.ui.FilmStripView.ImageData; - -/** - * A {@link LocalDataAdapter} which puts a {@link LocalData} fixed at the first - * position. It's done by combining a {@link LocalData} and another - * {@link LocalDataAdapter}. - */ -public class FixedFirstDataAdapter extends AbstractLocalDataAdapterWrapper - implements DataAdapter.Listener { - - private LocalData mFirstData; - private Listener mListener; - - /** - * Constructor. - * - * @param wrappedAdapter The {@link LocalDataAdapter} to be wrapped. - * @param firstData The {@link LocalData} to be placed at the first - * position. - */ - public FixedFirstDataAdapter( - LocalDataAdapter wrappedAdapter, - LocalData firstData) { - super(wrappedAdapter); - if (firstData == null) { - throw new AssertionError("data is null"); - } - mFirstData = firstData; - } - - @Override - public LocalData getLocalData(int dataID) { - if (dataID == 0) { - return mFirstData; - } - return mAdapter.getLocalData(dataID - 1); - } - - @Override - public void removeData(Context context, int dataID) { - if (dataID > 0) { - mAdapter.removeData(context, dataID - 1); - } - } - - @Override - public int findDataByContentUri(Uri uri) { - int pos = mAdapter.findDataByContentUri(uri); - if (pos != -1) { - return pos + 1; - } - return -1; - } - - @Override - public void updateData(int pos, LocalData data) { - if (pos == 0) { - mFirstData = data; - if (mListener != null) { - mListener.onDataUpdated(new UpdateReporter() { - @Override - public boolean isDataRemoved(int dataID) { - return false; - } - - @Override - public boolean isDataUpdated(int dataID) { - return (dataID == 0); - } - }); - } - } else { - mAdapter.updateData(pos - 1, data); - } - } - - @Override - public int getTotalNumber() { - return (mAdapter.getTotalNumber() + 1); - } - - @Override - public View getView(Context context, int dataID) { - if (dataID == 0) { - return mFirstData.getView( - context, mSuggestedWidth, mSuggestedHeight, null); - } - return mAdapter.getView(context, dataID - 1); - } - - @Override - public ImageData getImageData(int dataID) { - if (dataID == 0) { - return mFirstData; - } - return mAdapter.getImageData(dataID - 1); - } - - @Override - public void onDataFullScreen(int dataID, boolean fullScreen) { - if (dataID == 0) { - mFirstData.onFullScreen(fullScreen); - } else { - mAdapter.onDataFullScreen(dataID - 1, fullScreen); - } - } - - @Override - public void setListener(Listener listener) { - mListener = listener; - mAdapter.setListener((listener == null) ? null : this); - } - - @Override - public boolean canSwipeInFullScreen(int dataID) { - if (dataID == 0) { - return mFirstData.canSwipeInFullScreen(); - } - return mAdapter.canSwipeInFullScreen(dataID - 1); - } - - @Override - public void onDataLoaded() { - mListener.onDataLoaded(); - } - - @Override - public void onDataUpdated(final UpdateReporter reporter) { - mListener.onDataUpdated(new UpdateReporter() { - @Override - public boolean isDataRemoved(int dataID) { - return reporter.isDataRemoved(dataID - 1); - } - - @Override - public boolean isDataUpdated(int dataID) { - return reporter.isDataUpdated(dataID - 1); - } - }); - } - - @Override - public void onDataInserted(int dataID, ImageData data) { - mListener.onDataInserted(dataID + 1, data); - } - - @Override - public void onDataRemoved(int dataID, ImageData data) { - mListener.onDataRemoved(dataID + 1, data); - } -} diff --git a/src/com/android/camera/data/FixedLastDataAdapter.java b/src/com/android/camera/data/FixedLastDataAdapter.java deleted file mode 100644 index b8325ec72..000000000 --- a/src/com/android/camera/data/FixedLastDataAdapter.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2013 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.data; - -import android.content.Context; -import android.net.Uri; -import android.view.View; - -import com.android.camera.ui.FilmStripView; - -/** - * A {@link LocalDataAdapter} which puts a {@link LocalData} fixed at the last - * position. It's done by combining a {@link LocalData} and another - * {@link LocalDataAdapter}. - */ -public class FixedLastDataAdapter extends AbstractLocalDataAdapterWrapper { - - private LocalData mLastData; - private Listener mListener; - - /** - * Constructor. - * - * @param wrappedAdapter The {@link LocalDataAdapter} to be wrapped. - * @param lastData The {@link LocalData} to be placed at the last position. - */ - public FixedLastDataAdapter( - LocalDataAdapter wrappedAdapter, - LocalData lastData) { - super(wrappedAdapter); - if (lastData == null) { - throw new AssertionError("data is null"); - } - mLastData = lastData; - } - - @Override - public void setListener(Listener listener) { - super.setListener(listener); - mListener = listener; - } - - @Override - public LocalData getLocalData(int dataID) { - int totalNumber = mAdapter.getTotalNumber(); - - if (dataID < totalNumber) { - return mAdapter.getLocalData(dataID); - } else if (dataID == totalNumber) { - return mLastData; - } - - return null; - } - - @Override - public void removeData(Context context, int dataID) { - if (dataID < mAdapter.getTotalNumber()) { - mAdapter.removeData(context, dataID); - } - } - - @Override - public int findDataByContentUri(Uri uri) { - return mAdapter.findDataByContentUri(uri); - } - - @Override - public void updateData(final int pos, LocalData data) { - int totalNumber = mAdapter.getTotalNumber(); - - if (pos < totalNumber) { - mAdapter.updateData(pos, data); - } else if (pos == totalNumber) { - mLastData = data; - if (mListener != null) { - mListener.onDataUpdated(new UpdateReporter() { - @Override - public boolean isDataRemoved(int dataID) { - return false; - } - - @Override - public boolean isDataUpdated(int dataID) { - return (dataID == pos); - } - }); - } - } - } - - @Override - public int getTotalNumber() { - return mAdapter.getTotalNumber() + 1; - } - - @Override - public View getView(Context context, int dataID) { - int totalNumber = mAdapter.getTotalNumber(); - - if (dataID < totalNumber) { - return mAdapter.getView(context, dataID); - } else if (dataID == totalNumber) { - return mLastData.getView(context, - mSuggestedWidth, mSuggestedHeight, null); - } - - return null; - } - - @Override - public FilmStripView.ImageData getImageData(int dataID) { - int totalNumber = mAdapter.getTotalNumber(); - - if (dataID < totalNumber) { - return mAdapter.getImageData(dataID); - } else if (dataID == totalNumber) { - return mLastData; - } - return null; - } - - @Override - public void onDataFullScreen(int dataID, boolean fullScreen) { - int totalNumber = mAdapter.getTotalNumber(); - - if (dataID < totalNumber) { - mAdapter.onDataFullScreen(dataID, fullScreen); - } else if (dataID == totalNumber) { - mLastData.onFullScreen(fullScreen); - } - } - - @Override - public boolean canSwipeInFullScreen(int dataID) { - int totalNumber = mAdapter.getTotalNumber(); - - if (dataID < totalNumber) { - return mAdapter.canSwipeInFullScreen(dataID); - } else if (dataID == totalNumber) { - return mLastData.canSwipeInFullScreen(); - } - return false; - } -} - diff --git a/src/com/android/camera/data/LocalData.java b/src/com/android/camera/data/LocalData.java deleted file mode 100644 index 74055230f..000000000 --- a/src/com/android/camera/data/LocalData.java +++ /dev/null @@ -1,822 +0,0 @@ -/* - * Copyright (C) 2013 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.data; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.media.MediaMetadataRetriever; -import android.net.Uri; -import android.os.AsyncTask; -import android.provider.MediaStore; -import android.provider.MediaStore.Images.ImageColumns; -import android.provider.MediaStore.Video.VideoColumns; -import android.util.Log; -import android.view.Gravity; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.ImageView; - -import com.android.camera.Util; -import com.android.camera.data.PanoramaMetadataLoader.PanoramaMetadataCallback; -import com.android.camera.ui.FilmStripView; -import com.android.gallery3d.R; -import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; -import com.android.gallery3d.util.PanoramaViewHelper; - -import java.io.File; -import java.util.Comparator; -import java.util.Date; - -/** - * An abstract interface that represents the local media data. Also implements - * Comparable interface so we can sort in DataAdapter. - */ -public interface LocalData extends FilmStripView.ImageData { - static final String TAG = "CAM_LocalData"; - - public static final int ACTION_NONE = 0; - public static final int ACTION_PLAY = 1; - public static final int ACTION_DELETE = (1 << 1); - - View getView(Context c, int width, int height, Drawable placeHolder); - - /** - * Gets the date when this data is created. The returned date is also used - * for sorting data. - * - * @return The date when this data is created. - * @see {@link NewestFirstComparator} - */ - long getDateTaken(); - - /** - * Gets the date when this data is modified. The returned date is also used - * for sorting data. - * - * @return The date when this data is modified. - * @see {@link NewestFirstComparator} - */ - long getDateModified(); - - /** Gets the title of this data */ - String getTitle(); - - /** - * Checks if the data actions (delete/play ...) can be applied on this data. - * - * @param actions The actions to check. - * @return Whether all the actions are supported. - */ - boolean isDataActionSupported(int actions); - - boolean delete(Context c); - - void onFullScreen(boolean fullScreen); - - /** Returns {@code true} if it allows swipe to filmstrip in full screen. */ - boolean canSwipeInFullScreen(); - - /** - * Returns the path to the data on the storage. - * - * @return Empty path if there's none. - */ - String getPath(); - - /** - * Returns the content URI of this data item. - * - * @return {@code Uri.EMPTY} if not valid. - */ - Uri getContentUri(); - - /** - * Refresh the data content. - * - * @param resolver {@link ContentResolver} to refresh the data. - * @return {@code true} if success, {@code false} otherwise. - */ - boolean refresh(ContentResolver resolver); - - static class NewestFirstComparator implements Comparator<LocalData> { - - /** Compare taken/modified date of LocalData in descent order to make - newer data in the front. - The negative numbers here are always considered "bigger" than - positive ones. Thus, if any one of the numbers is negative, the logic - is reversed. */ - private static int compareDate(long v1, long v2) { - if (v1 >= 0 && v2 >= 0) { - return ((v1 < v2) ? 1 : ((v1 > v2) ? -1 : 0)); - } - return ((v2 < v1) ? 1 : ((v2 > v1) ? -1 : 0)); - } - - @Override - public int compare(LocalData d1, LocalData d2) { - int cmp = compareDate(d1.getDateTaken(), d2.getDateTaken()); - if (cmp == 0) { - cmp = compareDate(d1.getDateModified(), d2.getDateModified()); - } - if (cmp == 0) { - cmp = d1.getTitle().compareTo(d2.getTitle()); - } - return cmp; - } - } - - // Implementations below. - - /** - * A base class for all the local media files. The bitmap is loaded in - * background thread. Subclasses should implement their own background - * loading thread by sub-classing BitmapLoadTask and overriding - * doInBackground() to return a bitmap. - */ - abstract static class LocalMediaData implements LocalData { - protected long id; - protected String title; - protected String mimeType; - protected long dateTaken; - protected long dateModified; - protected String path; - // width and height should be adjusted according to orientation. - protected int width; - protected int height; - - /** The panorama metadata information of this media data. */ - private PanoramaMetadata mPanoramaMetadata; - - /** Used to load photo sphere metadata from image files. */ - private PanoramaMetadataLoader mPanoramaMetadataLoader = null; - - // true if this data has a corresponding visible view. - protected Boolean mUsing = false; - - @Override - public long getDateTaken() { - return dateTaken; - } - - @Override - public long getDateModified() { - return dateModified; - } - - @Override - public String getTitle() { - return new String(title); - } - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public String getPath() { - return path; - } - - @Override - public boolean isUIActionSupported(int action) { - return false; - } - - @Override - public boolean isDataActionSupported(int action) { - return false; - } - - @Override - public boolean delete(Context ctx) { - File f = new File(path); - return f.delete(); - } - - @Override - public void viewPhotoSphere(PanoramaViewHelper helper) { - helper.showPanorama(getContentUri()); - } - - @Override - public void isPhotoSphere(Context context, final PanoramaSupportCallback callback) { - // If we already have metadata, use it. - if (mPanoramaMetadata != null) { - callback.panoramaInfoAvailable(mPanoramaMetadata.mUsePanoramaViewer, - mPanoramaMetadata.mIsPanorama360); - } - - // Otherwise prepare a loader, if we don't have one already. - if (mPanoramaMetadataLoader == null) { - mPanoramaMetadataLoader = new PanoramaMetadataLoader(getContentUri()); - } - - // Load the metadata asynchronously. - mPanoramaMetadataLoader.getPanoramaMetadata(context, new PanoramaMetadataCallback() { - @Override - public void onPanoramaMetadataLoaded(PanoramaMetadata metadata) { - // Store the metadata and remove the loader to free up space. - mPanoramaMetadata = metadata; - mPanoramaMetadataLoader = null; - callback.panoramaInfoAvailable(metadata.mUsePanoramaViewer, - metadata.mIsPanorama360); - } - }); - } - - @Override - public void onFullScreen(boolean fullScreen) { - // do nothing. - } - - @Override - public boolean canSwipeInFullScreen() { - return true; - } - - protected ImageView fillImageView(Context ctx, ImageView v, - int decodeWidth, int decodeHeight, Drawable placeHolder) { - v.setScaleType(ImageView.ScaleType.FIT_XY); - v.setImageDrawable(placeHolder); - - BitmapLoadTask task = getBitmapLoadTask(v, decodeWidth, decodeHeight); - task.execute(); - return v; - } - - @Override - public View getView(Context ctx, - int decodeWidth, int decodeHeight, Drawable placeHolder) { - return fillImageView(ctx, new ImageView(ctx), - decodeWidth, decodeHeight, placeHolder); - } - - @Override - public void prepare() { - synchronized (mUsing) { - mUsing = true; - } - } - - @Override - public void recycle() { - synchronized (mUsing) { - mUsing = false; - } - } - - protected boolean isUsing() { - synchronized (mUsing) { - return mUsing; - } - } - - @Override - public abstract int getType(); - - protected abstract BitmapLoadTask getBitmapLoadTask( - ImageView v, int decodeWidth, int decodeHeight); - - /** - * An AsyncTask class that loads the bitmap in the background thread. - * Sub-classes should implement their own "protected Bitmap doInBackground(Void... )" - */ - protected abstract class BitmapLoadTask extends AsyncTask<Void, Void, Bitmap> { - protected ImageView mView; - - protected BitmapLoadTask(ImageView v) { - mView = v; - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (!isUsing()) return; - if (bitmap == null) { - Log.e(TAG, "Failed decoding bitmap for file:" + path); - return; - } - BitmapDrawable d = new BitmapDrawable(bitmap); - mView.setScaleType(ImageView.ScaleType.FIT_XY); - mView.setImageDrawable(d); - } - } - } - - static class Photo extends LocalMediaData { - public static final int COL_ID = 0; - public static final int COL_TITLE = 1; - public static final int COL_MIME_TYPE = 2; - public static final int COL_DATE_TAKEN = 3; - public static final int COL_DATE_MODIFIED = 4; - public static final int COL_DATA = 5; - public static final int COL_ORIENTATION = 6; - public static final int COL_WIDTH = 7; - public static final int COL_HEIGHT = 8; - - static final Uri CONTENT_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - - static final String QUERY_ORDER = ImageColumns.DATE_TAKEN + " DESC, " - + ImageColumns._ID + " DESC"; - /** - * These values should be kept in sync with column IDs (COL_*) above. - */ - static final String[] QUERY_PROJECTION = { - ImageColumns._ID, // 0, int - ImageColumns.TITLE, // 1, string - ImageColumns.MIME_TYPE, // 2, string - ImageColumns.DATE_TAKEN, // 3, int - ImageColumns.DATE_MODIFIED, // 4, int - ImageColumns.DATA, // 5, string - ImageColumns.ORIENTATION, // 6, int, 0, 90, 180, 270 - ImageColumns.WIDTH, // 7, int - ImageColumns.HEIGHT, // 8, int - }; - - private static final int mSupportedUIActions = - FilmStripView.ImageData.ACTION_DEMOTE - | FilmStripView.ImageData.ACTION_PROMOTE; - private static final int mSupportedDataActions = - LocalData.ACTION_DELETE; - - /** 32K buffer. */ - private static final byte[] DECODE_TEMP_STORAGE = new byte[32 * 1024]; - - /** from MediaStore, can only be 0, 90, 180, 270 */ - public int orientation; - - static Photo buildFromCursor(Cursor c) { - Photo d = new Photo(); - d.id = c.getLong(COL_ID); - d.title = c.getString(COL_TITLE); - d.mimeType = c.getString(COL_MIME_TYPE); - d.dateTaken = c.getLong(COL_DATE_TAKEN); - d.dateModified = c.getLong(COL_DATE_MODIFIED); - d.path = c.getString(COL_DATA); - d.orientation = c.getInt(COL_ORIENTATION); - d.width = c.getInt(COL_WIDTH); - d.height = c.getInt(COL_HEIGHT); - if (d.width <= 0 || d.height <= 0) { - Log.w(TAG, "Warning! zero dimension for " - + d.path + ":" + d.width + "x" + d.height); - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inJustDecodeBounds = true; - BitmapFactory.decodeFile(d.path, opts); - if (opts.outWidth != -1 && opts.outHeight != -1) { - d.width = opts.outWidth; - d.height = opts.outHeight; - } else { - Log.w(TAG, "Warning! dimension decode failed for " + d.path); - Bitmap b = BitmapFactory.decodeFile(d.path); - if (b == null) { - return null; - } - d.width = b.getWidth(); - d.height = b.getHeight(); - } - } - if (d.orientation == 90 || d.orientation == 270) { - int b = d.width; - d.width = d.height; - d.height = b; - } - return d; - } - - @Override - public String toString() { - return "Photo:" + ",data=" + path + ",mimeType=" + mimeType - + "," + width + "x" + height + ",orientation=" + orientation - + ",date=" + new Date(dateTaken); - } - - @Override - public int getType() { - return TYPE_PHOTO; - } - - @Override - public boolean isUIActionSupported(int action) { - return ((action & mSupportedUIActions) == action); - } - - @Override - public boolean isDataActionSupported(int action) { - return ((action & mSupportedDataActions) == action); - } - - @Override - public boolean delete(Context c) { - ContentResolver cr = c.getContentResolver(); - cr.delete(CONTENT_URI, ImageColumns._ID + "=" + id, null); - return super.delete(c); - } - - @Override - public Uri getContentUri() { - Uri baseUri = CONTENT_URI; - return baseUri.buildUpon().appendPath(String.valueOf(id)).build(); - } - - @Override - public boolean refresh(ContentResolver resolver) { - Cursor c = resolver.query( - getContentUri(), QUERY_PROJECTION, null, null, null); - if (c == null || !c.moveToFirst()) { - return false; - } - Photo newData = buildFromCursor(c); - id = newData.id; - title = newData.title; - mimeType = newData.mimeType; - dateTaken = newData.dateTaken; - dateModified = newData.dateModified; - path = newData.path; - orientation = newData.orientation; - width = newData.width; - height = newData.height; - return true; - } - - @Override - protected BitmapLoadTask getBitmapLoadTask( - ImageView v, int decodeWidth, int decodeHeight) { - return new PhotoBitmapLoadTask(v, decodeWidth, decodeHeight); - } - - private final class PhotoBitmapLoadTask extends BitmapLoadTask { - private int mDecodeWidth; - private int mDecodeHeight; - - public PhotoBitmapLoadTask(ImageView v, int decodeWidth, int decodeHeight) { - super(v); - mDecodeWidth = decodeWidth; - mDecodeHeight = decodeHeight; - } - - @Override - protected Bitmap doInBackground(Void... v) { - BitmapFactory.Options opts = null; - Bitmap b; - int sample = 1; - while (mDecodeWidth * sample < width - || mDecodeHeight * sample < height) { - sample *= 2; - } - opts = new BitmapFactory.Options(); - opts.inSampleSize = sample; - opts.inTempStorage = DECODE_TEMP_STORAGE; - if (isCancelled() || !isUsing()) { - return null; - } - b = BitmapFactory.decodeFile(path, opts); - if (orientation != 0) { - if (isCancelled() || !isUsing()) { - return null; - } - Matrix m = new Matrix(); - m.setRotate(orientation); - b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, false); - } - return b; - } - } - } - - static class Video extends LocalMediaData { - public static final int COL_ID = 0; - public static final int COL_TITLE = 1; - public static final int COL_MIME_TYPE = 2; - public static final int COL_DATE_TAKEN = 3; - public static final int COL_DATE_MODIFIED = 4; - public static final int COL_DATA = 5; - public static final int COL_WIDTH = 6; - public static final int COL_HEIGHT = 7; - public static final int COL_RESOLUTION = 8; - - static final Uri CONTENT_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - - private static final int mSupportedUIActions = - FilmStripView.ImageData.ACTION_DEMOTE - | FilmStripView.ImageData.ACTION_PROMOTE; - private static final int mSupportedDataActions = - LocalData.ACTION_DELETE - | LocalData.ACTION_PLAY; - - static final String QUERY_ORDER = VideoColumns.DATE_TAKEN + " DESC, " - + VideoColumns._ID + " DESC"; - /** - * These values should be kept in sync with column IDs (COL_*) above. - */ - static final String[] QUERY_PROJECTION = { - VideoColumns._ID, // 0, int - VideoColumns.TITLE, // 1, string - VideoColumns.MIME_TYPE, // 2, string - VideoColumns.DATE_TAKEN, // 3, int - VideoColumns.DATE_MODIFIED, // 4, int - VideoColumns.DATA, // 5, string - VideoColumns.WIDTH, // 6, int - VideoColumns.HEIGHT, // 7, int - VideoColumns.RESOLUTION // 8, string - }; - - private Uri mPlayUri; - - static Video buildFromCursor(Cursor c) { - Video d = new Video(); - d.id = c.getLong(COL_ID); - d.title = c.getString(COL_TITLE); - d.mimeType = c.getString(COL_MIME_TYPE); - d.dateTaken = c.getLong(COL_DATE_TAKEN); - d.dateModified = c.getLong(COL_DATE_MODIFIED); - d.path = c.getString(COL_DATA); - d.width = c.getInt(COL_WIDTH); - d.height = c.getInt(COL_HEIGHT); - d.mPlayUri = d.getContentUri(); - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setDataSource(d.path); - String rotation = retriever.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); - if (d.width == 0 || d.height == 0) { - d.width = Integer.parseInt(retriever.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)); - d.height = Integer.parseInt(retriever.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)); - } - retriever.release(); - if (rotation != null - && (rotation.equals("90") || rotation.equals("270"))) { - int b = d.width; - d.width = d.height; - d.height = b; - } - return d; - } - - @Override - public String toString() { - return "Video:" + ",data=" + path + ",mimeType=" + mimeType - + "," + width + "x" + height + ",date=" + new Date(dateTaken); - } - - @Override - public int getType() { - return TYPE_PHOTO; - } - - @Override - public boolean isUIActionSupported(int action) { - return ((action & mSupportedUIActions) == action); - } - - @Override - public boolean isDataActionSupported(int action) { - return ((action & mSupportedDataActions) == action); - } - - @Override - public boolean delete(Context ctx) { - ContentResolver cr = ctx.getContentResolver(); - cr.delete(CONTENT_URI, VideoColumns._ID + "=" + id, null); - return super.delete(ctx); - } - - @Override - public Uri getContentUri() { - Uri baseUri = CONTENT_URI; - return baseUri.buildUpon().appendPath(String.valueOf(id)).build(); - } - - @Override - public boolean refresh(ContentResolver resolver) { - Cursor c = resolver.query( - getContentUri(), QUERY_PROJECTION, null, null, null); - if (c == null && !c.moveToFirst()) { - return false; - } - Video newData = buildFromCursor(c); - id = newData.id; - title = newData.title; - mimeType = newData.mimeType; - dateTaken = newData.dateTaken; - dateModified = newData.dateModified; - path = newData.path; - width = newData.width; - height = newData.height; - mPlayUri = newData.mPlayUri; - return true; - } - - @Override - public View getView(final Context ctx, - int decodeWidth, int decodeHeight, Drawable placeHolder) { - - // ImageView for the bitmap. - ImageView iv = new ImageView(ctx); - iv.setLayoutParams(new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER)); - fillImageView(ctx, iv, decodeWidth, decodeHeight, placeHolder); - - // ImageView for the play icon. - ImageView icon = new ImageView(ctx); - icon.setImageResource(R.drawable.ic_control_play); - icon.setScaleType(ImageView.ScaleType.CENTER); - icon.setLayoutParams(new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.WRAP_CONTENT, - ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER)); - icon.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - Util.playVideo(ctx, mPlayUri, title); - } - }); - - FrameLayout f = new FrameLayout(ctx); - f.addView(iv); - f.addView(icon); - return f; - } - - @Override - protected BitmapLoadTask getBitmapLoadTask( - ImageView v, int decodeWidth, int decodeHeight) { - return new VideoBitmapLoadTask(v); - } - - private final class VideoBitmapLoadTask extends BitmapLoadTask { - - public VideoBitmapLoadTask(ImageView v) { - super(v); - } - - @Override - protected Bitmap doInBackground(Void... v) { - if (isCancelled() || !isUsing()) { - return null; - } - android.media.MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setDataSource(path); - byte[] data = retriever.getEmbeddedPicture(); - Bitmap bitmap = null; - if (isCancelled() || !isUsing()) { - retriever.release(); - return null; - } - if (data != null) { - bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); - } - if (bitmap == null) { - bitmap = retriever.getFrameAtTime(); - } - retriever.release(); - return bitmap; - } - } - } - - /** - * A LocalData that does nothing but only shows a view. - */ - public static class LocalViewData implements LocalData { - private int mWidth; - private int mHeight; - private View mView; - private long mDateTaken; - private long mDateModified; - - public LocalViewData(View v, - int width, int height, - int dateTaken, int dateModified) { - mView = v; - mWidth = width; - mHeight = height; - mDateTaken = dateTaken; - mDateModified = dateModified; - } - - @Override - public long getDateTaken() { - return mDateTaken; - } - - @Override - public long getDateModified() { - return mDateModified; - } - - @Override - public String getTitle() { - return ""; - } - - @Override - public int getWidth() { - return mWidth; - } - - @Override - public int getHeight() { - return mHeight; - } - - @Override - public int getType() { - return FilmStripView.ImageData.TYPE_PHOTO; - } - - @Override - public String getPath() { - return ""; - } - - @Override - public Uri getContentUri() { - return Uri.EMPTY; - } - - @Override - public boolean refresh(ContentResolver resolver) { - return false; - } - - @Override - public boolean isUIActionSupported(int action) { - return false; - } - - @Override - public boolean isDataActionSupported(int action) { - return false; - } - - @Override - public boolean delete(Context c) { - return false; - } - - @Override - public View getView(Context c, int width, int height, Drawable placeHolder) { - return mView; - } - - @Override - public void prepare() { - // do nothing. - } - - @Override - public void recycle() { - // do nothing. - } - - @Override - public void isPhotoSphere(Context context, PanoramaSupportCallback callback) { - // Not a photo sphere panorama. - callback.panoramaInfoAvailable(false, false); - } - - @Override - public void viewPhotoSphere(PanoramaViewHelper helper) { - // do nothing. - } - - @Override - public void onFullScreen(boolean fullScreen) { - // do nothing. - } - - @Override - public boolean canSwipeInFullScreen() { - return true; - } - } -} - diff --git a/src/com/android/camera/data/LocalDataAdapter.java b/src/com/android/camera/data/LocalDataAdapter.java deleted file mode 100644 index 0a5fde0b5..000000000 --- a/src/com/android/camera/data/LocalDataAdapter.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2013 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.data; - -import android.content.ContentResolver; -import android.content.Context; -import android.net.Uri; - -import static com.android.camera.ui.FilmStripView.DataAdapter; - -/** - * An interface which extends {@link DataAdapter} and defines operations on - * the data in the local camera folder. - */ -public interface LocalDataAdapter extends DataAdapter { - - /** - * Request for loading the local data. - * - * @param resolver {@link ContentResolver} used for data loading. - */ - public void requestLoad(ContentResolver resolver); - - /** - * Returns the specified {@link LocalData}. - * - * @param dataID The ID of the {@link LocalData} to get. - * @return The {@link LocalData} to get. {@code null} if not available. - */ - public LocalData getLocalData(int dataID); - - /** - * Remove the data in the local camera folder. - * - * @param context {@link Context} used to remove the data. - * @param dataID ID of data to be deleted. - */ - public void removeData(Context context, int dataID); - - /** - * Add new local video data. - * - * @param resolver {@link ContentResolver} used to add the data. - * @param uri {@link Uri} of the video. - */ - public void addNewVideo(ContentResolver resolver, Uri uri); - - /** - * Adds new local photo data. - * - * @param resolver {@link ContentResolver} used to add the data. - * @param uri {@link Uri} of the photo. - */ - public void addNewPhoto(ContentResolver resolver, Uri uri); - - /** - * Refresh the data by {@link Uri}. - * - * @param resolver {@link ContentResolver} used to refresh the data. - * @param uri The {@link Uri} of the data to refresh. - */ - public void refresh(ContentResolver resolver, Uri uri); - - /** - * Finds the {@link LocalData} of the specified content Uri. - * - * @param Uri The content Uri of the {@link LocalData}. - * @return The index of the data. {@code -1} if not found. - */ - public int findDataByContentUri(Uri uri); - - /** - * Clears all the data currently loaded. - */ - public void flush(); - - /** - * Executes the deletion task. Delete the data waiting in the deletion queue. - * - * @param context The {@link Context} from the caller. - * @return {@code true} if task has been executed, {@code false} - * otherwise. - */ - public boolean executeDeletion(Context context); - - /** - * Undo a deletion. If there is any data waiting to be deleted in the queue, - * move it out of the deletion queue. - * - * @return {@code true} if there are items in the queue, {@code false} otherwise. - */ - public boolean undoDataRemoval(); - - /** - * Update the data in a specific position. - * - * @param pos The position of the data to be updated. - * @param data The new data. - */ - public void updateData(int pos, LocalData data); - - /** Insert a data. */ - public void insertData(LocalData data); -} diff --git a/src/com/android/camera/data/PanoramaMetadataLoader.java b/src/com/android/camera/data/PanoramaMetadataLoader.java deleted file mode 100644 index 21b5f8a3d..000000000 --- a/src/com/android/camera/data/PanoramaMetadataLoader.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2013 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.data; - -import android.content.Context; -import android.net.Uri; - -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; - -import java.util.ArrayList; - -/** - * This class breaks out the off-thread panorama support. - */ -public class PanoramaMetadataLoader { - /** - * Classes implementing this interface can get information about loaded - * photo sphere metadata. - */ - public static interface PanoramaMetadataCallback { - /** - * Called with the loaded metadata or <code>null</code>. - */ - public void onPanoramaMetadataLoaded(PanoramaMetadata metadata); - } - - private PanoramaMetadata mPanoramaMetadata; - private ArrayList<PanoramaMetadataCallback> mCallbacksWaiting; - private Uri mMediaUri; - - /** - * Instantiated the meta data loader for the image resource with the given - * URI. - */ - public PanoramaMetadataLoader(Uri uri) { - mMediaUri = uri; - } - - /** - * Asynchronously extract and return panorama metadata from the item with - * the given URI. - * <p> - * NOTE: This call is backed by a cache to speed up successive calls, which - * will return immediately. Use {@link #clearCachedValues()} is called. - */ - public synchronized void getPanoramaMetadata(final Context context, - PanoramaMetadataCallback callback) { - if (mPanoramaMetadata != null) { - // Return the cached data right away, no need to fetch it again. - callback.onPanoramaMetadataLoaded(mPanoramaMetadata); - } else { - if (mCallbacksWaiting == null) { - mCallbacksWaiting = new ArrayList<PanoramaMetadataCallback>(); - - // TODO: Don't create a new thread each time, use a pool or - // single instance. - (new Thread() { - @Override - public void run() { - onLoadingDone(LightCycleHelper.getPanoramaMetadata(context, - mMediaUri)); - } - }).start(); - } - mCallbacksWaiting.add(callback); - } - } - - /** - * Clear cached value and stop all running loading threads. - */ - public synchronized void clearCachedValues() { - if (mPanoramaMetadata != null) { - mPanoramaMetadata = null; - } - - // TODO: Cancel running loading thread if active. - } - - private synchronized void onLoadingDone(PanoramaMetadata metadata) { - mPanoramaMetadata = metadata; - if (mPanoramaMetadata == null) { - // Error getting panorama data from file. Treat as not panorama. - mPanoramaMetadata = LightCycleHelper.NOT_PANORAMA; - } - for (PanoramaMetadataCallback cb : mCallbacksWaiting) { - cb.onPanoramaMetadataLoaded(mPanoramaMetadata); - } - mCallbacksWaiting = null; - } -} diff --git a/src/com/android/camera/drawable/TextDrawable.java b/src/com/android/camera/drawable/TextDrawable.java deleted file mode 100644 index 60d8719c4..000000000 --- a/src/com/android/camera/drawable/TextDrawable.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.drawable; - -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.Typeface; -import android.graphics.Paint.Align; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.util.TypedValue; - - -public class TextDrawable extends Drawable { - - private static final int DEFAULT_COLOR = Color.WHITE; - private static final int DEFAULT_TEXTSIZE = 15; - - private Paint mPaint; - private CharSequence mText; - private int mIntrinsicWidth; - private int mIntrinsicHeight; - private boolean mUseDropShadow; - - public TextDrawable(Resources res) { - this(res, ""); - } - - public TextDrawable(Resources res, CharSequence text) { - mText = text; - updatePaint(); - float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, - DEFAULT_TEXTSIZE, res.getDisplayMetrics()); - mPaint.setTextSize(textSize); - mIntrinsicWidth = (int) (mPaint.measureText(mText, 0, mText.length()) + .5); - mIntrinsicHeight = mPaint.getFontMetricsInt(null); - } - - private void updatePaint() { - if (mPaint == null) { - mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - } - mPaint.setColor(DEFAULT_COLOR); - mPaint.setTextAlign(Align.CENTER); - if (mUseDropShadow) { - mPaint.setTypeface(Typeface.DEFAULT_BOLD); - mPaint.setShadowLayer(10, 0, 0, 0xff000000); - } else { - mPaint.setTypeface(Typeface.DEFAULT); - mPaint.setShadowLayer(0, 0, 0, 0); - } - } - - public void setText(CharSequence txt) { - mText = txt; - if (txt == null) { - mIntrinsicWidth = 0; - mIntrinsicHeight = 0; - } else { - mIntrinsicWidth = (int) (mPaint.measureText(mText, 0, mText.length()) + .5); - mIntrinsicHeight = mPaint.getFontMetricsInt(null); - } - } - - @Override - public void draw(Canvas canvas) { - if (mText != null) { - Rect bounds = getBounds(); - canvas.drawText(mText, 0, mText.length(), - bounds.centerX(), bounds.centerY(), mPaint); - } - } - - public void setDropShadow(boolean shadow) { - mUseDropShadow = shadow; - updatePaint(); - } - - @Override - public int getOpacity() { - return mPaint.getAlpha(); - } - - @Override - public int getIntrinsicWidth() { - return mIntrinsicWidth; - } - - @Override - public int getIntrinsicHeight() { - return mIntrinsicHeight; - } - - @Override - public void setAlpha(int alpha) { - mPaint.setAlpha(alpha); - } - - @Override - public void setColorFilter(ColorFilter filter) { - mPaint.setColorFilter(filter); - } - -} diff --git a/src/com/android/camera/ui/AbstractSettingPopup.java b/src/com/android/camera/ui/AbstractSettingPopup.java deleted file mode 100644 index 783b6c771..000000000 --- a/src/com/android/camera/ui/AbstractSettingPopup.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2010 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.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.android.gallery3d.R; - -// A popup window that shows one or more camera settings. -abstract public class AbstractSettingPopup extends RotateLayout { - protected ViewGroup mSettingList; - protected TextView mTitle; - - public AbstractSettingPopup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - mTitle = (TextView) findViewById(R.id.title); - mSettingList = (ViewGroup) findViewById(R.id.settingList); - } - - abstract public void reloadPreference(); -} diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java deleted file mode 100644 index 7fa6890a7..000000000 --- a/src/com/android/camera/ui/CameraControls.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2013 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.ui; - -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.camera.Util; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -public class CameraControls extends RotatableLayout { - - private static final String TAG = "CAM_Controls"; - - private View mBackgroundView; - private View mShutter; - private View mSwitcher; - private View mMenu; - private View mIndicators; - private View mPreview; - - public CameraControls(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public CameraControls(Context context) { - super(context); - } - - @Override - public void onFinishInflate() { - super.onFinishInflate(); - mBackgroundView = findViewById(R.id.blocker); - mSwitcher = findViewById(R.id.camera_switcher); - mShutter = findViewById(R.id.shutter_button); - mMenu = findViewById(R.id.menu); - mIndicators = findViewById(R.id.on_screen_indicators); - mPreview = findViewById(R.id.preview_thumb); - } - - @Override - public void onLayout(boolean changed, int l, int t, int r, int b) { - int orientation = getResources().getConfiguration().orientation; - int size = getResources().getDimensionPixelSize(R.dimen.camera_controls_size); - int rotation = getUnifiedRotation(); - adjustBackground(); - // As l,t,r,b are positions relative to parents, we need to convert them - // to child's coordinates - r = r - l; - b = b - t; - l = 0; - t = 0; - for (int i = 0; i < getChildCount(); i++) { - View v = getChildAt(i); - v.layout(l, t, r, b); - } - Rect shutter = new Rect(); - topRight(mPreview, l, t, r, b); - if (size > 0) { - // restrict controls to size - switch (rotation) { - case 0: - case 180: - l = (l + r - size) / 2; - r = l + size; - break; - case 90: - case 270: - t = (t + b - size) / 2; - b = t + size; - break; - } - } - center(mShutter, l, t, r, b, orientation, rotation, shutter); - center(mBackgroundView, l, t, r, b, orientation, rotation, new Rect()); - toLeft(mSwitcher, shutter, rotation); - toRight(mMenu, shutter, rotation); - toRight(mIndicators, shutter, rotation); - View retake = findViewById(R.id.btn_retake); - if (retake != null) { - center(retake, shutter, rotation); - View cancel = findViewById(R.id.btn_cancel); - toLeft(cancel, shutter, rotation); - View done = findViewById(R.id.btn_done); - toRight(done, shutter, rotation); - } - } - - private void center(View v, int l, int t, int r, int b, int orientation, int rotation, Rect result) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin; - int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin; - switch (rotation) { - case 0: - // phone portrait; controls bottom - result.left = (r + l) / 2 - tw / 2 + lp.leftMargin; - result.right = (r + l) / 2 + tw / 2 - lp.rightMargin; - result.bottom = b - lp.bottomMargin; - result.top = b - th + lp.topMargin; - break; - case 90: - // phone landscape: controls right - result.right = r - lp.rightMargin; - result.left = r - tw + lp.leftMargin; - result.top = (b + t) / 2 - th / 2 + lp.topMargin; - result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin; - break; - case 180: - // phone upside down: controls top - result.left = (r + l) / 2 - tw / 2 + lp.leftMargin; - result.right = (r + l) / 2 + tw / 2 - lp.rightMargin; - result.top = t + lp.topMargin; - result.bottom = t + th - lp.bottomMargin; - break; - case 270: - // reverse landscape: controls left - result.left = l + lp.leftMargin; - result.right = l + tw - lp.rightMargin; - result.top = (b + t) / 2 - th / 2 + lp.topMargin; - result.bottom = (b + t) / 2 + th / 2 - lp.bottomMargin; - break; - } - v.layout(result.left, result.top, result.right, result.bottom); - } - - private void center(View v, Rect other, int rotation) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin; - int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin; - int cx = (other.left + other.right) / 2; - int cy = (other.top + other.bottom) / 2; - v.layout(cx - tw / 2 + lp.leftMargin, - cy - th / 2 + lp.topMargin, - cx + tw / 2 - lp.rightMargin, - cy + th / 2 - lp.bottomMargin); - } - - private void toLeft(View v, Rect other, int rotation) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin; - int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin; - int cx = (other.left + other.right) / 2; - int cy = (other.top + other.bottom) / 2; - int l = 0, r = 0, t = 0, b = 0; - switch (rotation) { - case 0: - // portrait, to left of anchor at bottom - l = other.left - tw + lp.leftMargin; - r = other.left - lp.rightMargin; - t = cy - th / 2 + lp.topMargin; - b = cy + th / 2 - lp.bottomMargin; - break; - case 90: - // phone landscape: below anchor on right - l = cx - tw / 2 + lp.leftMargin; - r = cx + tw / 2 - lp.rightMargin; - t = other.bottom + lp.topMargin; - b = other.bottom + th - lp.bottomMargin; - break; - case 180: - // phone upside down: right of anchor at top - l = other.right + lp.leftMargin; - r = other.right + tw - lp.rightMargin; - t = cy - th / 2 + lp.topMargin; - b = cy + th / 2 - lp.bottomMargin; - break; - case 270: - // reverse landscape: above anchor on left - l = cx - tw / 2 + lp.leftMargin; - r = cx + tw / 2 - lp.rightMargin; - t = other.top - th + lp.topMargin; - b = other.top - lp.bottomMargin; - break; - } - v.layout(l, t, r, b); - } - - private void toRight(View v, Rect other, int rotation) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - int tw = lp.leftMargin + v.getMeasuredWidth() + lp.rightMargin; - int th = lp.topMargin + v.getMeasuredHeight() + lp.bottomMargin; - int cx = (other.left + other.right) / 2; - int cy = (other.top + other.bottom) / 2; - int l = 0, r = 0, t = 0, b = 0; - switch (rotation) { - case 0: - l = other.right + lp.leftMargin; - r = other.right + tw - lp.rightMargin; - t = cy - th / 2 + lp.topMargin; - b = cy + th / 2 - lp.bottomMargin; - break; - case 90: - l = cx - tw / 2 + lp.leftMargin; - r = cx + tw / 2 - lp.rightMargin; - t = other.top - th + lp.topMargin; - b = other.top - lp.bottomMargin; - break; - case 180: - l = other.left - tw + lp.leftMargin; - r = other.left - lp.rightMargin; - t = cy - th / 2 + lp.topMargin; - b = cy + th / 2 - lp.bottomMargin; - break; - case 270: - l = cx - tw / 2 + lp.leftMargin; - r = cx + tw / 2 - lp.rightMargin; - t = other.bottom + lp.topMargin; - b = other.bottom + th - lp.bottomMargin; - break; - } - v.layout(l, t, r, b); - } - - private void topRight(View v, int l, int t, int r, int b) { - // layout using the specific margins; the rotation code messes up the others - int mt = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_top); - int mr = getContext().getResources().getDimensionPixelSize(R.dimen.capture_margin_right); - v.layout(r - v.getMeasuredWidth() - mr, t + mt, r - mr, t + mt + v.getMeasuredHeight()); - } - - private void adjustBackground() { - int rotation = getUnifiedRotation(); - // remove current drawable and reset rotation - mBackgroundView.setBackgroundDrawable(null); - mBackgroundView.setRotationX(0); - mBackgroundView.setRotationY(0); - // if the switcher background is top aligned we need to flip the background - // drawable vertically; if left aligned, flip horizontally - switch (rotation) { - case 180: - mBackgroundView.setRotationX(180); - break; - case 270: - mBackgroundView.setRotationY(180); - break; - default: - break; - } - mBackgroundView.setBackgroundResource(R.drawable.switcher_bg); - } - -} diff --git a/src/com/android/camera/ui/CameraRootView.java b/src/com/android/camera/ui/CameraRootView.java deleted file mode 100644 index adda70697..000000000 --- a/src/com/android/camera/ui/CameraRootView.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2013 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.ui; - -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.hardware.display.DisplayManager; -import android.hardware.display.DisplayManager.DisplayListener; -import android.util.AttributeSet; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.camera.Util; -import com.android.gallery3d.common.ApiHelper; - -public class CameraRootView extends FrameLayout { - - private int mTopMargin = 0; - private int mBottomMargin = 0; - private int mLeftMargin = 0; - private int mRightMargin = 0; - private Rect mCurrentInsets; - private int mOffset = 0; - private Object mDisplayListener; - private MyDisplayListener mListener; - public interface MyDisplayListener { - public void onDisplayChanged(); - } - - public CameraRootView(Context context, AttributeSet attrs) { - super(context, attrs); - initDisplayListener(); - setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); - } - - @Override - protected boolean fitSystemWindows(Rect insets) { - super.fitSystemWindows(insets); - mCurrentInsets = insets; - // insets include status bar, navigation bar, etc - // In this case, we are only concerned with the size of nav bar - if (mOffset > 0) return true; - - if (insets.bottom > 0) { - mOffset = insets.bottom; - } else if (insets.right > 0) { - mOffset = insets.right; - } - return true; - } - - public void initDisplayListener() { - if (ApiHelper.HAS_DISPLAY_LISTENER) { - mDisplayListener = new DisplayListener() { - - @Override - public void onDisplayAdded(int arg0) {} - - @Override - public void onDisplayChanged(int arg0) { - mListener.onDisplayChanged(); - } - - @Override - public void onDisplayRemoved(int arg0) {} - }; - } - } - - public void setDisplayChangeListener(MyDisplayListener listener) { - mListener = listener; - } - - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - if (ApiHelper.HAS_DISPLAY_LISTENER) { - ((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE)) - .registerDisplayListener((DisplayListener) mDisplayListener, null); - } - } - - @Override - public void onDetachedFromWindow () { - super.onDetachedFromWindow(); - if (ApiHelper.HAS_DISPLAY_LISTENER) { - ((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE)) - .unregisterDisplayListener((DisplayListener) mDisplayListener); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int rotation = Util.getDisplayRotation((Activity) getContext()); - // all the layout code assumes camera device orientation to be portrait - // adjust rotation for landscape - int orientation = getResources().getConfiguration().orientation; - int camOrientation = (rotation % 180 == 0) ? Configuration.ORIENTATION_PORTRAIT - : Configuration.ORIENTATION_LANDSCAPE; - if (camOrientation != orientation) { - rotation = (rotation + 90) % 360; - } - // calculate margins - mLeftMargin = 0; - mRightMargin = 0; - mBottomMargin = 0; - mTopMargin = 0; - switch (rotation) { - case 0: - mBottomMargin += mOffset; - break; - case 90: - mRightMargin += mOffset; - break; - case 180: - mTopMargin += mOffset; - break; - case 270: - mLeftMargin += mOffset; - break; - } - if (mCurrentInsets != null) { - if (mCurrentInsets.right > 0) { - // navigation bar on the right - mRightMargin = mRightMargin > 0 ? mRightMargin : mCurrentInsets.right; - } else { - // navigation bar on the bottom - mBottomMargin = mBottomMargin > 0 ? mBottomMargin : mCurrentInsets.bottom; - } - } - // make sure all the children are resized - super.onMeasure(widthMeasureSpec - mLeftMargin - mRightMargin, - heightMeasureSpec - mTopMargin - mBottomMargin); - setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); - } - - @Override - public void onLayout(boolean changed, int l, int t, int r, int b) { - r -= l; - b -= t; - l = 0; - t = 0; - int orientation = getResources().getConfiguration().orientation; - // Lay out children - for (int i = 0; i < getChildCount(); i++) { - View v = getChildAt(i); - if (v instanceof CameraControls) { - // Lay out camera controls to center on the short side of the screen - // so that they stay in place during rotation - int width = v.getMeasuredWidth(); - int height = v.getMeasuredHeight(); - if (orientation == Configuration.ORIENTATION_PORTRAIT) { - int left = (l + r - width) / 2; - v.layout(left, t + mTopMargin, left + width, b - mBottomMargin); - } else { - int top = (t + b - height) / 2; - v.layout(l + mLeftMargin, top, r - mRightMargin, top + height); - } - } else { - v.layout(l + mLeftMargin, t + mTopMargin, r - mRightMargin, b - mBottomMargin); - } - } - } -} diff --git a/src/com/android/camera/ui/CameraSwitcher.java b/src/com/android/camera/ui/CameraSwitcher.java deleted file mode 100644 index 6e4321571..000000000 --- a/src/com/android/camera/ui/CameraSwitcher.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.AnimatorListenerAdapter; -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.View.OnTouchListener; -import android.view.ViewGroup; -import android.widget.FrameLayout.LayoutParams; -import android.widget.LinearLayout; - -import com.android.camera.Util; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.UsageStatistics; - -public class CameraSwitcher extends RotateImageView - implements OnClickListener, OnTouchListener { - - private static final String TAG = "CAM_Switcher"; - private static final int SWITCHER_POPUP_ANIM_DURATION = 200; - - public static final int PHOTO_MODULE_INDEX = 0; - public static final int VIDEO_MODULE_INDEX = 1; - public static final int LIGHTCYCLE_MODULE_INDEX = 2; - public static final int REFOCUS_MODULE_INDEX = 3; - private static final int[] DRAW_IDS = { - R.drawable.ic_switch_camera, - R.drawable.ic_switch_video, - R.drawable.ic_switch_photosphere, - R.drawable.ic_switch_refocus - }; - public interface CameraSwitchListener { - public void onCameraSelected(int i); - public void onShowSwitcherPopup(); - } - - private CameraSwitchListener mListener; - private int mCurrentIndex; - private int[] mModuleIds; - private int[] mDrawIds; - private int mItemSize; - private View mPopup; - private View mParent; - private boolean mShowingPopup; - private boolean mNeedsAnimationSetup; - private Drawable mIndicator; - - private float mTranslationX = 0; - private float mTranslationY = 0; - - private AnimatorListener mHideAnimationListener; - private AnimatorListener mShowAnimationListener; - - public CameraSwitcher(Context context) { - super(context); - init(context); - } - - public CameraSwitcher(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - private void init(Context context) { - mItemSize = context.getResources().getDimensionPixelSize(R.dimen.switcher_size); - setOnClickListener(this); - mIndicator = context.getResources().getDrawable(R.drawable.ic_switcher_menu_indicator); - initializeDrawables(context); - } - - public void initializeDrawables(Context context) { - int totaldrawid = (LightCycleHelper.hasLightCycleCapture(context) - ? DRAW_IDS.length : DRAW_IDS.length - 1); - - int[] drawids = new int[totaldrawid]; - int[] moduleids = new int[totaldrawid]; - int ix = 0; - for (int i = 0; i < DRAW_IDS.length; i++) { - if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(context)) { - continue; // not enabled, so don't add to UI - } - moduleids[ix] = i; - drawids[ix++] = DRAW_IDS[i]; - } - setIds(moduleids, drawids); - } - - public void setIds(int[] moduleids, int[] drawids) { - mDrawIds = drawids; - mModuleIds = moduleids; - } - - public void setCurrentIndex(int i) { - mCurrentIndex = i; - setImageResource(mDrawIds[i]); - } - - public void setSwitchListener(CameraSwitchListener l) { - mListener = l; - } - - @Override - public void onClick(View v) { - showSwitcher(); - mListener.onShowSwitcherPopup(); - } - - private void onCameraSelected(int ix) { - hidePopup(); - if ((ix != mCurrentIndex) && (mListener != null)) { - UsageStatistics.onEvent("CameraModeSwitch", null, null); - UsageStatistics.setPendingTransitionCause( - UsageStatistics.TRANSITION_MENU_TAP); - setCurrentIndex(ix); - mListener.onCameraSelected(mModuleIds[ix]); - } - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - mIndicator.setBounds(getDrawable().getBounds()); - mIndicator.draw(canvas); - } - - private void initPopup() { - mParent = LayoutInflater.from(getContext()).inflate(R.layout.switcher_popup, - (ViewGroup) getParent()); - LinearLayout content = (LinearLayout) mParent.findViewById(R.id.content); - mPopup = content; - // Set the gravity of the popup, so that it shows up at the right position - // on screen - LayoutParams lp = ((LayoutParams) mPopup.getLayoutParams()); - lp.gravity = ((LayoutParams) mParent.findViewById(R.id.camera_switcher) - .getLayoutParams()).gravity; - mPopup.setLayoutParams(lp); - - mPopup.setVisibility(View.INVISIBLE); - mNeedsAnimationSetup = true; - for (int i = mDrawIds.length - 1; i >= 0; i--) { - RotateImageView item = new RotateImageView(getContext()); - item.setImageResource(mDrawIds[i]); - item.setBackgroundResource(R.drawable.bg_pressed); - final int index = i; - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (showsPopup()) onCameraSelected(index); - } - }); - switch (mDrawIds[i]) { - case R.drawable.ic_switch_camera: - item.setContentDescription(getContext().getResources().getString( - R.string.accessibility_switch_to_camera)); - break; - case R.drawable.ic_switch_video: - item.setContentDescription(getContext().getResources().getString( - R.string.accessibility_switch_to_video)); - break; - case R.drawable.ic_switch_photosphere: - item.setContentDescription(getContext().getResources().getString( - R.string.accessibility_switch_to_new_panorama)); - break; - case R.drawable.ic_switch_refocus: - item.setContentDescription(getContext().getResources().getString( - R.string.accessibility_switch_to_refocus)); - break; - default: - break; - } - content.addView(item, new LinearLayout.LayoutParams(mItemSize, mItemSize)); - } - mPopup.measure(MeasureSpec.makeMeasureSpec(mParent.getWidth(), MeasureSpec.AT_MOST), - MeasureSpec.makeMeasureSpec(mParent.getHeight(), MeasureSpec.AT_MOST)); - } - - public boolean showsPopup() { - return mShowingPopup; - } - - public boolean isInsidePopup(MotionEvent evt) { - if (!showsPopup()) return false; - int topLeft[] = new int[2]; - mPopup.getLocationOnScreen(topLeft); - int left = topLeft[0]; - int top = topLeft[1]; - int bottom = top + mPopup.getHeight(); - int right = left + mPopup.getWidth(); - return evt.getX() >= left && evt.getX() < right - && evt.getY() >= top && evt.getY() < bottom; - } - - private void hidePopup() { - mShowingPopup = false; - setVisibility(View.VISIBLE); - if (mPopup != null && !animateHidePopup()) { - mPopup.setVisibility(View.INVISIBLE); - } - mParent.setOnTouchListener(null); - } - - @Override - public void onConfigurationChanged(Configuration config) { - if (showsPopup()) { - ((ViewGroup) mParent).removeView(mPopup); - mPopup = null; - initPopup(); - mPopup.setVisibility(View.VISIBLE); - } - } - - private void showSwitcher() { - mShowingPopup = true; - if (mPopup == null) { - initPopup(); - } - layoutPopup(); - mPopup.setVisibility(View.VISIBLE); - if (!animateShowPopup()) { - setVisibility(View.INVISIBLE); - } - mParent.setOnTouchListener(this); - } - - @Override - public boolean onTouch(View v, MotionEvent event) { - closePopup(); - return true; - } - - public void closePopup() { - if (showsPopup()) { - hidePopup(); - } - } - - @Override - public void setOrientation(int degree, boolean animate) { - super.setOrientation(degree, animate); - ViewGroup content = (ViewGroup) mPopup; - if (content == null) return; - for (int i = 0; i < content.getChildCount(); i++) { - RotateImageView iv = (RotateImageView) content.getChildAt(i); - iv.setOrientation(degree, animate); - } - } - - private void layoutPopup() { - int orientation = Util.getDisplayRotation((Activity) getContext()); - int w = mPopup.getMeasuredWidth(); - int h = mPopup.getMeasuredHeight(); - if (orientation == 0) { - mPopup.layout(getRight() - w, getBottom() - h, getRight(), getBottom()); - mTranslationX = 0; - mTranslationY = h / 3; - } else if (orientation == 90) { - mTranslationX = w / 3; - mTranslationY = - h / 3; - mPopup.layout(getRight() - w, getTop(), getRight(), getTop() + h); - } else if (orientation == 180) { - mTranslationX = - w / 3; - mTranslationY = - h / 3; - mPopup.layout(getLeft(), getTop(), getLeft() + w, getTop() + h); - } else { - mTranslationX = - w / 3; - mTranslationY = h - getHeight(); - mPopup.layout(getLeft(), getBottom() - h, getLeft() + w, getBottom()); - } - } - - @Override - public void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (mPopup != null) { - layoutPopup(); - } - } - - private void popupAnimationSetup() { - if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) { - return; - } - layoutPopup(); - mPopup.setScaleX(0.3f); - mPopup.setScaleY(0.3f); - mPopup.setTranslationX(mTranslationX); - mPopup.setTranslationY(mTranslationY); - mNeedsAnimationSetup = false; - } - - private boolean animateHidePopup() { - if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) { - return false; - } - if (mHideAnimationListener == null) { - mHideAnimationListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - // Verify that we weren't canceled - if (!showsPopup() && mPopup != null) { - mPopup.setVisibility(View.INVISIBLE); - ((ViewGroup) mParent).removeView(mPopup); - mPopup = null; - } - } - }; - } - mPopup.animate() - .alpha(0f) - .scaleX(0.3f).scaleY(0.3f) - .translationX(mTranslationX) - .translationY(mTranslationY) - .setDuration(SWITCHER_POPUP_ANIM_DURATION) - .setListener(mHideAnimationListener); - animate().alpha(1f).setDuration(SWITCHER_POPUP_ANIM_DURATION) - .setListener(null); - return true; - } - - private boolean animateShowPopup() { - if (!ApiHelper.HAS_VIEW_PROPERTY_ANIMATOR) { - return false; - } - if (mNeedsAnimationSetup) { - popupAnimationSetup(); - } - if (mShowAnimationListener == null) { - mShowAnimationListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - // Verify that we weren't canceled - if (showsPopup()) { - setVisibility(View.INVISIBLE); - // request layout to make sure popup is laid out correctly on ICS - mPopup.requestLayout(); - } - } - }; - } - mPopup.animate() - .alpha(1f) - .scaleX(1f).scaleY(1f) - .translationX(0) - .translationY(0) - .setDuration(SWITCHER_POPUP_ANIM_DURATION) - .setListener(null); - animate().alpha(0f).setDuration(SWITCHER_POPUP_ANIM_DURATION) - .setListener(mShowAnimationListener); - return true; - } -} diff --git a/src/com/android/camera/ui/CheckedLinearLayout.java b/src/com/android/camera/ui/CheckedLinearLayout.java deleted file mode 100644 index 4e7750499..000000000 --- a/src/com/android/camera/ui/CheckedLinearLayout.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.Checkable; -import android.widget.LinearLayout; - -public class CheckedLinearLayout extends LinearLayout implements Checkable { - private static final int[] CHECKED_STATE_SET = { - android.R.attr.state_checked - }; - private boolean mChecked; - - public CheckedLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public boolean isChecked() { - return mChecked; - } - - @Override - public void setChecked(boolean checked) { - if (mChecked != checked) { - mChecked = checked; - refreshDrawableState(); - } - } - - @Override - public void toggle() { - setChecked(!mChecked); - } - - @Override - public int[] onCreateDrawableState(int extraSpace) { - final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); - if (mChecked) { - mergeDrawableStates(drawableState, CHECKED_STATE_SET); - } - return drawableState; - } -} diff --git a/src/com/android/camera/ui/CountDownView.java b/src/com/android/camera/ui/CountDownView.java deleted file mode 100644 index 907d33508..000000000 --- a/src/com/android/camera/ui/CountDownView.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import java.util.Locale; - -import android.content.Context; -import android.media.AudioManager; -import android.media.SoundPool; -import android.os.Handler; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.widget.FrameLayout; -import android.widget.TextView; - -import com.android.gallery3d.R; - -public class CountDownView extends FrameLayout { - - private static final String TAG = "CAM_CountDownView"; - private static final int SET_TIMER_TEXT = 1; - private TextView mRemainingSecondsView; - private int mRemainingSecs = 0; - private OnCountDownFinishedListener mListener; - private Animation mCountDownAnim; - private SoundPool mSoundPool; - private int mBeepTwice; - private int mBeepOnce; - private boolean mPlaySound; - private final Handler mHandler = new MainHandler(); - - public CountDownView(Context context, AttributeSet attrs) { - super(context, attrs); - mCountDownAnim = AnimationUtils.loadAnimation(context, R.anim.count_down_exit); - // Load the beeps - mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0); - mBeepOnce = mSoundPool.load(context, R.raw.beep_once, 1); - mBeepTwice = mSoundPool.load(context, R.raw.beep_twice, 1); - } - - public boolean isCountingDown() { - return mRemainingSecs > 0; - }; - - public interface OnCountDownFinishedListener { - public void onCountDownFinished(); - } - - private void remainingSecondsChanged(int newVal) { - mRemainingSecs = newVal; - if (newVal == 0) { - // Countdown has finished - setVisibility(View.INVISIBLE); - mListener.onCountDownFinished(); - } else { - Locale locale = getResources().getConfiguration().locale; - String localizedValue = String.format(locale, "%d", newVal); - mRemainingSecondsView.setText(localizedValue); - // Fade-out animation - mCountDownAnim.reset(); - mRemainingSecondsView.clearAnimation(); - mRemainingSecondsView.startAnimation(mCountDownAnim); - - // Play sound effect for the last 3 seconds of the countdown - if (mPlaySound) { - if (newVal == 1) { - mSoundPool.play(mBeepTwice, 1.0f, 1.0f, 0, 0, 1.0f); - } else if (newVal <= 3) { - mSoundPool.play(mBeepOnce, 1.0f, 1.0f, 0, 0, 1.0f); - } - } - // Schedule the next remainingSecondsChanged() call in 1 second - mHandler.sendEmptyMessageDelayed(SET_TIMER_TEXT, 1000); - } - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mRemainingSecondsView = (TextView) findViewById(R.id.remaining_seconds); - } - - public void setCountDownFinishedListener(OnCountDownFinishedListener listener) { - mListener = listener; - } - - public void startCountDown(int sec, boolean playSound) { - if (sec <= 0) { - Log.w(TAG, "Invalid input for countdown timer: " + sec + " seconds"); - return; - } - setVisibility(View.VISIBLE); - mPlaySound = playSound; - remainingSecondsChanged(sec); - } - - public void cancelCountDown() { - if (mRemainingSecs > 0) { - mRemainingSecs = 0; - mHandler.removeMessages(SET_TIMER_TEXT); - setVisibility(View.INVISIBLE); - } - } - - private class MainHandler extends Handler { - @Override - public void handleMessage(Message message) { - if (message.what == SET_TIMER_TEXT) { - remainingSecondsChanged(mRemainingSecs -1); - } - } - } -}
\ No newline at end of file diff --git a/src/com/android/camera/ui/CountdownTimerPopup.java b/src/com/android/camera/ui/CountdownTimerPopup.java deleted file mode 100644 index 7c3572b55..000000000 --- a/src/com/android/camera/ui/CountdownTimerPopup.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.NumberPicker; -import android.widget.NumberPicker.OnValueChangeListener; - -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -import java.util.Locale; - -/** - * This is a popup window that allows users to specify a countdown timer - */ - -public class CountdownTimerPopup extends AbstractSettingPopup { - private static final String TAG = "TimerSettingPopup"; - private NumberPicker mNumberSpinner; - private String[] mDurations; - private ListPreference mTimer; - private ListPreference mBeep; - private Listener mListener; - private Button mConfirmButton; - private View mPickerTitle; - private CheckBox mTimerSound; - private View mSoundTitle; - - static public interface Listener { - public void onListPrefChanged(ListPreference pref); - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - public CountdownTimerPopup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void initialize(ListPreference timer, ListPreference beep) { - mTimer = timer; - mBeep = beep; - // Set title. - mTitle.setText(mTimer.getTitle()); - - // Duration - CharSequence[] entries = mTimer.getEntryValues(); - mDurations = new String[entries.length]; - Locale locale = getResources().getConfiguration().locale; - mDurations[0] = getResources().getString(R.string.setting_off); // Off - for (int i = 1; i < entries.length; i++) - mDurations[i] = String.format(locale, "%d", Integer.parseInt(entries[i].toString())); - int durationCount = mDurations.length; - mNumberSpinner = (NumberPicker) findViewById(R.id.duration); - mNumberSpinner.setMinValue(0); - mNumberSpinner.setMaxValue(durationCount - 1); - mNumberSpinner.setDisplayedValues(mDurations); - mNumberSpinner.setWrapSelectorWheel(false); - mNumberSpinner.setOnValueChangedListener(new OnValueChangeListener() { - @Override - public void onValueChange(NumberPicker picker, int oldValue, int newValue) { - setTimeSelectionEnabled(newValue != 0); - } - }); - mConfirmButton = (Button) findViewById(R.id.timer_set_button); - mPickerTitle = findViewById(R.id.set_time_interval_title); - - // Disable focus on the spinners to prevent keyboard from coming up - mNumberSpinner.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); - - mConfirmButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - updateInputState(); - } - }); - mTimerSound = (CheckBox) findViewById(R.id.sound_check_box); - mSoundTitle = findViewById(R.id.beep_title); - } - - private void restoreSetting() { - int index = mTimer.findIndexOfValue(mTimer.getValue()); - if (index == -1) { - Log.e(TAG, "Invalid preference value."); - mTimer.print(); - throw new IllegalArgumentException(); - } else { - setTimeSelectionEnabled(index != 0); - mNumberSpinner.setValue(index); - } - boolean checked = mBeep.findIndexOfValue(mBeep.getValue()) != 0; - mTimerSound.setChecked(checked); - } - - @Override - public void setVisibility(int visibility) { - if (visibility == View.VISIBLE) { - if (getVisibility() != View.VISIBLE) { - // Set the number pickers and on/off switch to be consistent - // with the preference - restoreSetting(); - } - } - super.setVisibility(visibility); - } - - protected void setTimeSelectionEnabled(boolean enabled) { - mPickerTitle.setVisibility(enabled ? VISIBLE : INVISIBLE); - mTimerSound.setEnabled(enabled); - mSoundTitle.setEnabled(enabled); - } - - @Override - public void reloadPreference() { - } - - private void updateInputState() { - mTimer.setValueIndex(mNumberSpinner.getValue()); - mBeep.setValueIndex(mTimerSound.isChecked() ? 1 : 0); - if (mListener != null) { - mListener.onListPrefChanged(mTimer); - mListener.onListPrefChanged(mBeep); - } - } -} diff --git a/src/com/android/camera/ui/EffectSettingPopup.java b/src/com/android/camera/ui/EffectSettingPopup.java deleted file mode 100644 index 568781a01..000000000 --- a/src/com/android/camera/ui/EffectSettingPopup.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2010 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.ui; - -import android.annotation.TargetApi; -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.AdapterView; -import android.widget.GridView; -import android.widget.SimpleAdapter; - -import com.android.camera.IconListPreference; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; -import java.util.HashMap; - -// A popup window that shows video effect setting. It has two grid view. -// One shows the goofy face effects. The other shows the background replacer -// effects. -public class EffectSettingPopup extends AbstractSettingPopup implements - AdapterView.OnItemClickListener, View.OnClickListener { - private static final String TAG = "EffectSettingPopup"; - private String mNoEffect; - private IconListPreference mPreference; - private Listener mListener; - private View mClearEffects; - private GridView mSillyFacesGrid; - private GridView mBackgroundGrid; - - // Data for silly face items. (text, image, and preference value) - ArrayList<HashMap<String, Object>> mSillyFacesItem = - new ArrayList<HashMap<String, Object>>(); - - // Data for background replacer items. (text, image, and preference value) - ArrayList<HashMap<String, Object>> mBackgroundItem = - new ArrayList<HashMap<String, Object>>(); - - - static public interface Listener { - public void onSettingChanged(); - } - - public EffectSettingPopup(Context context, AttributeSet attrs) { - super(context, attrs); - mNoEffect = context.getString(R.string.pref_video_effect_default); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mClearEffects = findViewById(R.id.clear_effects); - mClearEffects.setOnClickListener(this); - mSillyFacesGrid = (GridView) findViewById(R.id.effect_silly_faces); - mBackgroundGrid = (GridView) findViewById(R.id.effect_background); - } - - public void initialize(IconListPreference preference) { - mPreference = preference; - Context context = getContext(); - CharSequence[] entries = mPreference.getEntries(); - CharSequence[] entryValues = mPreference.getEntryValues(); - int[] iconIds = mPreference.getImageIds(); - if (iconIds == null) { - iconIds = mPreference.getLargeIconIds(); - } - - // Set title. - mTitle.setText(mPreference.getTitle()); - - for(int i = 0; i < entries.length; ++i) { - String value = entryValues[i].toString(); - if (value.equals(mNoEffect)) continue; // no effect, skip it. - HashMap<String, Object> map = new HashMap<String, Object>(); - map.put("value", value); - map.put("text", entries[i].toString()); - if (iconIds != null) map.put("image", iconIds[i]); - if (value.startsWith("goofy_face")) { - mSillyFacesItem.add(map); - } else if (value.startsWith("backdropper")) { - mBackgroundItem.add(map); - } - } - - boolean hasSillyFaces = mSillyFacesItem.size() > 0; - boolean hasBackground = mBackgroundItem.size() > 0; - - // Initialize goofy face if it is supported. - if (hasSillyFaces) { - findViewById(R.id.effect_silly_faces_title).setVisibility(View.VISIBLE); - findViewById(R.id.effect_silly_faces_title_separator).setVisibility(View.VISIBLE); - mSillyFacesGrid.setVisibility(View.VISIBLE); - SimpleAdapter sillyFacesItemAdapter = new SimpleAdapter(context, - mSillyFacesItem, R.layout.effect_setting_item, - new String[] {"text", "image"}, - new int[] {R.id.text, R.id.image}); - mSillyFacesGrid.setAdapter(sillyFacesItemAdapter); - mSillyFacesGrid.setOnItemClickListener(this); - } - - if (hasSillyFaces && hasBackground) { - findViewById(R.id.effect_background_separator).setVisibility(View.VISIBLE); - } - - // Initialize background replacer if it is supported. - if (hasBackground) { - findViewById(R.id.effect_background_title).setVisibility(View.VISIBLE); - findViewById(R.id.effect_background_title_separator).setVisibility(View.VISIBLE); - mBackgroundGrid.setVisibility(View.VISIBLE); - SimpleAdapter backgroundItemAdapter = new SimpleAdapter(context, - mBackgroundItem, R.layout.effect_setting_item, - new String[] {"text", "image"}, - new int[] {R.id.text, R.id.image}); - mBackgroundGrid.setAdapter(backgroundItemAdapter); - mBackgroundGrid.setOnItemClickListener(this); - } - - reloadPreference(); - } - - @Override - public void setVisibility(int visibility) { - if (visibility == View.VISIBLE) { - if (getVisibility() != View.VISIBLE) { - // Do not show or hide "Clear effects" button when the popup - // is already visible. Otherwise it looks strange. - boolean noEffect = mPreference.getValue().equals(mNoEffect); - mClearEffects.setVisibility(noEffect ? View.GONE : View.VISIBLE); - } - reloadPreference(); - } - super.setVisibility(visibility); - } - - // The value of the preference may have changed. Update the UI. - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - public void reloadPreference() { - mBackgroundGrid.setItemChecked(mBackgroundGrid.getCheckedItemPosition(), false); - mSillyFacesGrid.setItemChecked(mSillyFacesGrid.getCheckedItemPosition(), false); - - String value = mPreference.getValue(); - if (value.equals(mNoEffect)) return; - - for (int i = 0; i < mSillyFacesItem.size(); i++) { - if (value.equals(mSillyFacesItem.get(i).get("value"))) { - mSillyFacesGrid.setItemChecked(i, true); - return; - } - } - - for (int i = 0; i < mBackgroundItem.size(); i++) { - if (value.equals(mBackgroundItem.get(i).get("value"))) { - mBackgroundGrid.setItemChecked(i, true); - return; - } - } - - Log.e(TAG, "Invalid preference value: " + value); - mPreference.print(); - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, - int index, long id) { - String value; - if (parent == mSillyFacesGrid) { - value = (String) mSillyFacesItem.get(index).get("value"); - } else if (parent == mBackgroundGrid) { - value = (String) mBackgroundItem.get(index).get("value"); - } else { - return; - } - - // Tapping the selected effect will deselect it (clear effects). - if (value.equals(mPreference.getValue())) { - mPreference.setValue(mNoEffect); - } else { - mPreference.setValue(value); - } - reloadPreference(); - if (mListener != null) mListener.onSettingChanged(); - } - - @Override - public void onClick(View v) { - // Clear the effect. - mPreference.setValue(mNoEffect); - reloadPreference(); - if (mListener != null) mListener.onSettingChanged(); - } -} diff --git a/src/com/android/camera/ui/ExpandedGridView.java b/src/com/android/camera/ui/ExpandedGridView.java deleted file mode 100644 index 13cf58f34..000000000 --- a/src/com/android/camera/ui/ExpandedGridView.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.GridView; - -public class ExpandedGridView extends GridView { - public ExpandedGridView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // If UNSPECIFIED is passed to GridView, it will show only one row. - // Here GridView is put in a ScrollView, so pass it a very big size with - // AT_MOST to show all the rows. - heightMeasureSpec = MeasureSpec.makeMeasureSpec(65536, MeasureSpec.AT_MOST); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } -} diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java deleted file mode 100644 index 7d66dc079..000000000 --- a/src/com/android/camera/ui/FaceView.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.RectF; -import android.hardware.Camera.Face; -import android.os.Handler; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; - -import com.android.camera.PhotoUI; -import com.android.camera.Util; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -@TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) -public class FaceView extends View - implements FocusIndicator, Rotatable, - PhotoUI.SurfaceTextureSizeChangedListener { - private static final String TAG = "CAM FaceView"; - private final boolean LOGV = false; - // The value for android.hardware.Camera.setDisplayOrientation. - private int mDisplayOrientation; - // The orientation compensation for the face indicator to make it look - // correctly in all device orientations. Ex: if the value is 90, the - // indicator should be rotated 90 degrees counter-clockwise. - private int mOrientation; - private boolean mMirror; - private boolean mPause; - private Matrix mMatrix = new Matrix(); - private RectF mRect = new RectF(); - // As face detection can be flaky, we add a layer of filtering on top of it - // to avoid rapid changes in state (eg, flickering between has faces and - // not having faces) - private Face[] mFaces; - private Face[] mPendingFaces; - private int mColor; - private final int mFocusingColor; - private final int mFocusedColor; - private final int mFailColor; - private Paint mPaint; - private volatile boolean mBlocked; - - private int mUncroppedWidth; - private int mUncroppedHeight; - private static final int MSG_SWITCH_FACES = 1; - private static final int SWITCH_DELAY = 70; - private boolean mStateSwitchPending = false; - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_SWITCH_FACES: - mStateSwitchPending = false; - mFaces = mPendingFaces; - invalidate(); - break; - } - } - }; - - public FaceView(Context context, AttributeSet attrs) { - super(context, attrs); - Resources res = getResources(); - mFocusingColor = res.getColor(R.color.face_detect_start); - mFocusedColor = res.getColor(R.color.face_detect_success); - mFailColor = res.getColor(R.color.face_detect_fail); - mColor = mFocusingColor; - mPaint = new Paint(); - mPaint.setAntiAlias(true); - mPaint.setStyle(Style.STROKE); - mPaint.setStrokeWidth(res.getDimension(R.dimen.face_circle_stroke)); - } - - @Override - public void onSurfaceTextureSizeChanged(int uncroppedWidth, int uncroppedHeight) { - mUncroppedWidth = uncroppedWidth; - mUncroppedHeight = uncroppedHeight; - } - - public void setFaces(Face[] faces) { - if (LOGV) Log.v(TAG, "Num of faces=" + faces.length); - if (mPause) return; - if (mFaces != null) { - if ((faces.length > 0 && mFaces.length == 0) - || (faces.length == 0 && mFaces.length > 0)) { - mPendingFaces = faces; - if (!mStateSwitchPending) { - mStateSwitchPending = true; - mHandler.sendEmptyMessageDelayed(MSG_SWITCH_FACES, SWITCH_DELAY); - } - return; - } - } - if (mStateSwitchPending) { - mStateSwitchPending = false; - mHandler.removeMessages(MSG_SWITCH_FACES); - } - mFaces = faces; - invalidate(); - } - - public void setDisplayOrientation(int orientation) { - mDisplayOrientation = orientation; - if (LOGV) Log.v(TAG, "mDisplayOrientation=" + orientation); - } - - @Override - public void setOrientation(int orientation, boolean animation) { - mOrientation = orientation; - invalidate(); - } - - public void setMirror(boolean mirror) { - mMirror = mirror; - if (LOGV) Log.v(TAG, "mMirror=" + mirror); - } - - public boolean faceExists() { - return (mFaces != null && mFaces.length > 0); - } - - @Override - public void showStart() { - mColor = mFocusingColor; - invalidate(); - } - - // Ignore the parameter. No autofocus animation for face detection. - @Override - public void showSuccess(boolean timeout) { - mColor = mFocusedColor; - invalidate(); - } - - // Ignore the parameter. No autofocus animation for face detection. - @Override - public void showFail(boolean timeout) { - mColor = mFailColor; - invalidate(); - } - - @Override - public void clear() { - // Face indicator is displayed during preview. Do not clear the - // drawable. - mColor = mFocusingColor; - mFaces = null; - invalidate(); - } - - public void pause() { - mPause = true; - } - - public void resume() { - mPause = false; - } - - public void setBlockDraw(boolean block) { - mBlocked = block; - } - - @Override - protected void onDraw(Canvas canvas) { - if (!mBlocked && (mFaces != null) && (mFaces.length > 0)) { - int rw, rh; - rw = mUncroppedWidth; - rh = mUncroppedHeight; - // Prepare the matrix. - if (((rh > rw) && ((mDisplayOrientation == 0) || (mDisplayOrientation == 180))) - || ((rw > rh) && ((mDisplayOrientation == 90) || (mDisplayOrientation == 270)))) { - int temp = rw; - rw = rh; - rh = temp; - } - Util.prepareMatrix(mMatrix, mMirror, mDisplayOrientation, rw, rh); - int dx = (getWidth() - rw) / 2; - int dy = (getHeight() - rh) / 2; - - // Focus indicator is directional. Rotate the matrix and the canvas - // so it looks correctly in all orientations. - canvas.save(); - mMatrix.postRotate(mOrientation); // postRotate is clockwise - canvas.rotate(-mOrientation); // rotate is counter-clockwise (for canvas) - for (int i = 0; i < mFaces.length; i++) { - // Filter out false positives. - if (mFaces[i].score < 50) continue; - - // Transform the coordinates. - mRect.set(mFaces[i].rect); - if (LOGV) Util.dumpRect(mRect, "Original rect"); - mMatrix.mapRect(mRect); - if (LOGV) Util.dumpRect(mRect, "Transformed rect"); - mPaint.setColor(mColor); - mRect.offset(dx, dy); - canvas.drawOval(mRect, mPaint); - } - canvas.restore(); - } - super.onDraw(canvas); - } -} diff --git a/src/com/android/camera/ui/FilmStripGestureRecognizer.java b/src/com/android/camera/ui/FilmStripGestureRecognizer.java deleted file mode 100644 index f870b5829..000000000 --- a/src/com/android/camera/ui/FilmStripGestureRecognizer.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2013 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.ui; - -import android.content.Context; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; - -// This class aggregates three gesture detectors: GestureDetector, -// ScaleGestureDetector. -public class FilmStripGestureRecognizer { - @SuppressWarnings("unused") - private static final String TAG = "FilmStripGestureRecognizer"; - - public interface Listener { - boolean onSingleTapUp(float x, float y); - boolean onDoubleTap(float x, float y); - boolean onScroll(float x, float y, float dx, float dy); - boolean onFling(float velocityX, float velocityY); - boolean onScaleBegin(float focusX, float focusY); - boolean onScale(float focusX, float focusY, float scale); - boolean onDown(float x, float y); - boolean onUp(float x, float y); - void onScaleEnd(); - } - - private final GestureDetector mGestureDetector; - private final ScaleGestureDetector mScaleDetector; - private final Listener mListener; - - public FilmStripGestureRecognizer(Context context, Listener listener) { - mListener = listener; - mGestureDetector = new GestureDetector(context, new MyGestureListener(), - null, true /* ignoreMultitouch */); - mScaleDetector = new ScaleGestureDetector( - context, new MyScaleListener()); - } - - public void onTouchEvent(MotionEvent event) { - mGestureDetector.onTouchEvent(event); - mScaleDetector.onTouchEvent(event); - if (event.getAction() == MotionEvent.ACTION_UP) { - mListener.onUp(event.getX(), event.getY()); - } - } - - private class MyGestureListener - extends GestureDetector.SimpleOnGestureListener { - @Override - public boolean onSingleTapUp(MotionEvent e) { - return mListener.onSingleTapUp(e.getX(), e.getY()); - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - return mListener.onDoubleTap(e.getX(), e.getY()); - } - - @Override - public boolean onScroll( - MotionEvent e1, MotionEvent e2, float dx, float dy) { - return mListener.onScroll(e2.getX(), e2.getY(), dx, dy); - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - return mListener.onFling(velocityX, velocityY); - } - - @Override - public boolean onDown(MotionEvent e) { - mListener.onDown(e.getX(), e.getY()); - return super.onDown(e); - } - } - - private class MyScaleListener - extends ScaleGestureDetector.SimpleOnScaleGestureListener { - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - return mListener.onScaleBegin( - detector.getFocusX(), detector.getFocusY()); - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - return mListener.onScale(detector.getFocusX(), - detector.getFocusY(), detector.getScaleFactor()); - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - mListener.onScaleEnd(); - } - } -} diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java deleted file mode 100644 index 8bc46b0d4..000000000 --- a/src/com/android/camera/ui/FilmStripView.java +++ /dev/null @@ -1,1724 +0,0 @@ -/* - * Copyright (C) 2013 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.ui; - -import android.animation.Animator; -import android.animation.TimeInterpolator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.DecelerateInterpolator; -import android.widget.FrameLayout; -import android.widget.ImageButton; -import android.widget.Scroller; - -import com.android.camera.ui.FilmStripView.ImageData.PanoramaSupportCallback; -import com.android.gallery3d.R; -import com.android.gallery3d.util.PanoramaViewHelper; - -public class FilmStripView extends ViewGroup { - @SuppressWarnings("unused") - private static final String TAG = "CAM_FilmStripView"; - - private static final int BUFFER_SIZE = 5; - private static final int DURATION_GEOMETRY_ADJUST = 200; - private static final float FILM_STRIP_SCALE = 0.6f; - private static final float FULLSCREEN_SCALE = 1f; - // Only check for intercepting touch events within first 500ms - private static final int SWIPE_TIME_OUT = 500; - - private Context mContext; - private FilmStripGestureRecognizer mGestureRecognizer; - private DataAdapter mDataAdapter; - private int mViewGap; - private final Rect mDrawArea = new Rect(); - - private final int mCurrentInfo = (BUFFER_SIZE - 1) / 2; - private float mScale; - private MyController mController; - private int mCenterX = -1; - private ViewInfo[] mViewInfo = new ViewInfo[BUFFER_SIZE]; - - private Listener mListener; - - private MotionEvent mDown; - private boolean mCheckToIntercept = true; - private View mCameraView; - private int mSlop; - private TimeInterpolator mViewAnimInterpolator; - - private ImageButton mViewPhotoSphereButton; - private PanoramaViewHelper mPanoramaViewHelper; - private long mLastItemId = -1; - - // This is used to resolve the misalignment problem when the device - // orientation is changed. If the current item is in fullscreen, it might - // be shifted because mCenterX is not adjusted with the orientation. - // Set this to true when onSizeChanged is called to make sure we adjust - // mCenterX accordingly. - private boolean mAnchorPending; - - /** - * Common interface for all images in the filmstrip. - */ - public interface ImageData { - /** - * Interface that is used to tell the caller whether an image is a photo - * sphere. - */ - public static interface PanoramaSupportCallback { - /** - * Called then photo sphere info has been loaded. - * - * @param isPanorama whether the image is a valid photo sphere - * @param isPanorama360 whether the photo sphere is a full 360 - * degree horizontal panorama - */ - void panoramaInfoAvailable(boolean isPanorama, - boolean isPanorama360); - } - - // Image data types. - public static final int TYPE_NONE = 0; - public static final int TYPE_CAMERA_PREVIEW = 1; - public static final int TYPE_PHOTO = 2; - - // Actions allowed to be performed on the image data. - // The actions are defined bit-wise so we can use bit operations like - // | and &. - public static final int ACTION_NONE = 0; - public static final int ACTION_PROMOTE = 1; - public static final int ACTION_DEMOTE = (1 << 1); - - /** - * SIZE_FULL can be returned by {@link ImageData#getWidth()} and - * {@link ImageData#getHeight()}. - * When SIZE_FULL is returned for width/height, it means the the - * width or height will be disregarded when deciding the view size - * of this ImageData, just use full screen size. - */ - public static final int SIZE_FULL = -2; - - /** - * Returns the width of the image. The final layout of the view returned - * by {@link DataAdapter#getView(android.content.Context, int)} will - * preserve the aspect ratio of - * {@link com.android.camera.ui.FilmStripView.ImageData#getWidth()} and - * {@link com.android.camera.ui.FilmStripView.ImageData#getHeight()}. - */ - public int getWidth(); - - - /** - * Returns the width of the image. The final layout of the view returned - * by {@link DataAdapter#getView(android.content.Context, int)} will - * preserve the aspect ratio of - * {@link com.android.camera.ui.FilmStripView.ImageData#getWidth()} and - * {@link com.android.camera.ui.FilmStripView.ImageData#getHeight()}. - */ - public int getHeight(); - - /** Returns the image data type */ - public int getType(); - - /** - * Checks if the UI action is supported. - * - * @param action The UI actions to check. - * @return {@code false} if at least one of the actions is not - * supported. {@code true} otherwise. - */ - public boolean isUIActionSupported(int action); - - /** - * Gives the data a hint when its view is going to be displayed. - * {@code FilmStripView} should always call this function before - * showing its corresponding view every time. - */ - public void prepare(); - - /** - * Gives the data a hint when its view is going to be removed from the - * view hierarchy. {@code FilmStripView} should always call this - * function after its corresponding view is removed from the view - * hierarchy. - */ - public void recycle(); - - /** - * Asynchronously checks if the image is a photo sphere. Notified the - * callback when the results are available. - */ - public void isPhotoSphere(Context context, PanoramaSupportCallback callback); - - /** - * If the item is a valid photo sphere panorama, this method will launch - * the viewer. - */ - public void viewPhotoSphere(PanoramaViewHelper helper); - } - - /** - * An interfaces which defines the interactions between the - * {@link ImageData} and the {@link FilmStripView}. - */ - public interface DataAdapter { - /** - * An interface which defines the update report used to return to - * the {@link com.android.camera.ui.FilmStripView.Listener}. - */ - public interface UpdateReporter { - /** Checks if the data of dataID is removed. */ - public boolean isDataRemoved(int dataID); - - /** Checks if the data of dataID is updated. */ - public boolean isDataUpdated(int dataID); - } - - /** - * An interface which defines the listener for data events over - * {@link ImageData}. - */ - public interface Listener { - // Called when the whole data loading is done. No any assumption - // on previous data. - public void onDataLoaded(); - - // Only some of the data is changed. The listener should check - // if any thing needs to be updated. - public void onDataUpdated(UpdateReporter reporter); - - public void onDataInserted(int dataID, ImageData data); - - public void onDataRemoved(int dataID, ImageData data); - } - - /** Returns the total number of image data */ - public int getTotalNumber(); - - /** - * Returns the view to visually present the image data. - * - * @param context The {@link Context} to create the view. - * @param dataID The ID of the image data to be presented. - * @return The view representing the image data. Null if - * unavailable or the {@code dataID} is out of range. - */ - public View getView(Context context, int dataID); - - /** - * Returns the {@link ImageData} specified by the ID. - * - * @param dataID The ID of the {@link ImageData}. - * @return The specified {@link ImageData}. Null if not available. - */ - public ImageData getImageData(int dataID); - - /** - * Suggests the data adapter the maximum possible size of the layout - * so the {@link DataAdapter} can optimize the view returned for the - * {@link ImageData}. - * - * @param w Maximum width. - * @param h Maximum height. - */ - public void suggestViewSizeBound(int w, int h); - - /** - * Sets the listener for data events over the ImageData. - * - * @param listener The listener to use. - */ - public void setListener(Listener listener); - - /** - * The callback when the item enters/leaves full-screen. - * TODO: Call this function actually. - * - * @param dataID The ID of the image data. - * @param fullScreen {@code true} if the data is entering full-screen. - * {@code false} otherwise. - */ - public void onDataFullScreen(int dataID, boolean fullScreen); - - /** - * Returns {@code true} if the view of the data can be moved by swipe - * gesture when in full-screen. - * - * @param dataID The ID of the data. - * @return {@code true} if the view can be moved, - * {@code false} otherwise. - */ - public boolean canSwipeInFullScreen(int dataID); - } - - /** - * An interface which defines the FilmStripView UI action listener. - */ - public interface Listener { - /** - * Callback when the data is promoted. - * - * @param dataID The ID of the promoted data. - */ - public void onDataPromoted(int dataID); - - /** - * Callback when the data is demoted. - * - * @param dataID The ID of the demoted data. - */ - public void onDataDemoted(int dataID); - - public void onDataFullScreenChange(int dataID, boolean full); - - /** - * Callback when entering/leaving camera mode. - * - * @param toCamera {@code true} if entering camera mode. Otherwise, - * {@code false} - */ - public void onSwitchMode(boolean toCamera); - - /** - * The callback when the item is centered/off-centered. - * - * @param dataID The ID of the image data. - * @param current {@code true} if the data is the current one. - * {@code false} otherwise. - */ - public void onCurrentDataChanged(int dataID, boolean current); - } - - /** - * An interface which defines the controller of {@link FilmStripView}. - */ - public interface Controller { - public boolean isScalling(); - - public void scroll(float deltaX); - - public void fling(float velocity); - - public void scrollTo(int position, int duration, boolean interruptible); - - public boolean stopScrolling(); - - public boolean isScrolling(); - - public void lockAtCurrentView(); - - public void unlockPosition(); - - public void gotoCameraFullScreen(); - - public void gotoFilmStrip(); - - public void gotoFullScreen(); - } - - /** - * A helper class to tract and calculate the view coordination. - */ - private static class ViewInfo { - private int mDataID; - /** The position of the left of the view in the whole filmstrip. */ - private int mLeftPosition; - private View mView; - private RectF mViewArea; - - public ViewInfo(int id, View v) { - v.setPivotX(0f); - v.setPivotY(0f); - mDataID = id; - mView = v; - mLeftPosition = -1; - mViewArea = new RectF(); - } - - public int getID() { - return mDataID; - } - - public void setID(int id) { - mDataID = id; - } - - public void setLeftPosition(int pos) { - mLeftPosition = pos; - } - - public int getLeftPosition() { - return mLeftPosition; - } - - public float getTranslationY(float scale) { - return mView.getTranslationY() / scale; - } - - public float getTranslationX(float scale) { - return mView.getTranslationX(); - } - - public void setTranslationY(float transY, float scale) { - mView.setTranslationY(transY * scale); - } - - public void setTranslationX(float transX, float scale) { - mView.setTranslationX(transX * scale); - } - - public void translateXBy(float transX, float scale) { - mView.setTranslationX(mView.getTranslationX() + transX * scale); - } - - public int getCenterX() { - return mLeftPosition + mView.getWidth() / 2; - } - - public View getView() { - return mView; - } - - private void layoutAt(int left, int top) { - mView.layout(left, top, left + mView.getMeasuredWidth(), - top + mView.getMeasuredHeight()); - } - - public void layoutIn(Rect drawArea, int refCenter, float scale) { - // drawArea is where to layout in. - // refCenter is the absolute horizontal position of the center of - // drawArea. - int left = (int) (drawArea.centerX() + (mLeftPosition - refCenter) * scale); - int top = (int) (drawArea.centerY() - (mView.getMeasuredHeight() / 2) * scale); - layoutAt(left, top); - mView.setScaleX(scale); - mView.setScaleY(scale); - - // update mViewArea for touch detection. - int l = mView.getLeft(); - int t = mView.getTop(); - mViewArea.set(l, t, - l + mView.getWidth() * scale, - t + mView.getHeight() * scale); - } - - public boolean areaContains(float x, float y) { - return mViewArea.contains(x, y); - } - } - - /** Constructor. */ - public FilmStripView(Context context) { - super(context); - init(context); - } - - /** Constructor. */ - public FilmStripView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - /** Constructor. */ - public FilmStripView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(context); - } - - private void init(Context context) { - // This is for positioning camera controller at the same place in - // different orientations. - setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - - setWillNotDraw(false); - mContext = context; - mScale = 1.0f; - mController = new MyController(context); - mViewAnimInterpolator = new DecelerateInterpolator(); - mGestureRecognizer = - new FilmStripGestureRecognizer(context, new MyGestureReceiver()); - mSlop = (int) getContext().getResources().getDimension(R.dimen.pie_touch_slop); - } - - /** - * Returns the controller. - * - * @return The {@code Controller}. - */ - public Controller getController() { - return mController; - } - - public void setListener(Listener l) { - mListener = l; - } - - public void setViewGap(int viewGap) { - mViewGap = viewGap; - } - - /** - * Sets the helper that's to be used to open photo sphere panoramas. - */ - public void setPanoramaViewHelper(PanoramaViewHelper helper) { - mPanoramaViewHelper = helper; - } - - public float getScale() { - return mScale; - } - - public boolean isAnchoredTo(int id) { - if (mViewInfo[mCurrentInfo].getID() == id - && mViewInfo[mCurrentInfo].getCenterX() == mCenterX) { - return true; - } - return false; - } - - private int getCurrentType() { - if (mDataAdapter == null) { - return ImageData.TYPE_NONE; - } - ViewInfo curr = mViewInfo[mCurrentInfo]; - if (curr == null) { - return ImageData.TYPE_NONE; - } - return mDataAdapter.getImageData(curr.getID()).getType(); - } - - @Override - public void onDraw(Canvas c) { - if (mController.hasNewGeometry()) { - layoutChildren(); - } - } - - /** Returns [width, height] preserving image aspect ratio. */ - private int[] calculateChildDimension( - int imageWidth, int imageHeight, - int boundWidth, int boundHeight) { - - if (imageWidth == ImageData.SIZE_FULL - || imageHeight == ImageData.SIZE_FULL) { - imageWidth = boundWidth; - imageHeight = boundHeight; - } - - int[] ret = new int[2]; - ret[0] = boundWidth; - ret[1] = boundHeight; - - if (imageWidth * ret[1] > ret[0] * imageHeight) { - ret[1] = imageHeight * ret[0] / imageWidth; - } else { - ret[0] = imageWidth * ret[1] / imageHeight; - } - - return ret; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - int boundWidth = MeasureSpec.getSize(widthMeasureSpec); - int boundHeight = MeasureSpec.getSize(heightMeasureSpec); - if (boundWidth == 0 || boundHeight == 0) { - // Either width or height is unknown, can't measure children yet. - return; - } - - if (mDataAdapter != null) { - mDataAdapter.suggestViewSizeBound(boundWidth / 2, boundHeight / 2); - } - - for (ViewInfo info : mViewInfo) { - if (info == null) continue; - - int id = info.getID(); - int[] dim = calculateChildDimension( - mDataAdapter.getImageData(id).getWidth(), - mDataAdapter.getImageData(id).getHeight(), - boundWidth, boundHeight); - - info.getView().measure( - MeasureSpec.makeMeasureSpec( - dim[0], MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec( - dim[1], MeasureSpec.EXACTLY)); - } - } - - @Override - protected boolean fitSystemWindows(Rect insets) { - if (mViewPhotoSphereButton != null) { - // Set the position of the "View Photo Sphere" button. - FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mViewPhotoSphereButton - .getLayoutParams(); - params.bottomMargin = insets.bottom; - mViewPhotoSphereButton.setLayoutParams(params); - } - - return super.fitSystemWindows(insets); - } - - private int findTheNearestView(int pointX) { - - int nearest = 0; - // Find the first non-null ViewInfo. - while (nearest < BUFFER_SIZE - && (mViewInfo[nearest] == null || mViewInfo[nearest].getLeftPosition() == -1)) { - nearest++; - } - // No existing available ViewInfo - if (nearest == BUFFER_SIZE) { - return -1; - } - int min = Math.abs(pointX - mViewInfo[nearest].getCenterX()); - - for (int infoID = nearest + 1; infoID < BUFFER_SIZE && mViewInfo[infoID] != null; infoID++) { - // Not measured yet. - if (mViewInfo[infoID].getLeftPosition() == -1) - continue; - - int c = mViewInfo[infoID].getCenterX(); - int dist = Math.abs(pointX - c); - if (dist < min) { - min = dist; - nearest = infoID; - } - } - return nearest; - } - - private ViewInfo buildInfoFromData(int dataID) { - ImageData data = mDataAdapter.getImageData(dataID); - if (data == null) { - return null; - } - data.prepare(); - View v = mDataAdapter.getView(mContext, dataID); - if (v == null) { - return null; - } - ViewInfo info = new ViewInfo(dataID, v); - v = info.getView(); - if (v != mCameraView) { - addView(info.getView()); - } else { - v.setVisibility(View.VISIBLE); - } - return info; - } - - private void removeInfo(int infoID) { - if (infoID >= mViewInfo.length || mViewInfo[infoID] == null) { - return; - } - - ImageData data = mDataAdapter.getImageData(mViewInfo[infoID].getID()); - checkForRemoval(data, mViewInfo[infoID].getView()); - mViewInfo[infoID] = null; - } - - /** - * We try to keep the one closest to the center of the screen at position - * mCurrentInfo. - */ - private void stepIfNeeded() { - if (!inFilmStrip() && !inFullScreen()) { - // The good timing to step to the next view is when everything is - // not in transition. - return; - } - int nearest = findTheNearestView(mCenterX); - // no change made. - if (nearest == -1 || nearest == mCurrentInfo) - return; - - // Going to change the current info, notify the listener. - if (mListener != null) { - mListener.onCurrentDataChanged(mViewInfo[mCurrentInfo].getID(), false); - } - int adjust = nearest - mCurrentInfo; - if (adjust > 0) { - for (int k = 0; k < adjust; k++) { - removeInfo(k); - } - for (int k = 0; k + adjust < BUFFER_SIZE; k++) { - mViewInfo[k] = mViewInfo[k + adjust]; - } - for (int k = BUFFER_SIZE - adjust; k < BUFFER_SIZE; k++) { - mViewInfo[k] = null; - if (mViewInfo[k - 1] != null) { - mViewInfo[k] = buildInfoFromData(mViewInfo[k - 1].getID() + 1); - } - } - } else { - for (int k = BUFFER_SIZE - 1; k >= BUFFER_SIZE + adjust; k--) { - removeInfo(k); - } - for (int k = BUFFER_SIZE - 1; k + adjust >= 0; k--) { - mViewInfo[k] = mViewInfo[k + adjust]; - } - for (int k = -1 - adjust; k >= 0; k--) { - mViewInfo[k] = null; - if (mViewInfo[k + 1] != null) { - mViewInfo[k] = buildInfoFromData(mViewInfo[k + 1].getID() - 1); - } - } - } - if (mListener != null) { - mListener.onCurrentDataChanged(mViewInfo[mCurrentInfo].getID(), true); - } - } - - /** Don't go beyond the bound. */ - private void clampCenterX() { - ViewInfo curr = mViewInfo[mCurrentInfo]; - if (curr == null) { - return; - } - - if (curr.getID() == 0 && mCenterX < curr.getCenterX()) { - mCenterX = curr.getCenterX(); - if (mController.isScrolling()) { - mController.stopScrolling(); - } - if (getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW - && !mController.isScalling() - && mScale != FULLSCREEN_SCALE) { - mController.gotoFullScreen(); - } - } - if (curr.getID() == mDataAdapter.getTotalNumber() - 1 - && mCenterX > curr.getCenterX()) { - mCenterX = curr.getCenterX(); - if (!mController.isScrolling()) { - mController.stopScrolling(); - } - } - } - - private void adjustChildZOrder() { - for (int i = BUFFER_SIZE - 1; i >= 0; i--) { - if (mViewInfo[i] == null) - continue; - bringChildToFront(mViewInfo[i].getView()); - } - } - - /** - * If the current photo is a photo sphere, this will launch the Photo Sphere - * panorama viewer. - */ - private void showPhotoSphere() { - ViewInfo curr = mViewInfo[mCurrentInfo]; - if (curr != null) { - mDataAdapter.getImageData(curr.getID()).viewPhotoSphere(mPanoramaViewHelper); - } - } - - /** - * @return The ID of the current item, or -1. - */ - public int getCurrentId() { - ViewInfo current = mViewInfo[mCurrentInfo]; - if (current == null) { - return -1; - } - return current.getID(); - } - - /** - * Updates the visibility of the View Photo Sphere button. - */ - private void updatePhotoSphereViewButton() { - if (mViewPhotoSphereButton == null) { - mViewPhotoSphereButton = (ImageButton) ((View) getParent()) - .findViewById(R.id.filmstrip_bottom_control_panorama); - mViewPhotoSphereButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - showPhotoSphere(); - } - }); - } - final int requestId = getCurrentId(); - - // Check if the item has changed since the last time we updated the - // visibility status. Only then check of the current image is a photo - // sphere. - if (requestId == mLastItemId || requestId < 0) { - return; - } - - ImageData data = mDataAdapter.getImageData(requestId); - data.isPhotoSphere(mContext, new PanoramaSupportCallback() { - @Override - public void panoramaInfoAvailable(final boolean isPanorama, - boolean isPanorama360) { - // Make sure the returned data is for the current image. - if (requestId == getCurrentId()) { - mViewPhotoSphereButton.post(new Runnable() { - @Override - public void run() { - mViewPhotoSphereButton.setVisibility(isPanorama ? View.VISIBLE - : View.GONE); - } - }); - } - } - }); - } - - private void layoutChildren() { - if (mAnchorPending) { - mCenterX = mViewInfo[mCurrentInfo].getCenterX(); - mAnchorPending = false; - } - - if (mController.hasNewGeometry()) { - mCenterX = mController.getNewPosition(); - mScale = mController.getNewScale(); - } - - clampCenterX(); - - mViewInfo[mCurrentInfo].layoutIn(mDrawArea, mCenterX, mScale); - - int currentViewLeft = mViewInfo[mCurrentInfo].getLeftPosition(); - int currentViewCenter = mViewInfo[mCurrentInfo].getCenterX(); - int fullScreenWidth = mDrawArea.width() + mViewGap; - float scaleFraction = mViewAnimInterpolator.getInterpolation( - (mScale - FILM_STRIP_SCALE) / (FULLSCREEN_SCALE - FILM_STRIP_SCALE)); - - // images on the left - for (int infoID = mCurrentInfo - 1; infoID >= 0; infoID--) { - ViewInfo curr = mViewInfo[infoID]; - if (curr == null) { - continue; - } - - ViewInfo next = mViewInfo[infoID + 1]; - int myLeft = - next.getLeftPosition() - curr.getView().getMeasuredWidth() - mViewGap; - curr.setLeftPosition(myLeft); - curr.layoutIn(mDrawArea, mCenterX, mScale); - curr.getView().setAlpha(1f); - int infoDiff = mCurrentInfo - infoID; - curr.setTranslationX( - (currentViewCenter - - fullScreenWidth * infoDiff - curr.getCenterX()) * scaleFraction, - mScale); - } - - // images on the right - for (int infoID = mCurrentInfo + 1; infoID < BUFFER_SIZE; infoID++) { - ViewInfo curr = mViewInfo[infoID]; - if (curr == null) { - continue; - } - - ViewInfo prev = mViewInfo[infoID - 1]; - int myLeft = - prev.getLeftPosition() + prev.getView().getMeasuredWidth() + mViewGap; - curr.setLeftPosition(myLeft); - curr.layoutIn(mDrawArea, mCenterX, mScale); - if (infoID == mCurrentInfo + 1) { - curr.getView().setAlpha(1f - scaleFraction); - } else { - if (scaleFraction == 0f) { - curr.getView().setAlpha(1f); - } else { - curr.getView().setAlpha(0f); - } - } - curr.setTranslationX((currentViewLeft - myLeft) * scaleFraction, mScale); - } - - stepIfNeeded(); - adjustChildZOrder(); - invalidate(); - updatePhotoSphereViewButton(); - mLastItemId = getCurrentId(); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - if (mViewInfo[mCurrentInfo] == null) { - return; - } - - mDrawArea.left = l; - mDrawArea.top = t; - mDrawArea.right = r; - mDrawArea.bottom = b; - - layoutChildren(); - } - - // Keeps the view in the view hierarchy if it's camera preview. - // Remove from the hierarchy otherwise. - private void checkForRemoval(ImageData data, View v) { - if (data.getType() != ImageData.TYPE_CAMERA_PREVIEW) { - removeView(v); - data.recycle(); - } else { - v.setVisibility(View.INVISIBLE); - if (mCameraView != null && mCameraView != v) { - removeView(mCameraView); - } - mCameraView = v; - } - } - - private void slideViewBack(View v) { - v.animate().translationX(0) - .alpha(1f) - .setDuration(DURATION_GEOMETRY_ADJUST) - .setInterpolator(mViewAnimInterpolator) - .start(); - } - - private void updateRemoval(int dataID, final ImageData data) { - int removedInfo = findInfoByDataID(dataID); - - // adjust the data id to be consistent - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null || mViewInfo[i].getID() <= dataID) { - continue; - } - mViewInfo[i].setID(mViewInfo[i].getID() - 1); - } - if (removedInfo == -1) { - return; - } - - final View removedView = mViewInfo[removedInfo].getView(); - final int offsetX = removedView.getMeasuredWidth() + mViewGap; - - for (int i = removedInfo + 1; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setLeftPosition(mViewInfo[i].getLeftPosition() - offsetX); - } - } - - if (removedInfo >= mCurrentInfo - && mViewInfo[removedInfo].getID() < mDataAdapter.getTotalNumber()) { - // Fill the removed info by left shift when the current one or - // anyone on the right is removed, and there's more data on the - // right available. - for (int i = removedInfo; i < BUFFER_SIZE - 1; i++) { - mViewInfo[i] = mViewInfo[i + 1]; - } - - // pull data out from the DataAdapter for the last one. - int curr = BUFFER_SIZE - 1; - int prev = curr - 1; - if (mViewInfo[prev] != null) { - mViewInfo[curr] = buildInfoFromData(mViewInfo[prev].getID() + 1); - } - - // Translate the views to their original places. - for (int i = removedInfo; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(offsetX, mScale); - } - } - - // The end of the filmstrip might have been changed. - // The mCenterX might be out of the bound. - ViewInfo currInfo = mViewInfo[mCurrentInfo]; - if (currInfo.getID() == mDataAdapter.getTotalNumber() - 1 - && mCenterX > currInfo.getCenterX()) { - int adjustDiff = currInfo.getCenterX() - mCenterX; - mCenterX = currInfo.getCenterX(); - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].translateXBy(adjustDiff, mScale); - } - } - } - } else { - // fill the removed place by right shift - mCenterX -= offsetX; - - for (int i = removedInfo; i > 0; i--) { - mViewInfo[i] = mViewInfo[i - 1]; - } - - // pull data out from the DataAdapter for the first one. - int curr = 0; - int next = curr + 1; - if (mViewInfo[next] != null) { - mViewInfo[curr] = buildInfoFromData(mViewInfo[next].getID() - 1); - } - - // Translate the views to their original places. - for (int i = removedInfo; i >= 0; i--) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(-offsetX, mScale); - } - } - } - - // Now, slide every one back. - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null - && mViewInfo[i].getTranslationX(mScale) != 0f) { - slideViewBack(mViewInfo[i].getView()); - } - } - - int transY = getHeight() / 8; - if (removedView.getTranslationY() < 0) { - transY = -transY; - } - removedView.animate() - .alpha(0f) - .translationYBy(transY) - .setInterpolator(mViewAnimInterpolator) - .setDuration(DURATION_GEOMETRY_ADJUST) - .withEndAction(new Runnable() { - @Override - public void run() { - checkForRemoval(data, removedView); - } - }) - .start(); - layoutChildren(); - } - - // returns -1 on failure. - private int findInfoByDataID(int dataID) { - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] != null - && mViewInfo[i].getID() == dataID) { - return i; - } - } - return -1; - } - - private void updateInsertion(int dataID) { - int insertedInfo = findInfoByDataID(dataID); - if (insertedInfo == -1) { - // Not in the current info buffers. Check if it's inserted - // at the end. - if (dataID == mDataAdapter.getTotalNumber() - 1) { - int prev = findInfoByDataID(dataID - 1); - if (prev >= 0 && prev < BUFFER_SIZE - 1) { - // The previous data is in the buffer and we still - // have room for the inserted data. - insertedInfo = prev + 1; - } - } - } - - // adjust the data id to be consistent - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null || mViewInfo[i].getID() < dataID) { - continue; - } - mViewInfo[i].setID(mViewInfo[i].getID() + 1); - } - if (insertedInfo == -1) { - return; - } - - final ImageData data = mDataAdapter.getImageData(dataID); - int[] dim = calculateChildDimension( - data.getWidth(), data.getHeight(), - getMeasuredWidth(), getMeasuredHeight()); - final int offsetX = dim[0] + mViewGap; - ViewInfo viewInfo = buildInfoFromData(dataID); - - if (insertedInfo >= mCurrentInfo) { - if (insertedInfo == mCurrentInfo) { - viewInfo.setLeftPosition(mViewInfo[mCurrentInfo].getLeftPosition()); - } - // Shift right to make rooms for newly inserted item. - removeInfo(BUFFER_SIZE - 1); - for (int i = BUFFER_SIZE - 1; i > insertedInfo; i--) { - mViewInfo[i] = mViewInfo[i - 1]; - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(-offsetX, mScale); - slideViewBack(mViewInfo[i].getView()); - } - } - } else { - // Shift left. Put the inserted data on the left instead of the - // found position. - --insertedInfo; - if (insertedInfo < 0) { - return; - } - removeInfo(0); - for (int i = 1; i <= insertedInfo; i++) { - if (mViewInfo[i] != null) { - mViewInfo[i].setTranslationX(offsetX, mScale); - slideViewBack(mViewInfo[i].getView()); - mViewInfo[i - 1] = mViewInfo[i]; - } - } - } - - mViewInfo[insertedInfo] = viewInfo; - View insertedView = mViewInfo[insertedInfo].getView(); - insertedView.setAlpha(0f); - insertedView.setTranslationY(getHeight() / 8); - insertedView.animate() - .alpha(1f) - .translationY(0f) - .setInterpolator(mViewAnimInterpolator) - .setDuration(DURATION_GEOMETRY_ADJUST) - .start(); - invalidate(); - } - - public void setDataAdapter(DataAdapter adapter) { - mDataAdapter = adapter; - mDataAdapter.suggestViewSizeBound(getMeasuredWidth(), getMeasuredHeight()); - mDataAdapter.setListener(new DataAdapter.Listener() { - @Override - public void onDataLoaded() { - reload(); - } - - @Override - public void onDataUpdated(DataAdapter.UpdateReporter reporter) { - update(reporter); - } - - @Override - public void onDataInserted(int dataID, ImageData data) { - if (mViewInfo[mCurrentInfo] == null) { - // empty now, simply do a reload. - reload(); - return; - } - updateInsertion(dataID); - } - - @Override - public void onDataRemoved(int dataID, ImageData data) { - updateRemoval(dataID, data); - } - }); - } - - public boolean inFilmStrip() { - return (mScale == FILM_STRIP_SCALE); - } - - public boolean inFullScreen() { - return (mScale == FULLSCREEN_SCALE); - } - - public boolean inCameraFullscreen() { - return isAnchoredTo(0) && inFullScreen() - && (getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (inFilmStrip()) { - return true; - } - - if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) { - mCheckToIntercept = true; - mDown = MotionEvent.obtain(ev); - ViewInfo viewInfo = mViewInfo[mCurrentInfo]; - // Do not intercept touch if swipe is not enabled - if (viewInfo != null && !mDataAdapter.canSwipeInFullScreen(viewInfo.getID())) { - mCheckToIntercept = false; - } - return false; - } else if (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) { - // Do not intercept touch once child is in zoom mode - mCheckToIntercept = false; - return false; - } else { - if (!mCheckToIntercept) { - return false; - } - if (ev.getEventTime() - ev.getDownTime() > SWIPE_TIME_OUT) { - return false; - } - int deltaX = (int) (ev.getX() - mDown.getX()); - int deltaY = (int) (ev.getY() - mDown.getY()); - if (ev.getActionMasked() == MotionEvent.ACTION_MOVE - && deltaX < mSlop * (-1)) { - // intercept left swipe - if (Math.abs(deltaX) >= Math.abs(deltaY) * 2) { - return true; - } - } - } - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - mGestureRecognizer.onTouchEvent(ev); - return true; - } - - private void updateViewInfo(int infoID) { - ViewInfo info = mViewInfo[infoID]; - removeView(info.getView()); - mViewInfo[infoID] = buildInfoFromData(info.getID()); - } - - /** Some of the data is changed. */ - private void update(DataAdapter.UpdateReporter reporter) { - // No data yet. - if (mViewInfo[mCurrentInfo] == null) { - reload(); - return; - } - - // Check the current one. - ViewInfo curr = mViewInfo[mCurrentInfo]; - int dataID = curr.getID(); - if (reporter.isDataRemoved(dataID)) { - mCenterX = -1; - reload(); - return; - } - if (reporter.isDataUpdated(dataID)) { - updateViewInfo(mCurrentInfo); - } - - // Check left - for (int i = mCurrentInfo - 1; i >= 0; i--) { - curr = mViewInfo[i]; - if (curr != null) { - dataID = curr.getID(); - if (reporter.isDataRemoved(dataID) || reporter.isDataUpdated(dataID)) { - updateViewInfo(i); - } - } else { - ViewInfo next = mViewInfo[i + 1]; - if (next != null) { - mViewInfo[i] = buildInfoFromData(next.getID() - 1); - } - } - } - - // Check right - for (int i = mCurrentInfo + 1; i < BUFFER_SIZE; i++) { - curr = mViewInfo[i]; - if (curr != null) { - dataID = curr.getID(); - if (reporter.isDataRemoved(dataID) || reporter.isDataUpdated(dataID)) { - updateViewInfo(i); - } - } else { - ViewInfo prev = mViewInfo[i - 1]; - if (prev != null) { - mViewInfo[i] = buildInfoFromData(prev.getID() + 1); - } - } - } - } - - /** - * The whole data might be totally different. Flush all and load from the - * start. - */ - private void reload() { - removeAllViews(); - int dataNumber = mDataAdapter.getTotalNumber(); - if (dataNumber == 0) { - return; - } - - mViewInfo[mCurrentInfo] = buildInfoFromData(0); - mViewInfo[mCurrentInfo].setLeftPosition(0); - if (getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW) { - // we are in camera mode by default. - mController.lockAtCurrentView(); - } - for (int i = 1; mCurrentInfo + i < BUFFER_SIZE || mCurrentInfo - i >= 0; i++) { - int infoID = mCurrentInfo + i; - if (infoID < BUFFER_SIZE && mViewInfo[infoID - 1] != null) { - mViewInfo[infoID] = buildInfoFromData(mViewInfo[infoID - 1].getID() + 1); - } - infoID = mCurrentInfo - i; - if (infoID >= 0 && mViewInfo[infoID + 1] != null) { - mViewInfo[infoID] = buildInfoFromData(mViewInfo[infoID + 1].getID() - 1); - } - } - layoutChildren(); - } - - private void promoteData(int infoID, int dataID) { - if (mListener != null) { - mListener.onDataPromoted(dataID); - } - } - - private void demoteData(int infoID, int dataID) { - if (mListener != null) { - mListener.onDataDemoted(dataID); - } - } - - /** - * MyController controls all the geometry animations. It passively tells the - * geometry information on demand. - */ - private class MyController implements - Controller, - ValueAnimator.AnimatorUpdateListener, - Animator.AnimatorListener { - - private ValueAnimator mScaleAnimator; - private boolean mHasNewScale; - private float mNewScale; - - private Scroller mScroller; - private boolean mHasNewPosition; - private DecelerateInterpolator mDecelerateInterpolator; - - private boolean mCanStopScroll; - - private boolean mIsPositionLocked; - private int mLockedViewInfo; - - MyController(Context context) { - mScroller = new Scroller(context); - mHasNewPosition = false; - mScaleAnimator = new ValueAnimator(); - mScaleAnimator.addUpdateListener(MyController.this); - mScaleAnimator.addListener(MyController.this); - mDecelerateInterpolator = new DecelerateInterpolator(); - mCanStopScroll = true; - mHasNewScale = false; - } - - @Override - public boolean isScrolling() { - return !mScroller.isFinished(); - } - - @Override - public boolean isScalling() { - return mScaleAnimator.isRunning(); - } - - boolean hasNewGeometry() { - mHasNewPosition = mScroller.computeScrollOffset(); - if (!mHasNewPosition) { - mCanStopScroll = true; - } - // If the position is locked, then we always return true to force - // the position value to use the locked value. - return (mHasNewPosition || mHasNewScale || mIsPositionLocked); - } - - /** - * Always call {@link #hasNewGeometry()} before getting the new scale - * value. - */ - float getNewScale() { - if (!mHasNewScale) { - return mScale; - } - mHasNewScale = false; - return mNewScale; - } - - /** - * Always call {@link #hasNewGeometry()} before getting the new position - * value. - */ - int getNewPosition() { - if (mIsPositionLocked) { - if (mViewInfo[mLockedViewInfo] == null) - return mCenterX; - return mViewInfo[mLockedViewInfo].getCenterX(); - } - if (!mHasNewPosition) - return mCenterX; - return mScroller.getCurrX(); - } - - @Override - public void lockAtCurrentView() { - mIsPositionLocked = true; - mLockedViewInfo = mCurrentInfo; - } - - @Override - public void unlockPosition() { - if (mIsPositionLocked) { - // only when the position is previously locked we set the - // current position to make it consistent. - if (mViewInfo[mLockedViewInfo] != null) { - mCenterX = mViewInfo[mLockedViewInfo].getCenterX(); - } - mIsPositionLocked = false; - } - } - - private int estimateMinX(int dataID, int leftPos, int viewWidth) { - return leftPos - (dataID + 100) * (viewWidth + mViewGap); - } - - private int estimateMaxX(int dataID, int leftPos, int viewWidth) { - return leftPos - + (mDataAdapter.getTotalNumber() - dataID + 100) - * (viewWidth + mViewGap); - } - - @Override - public void scroll(float deltaX) { - if (mController.isScrolling()) { - return; - } - mCenterX += deltaX; - } - - @Override - public void fling(float velocityX) { - if (!stopScrolling() || mIsPositionLocked) { - return; - } - ViewInfo info = mViewInfo[mCurrentInfo]; - if (info == null) { - return; - } - - float scaledVelocityX = velocityX / mScale; - if (inCameraFullscreen() && scaledVelocityX < 0) { - // Swipe left in camera preview. - gotoFilmStrip(); - } - - int w = getWidth(); - // Estimation of possible length on the left. To ensure the - // velocity doesn't become too slow eventually, we add a huge number - // to the estimated maximum. - int minX = estimateMinX(info.getID(), info.getLeftPosition(), w); - // Estimation of possible length on the right. Likewise, exaggerate - // the possible maximum too. - int maxX = estimateMaxX(info.getID(), info.getLeftPosition(), w); - mScroller.fling(mCenterX, 0, (int) -velocityX, 0, minX, maxX, 0, 0); - - layoutChildren(); - } - - @Override - public boolean stopScrolling() { - if (!mCanStopScroll) - return false; - mScroller.forceFinished(true); - mHasNewPosition = false; - return true; - } - - private void stopScale() { - mScaleAnimator.cancel(); - mHasNewScale = false; - } - - @Override - public void scrollTo(int position, int duration, boolean interruptible) { - if (!stopScrolling() || mIsPositionLocked) - return; - mCanStopScroll = interruptible; - stopScrolling(); - mScroller.startScroll(mCenterX, 0, position - mCenterX, - 0, duration); - invalidate(); - } - - private void scaleTo(float scale, int duration) { - stopScale(); - mScaleAnimator.setDuration(duration); - mScaleAnimator.setFloatValues(mScale, scale); - mScaleAnimator.setInterpolator(mDecelerateInterpolator); - mScaleAnimator.start(); - mHasNewScale = true; - layoutChildren(); - } - - @Override - public void gotoFilmStrip() { - unlockPosition(); - scaleTo(FILM_STRIP_SCALE, DURATION_GEOMETRY_ADJUST); - if (mListener != null) { - mListener.onSwitchMode(false); - } - } - - @Override - public void gotoFullScreen() { - if (mViewInfo[mCurrentInfo] != null) { - mController.scrollTo(mViewInfo[mCurrentInfo].getCenterX(), - DURATION_GEOMETRY_ADJUST, false); - } - enterFullScreen(); - } - - private void enterFullScreen() { - if (mListener != null) { - // TODO: After full size images snapping to fill the screen at - // the end of a scroll/fling is implemented, we should only make - // this call when the view on the center of the screen is - // camera preview - mListener.onSwitchMode(true); - } - if (inFullScreen()) { - return; - } - scaleTo(1f, DURATION_GEOMETRY_ADJUST); - } - - @Override - public void gotoCameraFullScreen() { - if (mDataAdapter.getImageData(0).getType() - != ImageData.TYPE_CAMERA_PREVIEW) { - return; - } - gotoFullScreen(); - scrollTo( - estimateMinX(mViewInfo[mCurrentInfo].getID(), - mViewInfo[mCurrentInfo].getLeftPosition(), - getWidth()), - DURATION_GEOMETRY_ADJUST, false); - } - - @Override - public void onAnimationUpdate(ValueAnimator animation) { - mHasNewScale = true; - mNewScale = (Float) animation.getAnimatedValue(); - layoutChildren(); - } - - @Override - public void onAnimationStart(Animator anim) { - } - - @Override - public void onAnimationEnd(Animator anim) { - ViewInfo info = mViewInfo[mCurrentInfo]; - if (info != null && mCenterX == info.getCenterX()) { - if (inFullScreen()) { - lockAtCurrentView(); - } else if (inFilmStrip()) { - unlockPosition(); - } - } - } - - @Override - public void onAnimationCancel(Animator anim) { - } - - @Override - public void onAnimationRepeat(Animator anim) { - } - } - - private class MyGestureReceiver implements FilmStripGestureRecognizer.Listener { - // Indicating the current trend of scaling is up (>1) or down (<1). - private float mScaleTrend; - - @Override - public boolean onSingleTapUp(float x, float y) { - if (inFilmStrip()) { - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null) { - continue; - } - - if (mViewInfo[i].areaContains(x, y)) { - mController.scrollTo(mViewInfo[i].getCenterX(), - DURATION_GEOMETRY_ADJUST, false); - return true; - } - } - } - return false; - } - - @Override - public boolean onDoubleTap(float x, float y) { - if (inFilmStrip()) { - ViewInfo centerInfo = mViewInfo[mCurrentInfo]; - if (centerInfo != null && centerInfo.areaContains(x, y)) { - mController.gotoFullScreen(); - return true; - } - } else if (inFullScreen()) { - mController.gotoFilmStrip(); - return true; - } - return false; - } - - @Override - public boolean onDown(float x, float y) { - if (mController.isScrolling()) { - mController.stopScrolling(); - } - return true; - } - - @Override - public boolean onUp(float x, float y) { - float halfH = getHeight() / 2; - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null) { - continue; - } - float transY = mViewInfo[i].getTranslationY(mScale); - if (transY == 0) { - continue; - } - int id = mViewInfo[i].getID(); - - if (mDataAdapter.getImageData(id) - .isUIActionSupported(ImageData.ACTION_DEMOTE) - && transY > halfH) { - demoteData(i, id); - } else if (mDataAdapter.getImageData(id) - .isUIActionSupported(ImageData.ACTION_PROMOTE) - && transY < -halfH) { - promoteData(i, id); - } else { - // put the view back. - mViewInfo[i].getView().animate() - .translationY(0f) - .alpha(1f) - .setDuration(DURATION_GEOMETRY_ADJUST) - .start(); - } - } - return false; - } - - @Override - public boolean onScroll(float x, float y, float dx, float dy) { - int deltaX = (int) (dx / mScale); - if (inFilmStrip()) { - if (Math.abs(dx) > Math.abs(dy)) { - if (deltaX > 0 && inCameraFullscreen()) { - mController.gotoFilmStrip(); - } - mController.scroll(deltaX); - } else { - // Vertical part. Promote or demote. - // int scaledDeltaY = (int) (dy * mScale); - int hit = 0; - Rect hitRect = new Rect(); - for (; hit < BUFFER_SIZE; hit++) { - if (mViewInfo[hit] == null) { - continue; - } - mViewInfo[hit].getView().getHitRect(hitRect); - if (hitRect.contains((int) x, (int) y)) { - break; - } - } - if (hit == BUFFER_SIZE) { - return false; - } - - ImageData data = mDataAdapter.getImageData(mViewInfo[hit].getID()); - float transY = mViewInfo[hit].getTranslationY(mScale) - dy / mScale; - if (!data.isUIActionSupported(ImageData.ACTION_DEMOTE) && transY > 0f) { - transY = 0f; - } - if (!data.isUIActionSupported(ImageData.ACTION_PROMOTE) && transY < 0f) { - transY = 0f; - } - mViewInfo[hit].setTranslationY(transY, mScale); - } - } else if (inFullScreen()) { - if (deltaX > 0 && inCameraFullscreen()) { - mController.gotoFilmStrip(); - } - mController.scroll(deltaX); - } - layoutChildren(); - - return true; - } - - @Override - public boolean onFling(float velocityX, float velocityY) { - if (Math.abs(velocityX) > Math.abs(velocityY)) { - mController.fling(velocityX); - } else { - // ignore vertical fling. - } - return true; - } - - @Override - public boolean onScaleBegin(float focusX, float focusY) { - if (inCameraFullscreen()) { - return false; - } - mScaleTrend = 1f; - return true; - } - - @Override - public boolean onScale(float focusX, float focusY, float scale) { - if (inCameraFullscreen()) { - return false; - } - - mScaleTrend = mScaleTrend * 0.3f + scale * 0.7f; - mScale *= scale; - if (mScale <= FILM_STRIP_SCALE) { - mScale = FILM_STRIP_SCALE; - } - if (mScale >= FULLSCREEN_SCALE) { - mScale = FULLSCREEN_SCALE; - } - layoutChildren(); - return true; - } - - @Override - public void onScaleEnd() { - if (mScaleTrend >= 1f) { - mController.gotoFullScreen(); - } else { - mController.gotoFilmStrip(); - } - mScaleTrend = 1f; - } - } -} diff --git a/src/com/android/camera/ui/FocusIndicator.java b/src/com/android/camera/ui/FocusIndicator.java deleted file mode 100644 index e06057041..000000000 --- a/src/com/android/camera/ui/FocusIndicator.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -public interface FocusIndicator { - public void showStart(); - public void showSuccess(boolean timeout); - public void showFail(boolean timeout); - public void clear(); -} diff --git a/src/com/android/camera/ui/InLineSettingCheckBox.java b/src/com/android/camera/ui/InLineSettingCheckBox.java deleted file mode 100644 index c1aa5a91c..000000000 --- a/src/com/android/camera/ui/InLineSettingCheckBox.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.accessibility.AccessibilityEvent; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; - - -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -/* A check box setting control which turns on/off the setting. */ -public class InLineSettingCheckBox extends InLineSettingItem { - private CheckBox mCheckBox; - - OnCheckedChangeListener mCheckedChangeListener = new OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean desiredState) { - changeIndex(desiredState ? 1 : 0); - } - }; - - public InLineSettingCheckBox(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mCheckBox = (CheckBox) findViewById(R.id.setting_check_box); - mCheckBox.setOnCheckedChangeListener(mCheckedChangeListener); - } - - @Override - public void initialize(ListPreference preference) { - super.initialize(preference); - // Add content descriptions for the increment and decrement buttons. - mCheckBox.setContentDescription(getContext().getResources().getString( - R.string.accessibility_check_box, mPreference.getTitle())); - } - - @Override - protected void updateView() { - mCheckBox.setOnCheckedChangeListener(null); - if (mOverrideValue == null) { - mCheckBox.setChecked(mIndex == 1); - } else { - int index = mPreference.findIndexOfValue(mOverrideValue); - mCheckBox.setChecked(index == 1); - } - mCheckBox.setOnCheckedChangeListener(mCheckedChangeListener); - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - event.getText().add(mPreference.getTitle()); - return true; - } - - @Override - public void setEnabled(boolean enable) { - if (mTitle != null) mTitle.setEnabled(enable); - if (mCheckBox != null) mCheckBox.setEnabled(enable); - } -} diff --git a/src/com/android/camera/ui/InLineSettingItem.java b/src/com/android/camera/ui/InLineSettingItem.java deleted file mode 100644 index 839a77fd0..000000000 --- a/src/com/android/camera/ui/InLineSettingItem.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.accessibility.AccessibilityEvent; -import android.widget.LinearLayout; -import android.widget.TextView; - -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -/** - * A one-line camera setting could be one of three types: knob, switch or restore - * preference button. The setting includes a title for showing the preference - * title which is initialized in the SimpleAdapter. A knob also includes - * (ex: Picture size), a previous button, the current value (ex: 5MP), - * and a next button. A switch, i.e. the preference RecordLocationPreference, - * has only two values on and off which will be controlled in a switch button. - * Other setting popup window includes several InLineSettingItem items with - * different types if possible. - */ -public abstract class InLineSettingItem extends LinearLayout { - private Listener mListener; - protected ListPreference mPreference; - protected int mIndex; - // Scene mode can override the original preference value. - protected String mOverrideValue; - protected TextView mTitle; - - static public interface Listener { - public void onSettingChanged(ListPreference pref); - } - - public InLineSettingItem(Context context, AttributeSet attrs) { - super(context, attrs); - } - - protected void setTitle(ListPreference preference) { - mTitle = ((TextView) findViewById(R.id.title)); - mTitle.setText(preference.getTitle()); - } - - public void initialize(ListPreference preference) { - setTitle(preference); - if (preference == null) return; - mPreference = preference; - reloadPreference(); - } - - protected abstract void updateView(); - - protected boolean changeIndex(int index) { - if (index >= mPreference.getEntryValues().length || index < 0) return false; - mIndex = index; - mPreference.setValueIndex(mIndex); - if (mListener != null) { - mListener.onSettingChanged(mPreference); - } - updateView(); - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); - return true; - } - - // The value of the preference may have changed. Update the UI. - public void reloadPreference() { - mIndex = mPreference.findIndexOfValue(mPreference.getValue()); - updateView(); - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - public void overrideSettings(String value) { - mOverrideValue = value; - updateView(); - } -} diff --git a/src/com/android/camera/ui/InLineSettingMenu.java b/src/com/android/camera/ui/InLineSettingMenu.java deleted file mode 100644 index 8e45c3e38..000000000 --- a/src/com/android/camera/ui/InLineSettingMenu.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.accessibility.AccessibilityEvent; -import android.widget.TextView; - -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -/* Setting menu item that will bring up a menu when you click on it. */ -public class InLineSettingMenu extends InLineSettingItem { - private static final String TAG = "InLineSettingMenu"; - // The view that shows the current selected setting. Ex: 5MP - private TextView mEntry; - - public InLineSettingMenu(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mEntry = (TextView) findViewById(R.id.current_setting); - } - - @Override - public void initialize(ListPreference preference) { - super.initialize(preference); - //TODO: add contentDescription - } - - @Override - protected void updateView() { - if (mOverrideValue == null) { - mEntry.setText(mPreference.getEntry()); - } else { - int index = mPreference.findIndexOfValue(mOverrideValue); - if (index != -1) { - mEntry.setText(mPreference.getEntries()[index]); - } else { - // Avoid the crash if camera driver has bugs. - Log.e(TAG, "Fail to find override value=" + mOverrideValue); - mPreference.print(); - } - } - } - - @Override - public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { - event.getText().add(mPreference.getTitle() + mPreference.getEntry()); - return true; - } - - @Override - public void setEnabled(boolean enable) { - super.setEnabled(enable); - if (mTitle != null) mTitle.setEnabled(enable); - if (mEntry != null) mEntry.setEnabled(enable); - } -} diff --git a/src/com/android/camera/ui/LayoutChangeHelper.java b/src/com/android/camera/ui/LayoutChangeHelper.java deleted file mode 100644 index ef4eb6a7a..000000000 --- a/src/com/android/camera/ui/LayoutChangeHelper.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.view.View; - -public class LayoutChangeHelper implements LayoutChangeNotifier { - private LayoutChangeNotifier.Listener mListener; - private boolean mFirstTimeLayout; - private View mView; - - public LayoutChangeHelper(View v) { - mView = v; - mFirstTimeLayout = true; - } - - @Override - public void setOnLayoutChangeListener(LayoutChangeNotifier.Listener listener) { - mListener = listener; - } - - public void onLayout(boolean changed, int l, int t, int r, int b) { - if (mListener == null) return; - if (mFirstTimeLayout || changed) { - mFirstTimeLayout = false; - mListener.onLayoutChange(mView, l, t, r, b); - } - } -} diff --git a/src/com/android/camera/ui/LayoutChangeNotifier.java b/src/com/android/camera/ui/LayoutChangeNotifier.java deleted file mode 100644 index 6261d34f6..000000000 --- a/src/com/android/camera/ui/LayoutChangeNotifier.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.view.View; - -public interface LayoutChangeNotifier { - public interface Listener { - // Invoked only when the layout has changed or it is the first layout. - public void onLayoutChange(View v, int l, int t, int r, int b); - } - - public void setOnLayoutChangeListener(LayoutChangeNotifier.Listener listener); -} diff --git a/src/com/android/camera/ui/LayoutNotifyView.java b/src/com/android/camera/ui/LayoutNotifyView.java deleted file mode 100644 index 6e118fc3a..000000000 --- a/src/com/android/camera/ui/LayoutNotifyView.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; - -/* - * Customized view to support onLayoutChange() at or before API 10. - */ -public class LayoutNotifyView extends View implements LayoutChangeNotifier { - private LayoutChangeHelper mLayoutChangeHelper = new LayoutChangeHelper(this); - - public LayoutNotifyView(Context context) { - super(context); - } - - public LayoutNotifyView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - public void setOnLayoutChangeListener( - LayoutChangeNotifier.Listener listener) { - mLayoutChangeHelper.setOnLayoutChangeListener(listener); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - mLayoutChangeHelper.onLayout(changed, l, t, r, b); - } -} diff --git a/src/com/android/camera/ui/ListPrefSettingPopup.java b/src/com/android/camera/ui/ListPrefSettingPopup.java deleted file mode 100644 index cfef73f49..000000000 --- a/src/com/android/camera/ui/ListPrefSettingPopup.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2010 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.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.ListView; -import android.widget.AdapterView; -import android.widget.ImageView; -import android.widget.SimpleAdapter; - -import com.android.camera.IconListPreference; -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -// A popup window that shows one camera setting. The title is the name of the -// setting (ex: white-balance). The entries are the supported values (ex: -// daylight, incandescent, etc). If initialized with an IconListPreference, -// the entries will contain both text and icons. Otherwise, entries will be -// shown in text. -public class ListPrefSettingPopup extends AbstractSettingPopup implements - AdapterView.OnItemClickListener { - private static final String TAG = "ListPrefSettingPopup"; - private ListPreference mPreference; - private Listener mListener; - - static public interface Listener { - public void onListPrefChanged(ListPreference pref); - } - - public ListPrefSettingPopup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - private class ListPrefSettingAdapter extends SimpleAdapter { - ListPrefSettingAdapter(Context context, List<? extends Map<String, ?>> data, - int resource, String[] from, int[] to) { - super(context, data, resource, from, to); - } - - @Override - public void setViewImage(ImageView v, String value) { - if ("".equals(value)) { - // Some settings have no icons. Ex: exposure compensation. - v.setVisibility(View.GONE); - } else { - super.setViewImage(v, value); - } - } - } - - public void initialize(ListPreference preference) { - mPreference = preference; - Context context = getContext(); - CharSequence[] entries = mPreference.getEntries(); - int[] iconIds = null; - if (preference instanceof IconListPreference) { - iconIds = ((IconListPreference) mPreference).getImageIds(); - if (iconIds == null) { - iconIds = ((IconListPreference) mPreference).getLargeIconIds(); - } - } - // Set title. - mTitle.setText(mPreference.getTitle()); - - // Prepare the ListView. - ArrayList<HashMap<String, Object>> listItem = - new ArrayList<HashMap<String, Object>>(); - for(int i = 0; i < entries.length; ++i) { - HashMap<String, Object> map = new HashMap<String, Object>(); - map.put("text", entries[i].toString()); - if (iconIds != null) map.put("image", iconIds[i]); - listItem.add(map); - } - SimpleAdapter listItemAdapter = new ListPrefSettingAdapter(context, listItem, - R.layout.setting_item, - new String[] {"text", "image"}, - new int[] {R.id.text, R.id.image}); - ((ListView) mSettingList).setAdapter(listItemAdapter); - ((ListView) mSettingList).setOnItemClickListener(this); - reloadPreference(); - } - - // The value of the preference may have changed. Update the UI. - @Override - public void reloadPreference() { - int index = mPreference.findIndexOfValue(mPreference.getValue()); - if (index != -1) { - ((ListView) mSettingList).setItemChecked(index, true); - } else { - Log.e(TAG, "Invalid preference value."); - mPreference.print(); - } - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, - int index, long id) { - mPreference.setValueIndex(index); - if (mListener != null) mListener.onListPrefChanged(mPreference); - } -} diff --git a/src/com/android/camera/ui/MoreSettingPopup.java b/src/com/android/camera/ui/MoreSettingPopup.java deleted file mode 100644 index 5900058df..000000000 --- a/src/com/android/camera/ui/MoreSettingPopup.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2010 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.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.ListView; - -import com.android.camera.ListPreference; -import com.android.camera.PreferenceGroup; -import com.android.gallery3d.R; - -import java.util.ArrayList; - -/* A popup window that contains several camera settings. */ -public class MoreSettingPopup extends AbstractSettingPopup - implements InLineSettingItem.Listener, - AdapterView.OnItemClickListener { - @SuppressWarnings("unused") - private static final String TAG = "MoreSettingPopup"; - - private Listener mListener; - private ArrayList<ListPreference> mListItem = new ArrayList<ListPreference>(); - - // Keep track of which setting items are disabled - // e.g. White balance will be disabled when scene mode is set to non-auto - private boolean[] mEnabled; - - static public interface Listener { - public void onSettingChanged(ListPreference pref); - public void onPreferenceClicked(ListPreference pref); - } - - private class MoreSettingAdapter extends ArrayAdapter<ListPreference> { - LayoutInflater mInflater; - String mOnString; - String mOffString; - MoreSettingAdapter() { - super(MoreSettingPopup.this.getContext(), 0, mListItem); - Context context = getContext(); - mInflater = LayoutInflater.from(context); - mOnString = context.getString(R.string.setting_on); - mOffString = context.getString(R.string.setting_off); - } - - private int getSettingLayoutId(ListPreference pref) { - - if (isOnOffPreference(pref)) { - return R.layout.in_line_setting_check_box; - } - return R.layout.in_line_setting_menu; - } - - private boolean isOnOffPreference(ListPreference pref) { - CharSequence[] entries = pref.getEntries(); - if (entries.length != 2) return false; - String str1 = entries[0].toString(); - String str2 = entries[1].toString(); - return ((str1.equals(mOnString) && str2.equals(mOffString)) || - (str1.equals(mOffString) && str2.equals(mOnString))); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView != null) return convertView; - - ListPreference pref = mListItem.get(position); - - int viewLayoutId = getSettingLayoutId(pref); - InLineSettingItem view = (InLineSettingItem) - mInflater.inflate(viewLayoutId, parent, false); - - view.initialize(pref); // no init for restore one - view.setSettingChangedListener(MoreSettingPopup.this); - if (position >= 0 && position < mEnabled.length) { - view.setEnabled(mEnabled[position]); - } else { - Log.w(TAG, "Invalid input: enabled list length, " + mEnabled.length - + " position " + position); - } - return view; - } - - @Override - public boolean isEnabled(int position) { - if (position >= 0 && position < mEnabled.length) { - return mEnabled[position]; - } - return true; - } - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - public MoreSettingPopup(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void initialize(PreferenceGroup group, String[] keys) { - // Prepare the setting items. - for (int i = 0; i < keys.length; ++i) { - ListPreference pref = group.findPreference(keys[i]); - if (pref != null) mListItem.add(pref); - } - - ArrayAdapter<ListPreference> mListItemAdapter = new MoreSettingAdapter(); - ((ListView) mSettingList).setAdapter(mListItemAdapter); - ((ListView) mSettingList).setOnItemClickListener(this); - ((ListView) mSettingList).setSelector(android.R.color.transparent); - // Initialize mEnabled - mEnabled = new boolean[mListItem.size()]; - for (int i = 0; i < mEnabled.length; i++) { - mEnabled[i] = true; - } - } - - // When preferences are disabled, we will display them grayed out. Users - // will not be able to change the disabled preferences, but they can still see - // the current value of the preferences - public void setPreferenceEnabled(String key, boolean enable) { - int count = mEnabled == null ? 0 : mEnabled.length; - for (int j = 0; j < count; j++) { - ListPreference pref = mListItem.get(j); - if (pref != null && key.equals(pref.getKey())) { - mEnabled[j] = enable; - break; - } - } - } - - public void onSettingChanged(ListPreference pref) { - if (mListener != null) { - mListener.onSettingChanged(pref); - } - } - - // Scene mode can override other camera settings (ex: flash mode). - public void overrideSettings(final String ... keyvalues) { - int count = mEnabled == null ? 0 : mEnabled.length; - for (int i = 0; i < keyvalues.length; i += 2) { - String key = keyvalues[i]; - String value = keyvalues[i + 1]; - for (int j = 0; j < count; j++) { - ListPreference pref = mListItem.get(j); - if (pref != null && key.equals(pref.getKey())) { - // Change preference - if (value != null) pref.setValue(value); - // If the preference is overridden, disable the preference - boolean enable = value == null; - mEnabled[j] = enable; - if (mSettingList.getChildCount() > j) { - mSettingList.getChildAt(j).setEnabled(enable); - } - } - } - } - reloadPreference(); - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, - long id) { - if (mListener != null) { - ListPreference pref = mListItem.get(position); - mListener.onPreferenceClicked(pref); - } - } - - @Override - public void reloadPreference() { - int count = mSettingList.getChildCount(); - for (int i = 0; i < count; i++) { - ListPreference pref = mListItem.get(i); - if (pref != null) { - InLineSettingItem settingItem = - (InLineSettingItem) mSettingList.getChildAt(i); - settingItem.reloadPreference(); - } - } - } -} diff --git a/src/com/android/camera/ui/OnIndicatorEventListener.java b/src/com/android/camera/ui/OnIndicatorEventListener.java deleted file mode 100644 index 566f5c7a8..000000000 --- a/src/com/android/camera/ui/OnIndicatorEventListener.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -public interface OnIndicatorEventListener { - public static int EVENT_ENTER_SECOND_LEVEL_INDICATOR_BAR = 0; - public static int EVENT_LEAVE_SECOND_LEVEL_INDICATOR_BAR = 1; - public static int EVENT_ENTER_ZOOM_CONTROL = 2; - public static int EVENT_LEAVE_ZOOM_CONTROL = 3; - void onIndicatorEvent(int event); -} diff --git a/src/com/android/camera/ui/OverlayRenderer.java b/src/com/android/camera/ui/OverlayRenderer.java deleted file mode 100644 index 417e219aa..000000000 --- a/src/com/android/camera/ui/OverlayRenderer.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.graphics.Canvas; -import android.view.MotionEvent; - -public abstract class OverlayRenderer implements RenderOverlay.Renderer { - - private static final String TAG = "CAM OverlayRenderer"; - protected RenderOverlay mOverlay; - - protected int mLeft, mTop, mRight, mBottom; - - protected boolean mVisible; - - public void setVisible(boolean vis) { - mVisible = vis; - update(); - } - - public boolean isVisible() { - return mVisible; - } - - // default does not handle touch - @Override - public boolean handlesTouch() { - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent evt) { - return false; - } - - public abstract void onDraw(Canvas canvas); - - public void draw(Canvas canvas) { - if (mVisible) { - onDraw(canvas); - } - } - - @Override - public void setOverlay(RenderOverlay overlay) { - mOverlay = overlay; - } - - @Override - public void layout(int left, int top, int right, int bottom) { - mLeft = left; - mRight = right; - mTop = top; - mBottom = bottom; - } - - protected Context getContext() { - if (mOverlay != null) { - return mOverlay.getContext(); - } else { - return null; - } - } - - public int getWidth() { - return mRight - mLeft; - } - - public int getHeight() { - return mBottom - mTop; - } - - protected void update() { - if (mOverlay != null) { - mOverlay.update(); - } - } - -} diff --git a/src/com/android/camera/ui/PieItem.java b/src/com/android/camera/ui/PieItem.java deleted file mode 100644 index 47fe06758..000000000 --- a/src/com/android/camera/ui/PieItem.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Path; -import android.graphics.drawable.Drawable; - -import java.util.ArrayList; -import java.util.List; - -/** - * Pie menu item - */ -public class PieItem { - - public static interface OnClickListener { - void onClick(PieItem item); - } - - private Drawable mDrawable; - private int level; - - private boolean mSelected; - private boolean mEnabled; - private List<PieItem> mItems; - private Path mPath; - private OnClickListener mOnClickListener; - private float mAlpha; - private CharSequence mLabel; - - // Gray out the view when disabled - private static final float ENABLED_ALPHA = 1; - private static final float DISABLED_ALPHA = (float) 0.3; - private boolean mChangeAlphaWhenDisabled = true; - - public PieItem(Drawable drawable, int level) { - mDrawable = drawable; - this.level = level; - if (drawable != null) { - setAlpha(1f); - } - mEnabled = true; - } - - public void setLabel(CharSequence txt) { - mLabel = txt; - } - - public CharSequence getLabel() { - return mLabel; - } - - public boolean hasItems() { - return mItems != null; - } - - public List<PieItem> getItems() { - return mItems; - } - - public void addItem(PieItem item) { - if (mItems == null) { - mItems = new ArrayList<PieItem>(); - } - mItems.add(item); - } - - public void clearItems() { - mItems = null; - } - - public void setLevel(int level) { - this.level = level; - } - - public void setPath(Path p) { - mPath = p; - } - - public Path getPath() { - return mPath; - } - - public void setChangeAlphaWhenDisabled (boolean enable) { - mChangeAlphaWhenDisabled = enable; - } - - public void setAlpha(float alpha) { - mAlpha = alpha; - mDrawable.setAlpha((int) (255 * alpha)); - } - - public void setEnabled(boolean enabled) { - mEnabled = enabled; - if (mChangeAlphaWhenDisabled) { - if (mEnabled) { - setAlpha(ENABLED_ALPHA); - } else { - setAlpha(DISABLED_ALPHA); - } - } - } - - public boolean isEnabled() { - return mEnabled; - } - - public void setSelected(boolean s) { - mSelected = s; - } - - public boolean isSelected() { - return mSelected; - } - - public int getLevel() { - return level; - } - - - public void setOnClickListener(OnClickListener listener) { - mOnClickListener = listener; - } - - public void performClick() { - if (mOnClickListener != null) { - mOnClickListener.onClick(this); - } - } - - public int getIntrinsicWidth() { - return mDrawable.getIntrinsicWidth(); - } - - public int getIntrinsicHeight() { - return mDrawable.getIntrinsicHeight(); - } - - public void setBounds(int left, int top, int right, int bottom) { - mDrawable.setBounds(left, top, right, bottom); - } - - public void draw(Canvas canvas) { - mDrawable.draw(canvas); - } - - public void setImageResource(Context context, int resId) { - Drawable d = context.getResources().getDrawable(resId).mutate(); - d.setBounds(mDrawable.getBounds()); - mDrawable = d; - setAlpha(mAlpha); - } - -} diff --git a/src/com/android/camera/ui/PieMenuButton.java b/src/com/android/camera/ui/PieMenuButton.java deleted file mode 100644 index 0e23226b2..000000000 --- a/src/com/android/camera/ui/PieMenuButton.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2013 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.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -public class PieMenuButton extends View { - private boolean mPressed; - private boolean mReadyToClick = false; - public PieMenuButton(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - mPressed = isPressed(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - boolean handled = super.onTouchEvent(event); - if (MotionEvent.ACTION_UP == event.getAction() && mPressed) { - // Perform a customized click as soon as the ACTION_UP event - // is received. The reason for doing this is that Framework - // delays the performClick() call after ACTION_UP. But we do not - // want the delay because it affects an important state change - // for PieRenderer. - mReadyToClick = true; - performClick(); - } - return handled; - } - - @Override - public boolean performClick() { - if (mReadyToClick) { - // We only respond to our customized click which happens right - // after ACTION_UP event is received, with no delay. - mReadyToClick = false; - return super.performClick(); - } - return false; - } -};
\ No newline at end of file diff --git a/src/com/android/camera/ui/PieRenderer.java b/src/com/android/camera/ui/PieRenderer.java deleted file mode 100644 index c78107ce9..000000000 --- a/src/com/android/camera/ui/PieRenderer.java +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.ValueAnimator; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Point; -import android.graphics.PointF; -import android.graphics.RectF; -import android.os.Handler; -import android.os.Message; -import android.util.FloatMath; -import android.view.MotionEvent; -import android.view.ViewConfiguration; -import android.view.animation.Animation; -import android.view.animation.Transformation; - -import com.android.camera.drawable.TextDrawable; -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.List; - -public class PieRenderer extends OverlayRenderer - implements FocusIndicator { - - private static final String TAG = "CAM Pie"; - - // Sometimes continuous autofocus starts and stops several times quickly. - // These states are used to make sure the animation is run for at least some - // time. - private volatile int mState; - private ScaleAnimation mAnimation = new ScaleAnimation(); - private static final int STATE_IDLE = 0; - private static final int STATE_FOCUSING = 1; - private static final int STATE_FINISHING = 2; - private static final int STATE_PIE = 8; - - private static final float MATH_PI_2 = (float)(Math.PI / 2); - - private Runnable mDisappear = new Disappear(); - private Animation.AnimationListener mEndAction = new EndAction(); - private static final int SCALING_UP_TIME = 600; - private static final int SCALING_DOWN_TIME = 100; - private static final int DISAPPEAR_TIMEOUT = 200; - private static final int DIAL_HORIZONTAL = 157; - // fade out timings - private static final int PIE_FADE_OUT_DURATION = 600; - - private static final long PIE_FADE_IN_DURATION = 200; - private static final long PIE_XFADE_DURATION = 200; - private static final long PIE_SELECT_FADE_DURATION = 300; - private static final long PIE_OPEN_SUB_DELAY = 400; - private static final long PIE_SLICE_DURATION = 80; - - private static final int MSG_OPEN = 0; - private static final int MSG_CLOSE = 1; - private static final int MSG_OPENSUBMENU = 2; - - protected static float CENTER = (float) Math.PI / 2; - protected static float RAD24 = (float)(24 * Math.PI / 180); - protected static final float SWEEP_SLICE = 0.14f; - protected static final float SWEEP_ARC = 0.23f; - - // geometry - private int mRadius; - private int mRadiusInc; - - // the detection if touch is inside a slice is offset - // inbounds by this amount to allow the selection to show before the - // finger covers it - private int mTouchOffset; - - private List<PieItem> mOpen; - - private Paint mSelectedPaint; - private Paint mSubPaint; - private Paint mMenuArcPaint; - - // touch handling - private PieItem mCurrentItem; - - private Paint mFocusPaint; - private int mSuccessColor; - private int mFailColor; - private int mCircleSize; - private int mFocusX; - private int mFocusY; - private int mCenterX; - private int mCenterY; - private int mArcCenterY; - private int mSliceCenterY; - private int mPieCenterX; - private int mPieCenterY; - private int mSliceRadius; - private int mArcRadius; - private int mArcOffset; - - private int mDialAngle; - private RectF mCircle; - private RectF mDial; - private Point mPoint1; - private Point mPoint2; - private int mStartAnimationAngle; - private boolean mFocused; - private int mInnerOffset; - private int mOuterStroke; - private int mInnerStroke; - private boolean mTapMode; - private boolean mBlockFocus; - private int mTouchSlopSquared; - private Point mDown; - private boolean mOpening; - private ValueAnimator mXFade; - private ValueAnimator mFadeIn; - private ValueAnimator mFadeOut; - private ValueAnimator mSlice; - private volatile boolean mFocusCancelled; - private PointF mPolar = new PointF(); - private TextDrawable mLabel; - private int mDeadZone; - private int mAngleZone; - private float mCenterAngle; - - - - private Handler mHandler = new Handler() { - public void handleMessage(Message msg) { - switch(msg.what) { - case MSG_OPEN: - if (mListener != null) { - mListener.onPieOpened(mPieCenterX, mPieCenterY); - } - break; - case MSG_CLOSE: - if (mListener != null) { - mListener.onPieClosed(); - } - break; - case MSG_OPENSUBMENU: - onEnterOpen(); - break; - } - - } - }; - - private PieListener mListener; - - static public interface PieListener { - public void onPieOpened(int centerX, int centerY); - public void onPieClosed(); - } - - public void setPieListener(PieListener pl) { - mListener = pl; - } - - public PieRenderer(Context context) { - init(context); - } - - private void init(Context ctx) { - setVisible(false); - mOpen = new ArrayList<PieItem>(); - mOpen.add(new PieItem(null, 0)); - Resources res = ctx.getResources(); - mRadius = (int) res.getDimensionPixelSize(R.dimen.pie_radius_start); - mRadiusInc = (int) res.getDimensionPixelSize(R.dimen.pie_radius_increment); - mCircleSize = mRadius - res.getDimensionPixelSize(R.dimen.focus_radius_offset); - mTouchOffset = (int) res.getDimensionPixelSize(R.dimen.pie_touch_offset); - mSelectedPaint = new Paint(); - mSelectedPaint.setColor(Color.argb(255, 51, 181, 229)); - mSelectedPaint.setAntiAlias(true); - mSubPaint = new Paint(); - mSubPaint.setAntiAlias(true); - mSubPaint.setColor(Color.argb(200, 250, 230, 128)); - mFocusPaint = new Paint(); - mFocusPaint.setAntiAlias(true); - mFocusPaint.setColor(Color.WHITE); - mFocusPaint.setStyle(Paint.Style.STROKE); - mSuccessColor = Color.GREEN; - mFailColor = Color.RED; - mCircle = new RectF(); - mDial = new RectF(); - mPoint1 = new Point(); - mPoint2 = new Point(); - mInnerOffset = res.getDimensionPixelSize(R.dimen.focus_inner_offset); - mOuterStroke = res.getDimensionPixelSize(R.dimen.focus_outer_stroke); - mInnerStroke = res.getDimensionPixelSize(R.dimen.focus_inner_stroke); - mState = STATE_IDLE; - mBlockFocus = false; - mTouchSlopSquared = ViewConfiguration.get(ctx).getScaledTouchSlop(); - mTouchSlopSquared = mTouchSlopSquared * mTouchSlopSquared; - mDown = new Point(); - mMenuArcPaint = new Paint(); - mMenuArcPaint.setAntiAlias(true); - mMenuArcPaint.setColor(Color.argb(140, 255, 255, 255)); - mMenuArcPaint.setStrokeWidth(10); - mMenuArcPaint.setStyle(Paint.Style.STROKE); - mSliceRadius = res.getDimensionPixelSize(R.dimen.pie_item_radius); - mArcRadius = res.getDimensionPixelSize(R.dimen.pie_arc_radius); - mArcOffset = res.getDimensionPixelSize(R.dimen.pie_arc_offset); - mLabel = new TextDrawable(res); - mLabel.setDropShadow(true); - mDeadZone = res.getDimensionPixelSize(R.dimen.pie_deadzone_width); - mAngleZone = res.getDimensionPixelSize(R.dimen.pie_anglezone_width); - } - - private PieItem getRoot() { - return mOpen.get(0); - } - - public boolean showsItems() { - return mTapMode; - } - - public void addItem(PieItem item) { - // add the item to the pie itself - getRoot().addItem(item); - } - - public void clearItems() { - getRoot().clearItems(); - } - - public void showInCenter() { - if ((mState == STATE_PIE) && isVisible()) { - mTapMode = false; - show(false); - } else { - if (mState != STATE_IDLE) { - cancelFocus(); - } - mState = STATE_PIE; - resetPieCenter(); - setCenter(mPieCenterX, mPieCenterY); - mTapMode = true; - show(true); - } - } - - public void hide() { - show(false); - } - - /** - * guaranteed has center set - * @param show - */ - private void show(boolean show) { - if (show) { - if (mXFade != null) { - mXFade.cancel(); - } - mState = STATE_PIE; - // ensure clean state - mCurrentItem = null; - PieItem root = getRoot(); - for (PieItem openItem : mOpen) { - if (openItem.hasItems()) { - for (PieItem item : openItem.getItems()) { - item.setSelected(false); - } - } - } - mLabel.setText(""); - mOpen.clear(); - mOpen.add(root); - layoutPie(); - fadeIn(); - } else { - mState = STATE_IDLE; - mTapMode = false; - if (mXFade != null) { - mXFade.cancel(); - } - if (mLabel != null) { - mLabel.setText(""); - } - } - setVisible(show); - mHandler.sendEmptyMessage(show ? MSG_OPEN : MSG_CLOSE); - } - - public boolean isOpen() { - return mState == STATE_PIE && isVisible(); - } - - private void fadeIn() { - mFadeIn = new ValueAnimator(); - mFadeIn.setFloatValues(0f, 1f); - mFadeIn.setDuration(PIE_FADE_IN_DURATION); - // linear interpolation - mFadeIn.setInterpolator(null); - mFadeIn.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - } - - @Override - public void onAnimationEnd(Animator animation) { - mFadeIn = null; - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - - @Override - public void onAnimationCancel(Animator arg0) { - } - }); - mFadeIn.start(); - } - - public void setCenter(int x, int y) { - mPieCenterX = x; - mPieCenterY = y; - mSliceCenterY = y + mSliceRadius - mArcOffset; - mArcCenterY = y - mArcOffset + mArcRadius; - } - - @Override - public void layout(int l, int t, int r, int b) { - super.layout(l, t, r, b); - mCenterX = (r - l) / 2; - mCenterY = (b - t) / 2; - - mFocusX = mCenterX; - mFocusY = mCenterY; - resetPieCenter(); - setCircle(mFocusX, mFocusY); - if (isVisible() && mState == STATE_PIE) { - setCenter(mPieCenterX, mPieCenterY); - layoutPie(); - } - } - - private void resetPieCenter() { - mPieCenterX = mCenterX; - mPieCenterY = (int) (getHeight() - 2.5f * mDeadZone); - } - - private void layoutPie() { - mCenterAngle = getCenterAngle(); - layoutItems(0, getRoot().getItems()); - layoutLabel(getLevel()); - } - - private void layoutLabel(int level) { - int x = mPieCenterX - (int) (FloatMath.sin(mCenterAngle - CENTER) - * (mArcRadius + (level + 2) * mRadiusInc)); - int y = mArcCenterY - mArcRadius - (level + 2) * mRadiusInc; - int w = mLabel.getIntrinsicWidth(); - int h = mLabel.getIntrinsicHeight(); - mLabel.setBounds(x - w/2, y - h/2, x + w/2, y + h/2); - } - - private void layoutItems(int level, List<PieItem> items) { - int extend = 1; - Path path = makeSlice(getDegrees(0) + extend, getDegrees(SWEEP_ARC) - extend, - mArcRadius, mArcRadius + mRadiusInc + mRadiusInc / 4, - mPieCenterX, mArcCenterY - level * mRadiusInc); - final int count = items.size(); - int pos = 0; - for (PieItem item : items) { - // shared between items - item.setPath(path); - float angle = getArcCenter(item, pos, count); - int w = item.getIntrinsicWidth(); - int h = item.getIntrinsicHeight(); - // move views to outer border - int r = mArcRadius + mRadiusInc * 2 / 3; - int x = (int) (r * Math.cos(angle)); - int y = mArcCenterY - (level * mRadiusInc) - (int) (r * Math.sin(angle)) - h / 2; - x = mPieCenterX + x - w / 2; - item.setBounds(x, y, x + w, y + h); - item.setLevel(level); - if (item.hasItems()) { - layoutItems(level + 1, item.getItems()); - } - pos++; - } - } - - private Path makeSlice(float start, float end, int inner, int outer, int cx, int cy) { - RectF bb = - new RectF(cx - outer, cy - outer, cx + outer, - cy + outer); - RectF bbi = - new RectF(cx - inner, cy - inner, cx + inner, - cy + inner); - Path path = new Path(); - path.arcTo(bb, start, end - start, true); - path.arcTo(bbi, end, start - end); - path.close(); - return path; - } - - private float getArcCenter(PieItem item, int pos, int count) { - return getCenter(pos, count, SWEEP_ARC); - } - - private float getSliceCenter(PieItem item, int pos, int count) { - float center = (getCenterAngle() - CENTER) * 0.5f + CENTER; - return center + (count - 1) * SWEEP_SLICE / 2f - - pos * SWEEP_SLICE; - } - - private float getCenter(int pos, int count, float sweep) { - return mCenterAngle + (count - 1) * sweep / 2f - pos * sweep; - } - - private float getCenterAngle() { - float center = CENTER; - if (mPieCenterX < mDeadZone + mAngleZone) { - center = CENTER - (mAngleZone - mPieCenterX + mDeadZone) * RAD24 - / (float) mAngleZone; - } else if (mPieCenterX > getWidth() - mDeadZone - mAngleZone) { - center = CENTER + (mPieCenterX - (getWidth() - mDeadZone - mAngleZone)) * RAD24 - / (float) mAngleZone; - } - return center; - } - - /** - * converts a - * @param angle from 0..PI to Android degrees (clockwise starting at 3 o'clock) - * @return skia angle - */ - private float getDegrees(double angle) { - return (float) (360 - 180 * angle / Math.PI); - } - - private void startFadeOut(final PieItem item) { - if (mFadeIn != null) { - mFadeIn.cancel(); - } - if (mXFade != null) { - mXFade.cancel(); - } - mFadeOut = new ValueAnimator(); - mFadeOut.setFloatValues(1f, 0f); - mFadeOut.setDuration(PIE_FADE_OUT_DURATION); - mFadeOut.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animator) { - } - - @Override - public void onAnimationEnd(Animator animator) { - item.performClick(); - mFadeOut = null; - deselect(); - show(false); - mOverlay.setAlpha(1); - } - - @Override - public void onAnimationRepeat(Animator animator) { - } - - @Override - public void onAnimationCancel(Animator animator) { - } - - }); - mFadeOut.start(); - } - - // root does not count - private boolean hasOpenItem() { - return mOpen.size() > 1; - } - - // pop an item of the open item stack - private PieItem closeOpenItem() { - PieItem item = getOpenItem(); - mOpen.remove(mOpen.size() -1); - return item; - } - - private PieItem getOpenItem() { - return mOpen.get(mOpen.size() - 1); - } - - // return the children either the root or parent of the current open item - private PieItem getParent() { - return mOpen.get(Math.max(0, mOpen.size() - 2)); - } - - private int getLevel() { - return mOpen.size() - 1; - } - - @Override - public void onDraw(Canvas canvas) { - float alpha = 1; - if (mXFade != null) { - alpha = (Float) mXFade.getAnimatedValue(); - } else if (mFadeIn != null) { - alpha = (Float) mFadeIn.getAnimatedValue(); - } else if (mFadeOut != null) { - alpha = (Float) mFadeOut.getAnimatedValue(); - } - int state = canvas.save(); - if (mFadeIn != null) { - float sf = 0.9f + alpha * 0.1f; - canvas.scale(sf, sf, mPieCenterX, mPieCenterY); - } - if (mState != STATE_PIE) { - drawFocus(canvas); - } - if (mState == STATE_FINISHING) { - canvas.restoreToCount(state); - return; - } - if (mState != STATE_PIE) return; - if (!hasOpenItem() || (mXFade != null)) { - // draw base menu - drawArc(canvas, getLevel(), getParent()); - List<PieItem> items = getParent().getItems(); - final int count = items.size(); - int pos = 0; - for (PieItem item : getParent().getItems()) { - drawItem(Math.max(0, mOpen.size() - 2), pos, count, canvas, item, alpha); - pos++; - } - mLabel.draw(canvas); - } - if (hasOpenItem()) { - int level = getLevel(); - drawArc(canvas, level, getOpenItem()); - List<PieItem> items = getOpenItem().getItems(); - final int count = items.size(); - int pos = 0; - for (PieItem inner : items) { - if (mFadeOut != null) { - drawItem(level, pos, count, canvas, inner, alpha); - } else { - drawItem(level, pos, count, canvas, inner, (mXFade != null) ? (1 - 0.5f * alpha) : 1); - } - pos++; - } - mLabel.draw(canvas); - } - canvas.restoreToCount(state); - } - - private void drawArc(Canvas canvas, int level, PieItem item) { - // arc - if (mState == STATE_PIE) { - final int count = item.getItems().size(); - float start = mCenterAngle + (count * SWEEP_ARC / 2f); - float end = mCenterAngle - (count * SWEEP_ARC / 2f); - int cy = mArcCenterY - level * mRadiusInc; - canvas.drawArc(new RectF(mPieCenterX - mArcRadius, cy - mArcRadius, - mPieCenterX + mArcRadius, cy + mArcRadius), - getDegrees(end), getDegrees(start) - getDegrees(end), false, mMenuArcPaint); - } - } - - private void drawItem(int level, int pos, int count, Canvas canvas, PieItem item, float alpha) { - if (mState == STATE_PIE) { - if (item.getPath() != null) { - int y = mArcCenterY - level * mRadiusInc; - if (item.isSelected()) { - Paint p = mSelectedPaint; - int state = canvas.save(); - float angle = 0; - if (mSlice != null) { - angle = (Float) mSlice.getAnimatedValue(); - } else { - angle = getArcCenter(item, pos, count) - SWEEP_ARC / 2f; - } - angle = getDegrees(angle); - canvas.rotate(angle, mPieCenterX, y); - if (mFadeOut != null) { - p.setAlpha((int)(255 * alpha)); - } - canvas.drawPath(item.getPath(), p); - if (mFadeOut != null) { - p.setAlpha(255); - } - canvas.restoreToCount(state); - } - if (mFadeOut == null) { - alpha = alpha * (item.isEnabled() ? 1 : 0.3f); - // draw the item view - item.setAlpha(alpha); - } - item.draw(canvas); - } - } - } - - @Override - public boolean onTouchEvent(MotionEvent evt) { - float x = evt.getX(); - float y = evt.getY(); - int action = evt.getActionMasked(); - getPolar(x, y, !mTapMode, mPolar); - if (MotionEvent.ACTION_DOWN == action) { - if ((x < mDeadZone) || (x > getWidth() - mDeadZone)) { - return false; - } - mDown.x = (int) evt.getX(); - mDown.y = (int) evt.getY(); - mOpening = false; - if (mTapMode) { - PieItem item = findItem(mPolar); - if ((item != null) && (mCurrentItem != item)) { - mState = STATE_PIE; - onEnter(item); - } - } else { - setCenter((int) x, (int) y); - show(true); - } - return true; - } else if (MotionEvent.ACTION_UP == action) { - if (isVisible()) { - PieItem item = mCurrentItem; - if (mTapMode) { - item = findItem(mPolar); - if (mOpening) { - mOpening = false; - return true; - } - } - if (item == null) { - mTapMode = false; - show(false); - } else if (!mOpening && !item.hasItems()) { - startFadeOut(item); - mTapMode = false; - } else { - mTapMode = true; - } - return true; - } - } else if (MotionEvent.ACTION_CANCEL == action) { - if (isVisible() || mTapMode) { - show(false); - } - deselect(); - mHandler.removeMessages(MSG_OPENSUBMENU); - return false; - } else if (MotionEvent.ACTION_MOVE == action) { - if (pulledToCenter(mPolar)) { - mHandler.removeMessages(MSG_OPENSUBMENU); - if (hasOpenItem()) { - if (mCurrentItem != null) { - mCurrentItem.setSelected(false); - } - closeOpenItem(); - mCurrentItem = null; - } else { - deselect(); - } - mLabel.setText(""); - return false; - } - PieItem item = findItem(mPolar); - boolean moved = hasMoved(evt); - if ((item != null) && (mCurrentItem != item) && (!mOpening || moved)) { - mHandler.removeMessages(MSG_OPENSUBMENU); - // only select if we didn't just open or have moved past slop - if (moved) { - // switch back to swipe mode - mTapMode = false; - } - onEnterSelect(item); - mHandler.sendEmptyMessageDelayed(MSG_OPENSUBMENU, PIE_OPEN_SUB_DELAY); - } - } - return false; - } - - private boolean pulledToCenter(PointF polarCoords) { - return polarCoords.y < mArcRadius - mRadiusInc; - } - - private boolean inside(PointF polar, PieItem item, int pos, int count) { - float start = getSliceCenter(item, pos, count) - SWEEP_SLICE / 2f; - boolean res = (mArcRadius < polar.y) - && (start < polar.x) - && (start + SWEEP_SLICE > polar.x) - && (!mTapMode || (mArcRadius + mRadiusInc > polar.y)); - return res; - } - - private void getPolar(float x, float y, boolean useOffset, PointF res) { - // get angle and radius from x/y - res.x = (float) Math.PI / 2; - x = x - mPieCenterX; - float y1 = mSliceCenterY - getLevel() * mRadiusInc - y; - float y2 = mArcCenterY - getLevel() * mRadiusInc - y; - res.y = (float) Math.sqrt(x * x + y2 * y2); - if (x != 0) { - res.x = (float) Math.atan2(y1, x); - if (res.x < 0) { - res.x = (float) (2 * Math.PI + res.x); - } - } - res.y = res.y + (useOffset ? mTouchOffset : 0); - } - - private boolean hasMoved(MotionEvent e) { - return mTouchSlopSquared < (e.getX() - mDown.x) * (e.getX() - mDown.x) - + (e.getY() - mDown.y) * (e.getY() - mDown.y); - } - - private void onEnterSelect(PieItem item) { - if (mCurrentItem != null) { - mCurrentItem.setSelected(false); - } - if (item != null && item.isEnabled()) { - moveSelection(mCurrentItem, item); - item.setSelected(true); - mCurrentItem = item; - mLabel.setText(mCurrentItem.getLabel()); - layoutLabel(getLevel()); - } else { - mCurrentItem = null; - } - } - - private void onEnterOpen() { - if ((mCurrentItem != null) && (mCurrentItem != getOpenItem()) && mCurrentItem.hasItems()) { - openCurrentItem(); - } - } - - /** - * enter a slice for a view - * updates model only - * @param item - */ - private void onEnter(PieItem item) { - if (mCurrentItem != null) { - mCurrentItem.setSelected(false); - } - if (item != null && item.isEnabled()) { - item.setSelected(true); - mCurrentItem = item; - mLabel.setText(mCurrentItem.getLabel()); - if ((mCurrentItem != getOpenItem()) && mCurrentItem.hasItems()) { - openCurrentItem(); - layoutLabel(getLevel()); - } - } else { - mCurrentItem = null; - } - } - - private void deselect() { - if (mCurrentItem != null) { - mCurrentItem.setSelected(false); - } - if (hasOpenItem()) { - PieItem item = closeOpenItem(); - onEnter(item); - } else { - mCurrentItem = null; - } - } - - private int getItemPos(PieItem target) { - List<PieItem> items = getOpenItem().getItems(); - return items.indexOf(target); - } - - private int getCurrentCount() { - return getOpenItem().getItems().size(); - } - - private void moveSelection(PieItem from, PieItem to) { - final int count = getCurrentCount(); - final int fromPos = getItemPos(from); - final int toPos = getItemPos(to); - if (fromPos != -1 && toPos != -1) { - float startAngle = getArcCenter(from, getItemPos(from), count) - - SWEEP_ARC / 2f; - float endAngle = getArcCenter(to, getItemPos(to), count) - - SWEEP_ARC / 2f; - mSlice = new ValueAnimator(); - mSlice.setFloatValues(startAngle, endAngle); - // linear interpolater - mSlice.setInterpolator(null); - mSlice.setDuration(PIE_SLICE_DURATION); - mSlice.addListener(new AnimatorListener() { - @Override - public void onAnimationEnd(Animator arg0) { - mSlice = null; - } - - @Override - public void onAnimationRepeat(Animator arg0) { - } - - @Override - public void onAnimationStart(Animator arg0) { - } - - @Override - public void onAnimationCancel(Animator arg0) { - } - }); - mSlice.start(); - } - } - - private void openCurrentItem() { - if ((mCurrentItem != null) && mCurrentItem.hasItems()) { - mOpen.add(mCurrentItem); - layoutLabel(getLevel()); - mOpening = true; - if (mFadeIn != null) { - mFadeIn.cancel(); - } - mXFade = new ValueAnimator(); - mXFade.setFloatValues(1f, 0f); - mXFade.setDuration(PIE_XFADE_DURATION); - // Linear interpolation - mXFade.setInterpolator(null); - final PieItem ci = mCurrentItem; - mXFade.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - } - - @Override - public void onAnimationEnd(Animator animation) { - mXFade = null; - ci.setSelected(false); - mOpening = false; - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - - @Override - public void onAnimationCancel(Animator arg0) { - } - }); - mXFade.start(); - } - } - - /** - * @param polar x: angle, y: dist - * @return the item at angle/dist or null - */ - private PieItem findItem(PointF polar) { - // find the matching item: - List<PieItem> items = getOpenItem().getItems(); - final int count = items.size(); - int pos = 0; - for (PieItem item : items) { - if (inside(polar, item, pos, count)) { - return item; - } - pos++; - } - return null; - } - - - @Override - public boolean handlesTouch() { - return true; - } - - // focus specific code - - public void setBlockFocus(boolean blocked) { - mBlockFocus = blocked; - if (blocked) { - clear(); - } - } - - public void setFocus(int x, int y) { - mFocusX = x; - mFocusY = y; - setCircle(mFocusX, mFocusY); - } - - public void alignFocus(int x, int y) { - mOverlay.removeCallbacks(mDisappear); - mAnimation.cancel(); - mAnimation.reset(); - mFocusX = x; - mFocusY = y; - mDialAngle = DIAL_HORIZONTAL; - setCircle(x, y); - mFocused = false; - } - - public int getSize() { - return 2 * mCircleSize; - } - - private int getRandomRange() { - return (int)(-60 + 120 * Math.random()); - } - - private void setCircle(int cx, int cy) { - mCircle.set(cx - mCircleSize, cy - mCircleSize, - cx + mCircleSize, cy + mCircleSize); - mDial.set(cx - mCircleSize + mInnerOffset, cy - mCircleSize + mInnerOffset, - cx + mCircleSize - mInnerOffset, cy + mCircleSize - mInnerOffset); - } - - public void drawFocus(Canvas canvas) { - if (mBlockFocus) return; - mFocusPaint.setStrokeWidth(mOuterStroke); - canvas.drawCircle((float) mFocusX, (float) mFocusY, (float) mCircleSize, mFocusPaint); - if (mState == STATE_PIE) return; - int color = mFocusPaint.getColor(); - if (mState == STATE_FINISHING) { - mFocusPaint.setColor(mFocused ? mSuccessColor : mFailColor); - } - mFocusPaint.setStrokeWidth(mInnerStroke); - drawLine(canvas, mDialAngle, mFocusPaint); - drawLine(canvas, mDialAngle + 45, mFocusPaint); - drawLine(canvas, mDialAngle + 180, mFocusPaint); - drawLine(canvas, mDialAngle + 225, mFocusPaint); - canvas.save(); - // rotate the arc instead of its offset to better use framework's shape caching - canvas.rotate(mDialAngle, mFocusX, mFocusY); - canvas.drawArc(mDial, 0, 45, false, mFocusPaint); - canvas.drawArc(mDial, 180, 45, false, mFocusPaint); - canvas.restore(); - mFocusPaint.setColor(color); - } - - private void drawLine(Canvas canvas, int angle, Paint p) { - convertCart(angle, mCircleSize - mInnerOffset, mPoint1); - convertCart(angle, mCircleSize - mInnerOffset + mInnerOffset / 3, mPoint2); - canvas.drawLine(mPoint1.x + mFocusX, mPoint1.y + mFocusY, - mPoint2.x + mFocusX, mPoint2.y + mFocusY, p); - } - - private static void convertCart(int angle, int radius, Point out) { - double a = 2 * Math.PI * (angle % 360) / 360; - out.x = (int) (radius * Math.cos(a) + 0.5); - out.y = (int) (radius * Math.sin(a) + 0.5); - } - - @Override - public void showStart() { - if (mState == STATE_PIE) return; - cancelFocus(); - mStartAnimationAngle = 67; - int range = getRandomRange(); - startAnimation(SCALING_UP_TIME, - false, mStartAnimationAngle, mStartAnimationAngle + range); - mState = STATE_FOCUSING; - } - - @Override - public void showSuccess(boolean timeout) { - if (mState == STATE_FOCUSING) { - startAnimation(SCALING_DOWN_TIME, - timeout, mStartAnimationAngle); - mState = STATE_FINISHING; - mFocused = true; - } - } - - @Override - public void showFail(boolean timeout) { - if (mState == STATE_FOCUSING) { - startAnimation(SCALING_DOWN_TIME, - timeout, mStartAnimationAngle); - mState = STATE_FINISHING; - mFocused = false; - } - } - - private void cancelFocus() { - mFocusCancelled = true; - mOverlay.removeCallbacks(mDisappear); - if (mAnimation != null && !mAnimation.hasEnded()) { - mAnimation.cancel(); - } - mFocusCancelled = false; - mFocused = false; - mState = STATE_IDLE; - } - - @Override - public void clear() { - if (mState == STATE_PIE) return; - cancelFocus(); - mOverlay.post(mDisappear); - } - - private void startAnimation(long duration, boolean timeout, - float toScale) { - startAnimation(duration, timeout, mDialAngle, - toScale); - } - - private void startAnimation(long duration, boolean timeout, - float fromScale, float toScale) { - setVisible(true); - mAnimation.reset(); - mAnimation.setDuration(duration); - mAnimation.setScale(fromScale, toScale); - mAnimation.setAnimationListener(timeout ? mEndAction : null); - mOverlay.startAnimation(mAnimation); - update(); - } - - private class EndAction implements Animation.AnimationListener { - @Override - public void onAnimationEnd(Animation animation) { - // Keep the focus indicator for some time. - if (!mFocusCancelled) { - mOverlay.postDelayed(mDisappear, DISAPPEAR_TIMEOUT); - } - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - - @Override - public void onAnimationStart(Animation animation) { - } - } - - private class Disappear implements Runnable { - @Override - public void run() { - if (mState == STATE_PIE) return; - setVisible(false); - mFocusX = mCenterX; - mFocusY = mCenterY; - mState = STATE_IDLE; - setCircle(mFocusX, mFocusY); - mFocused = false; - } - } - - private class ScaleAnimation extends Animation { - private float mFrom = 1f; - private float mTo = 1f; - - public ScaleAnimation() { - setFillAfter(true); - } - - public void setScale(float from, float to) { - mFrom = from; - mTo = to; - } - - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - mDialAngle = (int)(mFrom + (mTo - mFrom) * interpolatedTime); - } - } - -} diff --git a/src/com/android/camera/ui/PopupManager.java b/src/com/android/camera/ui/PopupManager.java deleted file mode 100644 index 0dcf34fd7..000000000 --- a/src/com/android/camera/ui/PopupManager.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.view.View; - -import java.util.ArrayList; -import java.util.HashMap; - -/** - * A manager which notifies the event of a new popup in order to dismiss the - * old popup if exists. - */ -public class PopupManager { - private static HashMap<Context, PopupManager> sMap = - new HashMap<Context, PopupManager>(); - - public interface OnOtherPopupShowedListener { - public void onOtherPopupShowed(); - } - - private PopupManager() {} - - private ArrayList<OnOtherPopupShowedListener> mListeners = new ArrayList<OnOtherPopupShowedListener>(); - - public void notifyShowPopup(View view) { - for (OnOtherPopupShowedListener listener : mListeners) { - if ((View) listener != view) { - listener.onOtherPopupShowed(); - } - } - } - - public void setOnOtherPopupShowedListener(OnOtherPopupShowedListener listener) { - mListeners.add(listener); - } - - public static PopupManager getInstance(Context context) { - PopupManager instance = sMap.get(context); - if (instance == null) { - instance = new PopupManager(); - sMap.put(context, instance); - } - return instance; - } - - public static void removeInstance(Context context) { - PopupManager instance = sMap.get(context); - sMap.remove(context); - } -} diff --git a/src/com/android/camera/ui/PreviewSurfaceView.java b/src/com/android/camera/ui/PreviewSurfaceView.java deleted file mode 100644 index 9a428e23c..000000000 --- a/src/com/android/camera/ui/PreviewSurfaceView.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.ViewGroup; - -import com.android.gallery3d.common.ApiHelper; - -public class PreviewSurfaceView extends SurfaceView { - public PreviewSurfaceView(Context context, AttributeSet attrs) { - super(context, attrs); - setZOrderMediaOverlay(true); - getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); - } - - public void shrink() { - setLayoutSize(1); - } - - public void expand() { - setLayoutSize(ViewGroup.LayoutParams.MATCH_PARENT); - } - - private void setLayoutSize(int size) { - ViewGroup.LayoutParams p = getLayoutParams(); - if (p.width != size || p.height != size) { - p.width = size; - p.height = size; - setLayoutParams(p); - } - } -} diff --git a/src/com/android/camera/ui/RenderOverlay.java b/src/com/android/camera/ui/RenderOverlay.java deleted file mode 100644 index d82ce18b6..000000000 --- a/src/com/android/camera/ui/RenderOverlay.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.graphics.Canvas; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.camera.PreviewGestures; - -import java.util.ArrayList; -import java.util.List; - -public class RenderOverlay extends FrameLayout { - - private static final String TAG = "CAM_Overlay"; - - interface Renderer { - - public boolean handlesTouch(); - public boolean onTouchEvent(MotionEvent evt); - public void setOverlay(RenderOverlay overlay); - public void layout(int left, int top, int right, int bottom); - public void draw(Canvas canvas); - - } - - private RenderView mRenderView; - private List<Renderer> mClients; - private PreviewGestures mGestures; - // reverse list of touch clients - private List<Renderer> mTouchClients; - private int[] mPosition = new int[2]; - - public RenderOverlay(Context context, AttributeSet attrs) { - super(context, attrs); - mRenderView = new RenderView(context); - addView(mRenderView, new LayoutParams(LayoutParams.MATCH_PARENT, - LayoutParams.MATCH_PARENT)); - mClients = new ArrayList<Renderer>(10); - mTouchClients = new ArrayList<Renderer>(10); - setWillNotDraw(false); - } - - public void setGestures(PreviewGestures gestures) { - mGestures = gestures; - } - - public void addRenderer(Renderer renderer) { - mClients.add(renderer); - renderer.setOverlay(this); - if (renderer.handlesTouch()) { - mTouchClients.add(0, renderer); - } - renderer.layout(getLeft(), getTop(), getRight(), getBottom()); - } - - public void addRenderer(int pos, Renderer renderer) { - mClients.add(pos, renderer); - renderer.setOverlay(this); - renderer.layout(getLeft(), getTop(), getRight(), getBottom()); - } - - public void remove(Renderer renderer) { - mClients.remove(renderer); - renderer.setOverlay(null); - } - - public int getClientSize() { - return mClients.size(); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent m) { - if (mGestures != null) { - if (!mGestures.isEnabled()) return false; - mGestures.dispatchTouch(m); - } - return true; - } - - public boolean directDispatchTouch(MotionEvent m, Renderer target) { - mRenderView.setTouchTarget(target); - boolean res = mRenderView.dispatchTouchEvent(m); - mRenderView.setTouchTarget(null); - return res; - } - - private void adjustPosition() { - getLocationInWindow(mPosition); - } - - public int getWindowPositionX() { - return mPosition[0]; - } - - public int getWindowPositionY() { - return mPosition[1]; - } - - public void update() { - mRenderView.invalidate(); - } - - private class RenderView extends View { - - private Renderer mTouchTarget; - - public RenderView(Context context) { - super(context); - setWillNotDraw(false); - } - - public void setTouchTarget(Renderer target) { - mTouchTarget = target; - } - - @Override - public boolean dispatchTouchEvent(MotionEvent evt) { - - if (mTouchTarget != null) { - return mTouchTarget.onTouchEvent(evt); - } - if (mTouchClients != null) { - boolean res = false; - for (Renderer client : mTouchClients) { - res |= client.onTouchEvent(evt); - } - return res; - } - return false; - } - - @Override - public void onLayout(boolean changed, int left, int top, int right, int bottom) { - adjustPosition(); - super.onLayout(changed, left, top, right, bottom); - if (mClients == null) return; - for (Renderer renderer : mClients) { - renderer.layout(left, top, right, bottom); - } - } - - @Override - public void draw(Canvas canvas) { - super.draw(canvas); - if (mClients == null) return; - boolean redraw = false; - for (Renderer renderer : mClients) { - renderer.draw(canvas); - redraw = redraw || ((OverlayRenderer) renderer).isVisible(); - } - if (redraw) { - invalidate(); - } - } - } - -} diff --git a/src/com/android/camera/ui/Rotatable.java b/src/com/android/camera/ui/Rotatable.java deleted file mode 100644 index 6d428b8c6..000000000 --- a/src/com/android/camera/ui/Rotatable.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -public interface Rotatable { - // Set parameter 'animation' to true to have animation when rotation. - public void setOrientation(int orientation, boolean animation); -} diff --git a/src/com/android/camera/ui/RotatableLayout.java b/src/com/android/camera/ui/RotatableLayout.java deleted file mode 100644 index 965d62a90..000000000 --- a/src/com/android/camera/ui/RotatableLayout.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2013 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.ui; - -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import com.android.camera.Util; - -/* RotatableLayout rotates itself as well as all its children when orientation - * changes. Specifically, when going from portrait to landscape, camera - * controls move from the bottom of the screen to right side of the screen - * (i.e. counter clockwise). Similarly, when the screen changes to portrait, we - * need to move the controls from right side to the bottom of the screen, which - * is a clockwise rotation. - */ - -public class RotatableLayout extends FrameLayout { - - private static final String TAG = "RotatableLayout"; - // Initial orientation of the layout (ORIENTATION_PORTRAIT, or ORIENTATION_LANDSCAPE) - private int mInitialOrientation; - private int mPrevRotation; - private RotationListener mListener = null; - public interface RotationListener { - public void onRotation(int rotation); - } - public RotatableLayout(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - mInitialOrientation = getResources().getConfiguration().orientation; - } - - public RotatableLayout(Context context, AttributeSet attrs) { - super(context, attrs); - mInitialOrientation = getResources().getConfiguration().orientation; - } - - public RotatableLayout(Context context) { - super(context); - mInitialOrientation = getResources().getConfiguration().orientation; - } - - @Override - public void onAttachedToWindow() { - mPrevRotation = Util.getDisplayRotation((Activity) getContext()); - // check if there is any rotation before the view is attached to window - int currentOrientation = getResources().getConfiguration().orientation; - int orientation = getUnifiedRotation(); - if (mInitialOrientation == currentOrientation && orientation < 180) { - return; - } - - if (mInitialOrientation == Configuration.ORIENTATION_LANDSCAPE - && currentOrientation == Configuration.ORIENTATION_PORTRAIT) { - rotateLayout(true); - } else if (mInitialOrientation == Configuration.ORIENTATION_PORTRAIT - && currentOrientation == Configuration.ORIENTATION_LANDSCAPE) { - rotateLayout(false); - } - // In reverse landscape and reverse portrait, camera controls will be laid out - // on the wrong side of the screen. We need to make adjustment to move the controls - // to the USB side - if (orientation >= 180) { - flipChildren(); - } - } - - protected int getUnifiedRotation() { - // all the layout code assumes camera device orientation to be portrait - // adjust rotation for landscape - int orientation = getResources().getConfiguration().orientation; - int rotation = Util.getDisplayRotation((Activity) getContext()); - int camOrientation = (rotation % 180 == 0) ? Configuration.ORIENTATION_PORTRAIT - : Configuration.ORIENTATION_LANDSCAPE; - if (camOrientation != orientation) { - return (rotation + 90) % 360; - } - return rotation; - } - - public void checkLayoutFlip() { - int currentRotation = Util.getDisplayRotation((Activity) getContext()); - if ((currentRotation - mPrevRotation + 360) % 360 == 180) { - mPrevRotation = currentRotation; - flipChildren(); - getParent().requestLayout(); - } - } - - @Override - public void onWindowVisibilityChanged(int visibility) { - if (visibility == View.VISIBLE) { - // Make sure when coming back from onPause, the layout is rotated correctly - checkLayoutFlip(); - } - } - - @Override - public void onConfigurationChanged(Configuration config) { - super.onConfigurationChanged(config); - int rotation = Util.getDisplayRotation((Activity) getContext()); - int diff = (rotation - mPrevRotation + 360) % 360; - if ( diff == 0) { - // No rotation - return; - } else if (diff == 180) { - // 180-degree rotation - mPrevRotation = rotation; - flipChildren(); - return; - } - // 90 or 270-degree rotation - boolean clockwise = isClockWiseRotation(mPrevRotation, rotation); - mPrevRotation = rotation; - rotateLayout(clockwise); - } - - protected void rotateLayout(boolean clockwise) { - // Change the size of the layout - ViewGroup.LayoutParams lp = getLayoutParams(); - int width = lp.width; - int height = lp.height; - lp.height = width; - lp.width = height; - setLayoutParams(lp); - - // rotate all the children - rotateChildren(clockwise); - } - - protected void rotateChildren(boolean clockwise) { - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - rotate(child, clockwise); - } - if (mListener != null) mListener.onRotation(clockwise ? 90 : 270); - } - - protected void flipChildren() { - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - flip(child); - } - if (mListener != null) mListener.onRotation(180); - } - - public void setRotationListener(RotationListener listener) { - mListener = listener; - } - - public static boolean isClockWiseRotation(int prevRotation, int currentRotation) { - if (prevRotation == (currentRotation + 90) % 360) { - return true; - } - return false; - } - - public static void rotate(View view, boolean isClockwise) { - if (isClockwise) { - rotateClockwise(view); - } else { - rotateCounterClockwise(view); - } - } - - private static boolean contains(int value, int mask) { - return (value & mask) == mask; - } - - public static void rotateClockwise(View view) { - if (view == null) return; - LayoutParams lp = (LayoutParams) view.getLayoutParams(); - int gravity = lp.gravity; - int ngravity = 0; - // rotate gravity - if (contains(gravity, Gravity.LEFT)) { - ngravity |= Gravity.TOP; - } - if (contains(gravity, Gravity.RIGHT)) { - ngravity |= Gravity.BOTTOM; - } - if (contains(gravity, Gravity.TOP)) { - ngravity |= Gravity.RIGHT; - } - if (contains(gravity, Gravity.BOTTOM)) { - ngravity |= Gravity.LEFT; - } - if (contains(gravity, Gravity.CENTER)) { - ngravity |= Gravity.CENTER; - } - if (contains(gravity, Gravity.CENTER_HORIZONTAL)) { - ngravity |= Gravity.CENTER_VERTICAL; - } - if (contains(gravity, Gravity.CENTER_VERTICAL)) { - ngravity |= Gravity.CENTER_HORIZONTAL; - } - lp.gravity = ngravity; - int ml = lp.leftMargin; - int mr = lp.rightMargin; - int mt = lp.topMargin; - int mb = lp.bottomMargin; - lp.leftMargin = mb; - lp.rightMargin = mt; - lp.topMargin = ml; - lp.bottomMargin = mr; - int width = lp.width; - int height = lp.height; - lp.width = height; - lp.height = width; - view.setLayoutParams(lp); - } - - public static void rotateCounterClockwise(View view) { - if (view == null) return; - LayoutParams lp = (LayoutParams) view.getLayoutParams(); - int gravity = lp.gravity; - int ngravity = 0; - // change gravity - if (contains(gravity, Gravity.RIGHT)) { - ngravity |= Gravity.TOP; - } - if (contains(gravity, Gravity.LEFT)) { - ngravity |= Gravity.BOTTOM; - } - if (contains(gravity, Gravity.TOP)) { - ngravity |= Gravity.LEFT; - } - if (contains(gravity, Gravity.BOTTOM)) { - ngravity |= Gravity.RIGHT; - } - if (contains(gravity, Gravity.CENTER)) { - ngravity |= Gravity.CENTER; - } - if (contains(gravity, Gravity.CENTER_HORIZONTAL)) { - ngravity |= Gravity.CENTER_VERTICAL; - } - if (contains(gravity, Gravity.CENTER_VERTICAL)) { - ngravity |= Gravity.CENTER_HORIZONTAL; - } - lp.gravity = ngravity; - int ml = lp.leftMargin; - int mr = lp.rightMargin; - int mt = lp.topMargin; - int mb = lp.bottomMargin; - lp.leftMargin = mt; - lp.rightMargin = mb; - lp.topMargin = mr; - lp.bottomMargin = ml; - int width = lp.width; - int height = lp.height; - lp.width = height; - lp.height = width; - view.setLayoutParams(lp); - } - - // Rotate a given view 180 degrees - public static void flip(View view) { - rotateClockwise(view); - rotateClockwise(view); - } -}
\ No newline at end of file diff --git a/src/com/android/camera/ui/RotateImageView.java b/src/com/android/camera/ui/RotateImageView.java deleted file mode 100644 index 05e1a7c5b..000000000 --- a/src/com/android/camera/ui/RotateImageView.java +++ /dev/null @@ -1,176 +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.ui; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.TransitionDrawable; -import android.media.ThumbnailUtils; -import android.util.AttributeSet; -import android.view.ViewGroup.LayoutParams; -import android.view.animation.AnimationUtils; -import android.widget.ImageView; - -/** - * A @{code ImageView} which can rotate it's content. - */ -public class RotateImageView extends TwoStateImageView implements Rotatable { - - @SuppressWarnings("unused") - private static final String TAG = "RotateImageView"; - - private static final int ANIMATION_SPEED = 270; // 270 deg/sec - - private int mCurrentDegree = 0; // [0, 359] - private int mStartDegree = 0; - private int mTargetDegree = 0; - - private boolean mClockwise = false, mEnableAnimation = true; - - private long mAnimationStartTime = 0; - private long mAnimationEndTime = 0; - - public RotateImageView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public RotateImageView(Context context) { - super(context); - } - - protected int getDegree() { - return mTargetDegree; - } - - // Rotate the view counter-clockwise - @Override - public void setOrientation(int degree, boolean animation) { - mEnableAnimation = animation; - // make sure in the range of [0, 359] - degree = degree >= 0 ? degree % 360 : degree % 360 + 360; - if (degree == mTargetDegree) return; - - mTargetDegree = degree; - if (mEnableAnimation) { - mStartDegree = mCurrentDegree; - mAnimationStartTime = AnimationUtils.currentAnimationTimeMillis(); - - int diff = mTargetDegree - mCurrentDegree; - diff = diff >= 0 ? diff : 360 + diff; // make it in range [0, 359] - - // Make it in range [-179, 180]. That's the shorted distance between the - // two angles - diff = diff > 180 ? diff - 360 : diff; - - mClockwise = diff >= 0; - mAnimationEndTime = mAnimationStartTime - + Math.abs(diff) * 1000 / ANIMATION_SPEED; - } else { - mCurrentDegree = mTargetDegree; - } - - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - Drawable drawable = getDrawable(); - if (drawable == null) return; - - Rect bounds = drawable.getBounds(); - int w = bounds.right - bounds.left; - int h = bounds.bottom - bounds.top; - - if (w == 0 || h == 0) return; // nothing to draw - - if (mCurrentDegree != mTargetDegree) { - long time = AnimationUtils.currentAnimationTimeMillis(); - if (time < mAnimationEndTime) { - int deltaTime = (int)(time - mAnimationStartTime); - int degree = mStartDegree + ANIMATION_SPEED - * (mClockwise ? deltaTime : -deltaTime) / 1000; - degree = degree >= 0 ? degree % 360 : degree % 360 + 360; - mCurrentDegree = degree; - invalidate(); - } else { - mCurrentDegree = mTargetDegree; - } - } - - int left = getPaddingLeft(); - int top = getPaddingTop(); - int right = getPaddingRight(); - int bottom = getPaddingBottom(); - int width = getWidth() - left - right; - int height = getHeight() - top - bottom; - - int saveCount = canvas.getSaveCount(); - - // Scale down the image first if required. - if ((getScaleType() == ImageView.ScaleType.FIT_CENTER) && - ((width < w) || (height < h))) { - float ratio = Math.min((float) width / w, (float) height / h); - canvas.scale(ratio, ratio, width / 2.0f, height / 2.0f); - } - canvas.translate(left + width / 2, top + height / 2); - canvas.rotate(-mCurrentDegree); - canvas.translate(-w / 2, -h / 2); - drawable.draw(canvas); - canvas.restoreToCount(saveCount); - } - - private Bitmap mThumb; - private Drawable[] mThumbs; - private TransitionDrawable mThumbTransition; - - public void setBitmap(Bitmap bitmap) { - // Make sure uri and original are consistently both null or both - // non-null. - if (bitmap == null) { - mThumb = null; - mThumbs = null; - setImageDrawable(null); - setVisibility(GONE); - return; - } - - LayoutParams param = getLayoutParams(); - final int miniThumbWidth = param.width - - getPaddingLeft() - getPaddingRight(); - final int miniThumbHeight = param.height - - getPaddingTop() - getPaddingBottom(); - mThumb = ThumbnailUtils.extractThumbnail( - bitmap, miniThumbWidth, miniThumbHeight); - Drawable drawable; - if (mThumbs == null || !mEnableAnimation) { - mThumbs = new Drawable[2]; - mThumbs[1] = new BitmapDrawable(getContext().getResources(), mThumb); - setImageDrawable(mThumbs[1]); - } else { - mThumbs[0] = mThumbs[1]; - mThumbs[1] = new BitmapDrawable(getContext().getResources(), mThumb); - mThumbTransition = new TransitionDrawable(mThumbs); - setImageDrawable(mThumbTransition); - mThumbTransition.startTransition(500); - } - setVisibility(VISIBLE); - } -} diff --git a/src/com/android/camera/ui/RotateLayout.java b/src/com/android/camera/ui/RotateLayout.java deleted file mode 100644 index 86f5c814d..000000000 --- a/src/com/android/camera/ui/RotateLayout.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2010 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.ui; - -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.MotionEventHelper; - -// A RotateLayout is designed to display a single item and provides the -// capabilities to rotate the item. -public class RotateLayout extends ViewGroup implements Rotatable { - @SuppressWarnings("unused") - private static final String TAG = "RotateLayout"; - private int mOrientation; - private Matrix mMatrix = new Matrix(); - protected View mChild; - - public RotateLayout(Context context, AttributeSet attrs) { - super(context, attrs); - // The transparent background here is a workaround of the render issue - // happened when the view is rotated as the device's orientation - // changed. The view looks fine in landscape. After rotation, the view - // is invisible. - setBackgroundResource(android.R.color.transparent); - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - protected void onFinishInflate() { - mChild = getChildAt(0); - if (ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES) { - mChild.setPivotX(0); - mChild.setPivotY(0); - } - } - - @Override - protected void onLayout( - boolean change, int left, int top, int right, int bottom) { - int width = right - left; - int height = bottom - top; - switch (mOrientation) { - case 0: - case 180: - mChild.layout(0, 0, width, height); - break; - case 90: - case 270: - mChild.layout(0, 0, height, width); - break; - } - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (!ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES) { - final int w = getMeasuredWidth(); - final int h = getMeasuredHeight(); - switch (mOrientation) { - case 0: - mMatrix.setTranslate(0, 0); - break; - case 90: - mMatrix.setTranslate(0, -h); - break; - case 180: - mMatrix.setTranslate(-w, -h); - break; - case 270: - mMatrix.setTranslate(-w, 0); - break; - } - mMatrix.postRotate(mOrientation); - event = MotionEventHelper.transformEvent(event, mMatrix); - } - return super.dispatchTouchEvent(event); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - if (ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES) { - super.dispatchDraw(canvas); - } else { - canvas.save(); - int w = getMeasuredWidth(); - int h = getMeasuredHeight(); - switch (mOrientation) { - case 0: - canvas.translate(0, 0); - break; - case 90: - canvas.translate(0, h); - break; - case 180: - canvas.translate(w, h); - break; - case 270: - canvas.translate(w, 0); - break; - } - canvas.rotate(-mOrientation, 0, 0); - super.dispatchDraw(canvas); - canvas.restore(); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - protected void onMeasure(int widthSpec, int heightSpec) { - int w = 0, h = 0; - switch(mOrientation) { - case 0: - case 180: - measureChild(mChild, widthSpec, heightSpec); - w = mChild.getMeasuredWidth(); - h = mChild.getMeasuredHeight(); - break; - case 90: - case 270: - measureChild(mChild, heightSpec, widthSpec); - w = mChild.getMeasuredHeight(); - h = mChild.getMeasuredWidth(); - break; - } - setMeasuredDimension(w, h); - - if (ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES) { - switch (mOrientation) { - case 0: - mChild.setTranslationX(0); - mChild.setTranslationY(0); - break; - case 90: - mChild.setTranslationX(0); - mChild.setTranslationY(h); - break; - case 180: - mChild.setTranslationX(w); - mChild.setTranslationY(h); - break; - case 270: - mChild.setTranslationX(w); - mChild.setTranslationY(0); - break; - } - mChild.setRotation(-mOrientation); - } - } - - @Override - public boolean shouldDelayChildPressedState() { - return false; - } - - // Rotate the view counter-clockwise - @Override - public void setOrientation(int orientation, boolean animation) { - orientation = orientation % 360; - if (mOrientation == orientation) return; - mOrientation = orientation; - requestLayout(); - } - - public int getOrientation() { - return mOrientation; - } - - @Override - public ViewParent invalidateChildInParent(int[] location, Rect r) { - if (!ApiHelper.HAS_VIEW_TRANSFORM_PROPERTIES && mOrientation != 0) { - // The workaround invalidates the entire rotate layout. After - // rotation, the correct area to invalidate may be larger than the - // size of the child. Ex: ListView. There is no way to invalidate - // only the necessary area. - r.set(0, 0, getWidth(), getHeight()); - } - return super.invalidateChildInParent(location, r); - } -} diff --git a/src/com/android/camera/ui/RotateTextToast.java b/src/com/android/camera/ui/RotateTextToast.java deleted file mode 100644 index c78a258b0..000000000 --- a/src/com/android/camera/ui/RotateTextToast.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.app.Activity; -import android.os.Handler; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import com.android.camera.Util; -import com.android.gallery3d.R; - -public class RotateTextToast { - private static final int TOAST_DURATION = 5000; // milliseconds - ViewGroup mLayoutRoot; - RotateLayout mToast; - Handler mHandler; - - public RotateTextToast(Activity activity, int textResourceId, int orientation) { - mLayoutRoot = (ViewGroup) activity.getWindow().getDecorView(); - LayoutInflater inflater = activity.getLayoutInflater(); - View v = inflater.inflate(R.layout.rotate_text_toast, mLayoutRoot); - mToast = (RotateLayout) v.findViewById(R.id.rotate_toast); - TextView tv = (TextView) mToast.findViewById(R.id.message); - tv.setText(textResourceId); - mToast.setOrientation(orientation, false); - mHandler = new Handler(); - } - - private final Runnable mRunnable = new Runnable() { - @Override - public void run() { - Util.fadeOut(mToast); - mLayoutRoot.removeView(mToast); - mToast = null; - } - }; - - public void show() { - mToast.setVisibility(View.VISIBLE); - mHandler.postDelayed(mRunnable, TOAST_DURATION); - } -} diff --git a/src/com/android/camera/ui/Switch.java b/src/com/android/camera/ui/Switch.java deleted file mode 100644 index ac21758a7..000000000 --- a/src/com/android/camera/ui/Switch.java +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.ViewConfiguration; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityNodeInfo; -import android.widget.CompoundButton; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.Arrays; - -/** - * A Switch is a two-state toggle switch widget that can select between two - * options. The user may drag the "thumb" back and forth to choose the selected option, - * or simply tap to toggle as if it were a checkbox. - */ -public class Switch extends CompoundButton { - private static final int TOUCH_MODE_IDLE = 0; - private static final int TOUCH_MODE_DOWN = 1; - private static final int TOUCH_MODE_DRAGGING = 2; - - private Drawable mThumbDrawable; - private Drawable mTrackDrawable; - private int mThumbTextPadding; - private int mSwitchMinWidth; - private int mSwitchTextMaxWidth; - private int mSwitchPadding; - private CharSequence mTextOn; - private CharSequence mTextOff; - - private int mTouchMode; - private int mTouchSlop; - private float mTouchX; - private float mTouchY; - private VelocityTracker mVelocityTracker = VelocityTracker.obtain(); - private int mMinFlingVelocity; - - private float mThumbPosition; - private int mSwitchWidth; - private int mSwitchHeight; - private int mThumbWidth; // Does not include padding - - private int mSwitchLeft; - private int mSwitchTop; - private int mSwitchRight; - private int mSwitchBottom; - - private TextPaint mTextPaint; - private ColorStateList mTextColors; - private Layout mOnLayout; - private Layout mOffLayout; - - @SuppressWarnings("hiding") - private final Rect mTempRect = new Rect(); - - private static final int[] CHECKED_STATE_SET = { - android.R.attr.state_checked - }; - - /** - * Construct a new Switch with default styling, overriding specific style - * attributes as requested. - * - * @param context The Context that will determine this widget's theming. - * @param attrs Specification of attributes that should deviate from default styling. - */ - public Switch(Context context, AttributeSet attrs) { - this(context, attrs, R.attr.switchStyle); - } - - /** - * Construct a new Switch with a default style determined by the given theme attribute, - * overriding specific style attributes as requested. - * - * @param context The Context that will determine this widget's theming. - * @param attrs Specification of attributes that should deviate from the default styling. - * @param defStyle An attribute ID within the active theme containing a reference to the - * default style for this widget. e.g. android.R.attr.switchStyle. - */ - public Switch(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - Resources res = getResources(); - DisplayMetrics dm = res.getDisplayMetrics(); - mTextPaint.density = dm.density; - mThumbDrawable = res.getDrawable(R.drawable.switch_inner_holo_dark); - mTrackDrawable = res.getDrawable(R.drawable.switch_track_holo_dark); - mTextOn = res.getString(R.string.capital_on); - mTextOff = res.getString(R.string.capital_off); - mThumbTextPadding = res.getDimensionPixelSize(R.dimen.thumb_text_padding); - mSwitchMinWidth = res.getDimensionPixelSize(R.dimen.switch_min_width); - mSwitchTextMaxWidth = res.getDimensionPixelSize(R.dimen.switch_text_max_width); - mSwitchPadding = res.getDimensionPixelSize(R.dimen.switch_padding); - setSwitchTextAppearance(context, android.R.style.TextAppearance_Holo_Small); - - ViewConfiguration config = ViewConfiguration.get(context); - mTouchSlop = config.getScaledTouchSlop(); - mMinFlingVelocity = config.getScaledMinimumFlingVelocity(); - - // Refresh display with current params - refreshDrawableState(); - setChecked(isChecked()); - } - - /** - * Sets the switch text color, size, style, hint color, and highlight color - * from the specified TextAppearance resource. - */ - public void setSwitchTextAppearance(Context context, int resid) { - Resources res = getResources(); - mTextColors = getTextColors(); - int ts = res.getDimensionPixelSize(R.dimen.thumb_text_size); - if (ts != mTextPaint.getTextSize()) { - mTextPaint.setTextSize(ts); - requestLayout(); - } - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - if (mOnLayout == null) { - mOnLayout = makeLayout(mTextOn, mSwitchTextMaxWidth); - } - if (mOffLayout == null) { - mOffLayout = makeLayout(mTextOff, mSwitchTextMaxWidth); - } - - mTrackDrawable.getPadding(mTempRect); - final int maxTextWidth = Math.min(mSwitchTextMaxWidth, - Math.max(mOnLayout.getWidth(), mOffLayout.getWidth())); - final int switchWidth = Math.max(mSwitchMinWidth, - maxTextWidth * 2 + mThumbTextPadding * 4 + mTempRect.left + mTempRect.right); - final int switchHeight = mTrackDrawable.getIntrinsicHeight(); - - mThumbWidth = maxTextWidth + mThumbTextPadding * 2; - - mSwitchWidth = switchWidth; - mSwitchHeight = switchHeight; - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - final int measuredHeight = getMeasuredHeight(); - final int measuredWidth = getMeasuredWidth(); - if (measuredHeight < switchHeight) { - setMeasuredDimension(measuredWidth, switchHeight); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public void onPopulateAccessibilityEvent(AccessibilityEvent event) { - super.onPopulateAccessibilityEvent(event); - CharSequence text = isChecked() ? mOnLayout.getText() : mOffLayout.getText(); - if (!TextUtils.isEmpty(text)) { - event.getText().add(text); - } - } - - private Layout makeLayout(CharSequence text, int maxWidth) { - int actual_width = (int) Math.ceil(Layout.getDesiredWidth(text, mTextPaint)); - StaticLayout l = new StaticLayout(text, 0, text.length(), mTextPaint, - actual_width, - Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true, - TextUtils.TruncateAt.END, - (int) Math.min(actual_width, maxWidth)); - return l; - } - - /** - * @return true if (x, y) is within the target area of the switch thumb - */ - private boolean hitThumb(float x, float y) { - mThumbDrawable.getPadding(mTempRect); - final int thumbTop = mSwitchTop - mTouchSlop; - final int thumbLeft = mSwitchLeft + (int) (mThumbPosition + 0.5f) - mTouchSlop; - final int thumbRight = thumbLeft + mThumbWidth + - mTempRect.left + mTempRect.right + mTouchSlop; - final int thumbBottom = mSwitchBottom + mTouchSlop; - return x > thumbLeft && x < thumbRight && y > thumbTop && y < thumbBottom; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - mVelocityTracker.addMovement(ev); - final int action = ev.getActionMasked(); - switch (action) { - case MotionEvent.ACTION_DOWN: { - final float x = ev.getX(); - final float y = ev.getY(); - if (isEnabled() && hitThumb(x, y)) { - mTouchMode = TOUCH_MODE_DOWN; - mTouchX = x; - mTouchY = y; - } - break; - } - - case MotionEvent.ACTION_MOVE: { - switch (mTouchMode) { - case TOUCH_MODE_IDLE: - // Didn't target the thumb, treat normally. - break; - - case TOUCH_MODE_DOWN: { - final float x = ev.getX(); - final float y = ev.getY(); - if (Math.abs(x - mTouchX) > mTouchSlop || - Math.abs(y - mTouchY) > mTouchSlop) { - mTouchMode = TOUCH_MODE_DRAGGING; - getParent().requestDisallowInterceptTouchEvent(true); - mTouchX = x; - mTouchY = y; - return true; - } - break; - } - - case TOUCH_MODE_DRAGGING: { - final float x = ev.getX(); - final float dx = x - mTouchX; - float newPos = Math.max(0, - Math.min(mThumbPosition + dx, getThumbScrollRange())); - if (newPos != mThumbPosition) { - mThumbPosition = newPos; - mTouchX = x; - invalidate(); - } - return true; - } - } - break; - } - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: { - if (mTouchMode == TOUCH_MODE_DRAGGING) { - stopDrag(ev); - return true; - } - mTouchMode = TOUCH_MODE_IDLE; - mVelocityTracker.clear(); - break; - } - } - - return super.onTouchEvent(ev); - } - - private void cancelSuperTouch(MotionEvent ev) { - MotionEvent cancel = MotionEvent.obtain(ev); - cancel.setAction(MotionEvent.ACTION_CANCEL); - super.onTouchEvent(cancel); - cancel.recycle(); - } - - /** - * Called from onTouchEvent to end a drag operation. - * - * @param ev Event that triggered the end of drag mode - ACTION_UP or ACTION_CANCEL - */ - private void stopDrag(MotionEvent ev) { - mTouchMode = TOUCH_MODE_IDLE; - // Up and not canceled, also checks the switch has not been disabled during the drag - boolean commitChange = ev.getAction() == MotionEvent.ACTION_UP && isEnabled(); - - cancelSuperTouch(ev); - - if (commitChange) { - boolean newState; - mVelocityTracker.computeCurrentVelocity(1000); - float xvel = mVelocityTracker.getXVelocity(); - if (Math.abs(xvel) > mMinFlingVelocity) { - newState = xvel > 0; - } else { - newState = getTargetCheckedState(); - } - animateThumbToCheckedState(newState); - } else { - animateThumbToCheckedState(isChecked()); - } - } - - private void animateThumbToCheckedState(boolean newCheckedState) { - setChecked(newCheckedState); - } - - private boolean getTargetCheckedState() { - return mThumbPosition >= getThumbScrollRange() / 2; - } - - private void setThumbPosition(boolean checked) { - mThumbPosition = checked ? getThumbScrollRange() : 0; - } - - @Override - public void setChecked(boolean checked) { - super.setChecked(checked); - setThumbPosition(checked); - invalidate(); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - setThumbPosition(isChecked()); - - int switchRight; - int switchLeft; - - switchRight = getWidth() - getPaddingRight(); - switchLeft = switchRight - mSwitchWidth; - - int switchTop = 0; - int switchBottom = 0; - switch (getGravity() & Gravity.VERTICAL_GRAVITY_MASK) { - default: - case Gravity.TOP: - switchTop = getPaddingTop(); - switchBottom = switchTop + mSwitchHeight; - break; - - case Gravity.CENTER_VERTICAL: - switchTop = (getPaddingTop() + getHeight() - getPaddingBottom()) / 2 - - mSwitchHeight / 2; - switchBottom = switchTop + mSwitchHeight; - break; - - case Gravity.BOTTOM: - switchBottom = getHeight() - getPaddingBottom(); - switchTop = switchBottom - mSwitchHeight; - break; - } - - mSwitchLeft = switchLeft; - mSwitchTop = switchTop; - mSwitchBottom = switchBottom; - mSwitchRight = switchRight; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - // Draw the switch - int switchLeft = mSwitchLeft; - int switchTop = mSwitchTop; - int switchRight = mSwitchRight; - int switchBottom = mSwitchBottom; - - mTrackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom); - mTrackDrawable.draw(canvas); - - canvas.save(); - - mTrackDrawable.getPadding(mTempRect); - int switchInnerLeft = switchLeft + mTempRect.left; - int switchInnerTop = switchTop + mTempRect.top; - int switchInnerRight = switchRight - mTempRect.right; - int switchInnerBottom = switchBottom - mTempRect.bottom; - canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom); - - mThumbDrawable.getPadding(mTempRect); - final int thumbPos = (int) (mThumbPosition + 0.5f); - int thumbLeft = switchInnerLeft - mTempRect.left + thumbPos; - int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + mTempRect.right; - - mThumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom); - mThumbDrawable.draw(canvas); - - // mTextColors should not be null, but just in case - if (mTextColors != null) { - mTextPaint.setColor(mTextColors.getColorForState(getDrawableState(), - mTextColors.getDefaultColor())); - } - mTextPaint.drawableState = getDrawableState(); - - Layout switchText = getTargetCheckedState() ? mOnLayout : mOffLayout; - - canvas.translate((thumbLeft + thumbRight) / 2 - switchText.getEllipsizedWidth() / 2, - (switchInnerTop + switchInnerBottom) / 2 - switchText.getHeight() / 2); - switchText.draw(canvas); - - canvas.restore(); - } - - @Override - public int getCompoundPaddingRight() { - int padding = super.getCompoundPaddingRight() + mSwitchWidth; - if (!TextUtils.isEmpty(getText())) { - padding += mSwitchPadding; - } - return padding; - } - - private int getThumbScrollRange() { - if (mTrackDrawable == null) { - return 0; - } - mTrackDrawable.getPadding(mTempRect); - return mSwitchWidth - mThumbWidth - mTempRect.left - mTempRect.right; - } - - @Override - protected int[] onCreateDrawableState(int extraSpace) { - final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); - - if (isChecked()) { - mergeDrawableStates(drawableState, CHECKED_STATE_SET); - } - return drawableState; - } - - @Override - protected void drawableStateChanged() { - super.drawableStateChanged(); - - int[] myDrawableState = getDrawableState(); - - // Set the state of the Drawable - // Drawable may be null when checked state is set from XML, from super constructor - if (mThumbDrawable != null) mThumbDrawable.setState(myDrawableState); - if (mTrackDrawable != null) mTrackDrawable.setState(myDrawableState); - - invalidate(); - } - - @Override - protected boolean verifyDrawable(Drawable who) { - return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable; - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - public void jumpDrawablesToCurrentState() { - super.jumpDrawablesToCurrentState(); - mThumbDrawable.jumpToCurrentState(); - mTrackDrawable.jumpToCurrentState(); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(event); - event.setClassName(Switch.class.getName()); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setClassName(Switch.class.getName()); - CharSequence switchText = isChecked() ? mTextOn : mTextOff; - if (!TextUtils.isEmpty(switchText)) { - CharSequence oldText = info.getText(); - if (TextUtils.isEmpty(oldText)) { - info.setText(switchText); - } else { - StringBuilder newText = new StringBuilder(); - newText.append(oldText).append(' ').append(switchText); - info.setText(newText); - } - } - } -} diff --git a/src/com/android/camera/ui/TimeIntervalPopup.java b/src/com/android/camera/ui/TimeIntervalPopup.java deleted file mode 100644 index 18ad9f5da..000000000 --- a/src/com/android/camera/ui/TimeIntervalPopup.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.camera.ui; - -import android.content.Context; -import android.content.res.Resources; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.Button; -import android.widget.CompoundButton; -import android.widget.NumberPicker; -import android.widget.Switch; -import android.widget.TextView; - -import com.android.camera.IconListPreference; -import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -/** - * This is a popup window that allows users to turn on/off time lapse feature, - * and to select a time interval for taking a time lapse video. - */ -public class TimeIntervalPopup extends AbstractSettingPopup { - private static final String TAG = "TimeIntervalPopup"; - private NumberPicker mNumberSpinner; - private NumberPicker mUnitSpinner; - private Switch mTimeLapseSwitch; - private final String[] mUnits; - private final String[] mDurations; - private IconListPreference mPreference; - private Listener mListener; - private Button mConfirmButton; - private TextView mHelpText; - private View mTimePicker; - - static public interface Listener { - public void onListPrefChanged(ListPreference pref); - } - - public void setSettingChangedListener(Listener listener) { - mListener = listener; - } - - public TimeIntervalPopup(Context context, AttributeSet attrs) { - super(context, attrs); - - Resources res = context.getResources(); - mUnits = res.getStringArray(R.array.pref_video_time_lapse_frame_interval_units); - mDurations = res - .getStringArray(R.array.pref_video_time_lapse_frame_interval_duration_values); - } - - public void initialize(IconListPreference preference) { - mPreference = preference; - - // Set title. - mTitle.setText(mPreference.getTitle()); - - // Duration - int durationCount = mDurations.length; - mNumberSpinner = (NumberPicker) findViewById(R.id.duration); - mNumberSpinner.setMinValue(0); - mNumberSpinner.setMaxValue(durationCount - 1); - mNumberSpinner.setDisplayedValues(mDurations); - mNumberSpinner.setWrapSelectorWheel(false); - - // Units for duration (i.e. seconds, minutes, etc) - mUnitSpinner = (NumberPicker) findViewById(R.id.duration_unit); - mUnitSpinner.setMinValue(0); - mUnitSpinner.setMaxValue(mUnits.length - 1); - mUnitSpinner.setDisplayedValues(mUnits); - mUnitSpinner.setWrapSelectorWheel(false); - - mTimePicker = findViewById(R.id.time_interval_picker); - mTimeLapseSwitch = (Switch) findViewById(R.id.time_lapse_switch); - mHelpText = (TextView) findViewById(R.id.set_time_interval_help_text); - mConfirmButton = (Button) findViewById(R.id.time_lapse_interval_set_button); - - // Disable focus on the spinners to prevent keyboard from coming up - mNumberSpinner.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); - mUnitSpinner.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); - - mTimeLapseSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - setTimeSelectionEnabled(isChecked); - } - }); - mConfirmButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - updateInputState(); - } - }); - } - - private void restoreSetting() { - int index = mPreference.findIndexOfValue(mPreference.getValue()); - if (index == -1) { - Log.e(TAG, "Invalid preference value."); - mPreference.print(); - throw new IllegalArgumentException(); - } else if (index == 0) { - // default choice: time lapse off - mTimeLapseSwitch.setChecked(false); - setTimeSelectionEnabled(false); - } else { - mTimeLapseSwitch.setChecked(true); - setTimeSelectionEnabled(true); - int durationCount = mNumberSpinner.getMaxValue() + 1; - int unit = (index - 1) / durationCount; - int number = (index - 1) % durationCount; - mUnitSpinner.setValue(unit); - mNumberSpinner.setValue(number); - } - } - - @Override - public void setVisibility(int visibility) { - if (visibility == View.VISIBLE) { - if (getVisibility() != View.VISIBLE) { - // Set the number pickers and on/off switch to be consistent - // with the preference - restoreSetting(); - } - } - super.setVisibility(visibility); - } - - protected void setTimeSelectionEnabled(boolean enabled) { - mHelpText.setVisibility(enabled ? GONE : VISIBLE); - mTimePicker.setVisibility(enabled ? VISIBLE : GONE); - } - - @Override - public void reloadPreference() { - } - - private void updateInputState() { - if (mTimeLapseSwitch.isChecked()) { - int newId = mUnitSpinner.getValue() * (mNumberSpinner.getMaxValue() + 1) - + mNumberSpinner.getValue() + 1; - mPreference.setValueIndex(newId); - } else { - mPreference.setValueIndex(0); - } - - if (mListener != null) { - mListener.onListPrefChanged(mPreference); - } - } -} diff --git a/src/com/android/camera/ui/TwoStateImageView.java b/src/com/android/camera/ui/TwoStateImageView.java deleted file mode 100644 index cd5b27fc1..000000000 --- a/src/com/android/camera/ui/TwoStateImageView.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.ImageView; - -/** - * A @{code ImageView} which change the opacity of the icon if disabled. - */ -public class TwoStateImageView extends ImageView { - private static final int ENABLED_ALPHA = 255; - private static final int DISABLED_ALPHA = (int) (255 * 0.4); - private boolean mFilterEnabled = true; - - public TwoStateImageView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public TwoStateImageView(Context context) { - this(context, null); - } - - @SuppressWarnings("deprecation") - @Override - public void setEnabled(boolean enabled) { - super.setEnabled(enabled); - if (mFilterEnabled) { - if (enabled) { - setAlpha(ENABLED_ALPHA); - } else { - setAlpha(DISABLED_ALPHA); - } - } - } - - public void enableFilter(boolean enabled) { - mFilterEnabled = enabled; - } -} diff --git a/src/com/android/camera/ui/ZoomRenderer.java b/src/com/android/camera/ui/ZoomRenderer.java deleted file mode 100644 index 86b82b459..000000000 --- a/src/com/android/camera/ui/ZoomRenderer.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Rect; -import android.view.ScaleGestureDetector; - -import com.android.gallery3d.R; - -public class ZoomRenderer extends OverlayRenderer - implements ScaleGestureDetector.OnScaleGestureListener { - - private static final String TAG = "CAM_Zoom"; - - private int mMaxZoom; - private int mMinZoom; - private OnZoomChangedListener mListener; - - private ScaleGestureDetector mDetector; - private Paint mPaint; - private Paint mTextPaint; - private int mCircleSize; - private int mCenterX; - private int mCenterY; - private float mMaxCircle; - private float mMinCircle; - private int mInnerStroke; - private int mOuterStroke; - private int mZoomSig; - private int mZoomFraction; - private Rect mTextBounds; - - public interface OnZoomChangedListener { - void onZoomStart(); - void onZoomEnd(); - void onZoomValueChanged(int index); // only for immediate zoom - } - - public ZoomRenderer(Context ctx) { - Resources res = ctx.getResources(); - mPaint = new Paint(); - mPaint.setAntiAlias(true); - mPaint.setColor(Color.WHITE); - mPaint.setStyle(Paint.Style.STROKE); - mTextPaint = new Paint(mPaint); - mTextPaint.setStyle(Paint.Style.FILL); - mTextPaint.setTextSize(res.getDimensionPixelSize(R.dimen.zoom_font_size)); - mTextPaint.setTextAlign(Paint.Align.LEFT); - mTextPaint.setAlpha(192); - mInnerStroke = res.getDimensionPixelSize(R.dimen.focus_inner_stroke); - mOuterStroke = res.getDimensionPixelSize(R.dimen.focus_outer_stroke); - mDetector = new ScaleGestureDetector(ctx, this); - mMinCircle = res.getDimensionPixelSize(R.dimen.zoom_ring_min); - mTextBounds = new Rect(); - setVisible(false); - } - - // set from module - public void setZoomMax(int zoomMaxIndex) { - mMaxZoom = zoomMaxIndex; - mMinZoom = 0; - } - - public void setZoom(int index) { - mCircleSize = (int) (mMinCircle + index * (mMaxCircle - mMinCircle) / (mMaxZoom - mMinZoom)); - } - - public void setZoomValue(int value) { - value = value / 10; - mZoomSig = value / 10; - mZoomFraction = value % 10; - } - - public void setOnZoomChangeListener(OnZoomChangedListener listener) { - mListener = listener; - } - - @Override - public void layout(int l, int t, int r, int b) { - super.layout(l, t, r, b); - mCenterX = (r - l) / 2; - mCenterY = (b - t) / 2; - mMaxCircle = Math.min(getWidth(), getHeight()); - mMaxCircle = (mMaxCircle - mMinCircle) / 2; - } - - public boolean isScaling() { - return mDetector.isInProgress(); - } - - @Override - public void onDraw(Canvas canvas) { - mPaint.setStrokeWidth(mInnerStroke); - canvas.drawCircle(mCenterX, mCenterY, mMinCircle, mPaint); - canvas.drawCircle(mCenterX, mCenterY, mMaxCircle, mPaint); - canvas.drawLine(mCenterX - mMinCircle, mCenterY, - mCenterX - mMaxCircle - 4, mCenterY, mPaint); - mPaint.setStrokeWidth(mOuterStroke); - canvas.drawCircle((float) mCenterX, (float) mCenterY, - (float) mCircleSize, mPaint); - String txt = mZoomSig+"."+mZoomFraction+"x"; - mTextPaint.getTextBounds(txt, 0, txt.length(), mTextBounds); - canvas.drawText(txt, mCenterX - mTextBounds.centerX(), mCenterY - mTextBounds.centerY(), - mTextPaint); - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - final float sf = detector.getScaleFactor(); - float circle = (int) (mCircleSize * sf * sf); - circle = Math.max(mMinCircle, circle); - circle = Math.min(mMaxCircle, circle); - if (mListener != null && (int) circle != mCircleSize) { - mCircleSize = (int) circle; - int zoom = mMinZoom + (int) ((mCircleSize - mMinCircle) * (mMaxZoom - mMinZoom) / (mMaxCircle - mMinCircle)); - mListener.onZoomValueChanged(zoom); - } - return true; - } - - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - setVisible(true); - if (mListener != null) { - mListener.onZoomStart(); - } - update(); - return true; - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - setVisible(false); - if (mListener != null) { - mListener.onZoomEnd(); - } - } - -} diff --git a/src/com/android/gallery3d/app/GalleryApp.java b/src/com/android/gallery3d/app/GalleryApp.java index b56b8a82c..98bf75b62 100644 --- a/src/com/android/gallery3d/app/GalleryApp.java +++ b/src/com/android/gallery3d/app/GalleryApp.java @@ -29,7 +29,6 @@ import com.android.gallery3d.util.ThreadPool; public interface GalleryApp { public DataManager getDataManager(); - public StitchingProgressManager getStitchingProgressManager(); public ImageCacheService getImageCacheService(); public DownloadCache getDownloadCache(); public ThreadPool getThreadPool(); diff --git a/src/com/android/gallery3d/app/GalleryAppImpl.java b/src/com/android/gallery3d/app/GalleryAppImpl.java index d080a0331..c6e7a0b57 100644 --- a/src/com/android/gallery3d/app/GalleryAppImpl.java +++ b/src/com/android/gallery3d/app/GalleryAppImpl.java @@ -42,22 +42,15 @@ public class GalleryAppImpl extends Application implements GalleryApp { private DataManager mDataManager; private ThreadPool mThreadPool; private DownloadCache mDownloadCache; - private StitchingProgressManager mStitchingProgressManager; @Override public void onCreate() { super.onCreate(); - com.android.camera.Util.initialize(this); initializeAsyncTask(); GalleryUtils.initialize(this); WidgetUtils.initialize(this); PicasaSource.initialize(this); UsageStatistics.initialize(this); - - mStitchingProgressManager = LightCycleHelper.createStitchingManagerInstance(this); - if (mStitchingProgressManager != null) { - mStitchingProgressManager.addChangeListener(getDataManager()); - } } @Override @@ -74,10 +67,6 @@ public class GalleryAppImpl extends Application implements GalleryApp { return mDataManager; } - @Override - public StitchingProgressManager getStitchingProgressManager() { - return mStitchingProgressManager; - } @Override public ImageCacheService getImageCacheService() { diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java index 7a71e9109..3c3738a60 100644 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ b/src/com/android/gallery3d/app/PhotoPage.java @@ -39,8 +39,6 @@ import android.widget.RelativeLayout; import android.widget.ShareActionProvider; import android.widget.Toast; -import com.android.camera.CameraActivity; -import com.android.camera.ProxyLauncher; import com.android.gallery3d.R; import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.data.ComboAlbum; @@ -88,7 +86,6 @@ public abstract class PhotoPage extends ActivityState implements private static final int MSG_ON_PICTURE_CENTER = 10; private static final int MSG_REFRESH_IMAGE = 11; private static final int MSG_UPDATE_PHOTO_UI = 12; - private static final int MSG_UPDATE_PROGRESS = 13; private static final int MSG_UPDATE_DEFERRED = 14; private static final int MSG_UPDATE_SHARE_URI = 15; private static final int MSG_UPDATE_PANORAMA_UI = 16; @@ -146,7 +143,6 @@ public abstract class PhotoPage extends ActivityState implements private boolean mIsMenuVisible; private boolean mHaveImageEditor; private PhotoPageBottomControls mBottomControls; - private PhotoPageProgressBar mProgressBar; private MediaItem mCurrentPhoto = null; private MenuExecutor mMenuExecutor; private boolean mIsActive; @@ -183,7 +179,6 @@ public abstract class PhotoPage extends ActivityState implements private final MyMenuVisibilityListener mMenuVisibilityListener = new MyMenuVisibilityListener(); - private UpdateProgressListener mProgressListener; private final PanoramaSupportCallback mUpdatePanoramaMenuItemsCallback = new PanoramaSupportCallback() { @Override @@ -233,33 +228,6 @@ public abstract class PhotoPage extends ActivityState implements } } - private class UpdateProgressListener implements StitchingChangeListener { - - @Override - public void onStitchingResult(Uri uri) { - sendUpdate(uri, MSG_REFRESH_IMAGE); - } - - @Override - public void onStitchingQueued(Uri uri) { - sendUpdate(uri, MSG_UPDATE_PROGRESS); - } - - @Override - public void onStitchingProgress(Uri uri, final int progress) { - sendUpdate(uri, MSG_UPDATE_PROGRESS); - } - - private void sendUpdate(Uri uri, int message) { - MediaObject currentPhoto = mCurrentPhoto; - boolean isCurrentPhoto = currentPhoto instanceof LocalImage - && currentPhoto.getContentUri().equals(uri); - if (isCurrentPhoto) { - mHandler.sendEmptyMessage(message); - } - } - }; - @Override protected int getBackgroundColorId() { return R.color.photo_background; @@ -379,10 +347,6 @@ public abstract class PhotoPage extends ActivityState implements updateUIForCurrentPhoto(); break; } - case MSG_UPDATE_PROGRESS: { - updateProgressBar(); - break; - } case MSG_UPDATE_SHARE_URI: { if (mCurrentPhoto == message.obj) { boolean isPanorama360 = message.arg1 != 0; @@ -577,15 +541,6 @@ public abstract class PhotoPage extends ActivityState implements if (mSecureAlbum == null) { mBottomControls = new PhotoPageBottomControls(this, mActivity, galleryRoot); } - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null) { - mProgressBar = new PhotoPageProgressBar(mActivity, galleryRoot); - mProgressListener = new UpdateProgressListener(); - progressManager.addChangeListener(mProgressListener); - if (mSecureAlbum != null) { - progressManager.addChangeListener(mSecureAlbum); - } - } } } @@ -696,10 +651,11 @@ public abstract class PhotoPage extends ActivityState implements } private void launchCamera() { - Intent intent = new Intent(mActivity, CameraActivity.class) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mRecenterCameraOnResume = false; - mActivity.startActivity(intent); + throw new RuntimeException("Not implemented yet."); +// Intent intent = new Intent(mActivity, CameraActivity.class) +// .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); +// mRecenterCameraOnResume = false; +// mActivity.startActivity(intent); } private void launchPhotoEditor() { @@ -774,7 +730,6 @@ public abstract class PhotoPage extends ActivityState implements && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_SHARE) != 0) { mCurrentPhoto.getPanoramaSupport(mUpdateShareURICallback); } - updateProgressBar(); } private void updateCurrentPhoto(MediaItem photo) { @@ -787,19 +742,6 @@ public abstract class PhotoPage extends ActivityState implements } } - private void updateProgressBar() { - if (mProgressBar != null) { - mProgressBar.hideProgress(); - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null && mCurrentPhoto instanceof LocalImage) { - Integer progress = progressManager.getProgress(mCurrentPhoto.getContentUri()); - if (progress != null) { - mProgressBar.setProgress(progress); - } - } - } - } - private void updateMenuOperations() { Menu menu = mActionBar.getMenu(); @@ -1016,10 +958,6 @@ public abstract class PhotoPage extends ActivityState implements onUpPressed(); } else { if (mOriginalSetPathString == null) return; - if (mProgressBar != null) { - updateCurrentPhoto(null); - mProgressBar.hideProgress(); - } Bundle data = new Bundle(getData()); data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString); data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, @@ -1295,10 +1233,6 @@ public abstract class PhotoPage extends ActivityState implements // This is a reset, not a canceled return; } - if (resultCode == ProxyLauncher.RESULT_USER_CANCELED) { - // Unmap reset vs. canceled - resultCode = Activity.RESULT_CANCELED; - } mRecenterCameraOnResume = false; switch (requestCode) { case REQUEST_EDIT: diff --git a/src/com/android/gallery3d/app/StateManager.java b/src/com/android/gallery3d/app/StateManager.java index 53c3fc228..aa372a824 100644 --- a/src/com/android/gallery3d/app/StateManager.java +++ b/src/com/android/gallery3d/app/StateManager.java @@ -24,7 +24,6 @@ import android.os.Parcelable; import android.view.Menu; import android.view.MenuItem; -import com.android.camera.CameraActivity; import com.android.gallery3d.anim.StateTransitionAnimation; import com.android.gallery3d.common.Utils; import com.android.gallery3d.util.UsageStatistics; diff --git a/src/com/android/gallery3d/data/Exif.java b/src/com/android/gallery3d/data/Exif.java index 950e7de18..20f072454 100644 --- a/src/com/android/gallery3d/data/Exif.java +++ b/src/com/android/gallery3d/data/Exif.java @@ -24,9 +24,11 @@ import java.io.IOException; import java.io.InputStream; public class Exif { - private static final String TAG = "CameraExif"; + private static final String TAG = "GalleryExif"; - // Returns the degrees in clockwise. Values are 0, 90, 180, or 270. + /** + * Returns the degrees in clockwise. Values are 0, 90, 180, or 270. + */ public static int getOrientation(InputStream is) { if (is == null) { return 0; @@ -45,4 +47,42 @@ public class Exif { return 0; } } + + /** + * Returns an exif interface instance for the given JPEG image. + * + * @param jpegData a valid JPEG image containing EXIF data + */ + public static ExifInterface getExif(byte[] jpegData) { + ExifInterface exif = new ExifInterface(); + try { + exif.readExif(jpegData); + } catch (IOException e) { + Log.w(TAG, "Failed to read EXIF data", e); + } + return exif; + } + + /** + * Returns the degrees in clockwise. Values are 0, 90, 180, or 270. + */ + public static int getOrientation(ExifInterface exif) { + Integer val = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION); + if (val == null) { + return 0; + } else { + return ExifInterface.getRotationForOrientationValue(val.shortValue()); + } + } + + /** + * See {@link #getOrientation(byte[])}, but using the picture bytes instead. + */ + public static int getOrientation(byte[] jpegData) { + if (jpegData == null) + return 0; + + ExifInterface exif = getExif(jpegData); + return getOrientation(exif); + } } diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java index cc70dd457..94cb05936 100644 --- a/src/com/android/gallery3d/data/LocalImage.java +++ b/src/com/android/gallery3d/data/LocalImage.java @@ -32,7 +32,6 @@ import android.util.Log; import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.app.PanoramaMetadataSupport; -import com.android.gallery3d.app.StitchingProgressManager; import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.common.BitmapUtils; import com.android.gallery3d.exif.ExifInterface; @@ -237,10 +236,6 @@ public class LocalImage extends LocalMediaItem { @Override public int getSupportedOperations() { - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null && progressManager.getProgress(getContentUri()) != null) { - return 0; // doesn't support anything while stitching! - } int operation = SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_CROP | SUPPORT_SETAS | SUPPORT_EDIT | SUPPORT_INFO; if (BitmapUtils.isSupportedByRegionDecoder(mimeType)) { diff --git a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java b/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java index 30868c22b..c6504a561 100644 --- a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java +++ b/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java @@ -24,7 +24,7 @@ import android.mtp.MtpObjectInfo; import android.util.DisplayMetrics; import android.view.WindowManager; -import com.android.camera.Exif; +import com.android.gallery3d.data.Exif; import com.android.photos.data.GalleryBitmapPool; public class MtpBitmapFetch { diff --git a/src/com/android/photos/GalleryActivity.java b/src/com/android/photos/GalleryActivity.java index 710767d77..f3279fe07 100644 --- a/src/com/android/photos/GalleryActivity.java +++ b/src/com/android/photos/GalleryActivity.java @@ -29,7 +29,6 @@ import android.view.Menu; import android.view.MenuItem; import android.view.ViewGroup; -import com.android.camera.CameraActivity; import com.android.gallery3d.R; import java.util.ArrayList; @@ -80,10 +79,12 @@ public class GalleryActivity extends Activity implements MultiChoiceManager.Prov public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_camera: - Intent intent = new Intent(this, CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - return true; + // TODO: Call the correct Camera intent. + throw new RuntimeException("Not implemented yet."); +// Intent intent = new Intent(this, CameraActivity.class); +// intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); +// startActivity(intent); +// return true; default: return super.onOptionsItemSelected(item); } diff --git a/src_pd/com/android/camera/PanoramaStitchingManager.java b/src_pd/com/android/camera/PanoramaStitchingManager.java deleted file mode 100644 index 5ba16b863..000000000 --- a/src_pd/com/android/camera/PanoramaStitchingManager.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2013 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.net.Uri; - -class PanoramaStitchingManager implements ImageTaskManager { - - public PanoramaStitchingManager(Context ctx) { - } - - @Override - public void addTaskListener(TaskListener l) { - // do nothing. - } - - @Override - public void removeTaskListener(TaskListener l) { - // do nothing. - } - - @Override - public int getTaskProgress(Uri uri) { - return -1; - } -} diff --git a/src_pd/com/android/gallery3d/util/LightCycleHelper.java b/src_pd/com/android/gallery3d/util/LightCycleHelper.java index 7ef7699df..350882463 100644 --- a/src_pd/com/android/gallery3d/util/LightCycleHelper.java +++ b/src_pd/com/android/gallery3d/util/LightCycleHelper.java @@ -18,13 +18,8 @@ package com.android.gallery3d.util; import android.content.ContentResolver; import android.content.Context; -import android.content.Intent; import android.net.Uri; -import com.android.camera.CameraModule; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.StitchingProgressManager; - public class LightCycleHelper { public static class PanoramaMetadata { // Whether a panorama viewer should be used @@ -40,26 +35,10 @@ public class LightCycleHelper { public static final PanoramaMetadata NOT_PANORAMA = new PanoramaMetadata(false, false); - public static void setupCaptureIntent(Context context, Intent it, String outputDir) { - /* Do nothing */ - } - - public static boolean hasLightCycleCapture(Context context) { - return false; - } - public static PanoramaMetadata getPanoramaMetadata(Context context, Uri uri) { return NOT_PANORAMA; } - public static CameraModule createPanoramaModule() { - return null; - } - - public static StitchingProgressManager createStitchingManagerInstance(GalleryApp app) { - return null; - } - /** * Get the file path from a Media storage URI. */ diff --git a/src_pd/com/android/gallery3d/util/RefocusHelper.java b/src_pd/com/android/gallery3d/util/RefocusHelper.java deleted file mode 100644 index 39ded4740..000000000 --- a/src_pd/com/android/gallery3d/util/RefocusHelper.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2013 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.gallery3d.util; - -import com.android.camera.CameraModule; - -public class RefocusHelper { - public static CameraModule createRefocusModule() { - return null; - } -} diff --git a/tests/src/com/android/gallery3d/CameraTestRunner.java b/tests/src/com/android/gallery3d/CameraTestRunner.java deleted file mode 100755 index 503233675..000000000 --- a/tests/src/com/android/gallery3d/CameraTestRunner.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d; - -import android.test.InstrumentationTestRunner; -import android.test.InstrumentationTestSuite; - -import com.android.gallery3d.functional.CameraTest; -import com.android.gallery3d.functional.ImageCaptureIntentTest; -import com.android.gallery3d.functional.VideoCaptureIntentTest; -import com.android.gallery3d.unittest.CameraUnitTest; - -import junit.framework.TestSuite; - - -public class CameraTestRunner extends InstrumentationTestRunner { - - @Override - public TestSuite getAllTests() { - TestSuite suite = new InstrumentationTestSuite(this); - suite.addTestSuite(CameraTest.class); - suite.addTestSuite(ImageCaptureIntentTest.class); - suite.addTestSuite(VideoCaptureIntentTest.class); - suite.addTestSuite(CameraUnitTest.class); - return suite; - } - - @Override - public ClassLoader getLoader() { - return CameraTestRunner.class.getClassLoader(); - } -} diff --git a/tests/src/com/android/gallery3d/StressTests.java b/tests/src/com/android/gallery3d/StressTests.java deleted file mode 100755 index b991e9e8d..000000000 --- a/tests/src/com/android/gallery3d/StressTests.java +++ /dev/null @@ -1,47 +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.gallery3d; - -import com.android.gallery3d.stress.CameraLatency; -import com.android.gallery3d.stress.CameraStartUp; -import com.android.gallery3d.stress.ImageCapture; -import com.android.gallery3d.stress.SwitchPreview; - -import junit.framework.Test; -import junit.framework.TestSuite; - - -/** - * Instrumentation Test Runner for all Camera tests. - * - * Running all tests: - * - * adb shell am instrument \ - * -e class com.android.gallery3d.StressTests \ - * -w com.google.android.gallery3d.tests/com.android.gallery3d.stress.CameraStressTestRunner - */ - -public class StressTests extends TestSuite { - public static Test suite() { - TestSuite result = new TestSuite(); - result.addTestSuite(CameraLatency.class); - result.addTestSuite(CameraStartUp.class); - result.addTestSuite(ImageCapture.class); -// result.addTestSuite(SwitchPreview.class); - return result; - } -} diff --git a/tests/src/com/android/gallery3d/data/GalleryAppStub.java b/tests/src/com/android/gallery3d/data/GalleryAppStub.java index 5aff2a2b2..47693d2d4 100644 --- a/tests/src/com/android/gallery3d/data/GalleryAppStub.java +++ b/tests/src/com/android/gallery3d/data/GalleryAppStub.java @@ -18,7 +18,6 @@ package com.android.gallery3d.data; import com.android.gallery3d.app.GalleryApp; import com.android.gallery3d.app.StateManager; -import com.android.gallery3d.app.StitchingProgressManager; import com.android.gallery3d.ui.GLRoot; import com.android.gallery3d.util.ThreadPool; @@ -43,5 +42,4 @@ class GalleryAppStub implements GalleryApp { public ContentResolver getContentResolver() { return null; } public ThreadPool getThreadPool() { return null; } public DownloadCache getDownloadCache() { return null; } - public StitchingProgressManager getStitchingProgressManager() { return null; } } diff --git a/tests/src/com/android/gallery3d/functional/CameraTest.java b/tests/src/com/android/gallery3d/functional/CameraTest.java deleted file mode 100644 index c293c0d4a..000000000 --- a/tests/src/com/android/gallery3d/functional/CameraTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2010 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.gallery3d.functional; - -import com.android.camera.CameraActivity; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Environment; -import android.os.Process; -import android.provider.MediaStore; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.LargeTest; - -import java.io.File; -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -public class CameraTest extends InstrumentationTestCase { - @LargeTest - public void testVideoCaptureIntentFdLeak() throws Exception { - Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://" - + Environment.getExternalStorageDirectory().toString() - + "test_fd_leak.3gp")); - getInstrumentation().startActivitySync(intent).finish(); - // Test if the fd is closed. - for (File f: new File("/proc/" + Process.myPid() + "/fd").listFiles()) { - assertEquals(-1, f.getCanonicalPath().indexOf("test_fd_leak.3gp")); - } - } - - @LargeTest - public void testActivityLeak() throws Exception { - checkActivityLeak(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); - checkActivityLeak(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - } - - private void checkActivityLeak(String action) throws Exception { - final int TEST_COUNT = 5; - Intent intent = new Intent(action); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setClass(getInstrumentation().getTargetContext(), - CameraActivity.class); - ArrayList<WeakReference<Activity>> refs = - new ArrayList<WeakReference<Activity>>(); - for (int i = 0; i < TEST_COUNT; i++) { - Activity activity = getInstrumentation().startActivitySync(intent); - refs.add(new WeakReference<Activity>(activity)); - activity.finish(); - getInstrumentation().waitForIdleSync(); - activity = null; - } - Runtime.getRuntime().gc(); - Runtime.getRuntime().runFinalization(); - Runtime.getRuntime().gc(); - int refCount = 0; - for (WeakReference<Activity> c: refs) { - if (c.get() != null) refCount++; - } - // If applications are leaking activity, every reference is reachable. - assertTrue(refCount != TEST_COUNT); - } -} diff --git a/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java b/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java deleted file mode 100644 index 8d394b5db..000000000 --- a/tests/src/com/android/gallery3d/functional/ImageCaptureIntentTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.functional; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.R; - -import android.app.Activity; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.view.KeyEvent; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; - -public class ImageCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> { - private Intent mIntent; - - public ImageCaptureIntentTest() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - } - - @LargeTest - public void testNoExtraOutput() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - takePicture(); - pressDone(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_OK, getActivity().getResultCode()); - Intent resultData = getActivity().getResultData(); - Bitmap bitmap = (Bitmap) resultData.getParcelableExtra("data"); - assertNotNull(bitmap); - assertTrue(bitmap.getWidth() > 0); - assertTrue(bitmap.getHeight() > 0); - } - - @LargeTest - public void testExtraOutput() throws Exception { - File file = new File(Environment.getExternalStorageDirectory(), - "test.jpg"); - BufferedInputStream stream = null; - byte[] jpegData; - - try { - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); - setActivityIntent(mIntent); - getActivity(); - - takePicture(); - pressDone(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_OK, getActivity().getResultCode()); - - // Verify the jpeg file - int fileLength = (int) file.length(); - assertTrue(fileLength > 0); - jpegData = new byte[fileLength]; - stream = new BufferedInputStream(new FileInputStream(file)); - stream.read(jpegData); - } finally { - if (stream != null) stream.close(); - file.delete(); - } - - Bitmap b = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length); - assertTrue(b.getWidth() > 0); - assertTrue(b.getHeight() > 0); - } - - @LargeTest - public void testCancel() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - pressCancel(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); - } - - @LargeTest - public void testSnapshotCancel() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - takePicture(); - pressCancel(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); - } - - private void takePicture() throws Exception { - getInstrumentation().sendKeySync( - new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS)); - getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - Thread.sleep(4000); - } - - private void pressDone() { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - getActivity().findViewById(R.id.btn_done).performClick(); - } - }); - } - - private void pressCancel() { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - getActivity().findViewById(R.id.btn_cancel).performClick(); - } - }); - } -} diff --git a/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java b/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java deleted file mode 100644 index c8d7bbb1c..000000000 --- a/tests/src/com/android/gallery3d/functional/VideoCaptureIntentTest.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.functional; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.R; - -import android.app.Activity; -import android.content.ContentResolver; -import android.content.Intent; -import android.database.Cursor; -import android.media.MediaMetadataRetriever; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.provider.MediaStore.Video.VideoColumns; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; - -import java.io.File; - -public class VideoCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> { - private static final String TAG = "VideoCaptureIntentTest"; - private Intent mIntent; - private Uri mVideoUri; - private File mFile, mFile2; - - public VideoCaptureIntentTest() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); - } - - @Override - protected void tearDown() throws Exception { - if (mVideoUri != null) { - ContentResolver resolver = getActivity().getContentResolver(); - Uri query = mVideoUri.buildUpon().build(); - String[] projection = new String[] {VideoColumns.DATA}; - - Cursor cursor = null; - try { - cursor = resolver.query(query, projection, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - new File(cursor.getString(0)).delete(); - } - } finally { - if (cursor != null) cursor.close(); - } - - resolver.delete(mVideoUri, null, null); - } - if (mFile != null) mFile.delete(); - if (mFile2 != null) mFile2.delete(); - super.tearDown(); - } - - @LargeTest - public void testNoExtraOutput() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressDone(); - - Intent resultData = getActivity().getResultData(); - mVideoUri = resultData.getData(); - assertNotNull(mVideoUri); - verify(getActivity(), mVideoUri); - } - - @LargeTest - public void testExtraOutput() throws Exception { - mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); - - Uri uri = Uri.fromFile(mFile); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressDone(); - - verify(getActivity(), uri); - } - - @LargeTest - public void testCancel() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - pressCancel(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); - } - - @LargeTest - public void testRecordCancel() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressCancel(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); - } - - @LargeTest - public void testExtraSizeLimit() throws Exception { - mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); - final long sizeLimit = 500000; // bytes - - Uri uri = Uri.fromFile(mFile); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, sizeLimit); - mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // use low quality to speed up - setActivityIntent(mIntent); - getActivity(); - - recordVideo(5000); - pressDone(); - - verify(getActivity(), uri); - long length = mFile.length(); - Log.v(TAG, "Video size is " + length + " bytes."); - assertTrue(length > 0); - assertTrue("Actual size=" + length, length <= sizeLimit); - } - - @LargeTest - public void testExtraDurationLimit() throws Exception { - mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); - final int durationLimit = 2; // seconds - - Uri uri = Uri.fromFile(mFile); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationLimit); - setActivityIntent(mIntent); - getActivity(); - - recordVideo(5000); - pressDone(); - - int duration = verify(getActivity(), uri); - // The duraion should be close to to the limit. The last video duration - // also has duration, so the total duration may exceeds the limit a - // little bit. - Log.v(TAG, "Video length is " + duration + " ms."); - assertTrue(duration < (durationLimit + 1) * 1000); - } - - @LargeTest - public void testExtraVideoQuality() throws Exception { - mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); - mFile2 = new File(Environment.getExternalStorageDirectory(), "video2.tmp"); - - Uri uri = Uri.fromFile(mFile); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // low quality - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressDone(); - - verify(getActivity(), uri); - setActivity(null); - - uri = Uri.fromFile(mFile2); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // high quality - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressDone(); - - verify(getActivity(), uri); - assertTrue(mFile.length() <= mFile2.length()); - } - - // Verify result code, result data, and the duration. - private int verify(CameraActivity activity, Uri uri) throws Exception { - assertTrue(activity.isFinishing()); - assertEquals(Activity.RESULT_OK, activity.getResultCode()); - - // Verify the video file - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setDataSource(activity, uri); - String duration = retriever.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_DURATION); - assertNotNull(duration); - int durationValue = Integer.parseInt(duration); - Log.v(TAG, "Video duration is " + durationValue); - assertTrue(durationValue > 0); - return durationValue; - } - - private void recordVideo(int ms) throws Exception { - getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - Thread.sleep(ms); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - // If recording is in progress, stop it. Run these atomically in - // UI thread. - CameraActivity activity = getActivity(); - if (activity.isRecording()) { - activity.findViewById(R.id.shutter_button).performClick(); - } - } - }); - } - - private void recordVideo() throws Exception { - recordVideo(2000); - } - - private void pressDone() { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - getActivity().findViewById(R.id.btn_done).performClick(); - } - }); - } - - private void pressCancel() { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - getActivity().findViewById(R.id.btn_cancel).performClick(); - } - }); - } -} diff --git a/tests/src/com/android/gallery3d/stress/CameraLatency.java b/tests/src/com/android/gallery3d/stress/CameraLatency.java deleted file mode 100755 index 2cdc2f1b7..000000000 --- a/tests/src/com/android/gallery3d/stress/CameraLatency.java +++ /dev/null @@ -1,148 +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.gallery3d.stress; - -import com.android.camera.CameraActivity; - -import android.app.Instrumentation; -import android.os.Environment; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; - -import java.io.BufferedWriter; -import java.io.FileWriter; - -/** - * Junit / Instrumentation test case for camera test - * - */ - -public class CameraLatency extends ActivityInstrumentationTestCase2 <CameraActivity> { - private String TAG = "CameraLatency"; - private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 20; - private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 4000; - private static final String CAMERA_TEST_OUTPUT_FILE = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - - private long mTotalAutoFocusTime; - private long mTotalShutterLag; - private long mTotalShutterToPictureDisplayedTime; - private long mTotalPictureDisplayedToJpegCallbackTime; - private long mTotalJpegCallbackFinishTime; - private long mAvgAutoFocusTime; - private long mAvgShutterLag = mTotalShutterLag; - private long mAvgShutterToPictureDisplayedTime; - private long mAvgPictureDisplayedToJpegCallbackTime; - private long mAvgJpegCallbackFinishTime; - - public CameraLatency() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - getActivity(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - public void testImageCapture() { - Log.v(TAG, "start testImageCapture test"); - Instrumentation inst = getInstrumentation(); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); - try { - for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) { - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - //skip the first measurement - if (i != 0) { - CameraActivity c = getActivity(); - - // if any of the latency var accessor methods return -1 then the - // camera is set to a different module other than PhotoModule so - // skip the shot and try again - if (c.getAutoFocusTime() != -1) { - mTotalAutoFocusTime += c.getAutoFocusTime(); - mTotalShutterLag += c.getShutterLag(); - mTotalShutterToPictureDisplayedTime += - c.getShutterToPictureDisplayedTime(); - mTotalPictureDisplayedToJpegCallbackTime += - c.getPictureDisplayedToJpegCallbackTime(); - mTotalJpegCallbackFinishTime += c.getJpegCallbackFinishTime(); - } - else { - i--; - continue; - } - } - } - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - } - //ToDO: yslau - //1) Need to get the baseline from the cupcake so that we can add the - //failure condition of the camera latency. - //2) Only count those number with succesful capture. Set the timer to invalid - //before capture and ignore them if the value is invalid - int numberofRun = TOTAL_NUMBER_OF_IMAGECAPTURE - 1; - mAvgAutoFocusTime = mTotalAutoFocusTime / numberofRun; - mAvgShutterLag = mTotalShutterLag / numberofRun; - mAvgShutterToPictureDisplayedTime = - mTotalShutterToPictureDisplayedTime / numberofRun; - mAvgPictureDisplayedToJpegCallbackTime = - mTotalPictureDisplayedToJpegCallbackTime / numberofRun; - mAvgJpegCallbackFinishTime = - mTotalJpegCallbackFinishTime / numberofRun; - - try { - FileWriter fstream = null; - fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); - BufferedWriter out = new BufferedWriter(fstream); - out.write("Camera Latency : \n"); - out.write("Number of loop: " + TOTAL_NUMBER_OF_IMAGECAPTURE + "\n"); - out.write("Avg AutoFocus = " + mAvgAutoFocusTime + "\n"); - out.write("Avg mShutterLag = " + mAvgShutterLag + "\n"); - out.write("Avg mShutterToPictureDisplayedTime = " - + mAvgShutterToPictureDisplayedTime + "\n"); - out.write("Avg mPictureDisplayedToJpegCallbackTime = " - + mAvgPictureDisplayedToJpegCallbackTime + "\n"); - out.write("Avg mJpegCallbackFinishTime = " + - mAvgJpegCallbackFinishTime + "\n"); - out.close(); - fstream.close(); - } catch (Exception e) { - fail("Camera Latency write output to file"); - } - Log.v(TAG, "The Image capture wait time = " + - WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - Log.v(TAG, "Avg AutoFocus = " + mAvgAutoFocusTime); - Log.v(TAG, "Avg mShutterLag = " + mAvgShutterLag); - Log.v(TAG, "Avg mShutterToPictureDisplayedTime = " - + mAvgShutterToPictureDisplayedTime); - Log.v(TAG, "Avg mPictureDisplayedToJpegCallbackTime = " - + mAvgPictureDisplayedToJpegCallbackTime); - Log.v(TAG, "Avg mJpegCallbackFinishTime = " + mAvgJpegCallbackFinishTime); - } -} - diff --git a/tests/src/com/android/gallery3d/stress/CameraStartUp.java b/tests/src/com/android/gallery3d/stress/CameraStartUp.java deleted file mode 100644 index 3ca163227..000000000 --- a/tests/src/com/android/gallery3d/stress/CameraStartUp.java +++ /dev/null @@ -1,155 +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.gallery3d.stress; - -import com.android.camera.CameraActivity; - -import android.app.Activity; -import android.app.Instrumentation; -import android.content.Intent; -import android.os.Environment; -import android.provider.MediaStore; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; - -import java.io.FileWriter; -import java.io.BufferedWriter; - -/** - * Test cases to measure the camera and video recorder startup time. - */ -public class CameraStartUp extends InstrumentationTestCase { - - private static final int TOTAL_NUMBER_OF_STARTUP = 20; - - private String TAG = "CameraStartUp"; - private static final String CAMERA_TEST_OUTPUT_FILE = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - private static int WAIT_TIME_FOR_PREVIEW = 1500; //1.5 second - - private long launchCamera() { - long startupTime = 0; - try { - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - long beforeStart = System.currentTimeMillis(); - Instrumentation inst = getInstrumentation(); - Activity cameraActivity = inst.startActivitySync(intent); - long cameraStarted = System.currentTimeMillis(); - Thread.sleep(WAIT_TIME_FOR_PREVIEW); - cameraActivity.finish(); - startupTime = cameraStarted - beforeStart; - Thread.sleep(1000); - Log.v(TAG, "camera startup time: " + startupTime); - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - fail("Fails to get the output file"); - } - return startupTime; - } - - private long launchVideo() { - long startupTime = 0; - - try { - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - long beforeStart = System.currentTimeMillis(); - Instrumentation inst = getInstrumentation(); - Activity recorderActivity = inst.startActivitySync(intent); - long cameraStarted = System.currentTimeMillis(); - recorderActivity.finish(); - startupTime = cameraStarted - beforeStart; - Log.v(TAG, "Video Startup Time = " + startupTime); - // wait for 1s to make sure it reach a clean stage - Thread.sleep(WAIT_TIME_FOR_PREVIEW); - Log.v(TAG, "video startup time: " + startupTime); - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - fail("Fails to launch video output file"); - } - return startupTime; - } - - private void writeToOutputFile(long totalStartupTime, - String individualStartupTime, boolean firstStartUp, String Type) throws Exception { - // TODO (yslau) : Need to integrate the output data with central - // dashboard - try { - FileWriter fstream = null; - fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); - BufferedWriter out = new BufferedWriter(fstream); - if (firstStartUp) { - out.write("First " + Type + " Startup: " + totalStartupTime + "\n"); - } else { - long averageStartupTime = totalStartupTime / (TOTAL_NUMBER_OF_STARTUP -1); - out.write(Type + "startup time: " + "\n"); - out.write("Number of loop: " + (TOTAL_NUMBER_OF_STARTUP -1) + "\n"); - out.write(individualStartupTime + "\n\n"); - out.write(Type + " average startup time: " + averageStartupTime + " ms\n\n"); - } - out.close(); - fstream.close(); - } catch (Exception e) { - fail("Camera write output to file"); - } - } - - public void testLaunchVideo() throws Exception { - String individualStartupTime; - individualStartupTime = "Individual Video Startup Time = "; - long totalStartupTime = 0; - long startupTime = 0; - for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) { - if (i == 0) { - // Capture the first startup time individually - long firstStartUpTime = launchVideo(); - writeToOutputFile(firstStartUpTime, "na", true, "Video"); - } else { - startupTime = launchVideo(); - totalStartupTime += startupTime; - individualStartupTime += startupTime + " ,"; - } - } - Log.v(TAG, "totalStartupTime =" + totalStartupTime); - writeToOutputFile(totalStartupTime, individualStartupTime, false, "Video"); - } - - public void testLaunchCamera() throws Exception { - String individualStartupTime; - individualStartupTime = "Individual Camera Startup Time = "; - long totalStartupTime = 0; - long startupTime = 0; - for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) { - if (i == 0) { - // Capture the first startup time individually - long firstStartUpTime = launchCamera(); - writeToOutputFile(firstStartUpTime, "na", true, "Camera"); - } else { - startupTime = launchCamera(); - totalStartupTime += startupTime; - individualStartupTime += startupTime + " ,"; - } - } - Log.v(TAG, "totalStartupTime =" + totalStartupTime); - writeToOutputFile(totalStartupTime, - individualStartupTime, false, "Camera"); - } -} diff --git a/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java b/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java deleted file mode 100755 index d3fb10dad..000000000 --- a/tests/src/com/android/gallery3d/stress/CameraStressTestRunner.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2010 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.gallery3d.stress; - -import android.os.Bundle; -import android.test.InstrumentationTestRunner; -import android.test.InstrumentationTestSuite; -import junit.framework.TestSuite; - -public class CameraStressTestRunner extends InstrumentationTestRunner { - - // Default recorder settings - public static int mVideoDuration = 20000; // set default to 20 seconds - public static int mVideoIterations = 1; // set default to 1 video - public static int mImageIterations = 10; // set default to 10 images - - @Override - public TestSuite getAllTests() { - TestSuite suite = new InstrumentationTestSuite(this); - suite.addTestSuite(ImageCapture.class); - suite.addTestSuite(VideoCapture.class); - return suite; - } - - @Override - public ClassLoader getLoader() { - return CameraStressTestRunner.class.getClassLoader(); - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - String video_iterations = (String) icicle.get("video_iterations"); - String image_iterations = (String) icicle.get("image_iterations"); - String video_duration = (String) icicle.get("video_duration"); - - if ( video_iterations != null ) { - mVideoIterations = Integer.parseInt(video_iterations); - } - if ( image_iterations != null) { - mImageIterations = Integer.parseInt(image_iterations); - } - if ( video_duration != null) { - mVideoDuration = Integer.parseInt(video_duration); - } - } -} diff --git a/tests/src/com/android/gallery3d/stress/ImageCapture.java b/tests/src/com/android/gallery3d/stress/ImageCapture.java deleted file mode 100755 index 5a9ee6a6c..000000000 --- a/tests/src/com/android/gallery3d/stress/ImageCapture.java +++ /dev/null @@ -1,119 +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.gallery3d.stress; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.stress.CameraStressTestRunner; - -import android.app.Instrumentation; -import android.content.Intent; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; -import android.app.Activity; - -/** - * Junit / Instrumentation test case for camera test - * - * Running the test suite: - * - * adb shell am instrument \ - * -e class com.android.camera.stress.ImageCapture \ - * -w com.google.android.camera.tests/android.test.InstrumentationTestRunner - * - */ - -public class ImageCapture extends ActivityInstrumentationTestCase2 <CameraActivity> { - private String TAG = "ImageCapture"; - private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1500; //1.5 sedconds - private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //3 seconds - - private TestUtil testUtil = new TestUtil(); - - // Private intent extras. - private final static String EXTRAS_CAMERA_FACING = - "android.intent.extras.CAMERA_FACING"; - - public ImageCapture() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - testUtil.prepareOutputFile(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - testUtil.closeOutputFile(); - super.tearDown(); - } - - public void captureImages(String reportTag, Instrumentation inst) { - int total_num_of_images = CameraStressTestRunner.mImageIterations; - Log.v(TAG, "no of images = " + total_num_of_images); - - //TODO(yslau): Need to integrate the outoput with the central dashboard, - //write to a txt file as a temp solution - boolean memoryResult = false; - KeyEvent focusEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS); - - try { - testUtil.writeReportHeader(reportTag, total_num_of_images); - for (int i = 0; i < total_num_of_images; i++) { - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - inst.sendKeySync(focusEvent); - inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - testUtil.writeResult(i); - } - } catch (Exception e) { - Log.v(TAG, "Got exception: " + e.toString()); - assertTrue("testImageCapture", false); - } - } - - public void testBackImageCapture() throws Exception { - Instrumentation inst = getInstrumentation(); - Intent intent = new Intent(); - - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(EXTRAS_CAMERA_FACING, - android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); - Activity act = inst.startActivitySync(intent); - Thread.sleep(WAIT_FOR_SWITCH_CAMERA); - captureImages("Back Camera Image Capture\n", inst); - act.finish(); - } - - public void testFrontImageCapture() throws Exception { - Instrumentation inst = getInstrumentation(); - Intent intent = new Intent(); - - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(EXTRAS_CAMERA_FACING, - android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); - Activity act = inst.startActivitySync(intent); - Thread.sleep(WAIT_FOR_SWITCH_CAMERA); - captureImages("Front Camera Image Capture\n", inst); - act.finish(); - } -} diff --git a/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java b/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java deleted file mode 100644 index 0d5749e7d..000000000 --- a/tests/src/com/android/gallery3d/stress/ShotToShotLatency.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.stress; - -import android.app.Instrumentation; -import android.os.Environment; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; -import com.android.camera.CameraActivity; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FilenameFilter; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; - -/** - * Junit / Instrumentation test case for measuring camera shot to shot latency - */ -public class ShotToShotLatency extends ActivityInstrumentationTestCase2<CameraActivity> { - private String TAG = "ShotToShotLatency"; - private static final int TOTAL_NUMBER_OF_SNAPSHOTS = 250; - private static final long SNAPSHOT_WAIT = 1000; - private static final String CAMERA_TEST_OUTPUT_FILE = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - private static final String CAMERA_IMAGE_DIRECTORY = - Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/"; - - public ShotToShotLatency() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - getActivity(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - private void cleanupLatencyImages() { - try { - File sdcard = new File(CAMERA_IMAGE_DIRECTORY); - File[] pics = null; - FilenameFilter filter = new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.endsWith(".jpg"); - } - }; - pics = sdcard.listFiles(filter); - for (File f : pics) { - f.delete(); - } - } catch (SecurityException e) { - Log.e(TAG, "Security manager access violation: " + e.toString()); - } - } - - private void sleep(long time) { - try { - Thread.sleep(time); - } catch (InterruptedException e) { - Log.e(TAG, "Sleep InterruptedException " + e.toString()); - } - } - - public void testShotToShotLatency() { - long sigmaOfDiffFromMeanSquared = 0; - double mean = 0; - double standardDeviation = 0; - ArrayList<Long> captureTimes = new ArrayList<Long>(); - ArrayList<Long> latencyTimes = new ArrayList<Long>(); - - Log.v(TAG, "start testShotToShotLatency test"); - Instrumentation inst = getInstrumentation(); - - // Generate data points - for (int i = 0; i < TOTAL_NUMBER_OF_SNAPSHOTS; i++) { - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); - sleep(SNAPSHOT_WAIT); - CameraActivity c = getActivity(); - if (c.getCaptureStartTime() > 0) { - captureTimes.add(c.getCaptureStartTime()); - } - } - - // Calculate latencies - for (int j = 1; j < captureTimes.size(); j++) { - latencyTimes.add(captureTimes.get(j) - captureTimes.get(j - 1)); - } - - // Crunch numbers - for (long dataPoint : latencyTimes) { - mean += (double) dataPoint; - } - mean /= latencyTimes.size(); - - for (long dataPoint : latencyTimes) { - sigmaOfDiffFromMeanSquared += (dataPoint - mean) * (dataPoint - mean); - } - standardDeviation = Math.sqrt(sigmaOfDiffFromMeanSquared / latencyTimes.size()); - - // Report statistics - File outFile = new File(CAMERA_TEST_OUTPUT_FILE); - BufferedWriter output = null; - try { - output = new BufferedWriter(new FileWriter(outFile, true)); - output.write("Shot to shot latency - mean: " + mean + "\n"); - output.write("Shot to shot latency - standard deviation: " + standardDeviation + "\n"); - cleanupLatencyImages(); - } catch (IOException e) { - Log.e(TAG, "testShotToShotLatency IOException writing to log " + e.toString()); - } finally { - try { - if (output != null) { - output.close(); - } - } catch (IOException e) { - Log.e(TAG, "Error closing file: " + e.toString()); - } - } - } -} diff --git a/tests/src/com/android/gallery3d/stress/SwitchPreview.java b/tests/src/com/android/gallery3d/stress/SwitchPreview.java deleted file mode 100755 index 3545f3b3e..000000000 --- a/tests/src/com/android/gallery3d/stress/SwitchPreview.java +++ /dev/null @@ -1,116 +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.gallery3d.stress; - -import com.android.camera.CameraActivity; - -import android.app.Instrumentation; -import android.content.Intent; -import android.provider.MediaStore; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.os.Environment; -import android.util.Log; - -import java.io.BufferedWriter; -import java.io.FileWriter; - -/** - * Junit / Instrumentation test case for camera test - * - * Running the test suite: - * - * adb shell am instrument \ - * -e class com.android.camera.stress.SwitchPreview \ - * -w com.android.camera.tests/com.android.camera.stress.CameraStressTestRunner - * - */ -public class SwitchPreview extends ActivityInstrumentationTestCase2 <CameraActivity>{ - private String TAG = "SwitchPreview"; - private static final int TOTAL_NUMBER_OF_SWITCHING = 200; - private static final long WAIT_FOR_PREVIEW = 4000; - - private static final String CAMERA_TEST_OUTPUT_FILE = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - private BufferedWriter mOut; - private FileWriter mfstream; - - public SwitchPreview() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - getActivity(); - prepareOutputFile(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - getActivity().finish(); - closeOutputFile(); - super.tearDown(); - } - - private void prepareOutputFile(){ - try{ - mfstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); - mOut = new BufferedWriter(mfstream); - } catch (Exception e){ - assertTrue("Camera Switch Mode", false); - } - } - - private void closeOutputFile() { - try { - mOut.write("\n"); - mOut.close(); - mfstream.close(); - } catch (Exception e) { - assertTrue("CameraSwitchMode close output", false); - } - } - - public void testSwitchMode() { - //Switching the video and the video recorder mode - Instrumentation inst = getInstrumentation(); - try{ - mOut.write("Camera Switch Mode:\n"); - mOut.write("No of loops :" + TOTAL_NUMBER_OF_SWITCHING + "\n"); - mOut.write("loop: "); - for (int i=0; i< TOTAL_NUMBER_OF_SWITCHING; i++) { - Thread.sleep(WAIT_FOR_PREVIEW); - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.setClass(getInstrumentation().getTargetContext(), - CameraActivity.class); - getActivity().startActivity(intent); - Thread.sleep(WAIT_FOR_PREVIEW); - intent = new Intent(); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.setClass(getInstrumentation().getTargetContext(), - CameraActivity.class); - getActivity().startActivity(intent); - mOut.write(" ," + i); - mOut.flush(); - } - } catch (Exception e){ - Log.v(TAG, "Got exception", e); - } - } -} diff --git a/tests/src/com/android/gallery3d/stress/TestUtil.java b/tests/src/com/android/gallery3d/stress/TestUtil.java deleted file mode 100644 index 56ab715f7..000000000 --- a/tests/src/com/android/gallery3d/stress/TestUtil.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.stress; - -import android.os.Environment; -import java.io.FileWriter; -import java.io.BufferedWriter; - - -/** - * Collection of utility functions used for the test. - */ -public class TestUtil { - public BufferedWriter mOut; - public FileWriter mfstream; - - public TestUtil() { - } - - public void prepareOutputFile() throws Exception { - String camera_test_output_file = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - mfstream = new FileWriter(camera_test_output_file, true); - mOut = new BufferedWriter(mfstream); - } - - public void closeOutputFile() throws Exception { - mOut.write("\n"); - mOut.close(); - mfstream.close(); - } - - public void writeReportHeader(String reportTag, int iteration) throws Exception { - mOut.write(reportTag); - mOut.write("No of loops :" + iteration + "\n"); - mOut.write("loop: "); - } - - public void writeResult(int iteration) throws Exception { - mOut.write(" ," + iteration); - mOut.flush(); - } -} diff --git a/tests/src/com/android/gallery3d/stress/VideoCapture.java b/tests/src/com/android/gallery3d/stress/VideoCapture.java deleted file mode 100755 index 8211badf7..000000000 --- a/tests/src/com/android/gallery3d/stress/VideoCapture.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2010 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.gallery3d.stress; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.stress.TestUtil; - -import android.app.Activity; -import android.app.Instrumentation; -import android.content.Intent; -import android.provider.MediaStore; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.view.KeyEvent; - -import com.android.gallery3d.stress.CameraStressTestRunner; - -/** - * Junit / Instrumentation test case for camera test - * - * Running the test suite: - * - * adb shell am instrument \ - * -e class com.android.camera.stress.VideoCapture \ - * -w com.google.android.camera.tests/android.test.InstrumentationTestRunner - * - */ - -public class VideoCapture extends ActivityInstrumentationTestCase2 <CameraActivity> { - private static final long WAIT_FOR_PREVIEW = 1500; //1.5 seconds - private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //2 seconds - - // Private intent extras which control the camera facing. - private final static String EXTRAS_CAMERA_FACING = - "android.intent.extras.CAMERA_FACING"; - - private TestUtil testUtil = new TestUtil(); - - public VideoCapture() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - testUtil.prepareOutputFile(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - testUtil.closeOutputFile(); - super.tearDown(); - } - - public void captureVideos(String reportTag, Instrumentation inst) throws Exception{ - boolean memoryResult = false; - int total_num_of_videos = CameraStressTestRunner.mVideoIterations; - int video_duration = CameraStressTestRunner.mVideoDuration; - testUtil.writeReportHeader(reportTag, total_num_of_videos); - - for (int i = 0; i < total_num_of_videos; i++) { - Thread.sleep(WAIT_FOR_PREVIEW); - // record a video - inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - Thread.sleep(video_duration); - inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - testUtil.writeResult(i); - } - } - - public void testBackVideoCapture() throws Exception { - Instrumentation inst = getInstrumentation(); - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(EXTRAS_CAMERA_FACING, - android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); - Activity act = inst.startActivitySync(intent); - Thread.sleep(WAIT_FOR_SWITCH_CAMERA); - captureVideos("Back Camera Video Capture\n", inst); - act.finish(); - } - - public void testFrontVideoCapture() throws Exception { - Instrumentation inst = getInstrumentation(); - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(EXTRAS_CAMERA_FACING, - android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); - Activity act = inst.startActivitySync(intent); - Thread.sleep(WAIT_FOR_SWITCH_CAMERA); - captureVideos("Front Camera Video Capture\n", inst); - act.finish(); - } -} diff --git a/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java b/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java deleted file mode 100644 index b8fb05fc2..000000000 --- a/tests/src/com/android/gallery3d/unittest/CameraUnitTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2010 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.gallery3d.unittest; - -import com.android.camera.Util; - -import android.graphics.Matrix; -import android.test.suitebuilder.annotation.SmallTest; - -import junit.framework.TestCase; - -@SmallTest -public class CameraUnitTest extends TestCase { - public void testRoundOrientation() { - int h = Util.ORIENTATION_HYSTERESIS; - assertEquals(0, Util.roundOrientation(0, 0)); - assertEquals(0, Util.roundOrientation(359, 0)); - assertEquals(0, Util.roundOrientation(0 + 44 + h, 0)); - assertEquals(90, Util.roundOrientation(0 + 45 + h, 0)); - assertEquals(0, Util.roundOrientation(360 - 44 - h, 0)); - assertEquals(270, Util.roundOrientation(360 - 45 - h, 0)); - - assertEquals(90, Util.roundOrientation(90, 90)); - assertEquals(90, Util.roundOrientation(90 + 44 + h, 90)); - assertEquals(180, Util.roundOrientation(90 + 45 + h, 90)); - assertEquals(90, Util.roundOrientation(90 - 44 - h, 90)); - assertEquals(0, Util.roundOrientation(90 - 45 - h, 90)); - - assertEquals(180, Util.roundOrientation(180, 180)); - assertEquals(180, Util.roundOrientation(180 + 44 + h, 180)); - assertEquals(270, Util.roundOrientation(180 + 45 + h, 180)); - assertEquals(180, Util.roundOrientation(180 - 44 - h, 180)); - assertEquals(90, Util.roundOrientation(180 - 45 - h, 180)); - - assertEquals(270, Util.roundOrientation(270, 270)); - assertEquals(270, Util.roundOrientation(270 + 44 + h, 270)); - assertEquals(0, Util.roundOrientation(270 + 45 + h, 270)); - assertEquals(270, Util.roundOrientation(270 - 44 - h, 270)); - assertEquals(180, Util.roundOrientation(270 - 45 - h, 270)); - - assertEquals(90, Util.roundOrientation(90, 0)); - assertEquals(180, Util.roundOrientation(180, 0)); - assertEquals(270, Util.roundOrientation(270, 0)); - - assertEquals(0, Util.roundOrientation(0, 90)); - assertEquals(180, Util.roundOrientation(180, 90)); - assertEquals(270, Util.roundOrientation(270, 90)); - - assertEquals(0, Util.roundOrientation(0, 180)); - assertEquals(90, Util.roundOrientation(90, 180)); - assertEquals(270, Util.roundOrientation(270, 180)); - - assertEquals(0, Util.roundOrientation(0, 270)); - assertEquals(90, Util.roundOrientation(90, 270)); - assertEquals(180, Util.roundOrientation(180, 270)); - } - - public void testPrepareMatrix() { - Matrix matrix = new Matrix(); - float[] points; - int[] expected; - - Util.prepareMatrix(matrix, false, 0, 800, 480); - points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; - expected = new int[] {0, 0, 400, 240, 800, 480, 400, 480, 100, 300}; - matrix.mapPoints(points); - assertEquals(expected, points); - - Util.prepareMatrix(matrix, false, 90, 800, 480); - points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; - expected = new int[] {800, 0, 400, 240, 0, 480, 0, 240, 300, 60}; - matrix.mapPoints(points); - assertEquals(expected, points); - - Util.prepareMatrix(matrix, false, 180, 800, 480); - points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; - expected = new int[] {800, 480, 400, 240, 0, 0, 400, 0, 700, 180}; - matrix.mapPoints(points); - assertEquals(expected, points); - - Util.prepareMatrix(matrix, true, 180, 800, 480); - points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; - expected = new int[] {0, 480, 400, 240, 800, 0, 400, 0, 100, 180}; - matrix.mapPoints(points); - assertEquals(expected, points); - } - - private void assertEquals(int expected[], float[] actual) { - for (int i = 0; i < expected.length; i++) { - assertEquals("Array index " + i + " mismatch", expected[i], Math.round(actual[i])); - } - } -} diff --git a/tests_camera/Android.mk b/tests_camera/Android.mk deleted file mode 100644 index f39533a71..000000000 --- a/tests_camera/Android.mk +++ /dev/null @@ -1,16 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -# We only want this apk build for tests. -LOCAL_MODULE_TAGS := tests - -LOCAL_SDK_VERSION := 16 - -# Include all test java files. -LOCAL_SRC_FILES := $(call all-java-files-under, src) - -LOCAL_PACKAGE_NAME := CameraTests - -LOCAL_INSTRUMENTATION_FOR := Gallery2 - -include $(BUILD_PACKAGE) diff --git a/tests_camera/AndroidManifest.xml b/tests_camera/AndroidManifest.xml deleted file mode 100644 index 164bbd55c..000000000 --- a/tests_camera/AndroidManifest.xml +++ /dev/null @@ -1,44 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.camera.tests"> - - <uses-permission android:name="android.permission.INJECT_EVENTS" /> - - <application> - <uses-library android:name="android.test.runner" /> - </application> - - <instrumentation android:name="com.android.camera.CameraLaunchPerformance" - android:targetPackage="com.android.camera" - android:label="Camera Launch Performance"> - </instrumentation> - - <instrumentation android:name="com.android.camera.stress.CameraStressTestRunner" - android:targetPackage="com.android.camera" - android:label="Camera stress test runner"> - </instrumentation> - - <instrumentation android:name="com.android.camera.CameraTestRunner" - android:targetPackage="com.android.camera" - android:label="Camera continuous test runner"> - </instrumentation> - - <instrumentation android:name="android.test.InstrumentationTestRunner" - android:targetPackage="com.android.camera" - android:label="Tests for Camera application."/> -</manifest> diff --git a/tests_camera/src/com/android/camera/CameraLaunchPerformance.java b/tests_camera/src/com/android/camera/CameraLaunchPerformance.java deleted file mode 100644 index fe2b7761a..000000000 --- a/tests_camera/src/com/android/camera/CameraLaunchPerformance.java +++ /dev/null @@ -1,47 +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.app.Activity; -import android.os.Bundle; -import android.test.LaunchPerformanceBase; - -/** - * Instrumentation class for Camera launch performance testing. - */ -public class CameraLaunchPerformance extends LaunchPerformanceBase { - @SuppressWarnings("unused") - private static final String TAG = "CameraLaunchPerformance"; - - @Override - public void onCreate(Bundle arguments) { - super.onCreate(arguments); - mIntent.setClassName(getTargetContext(), - "com.android.camera.CameraActivity"); - start(); - } - - /** - * Calls LaunchApp and finish. - */ - @Override - public void onStart() { - super.onStart(); - LaunchApp(); - finish(Activity.RESULT_OK, mResults); - } -} diff --git a/tests_camera/src/com/android/camera/CameraTestRunner.java b/tests_camera/src/com/android/camera/CameraTestRunner.java deleted file mode 100755 index 96c48a4c8..000000000 --- a/tests_camera/src/com/android/camera/CameraTestRunner.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.test.InstrumentationTestRunner; -import android.test.InstrumentationTestSuite; - -import com.android.camera.activity.CameraActivityTest; -import com.android.camera.functional.CameraTest; -import com.android.camera.functional.ImageCaptureIntentTest; -import com.android.camera.functional.VideoCaptureIntentTest; -import com.android.camera.unittest.CameraUnitTest; - -import junit.framework.TestSuite; - - -public class CameraTestRunner extends InstrumentationTestRunner { - - @Override - public TestSuite getAllTests() { - TestSuite suite = new InstrumentationTestSuite(this); - suite.addTestSuite(CameraActivityTest.class); - suite.addTestSuite(CameraTest.class); - suite.addTestSuite(ImageCaptureIntentTest.class); - suite.addTestSuite(VideoCaptureIntentTest.class); - suite.addTestSuite(CameraUnitTest.class); - return suite; - } - - @Override - public ClassLoader getLoader() { - return CameraTestRunner.class.getClassLoader(); - } -} diff --git a/tests_camera/src/com/android/camera/StressTests.java b/tests_camera/src/com/android/camera/StressTests.java deleted file mode 100755 index 7ed8317cc..000000000 --- a/tests_camera/src/com/android/camera/StressTests.java +++ /dev/null @@ -1,47 +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.camera.stress.ImageCapture; -import com.android.camera.stress.SwitchPreview; -import com.android.camera.stress.CameraLatency; -import com.android.camera.stress.CameraStartUp; - -import junit.framework.Test; -import junit.framework.TestSuite; - - -/** - * Instrumentation Test Runner for all Camera tests. - * - * Running all tests: - * - * adb shell am instrument \ - * -e class com.android.camera.StressTests \ - * -w com.android.camera.tests/com.android.camera.stress.CameraStressTestRunner - */ - -public class StressTests extends TestSuite { - public static Test suite() { - TestSuite result = new TestSuite(); - result.addTestSuite(SwitchPreview.class); - result.addTestSuite(ImageCapture.class); - result.addTestSuite(CameraLatency.class); - result.addTestSuite(CameraStartUp.class); - return result; - } -} diff --git a/tests_camera/src/com/android/camera/UnitTests.java b/tests_camera/src/com/android/camera/UnitTests.java deleted file mode 100644 index e56a907f0..000000000 --- a/tests_camera/src/com/android/camera/UnitTests.java +++ /dev/null @@ -1,35 +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.test.suitebuilder.UnitTestSuiteBuilder; - -import junit.framework.Test; -import junit.framework.TestSuite; - -/** - * TestSuite for all Camera unit tests. - */ -public class UnitTests extends TestSuite { - - public static Test suite() { - return new UnitTestSuiteBuilder(UnitTests.class) - .includePackages("com.android.camera.unittest") - .named("Camera Unit Tests") - .build(); - } -} diff --git a/tests_camera/src/com/android/camera/activity/CameraActivityTest.java b/tests_camera/src/com/android/camera/activity/CameraActivityTest.java deleted file mode 100644 index eb027e9d3..000000000 --- a/tests_camera/src/com/android/camera/activity/CameraActivityTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.activity; - -import android.hardware.Camera.Parameters; -import android.test.suitebuilder.annotation.LargeTest; - -import com.android.camera.CameraActivity; -import com.android.camera.CameraHolder; -import com.android.gallery3d.R; - -import static com.google.testing.littlemock.LittleMock.doReturn; - -public class CameraActivityTest extends CameraTestCase <CameraActivity> { - public CameraActivityTest() { - super(CameraActivity.class); - } - - @LargeTest - public void testFailToConnect() throws Exception { - super.internalTestFailToConnect(); - } - - @LargeTest - public void testTakePicture() throws Exception { - CameraHolder.injectMockCamera(mCameraInfo, mOneMockCamera); - - getActivity(); - getInstrumentation().waitForIdleSync(); - - // Press shutter button to take a picture. - performClick(R.id.shutter_button); - getInstrumentation().waitForIdleSync(); - - // Force the activity to finish. - getActivity().finish(); - getInstrumentation().waitForIdleSync(); - } -} diff --git a/tests_camera/src/com/android/camera/activity/CameraTestCase.java b/tests_camera/src/com/android/camera/activity/CameraTestCase.java deleted file mode 100644 index 27be3c7d3..000000000 --- a/tests_camera/src/com/android/camera/activity/CameraTestCase.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.activity; - -import android.app.Activity; -import android.app.Instrumentation; -import android.hardware.Camera; -import android.hardware.Camera.AutoFocusCallback; -import android.hardware.Camera.CameraInfo; -import android.hardware.Camera.Parameters; -import android.hardware.Camera.PictureCallback; -import android.hardware.Camera.ShutterCallback; -import android.test.ActivityInstrumentationTestCase2; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; - -import com.android.camera.CameraHolder; -import com.android.camera.CameraManager.CameraProxy; -import com.android.camera.Util; -import com.android.gallery3d.R; - -import static com.google.testing.littlemock.LittleMock.mock; -import static com.google.testing.littlemock.LittleMock.doAnswer; -import static com.google.testing.littlemock.LittleMock.doReturn; -import static com.google.testing.littlemock.LittleMock.anyObject; -import com.google.testing.littlemock.AppDataDirGuesser; -import com.google.testing.littlemock.ArgumentCaptor; -import com.google.testing.littlemock.Captor; -import com.google.testing.littlemock.LittleMock; -import com.google.testing.littlemock.Mock; - -import java.io.File; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.io.IOException; -import java.util.concurrent.Callable; - - -public class CameraTestCase<T extends Activity> extends ActivityInstrumentationTestCase2<T> { - protected CameraInfo mCameraInfo[]; - protected CameraProxy mMockCamera[]; - protected CameraInfo mOneCameraInfo[]; - protected CameraProxy mOneMockCamera[]; - private static Parameters mParameters; - private byte[] mBlankJpeg; - @Mock private CameraProxy mMockBackCamera; - @Mock private CameraProxy mMockFrontCamera; - @Captor private ArgumentCaptor<ShutterCallback> mShutterCallback; - @Captor private ArgumentCaptor<PictureCallback> mRawPictureCallback; - @Captor private ArgumentCaptor<PictureCallback> mJpegPictureCallback; - @Captor private ArgumentCaptor<AutoFocusCallback> mAutoFocusCallback; - Callable<Object> mAutoFocusCallable = new AutoFocusCallable(); - Callable<Object> mTakePictureCallable = new TakePictureCallable(); - - private class TakePictureCallable implements Callable<Object> { - @Override - public Object call() throws Exception { - Runnable runnable = new Runnable() { - @Override - public void run() { - readBlankJpeg(); - Camera camera = mOneMockCamera[0].getCamera(); - mShutterCallback.getValue().onShutter(); - mRawPictureCallback.getValue().onPictureTaken(null, camera); - mJpegPictureCallback.getValue().onPictureTaken(mBlankJpeg, camera); - } - }; - // Probably need some delay. Make sure shutter callback is called - // after onShutterButtonFocus(false). - getActivity().findViewById(R.id.gl_root_view).postDelayed(runnable, 50); - return null; - } - } - - private class AutoFocusCallable implements Callable<Object> { - @Override - public Object call() throws Exception { - Runnable runnable = new Runnable() { - @Override - public void run() { - Camera camera = mOneMockCamera[0].getCamera(); - mAutoFocusCallback.getValue().onAutoFocus(true, camera); - } - }; - // Need some delay. Otherwise, focus callback will be run before - // onShutterButtonClick - getActivity().findViewById(R.id.gl_root_view).postDelayed(runnable, 50); - return null; - } - } - - public CameraTestCase(Class<T> activityClass) { - super(activityClass); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - AppDataDirGuesser.setInstance(new AppDataDirGuesser() { - @Override - public File guessSuitableDirectoryForGeneratedClasses() { - return getInstrumentation().getTargetContext().getCacheDir(); - } - }); - AppDataDirGuesser.getsInstance().guessSuitableDirectoryForGeneratedClasses(); - LittleMock.initMocks(this); - mCameraInfo = new CameraInfo[2]; - mCameraInfo[0] = new CameraInfo(); - mCameraInfo[0].facing = CameraInfo.CAMERA_FACING_BACK; - mCameraInfo[1] = new CameraInfo(); - mCameraInfo[1].facing = CameraInfo.CAMERA_FACING_FRONT; - mMockCamera = new CameraProxy[2]; - mMockCamera[0] = mMockBackCamera; - mMockCamera[1] = mMockFrontCamera; - doReturn(getParameters()).when(mMockCamera[0]).getParameters(); - doReturn(getParameters()).when(mMockCamera[1]).getParameters(); - - mOneCameraInfo = new CameraInfo[1]; - mOneCameraInfo[0] = new CameraInfo(); - mOneCameraInfo[0].facing = CameraInfo.CAMERA_FACING_BACK; - mOneMockCamera = new CameraProxy[1]; - mOneMockCamera[0] = mMockBackCamera; - doReturn(getParameters()).when(mOneMockCamera[0]).getParameters(); - - // Mock takePicture call. - doAnswer(mTakePictureCallable).when(mMockBackCamera).takePicture( - mShutterCallback.capture(), mRawPictureCallback.capture(), - (PictureCallback) anyObject(), mJpegPictureCallback.capture()); - - // Mock autoFocus call. - doAnswer(mAutoFocusCallable).when(mMockBackCamera).autoFocus( - mAutoFocusCallback.capture()); - } - - private void readBlankJpeg() { - InputStream ins = getActivity().getResources().openRawResource(R.raw.blank); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - int size = 0; - - // Read the entire resource into a local byte buffer. - byte[] buffer = new byte[1024]; - try { - while((size = ins.read(buffer, 0, 1024)) >= 0){ - outputStream.write(buffer, 0, size); - } - } catch (IOException e) { - // ignore - } finally { - Util.closeSilently(ins); - } - mBlankJpeg = outputStream.toByteArray(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - CameraHolder.injectMockCamera(null, null); - } - - protected void internalTestFailToConnect() throws Exception { - CameraHolder.injectMockCamera(mCameraInfo, null); - - getActivity(); - Instrumentation inst = getInstrumentation(); - inst.waitForIdleSync(); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); // close dialog - } - - protected void performClick(final int id) { - Activity activity = getActivity(); - getInstrumentation().waitForIdleSync(); - assertNotNull(activity.findViewById(id)); - Instrumentation inst = getInstrumentation(); - inst.runOnMainSync(new Runnable() { - @Override - public void run() { - View v = getActivity().findViewById(id); - float x = (v.getLeft() + v.getRight()) / 2; - float y = (v.getTop() + v.getBottom()) / 2; - MotionEvent down = MotionEvent.obtain(0, 0, - MotionEvent.ACTION_DOWN, x, y, 0, 0, 0, 0, 0, 0, 0); - MotionEvent up = MotionEvent.obtain(0, 0, - MotionEvent.ACTION_UP, x, y, 0, 0, 0, 0, 0, 0, 0); - View parent = (View) v.getParent(); - parent.dispatchTouchEvent(down); - parent.dispatchTouchEvent(up); - } - }); - inst.waitForIdleSync(); - } - - protected void assertViewNotExist(int id) { - Activity activity = getActivity(); - getInstrumentation().waitForIdleSync(); - assertNull(activity.findViewById(id)); - } - - protected void assertViewNotVisible(int id) { - Activity activity = getActivity(); - getInstrumentation().waitForIdleSync(); - View view = activity.findViewById(id); - assertTrue(view.getVisibility() != View.VISIBLE); - } - - protected static Parameters getParameters() { - synchronized (CameraTestCase.class) { - if (mParameters == null) { - mParameters = android.hardware.Camera.getEmptyParameters(); - mParameters.unflatten("preview-format-values=yuv420sp,yuv420p,yuv422i-yuyv,yuv420p;" + - "preview-format=yuv420sp;" + - "preview-size-values=800x480;preview-size=800x480;" + - "picture-size-values=320x240;picture-size=320x240;" + - "jpeg-thumbnail-size-values=320x240,0x0;jpeg-thumbnail-width=320;jpeg-thumbnail-height=240;" + - "jpeg-thumbnail-quality=60;jpeg-quality=95;" + - "preview-frame-rate-values=30,15;preview-frame-rate=30;" + - "focus-mode-values=continuous-video,auto,macro,infinity,continuous-picture;focus-mode=auto;" + - "preview-fps-range-values=(15000,30000);preview-fps-range=15000,30000;" + - "scene-mode-values=auto,action,night;scene-mode=auto;" + - "flash-mode-values=off,on,auto,torch;flash-mode=off;" + - "whitebalance-values=auto,daylight,fluorescent,incandescent;whitebalance=auto;" + - "effect-values=none,mono,sepia;effect=none;" + - "zoom-supported=true;zoom-ratios=100,200,400;max-zoom=2;" + - "picture-format-values=jpeg;picture-format=jpeg;" + - "min-exposure-compensation=-30;max-exposure-compensation=30;" + - "exposure-compensation=0;exposure-compensation-step=0.1;" + - "horizontal-view-angle=40;vertical-view-angle=40;"); - } - } - return mParameters; - } -} diff --git a/tests_camera/src/com/android/camera/functional/CameraTest.java b/tests_camera/src/com/android/camera/functional/CameraTest.java deleted file mode 100644 index 3fdebc030..000000000 --- a/tests_camera/src/com/android/camera/functional/CameraTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2010 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.functional; - -import com.android.camera.CameraActivity; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Environment; -import android.os.Process; -import android.provider.MediaStore; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.LargeTest; - -import java.io.File; -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -public class CameraTest extends InstrumentationTestCase { - @LargeTest - public void testVideoCaptureIntentFdLeak() throws Exception { - Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.parse("file://" - + Environment.getExternalStorageDirectory().toString() - + "test_fd_leak.3gp")); - getInstrumentation().startActivitySync(intent).finish(); - // Test if the fd is closed. - for (File f: new File("/proc/" + Process.myPid() + "/fd").listFiles()) { - assertEquals(-1, f.getCanonicalPath().indexOf("test_fd_leak.3gp")); - } - } - - @LargeTest - public void testActivityLeak() throws Exception { - checkActivityLeak(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); - checkActivityLeak(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - } - - private void checkActivityLeak(String action) throws Exception { - final int TEST_COUNT = 5; - Intent intent = new Intent(action); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setClass(getInstrumentation().getTargetContext(), - CameraActivity.class); - ArrayList<WeakReference<Activity>> refs = - new ArrayList<WeakReference<Activity>>(); - for (int i = 0; i < TEST_COUNT; i++) { - Activity activity = getInstrumentation().startActivitySync(intent); - refs.add(new WeakReference<Activity>(activity)); - activity.finish(); - getInstrumentation().waitForIdleSync(); - activity = null; - } - Runtime.getRuntime().gc(); - Runtime.getRuntime().runFinalization(); - Runtime.getRuntime().gc(); - int refCount = 0; - for (WeakReference<Activity> c: refs) { - if (c.get() != null) refCount++; - } - // If applications are leaking activity, every reference is reachable. - assertTrue(refCount != TEST_COUNT); - } -} diff --git a/tests_camera/src/com/android/camera/functional/ImageCaptureIntentTest.java b/tests_camera/src/com/android/camera/functional/ImageCaptureIntentTest.java deleted file mode 100644 index 54ac1b497..000000000 --- a/tests_camera/src/com/android/camera/functional/ImageCaptureIntentTest.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.functional; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.R; - -import android.app.Activity; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.view.KeyEvent; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; - -public class ImageCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> { - private Intent mIntent; - - public ImageCaptureIntentTest() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - } - - @LargeTest - public void testNoExtraOutput() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - takePicture(); - pressDone(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_OK, getActivity().getResultCode()); - Intent resultData = getActivity().getResultData(); - Bitmap bitmap = (Bitmap) resultData.getParcelableExtra("data"); - assertNotNull(bitmap); - assertTrue(bitmap.getWidth() > 0); - assertTrue(bitmap.getHeight() > 0); - } - - @LargeTest - public void testExtraOutput() throws Exception { - File file = new File(Environment.getExternalStorageDirectory(), - "test.jpg"); - BufferedInputStream stream = null; - byte[] jpegData; - - try { - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file)); - setActivityIntent(mIntent); - getActivity(); - - takePicture(); - pressDone(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_OK, getActivity().getResultCode()); - - // Verify the jpeg file - int fileLength = (int) file.length(); - assertTrue(fileLength > 0); - jpegData = new byte[fileLength]; - stream = new BufferedInputStream(new FileInputStream(file)); - stream.read(jpegData); - } finally { - if (stream != null) stream.close(); - file.delete(); - } - - Bitmap b = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length); - assertTrue(b.getWidth() > 0); - assertTrue(b.getHeight() > 0); - } - - @LargeTest - public void testCancel() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - pressCancel(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); - } - - @LargeTest - public void testSnapshotCancel() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - takePicture(); - pressCancel(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); - } - - private void takePicture() throws Exception { - getInstrumentation().sendKeySync( - new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS)); - getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - Thread.sleep(4000); - } - - private void pressDone() { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - getActivity().findViewById(R.id.btn_done).performClick(); - } - }); - } - - private void pressCancel() { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - getActivity().findViewById(R.id.btn_cancel).performClick(); - } - }); - } -} diff --git a/tests_camera/src/com/android/camera/functional/VideoCaptureIntentTest.java b/tests_camera/src/com/android/camera/functional/VideoCaptureIntentTest.java deleted file mode 100644 index 43e91ca84..000000000 --- a/tests_camera/src/com/android/camera/functional/VideoCaptureIntentTest.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.functional; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.R; - -import android.app.Activity; -import android.content.ContentResolver; -import android.content.Intent; -import android.database.Cursor; -import android.media.MediaMetadataRetriever; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.provider.MediaStore.Video.VideoColumns; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; - -import java.io.File; - -public class VideoCaptureIntentTest extends ActivityInstrumentationTestCase2 <CameraActivity> { - private static final String TAG = "VideoCaptureIntentTest"; - private Intent mIntent; - private Uri mVideoUri; - private File mFile, mFile2; - - public VideoCaptureIntentTest() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - mIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); - } - - @Override - protected void tearDown() throws Exception { - if (mVideoUri != null) { - ContentResolver resolver = getActivity().getContentResolver(); - Uri query = mVideoUri.buildUpon().build(); - String[] projection = new String[] {VideoColumns.DATA}; - - Cursor cursor = null; - try { - cursor = resolver.query(query, projection, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - new File(cursor.getString(0)).delete(); - } - } finally { - if (cursor != null) cursor.close(); - } - - resolver.delete(mVideoUri, null, null); - } - if (mFile != null) mFile.delete(); - if (mFile2 != null) mFile2.delete(); - super.tearDown(); - } - - @LargeTest - public void testNoExtraOutput() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressDone(); - - Intent resultData = getActivity().getResultData(); - mVideoUri = resultData.getData(); - assertNotNull(mVideoUri); - verify(getActivity(), mVideoUri); - } - - @LargeTest - public void testExtraOutput() throws Exception { - mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); - - Uri uri = Uri.fromFile(mFile); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressDone(); - - verify(getActivity(), uri); - } - - @LargeTest - public void testCancel() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - pressCancel(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); - } - - @LargeTest - public void testRecordCancel() throws Exception { - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressCancel(); - - assertTrue(getActivity().isFinishing()); - assertEquals(Activity.RESULT_CANCELED, getActivity().getResultCode()); - } - - @LargeTest - public void testExtraSizeLimit() throws Exception { - mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); - final long sizeLimit = 500000; // bytes - - Uri uri = Uri.fromFile(mFile); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, sizeLimit); - mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // use low quality to speed up - setActivityIntent(mIntent); - getActivity(); - - recordVideo(5000); - pressDone(); - - verify(getActivity(), uri); - long length = mFile.length(); - Log.v(TAG, "Video size is " + length + " bytes."); - assertTrue(length > 0); - assertTrue("Actual size=" + length, length <= sizeLimit); - } - - @LargeTest - public void testExtraDurationLimit() throws Exception { - mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); - final int durationLimit = 2; // seconds - - Uri uri = Uri.fromFile(mFile); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, durationLimit); - setActivityIntent(mIntent); - getActivity(); - - recordVideo(5000); - pressDone(); - - int duration = verify(getActivity(), uri); - // The duraion should be close to to the limit. The last video duration - // also has duration, so the total duration may exceeds the limit a - // little bit. - Log.v(TAG, "Video length is " + duration + " ms."); - assertTrue(duration < (durationLimit + 1) * 1000); - } - - @LargeTest - public void testExtraVideoQuality() throws Exception { - mFile = new File(Environment.getExternalStorageDirectory(), "video.tmp"); - mFile2 = new File(Environment.getExternalStorageDirectory(), "video2.tmp"); - - Uri uri = Uri.fromFile(mFile); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0); // low quality - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressDone(); - - verify(getActivity(), uri); - setActivity(null); - - uri = Uri.fromFile(mFile2); - mIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); - mIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // high quality - setActivityIntent(mIntent); - getActivity(); - - recordVideo(); - pressDone(); - - verify(getActivity(), uri); - assertTrue(mFile.length() <= mFile2.length()); - } - - // Verify result code, result data, and the duration. - private int verify(CameraActivity activity, Uri uri) throws Exception { - assertTrue(activity.isFinishing()); - assertEquals(Activity.RESULT_OK, activity.getResultCode()); - - // Verify the video file - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setDataSource(activity, uri); - String duration = retriever.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_DURATION); - assertNotNull(duration); - int durationValue = Integer.parseInt(duration); - Log.v(TAG, "Video duration is " + durationValue); - assertTrue(durationValue > 0); - return durationValue; - } - - private void recordVideo(int ms) throws Exception { - getInstrumentation().sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - Thread.sleep(ms); - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - // If recording is in progress, stop it. Run these atomically in - // UI thread. - CameraActivity activity = getActivity(); - if (activity.isRecording()) { - activity.findViewById(R.id.shutter_button).performClick(); - } - } - }); - } - - private void recordVideo() throws Exception { - recordVideo(2000); - } - - private void pressDone() { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - getActivity().findViewById(R.id.btn_done).performClick(); - } - }); - } - - private void pressCancel() { - getInstrumentation().runOnMainSync(new Runnable() { - @Override - public void run() { - getActivity().findViewById(R.id.btn_cancel).performClick(); - } - }); - } -} diff --git a/tests_camera/src/com/android/camera/power/ImageAndVideoCapture.java b/tests_camera/src/com/android/camera/power/ImageAndVideoCapture.java deleted file mode 100755 index b89b764c3..000000000 --- a/tests_camera/src/com/android/camera/power/ImageAndVideoCapture.java +++ /dev/null @@ -1,116 +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.power; - -import com.android.camera.CameraActivity; - -import android.app.Instrumentation; -import android.provider.MediaStore; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; -import android.content.Intent; -/** - * Junit / Instrumentation test case for camera power measurement - * - * Running the test suite: - * - * adb shell am instrument \ - * -e com.android.camera.power.ImageAndVideoCapture \ - * -w com.android.camera.tests/android.test.InstrumentationTestRunner - * - */ - -public class ImageAndVideoCapture extends ActivityInstrumentationTestCase2 <CameraActivity> { - private String TAG = "ImageAndVideoCapture"; - private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 5; - private static final int TOTAL_NUMBER_OF_VIDEOCAPTURE = 5; - private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1500; //1.5 sedconds - private static final long WAIT_FOR_VIDEO_CAPTURE_TO_BE_TAKEN = 10000; //10 seconds - private static final long WAIT_FOR_PREVIEW = 1500; //1.5 seconds - private static final long WAIT_FOR_STABLE_STATE = 2000; //2 seconds - - public ImageAndVideoCapture() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - getActivity(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @LargeTest - public void testLaunchCamera() { - // This test case capture the baseline for the image preview. - try { - Thread.sleep(WAIT_FOR_STABLE_STATE); - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - assertTrue("testImageCaptureDoNothing", false); - } - } - - @LargeTest - public void testCapture5Image() { - // This test case will use the default camera setting - Instrumentation inst = getInstrumentation(); - try { - for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) { - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_UP); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - } - Thread.sleep(WAIT_FOR_STABLE_STATE); - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - assertTrue("testImageCapture", false); - } - } - - @LargeTest - public void testCapture5Videos() { - // This test case will use the default camera setting - Instrumentation inst = getInstrumentation(); - try { - // Switch to the video mode - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - intent.setClass(getInstrumentation().getTargetContext(), - CameraActivity.class); - getActivity().startActivity(intent); - for (int i = 0; i < TOTAL_NUMBER_OF_VIDEOCAPTURE; i++) { - Thread.sleep(WAIT_FOR_PREVIEW); - // record a video - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); - Thread.sleep(WAIT_FOR_VIDEO_CAPTURE_TO_BE_TAKEN); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); - Thread.sleep(WAIT_FOR_PREVIEW); - } - Thread.sleep(WAIT_FOR_STABLE_STATE); - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - assertTrue("testVideoCapture", false); - } - } -} diff --git a/tests_camera/src/com/android/camera/stress/CameraLatency.java b/tests_camera/src/com/android/camera/stress/CameraLatency.java deleted file mode 100755 index 35ff717a1..000000000 --- a/tests_camera/src/com/android/camera/stress/CameraLatency.java +++ /dev/null @@ -1,149 +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.stress; - -import com.android.camera.CameraActivity; - -import android.app.Instrumentation; -import android.os.Environment; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; - -import java.io.BufferedWriter; -import java.io.FileWriter; - -/** - * Junit / Instrumentation test case for camera test - * - */ - -public class CameraLatency extends ActivityInstrumentationTestCase2 <CameraActivity> { - private String TAG = "CameraLatency"; - private static final int TOTAL_NUMBER_OF_IMAGECAPTURE = 20; - private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 4000; - private static final String CAMERA_TEST_OUTPUT_FILE = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - - private long mTotalAutoFocusTime; - private long mTotalShutterLag; - private long mTotalShutterToPictureDisplayedTime; - private long mTotalPictureDisplayedToJpegCallbackTime; - private long mTotalJpegCallbackFinishTime; - private long mAvgAutoFocusTime; - private long mAvgShutterLag = mTotalShutterLag; - private long mAvgShutterToPictureDisplayedTime; - private long mAvgPictureDisplayedToJpegCallbackTime; - private long mAvgJpegCallbackFinishTime; - - public CameraLatency() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - getActivity(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - @LargeTest - public void testImageCapture() { - Log.v(TAG, "start testImageCapture test"); - Instrumentation inst = getInstrumentation(); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN); - try { - for (int i = 0; i < TOTAL_NUMBER_OF_IMAGECAPTURE; i++) { - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - //skip the first measurement - if (i != 0) { - CameraActivity c = getActivity(); - - // if any of the latency var accessor methods return -1 then the - // camera is set to a different module other than PhotoModule so - // skip the shot and try again - if (c.getAutoFocusTime() != -1) { - mTotalAutoFocusTime += c.getAutoFocusTime(); - mTotalShutterLag += c.getShutterLag(); - mTotalShutterToPictureDisplayedTime += - c.getShutterToPictureDisplayedTime(); - mTotalPictureDisplayedToJpegCallbackTime += - c.getPictureDisplayedToJpegCallbackTime(); - mTotalJpegCallbackFinishTime += c.getJpegCallbackFinishTime(); - } - else { - i--; - continue; - } - } - } - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - } - //ToDO: yslau - //1) Need to get the baseline from the cupcake so that we can add the - //failure condition of the camera latency. - //2) Only count those number with succesful capture. Set the timer to invalid - //before capture and ignore them if the value is invalid - int numberofRun = TOTAL_NUMBER_OF_IMAGECAPTURE - 1; - mAvgAutoFocusTime = mTotalAutoFocusTime / numberofRun; - mAvgShutterLag = mTotalShutterLag / numberofRun; - mAvgShutterToPictureDisplayedTime = - mTotalShutterToPictureDisplayedTime / numberofRun; - mAvgPictureDisplayedToJpegCallbackTime = - mTotalPictureDisplayedToJpegCallbackTime / numberofRun; - mAvgJpegCallbackFinishTime = - mTotalJpegCallbackFinishTime / numberofRun; - - try { - FileWriter fstream = null; - fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); - BufferedWriter out = new BufferedWriter(fstream); - out.write("Camera Latency : \n"); - out.write("Number of loop: " + TOTAL_NUMBER_OF_IMAGECAPTURE + "\n"); - out.write("Avg AutoFocus = " + mAvgAutoFocusTime + "\n"); - out.write("Avg mShutterLag = " + mAvgShutterLag + "\n"); - out.write("Avg mShutterToPictureDisplayedTime = " - + mAvgShutterToPictureDisplayedTime + "\n"); - out.write("Avg mPictureDisplayedToJpegCallbackTime = " - + mAvgPictureDisplayedToJpegCallbackTime + "\n"); - out.write("Avg mJpegCallbackFinishTime = " + - mAvgJpegCallbackFinishTime + "\n"); - out.close(); - fstream.close(); - } catch (Exception e) { - fail("Camera Latency write output to file"); - } - Log.v(TAG, "The Image capture wait time = " + - WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - Log.v(TAG, "Avg AutoFocus = " + mAvgAutoFocusTime); - Log.v(TAG, "Avg mShutterLag = " + mAvgShutterLag); - Log.v(TAG, "Avg mShutterToPictureDisplayedTime = " - + mAvgShutterToPictureDisplayedTime); - Log.v(TAG, "Avg mPictureDisplayedToJpegCallbackTime = " - + mAvgPictureDisplayedToJpegCallbackTime); - Log.v(TAG, "Avg mJpegCallbackFinishTime = " + mAvgJpegCallbackFinishTime); - } -} - diff --git a/tests_camera/src/com/android/camera/stress/CameraStartUp.java b/tests_camera/src/com/android/camera/stress/CameraStartUp.java deleted file mode 100644 index 94e9a9419..000000000 --- a/tests_camera/src/com/android/camera/stress/CameraStartUp.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.stress; - -import com.android.camera.CameraActivity; - -import android.app.Activity; -import android.app.Instrumentation; -import android.content.Intent; -import android.os.Environment; -import android.provider.MediaStore; -import android.test.InstrumentationTestCase; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; - -import java.io.FileWriter; -import java.io.BufferedWriter; - -/** - * Test cases to measure the camera and video recorder startup time. - */ -public class CameraStartUp extends InstrumentationTestCase { - - private static final int TOTAL_NUMBER_OF_STARTUP = 20; - - private String TAG = "CameraStartUp"; - private static final String CAMERA_TEST_OUTPUT_FILE = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - private static int WAIT_TIME_FOR_PREVIEW = 1500; //1.5 second - - private long launchCamera() { - long startupTime = 0; - try { - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - long beforeStart = System.currentTimeMillis(); - Instrumentation inst = getInstrumentation(); - Activity cameraActivity = inst.startActivitySync(intent); - long cameraStarted = System.currentTimeMillis(); - Thread.sleep(WAIT_TIME_FOR_PREVIEW); - cameraActivity.finish(); - startupTime = cameraStarted - beforeStart; - Thread.sleep(1000); - Log.v(TAG, "camera startup time: " + startupTime); - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - fail("Fails to get the output file"); - } - return startupTime; - } - - private long launchVideo() { - long startupTime = 0; - - try { - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - long beforeStart = System.currentTimeMillis(); - Instrumentation inst = getInstrumentation(); - Activity recorderActivity = inst.startActivitySync(intent); - long cameraStarted = System.currentTimeMillis(); - recorderActivity.finish(); - startupTime = cameraStarted - beforeStart; - Log.v(TAG, "Video Startup Time = " + startupTime); - // wait for 1s to make sure it reach a clean stage - Thread.sleep(WAIT_TIME_FOR_PREVIEW); - Log.v(TAG, "video startup time: " + startupTime); - } catch (Exception e) { - Log.v(TAG, "Got exception", e); - fail("Fails to launch video output file"); - } - return startupTime; - } - - private void writeToOutputFile(long totalStartupTime, - String individualStartupTime, boolean firstStartUp, String Type) throws Exception { - // TODO (yslau) : Need to integrate the output data with central - // dashboard - try { - FileWriter fstream = null; - fstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); - BufferedWriter out = new BufferedWriter(fstream); - if (firstStartUp) { - out.write("First " + Type + " Startup: " + totalStartupTime + "\n"); - } else { - long averageStartupTime = totalStartupTime / (TOTAL_NUMBER_OF_STARTUP -1); - out.write(Type + "startup time: " + "\n"); - out.write("Number of loop: " + (TOTAL_NUMBER_OF_STARTUP -1) + "\n"); - out.write(individualStartupTime + "\n\n"); - out.write(Type + " average startup time: " + averageStartupTime + " ms\n\n"); - } - out.close(); - fstream.close(); - } catch (Exception e) { - fail("Camera write output to file"); - } - } - - @LargeTest - public void testLaunchVideo() throws Exception { - String individualStartupTime; - individualStartupTime = "Individual Video Startup Time = "; - long totalStartupTime = 0; - long startupTime = 0; - for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) { - if (i == 0) { - // Capture the first startup time individually - long firstStartUpTime = launchVideo(); - writeToOutputFile(firstStartUpTime, "na", true, "Video"); - } else { - startupTime = launchVideo(); - totalStartupTime += startupTime; - individualStartupTime += startupTime + " ,"; - } - } - Log.v(TAG, "totalStartupTime =" + totalStartupTime); - writeToOutputFile(totalStartupTime, individualStartupTime, false, "Video"); - } - - @LargeTest - public void testLaunchCamera() throws Exception { - String individualStartupTime; - individualStartupTime = "Individual Camera Startup Time = "; - long totalStartupTime = 0; - long startupTime = 0; - for (int i = 0; i < TOTAL_NUMBER_OF_STARTUP; i++) { - if (i == 0) { - // Capture the first startup time individually - long firstStartUpTime = launchCamera(); - writeToOutputFile(firstStartUpTime, "na", true, "Camera"); - } else { - startupTime = launchCamera(); - totalStartupTime += startupTime; - individualStartupTime += startupTime + " ,"; - } - } - Log.v(TAG, "totalStartupTime =" + totalStartupTime); - writeToOutputFile(totalStartupTime, - individualStartupTime, false, "Camera"); - } -} diff --git a/tests_camera/src/com/android/camera/stress/CameraStressTestRunner.java b/tests_camera/src/com/android/camera/stress/CameraStressTestRunner.java deleted file mode 100755 index 4047da0a2..000000000 --- a/tests_camera/src/com/android/camera/stress/CameraStressTestRunner.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2010 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.stress; - -import android.os.Bundle; -import android.test.InstrumentationTestRunner; -import android.test.InstrumentationTestSuite; -import junit.framework.TestSuite; - -public class CameraStressTestRunner extends InstrumentationTestRunner { - - // Default recorder settings - public static int mVideoDuration = 20000; // set default to 20 seconds - public static int mVideoIterations = 100; // set default to 100 videos - public static int mImageIterations = 100; // set default to 100 images - - @Override - public TestSuite getAllTests() { - TestSuite suite = new InstrumentationTestSuite(this); - suite.addTestSuite(ImageCapture.class); - suite.addTestSuite(VideoCapture.class); - return suite; - } - - @Override - public ClassLoader getLoader() { - return CameraStressTestRunner.class.getClassLoader(); - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - String video_iterations = (String) icicle.get("video_iterations"); - String image_iterations = (String) icicle.get("image_iterations"); - String video_duration = (String) icicle.get("video_duration"); - - if ( video_iterations != null ) { - mVideoIterations = Integer.parseInt(video_iterations); - } - if ( image_iterations != null) { - mImageIterations = Integer.parseInt(image_iterations); - } - if ( video_duration != null) { - mVideoDuration = Integer.parseInt(video_duration); - } - } -} diff --git a/tests_camera/src/com/android/camera/stress/ImageCapture.java b/tests_camera/src/com/android/camera/stress/ImageCapture.java deleted file mode 100755 index ad06db188..000000000 --- a/tests_camera/src/com/android/camera/stress/ImageCapture.java +++ /dev/null @@ -1,121 +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.stress; - -import com.android.camera.CameraActivity; -import com.android.camera.stress.CameraStressTestRunner; - -import android.app.Instrumentation; -import android.content.Intent; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; -import android.app.Activity; - -/** - * Junit / Instrumentation test case for camera test - * - * Running the test suite: - * - * adb shell am instrument \ - * -e class com.android.camera.stress.ImageCapture \ - * -w com.google.android.camera.tests/android.test.InstrumentationTestRunner - * - */ - -public class ImageCapture extends ActivityInstrumentationTestCase2 <CameraActivity> { - private String TAG = "ImageCapture"; - private static final long WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN = 1500; //1.5 sedconds - private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //3 seconds - - private TestUtil testUtil = new TestUtil(); - - // Private intent extras. - private final static String EXTRAS_CAMERA_FACING = - "android.intent.extras.CAMERA_FACING"; - - public ImageCapture() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - testUtil.prepareOutputFile(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - testUtil.closeOutputFile(); - super.tearDown(); - } - - public void captureImages(String reportTag, Instrumentation inst) { - int total_num_of_images = CameraStressTestRunner.mImageIterations; - Log.v(TAG, "no of images = " + total_num_of_images); - - //TODO(yslau): Need to integrate the outoput with the central dashboard, - //write to a txt file as a temp solution - boolean memoryResult = false; - KeyEvent focusEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_FOCUS); - - try { - testUtil.writeReportHeader(reportTag, total_num_of_images); - for (int i = 0; i < total_num_of_images; i++) { - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - inst.sendKeySync(focusEvent); - inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - Thread.sleep(WAIT_FOR_IMAGE_CAPTURE_TO_BE_TAKEN); - testUtil.writeResult(i); - } - } catch (Exception e) { - Log.v(TAG, "Got exception: " + e.toString()); - assertTrue("testImageCapture", false); - } - } - - @LargeTest - public void testBackImageCapture() throws Exception { - Instrumentation inst = getInstrumentation(); - Intent intent = new Intent(); - - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(EXTRAS_CAMERA_FACING, - android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); - Activity act = inst.startActivitySync(intent); - Thread.sleep(WAIT_FOR_SWITCH_CAMERA); - captureImages("Back Camera Image Capture\n", inst); - act.finish(); - } - - @LargeTest - public void testFrontImageCapture() throws Exception { - Instrumentation inst = getInstrumentation(); - Intent intent = new Intent(); - - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(EXTRAS_CAMERA_FACING, - android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); - Activity act = inst.startActivitySync(intent); - Thread.sleep(WAIT_FOR_SWITCH_CAMERA); - captureImages("Front Camera Image Capture\n", inst); - act.finish(); - } -} diff --git a/tests_camera/src/com/android/camera/stress/ShotToShotLatency.java b/tests_camera/src/com/android/camera/stress/ShotToShotLatency.java deleted file mode 100644 index 0c1ef45b9..000000000 --- a/tests_camera/src/com/android/camera/stress/ShotToShotLatency.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.stress; - -import android.app.Instrumentation; -import android.os.Environment; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; -import android.view.KeyEvent; -import com.android.camera.CameraActivity; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FilenameFilter; -import java.io.FileWriter; -import java.io.IOException; -import java.util.ArrayList; - -/** - * Junit / Instrumentation test case for measuring camera shot to shot latency - */ -public class ShotToShotLatency extends ActivityInstrumentationTestCase2<CameraActivity> { - private String TAG = "ShotToShotLatency"; - private static final int TOTAL_NUMBER_OF_SNAPSHOTS = 250; - private static final long SNAPSHOT_WAIT = 1000; - private static final String CAMERA_TEST_OUTPUT_FILE = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - private static final String CAMERA_IMAGE_DIRECTORY = - Environment.getExternalStorageDirectory().toString() + "/DCIM/Camera/"; - - public ShotToShotLatency() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - getActivity(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - private void cleanupLatencyImages() { - try { - File sdcard = new File(CAMERA_IMAGE_DIRECTORY); - File[] pics = null; - FilenameFilter filter = new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.endsWith(".jpg"); - } - }; - pics = sdcard.listFiles(filter); - for (File f : pics) { - f.delete(); - } - } catch (SecurityException e) { - Log.e(TAG, "Security manager access violation: " + e.toString()); - } - } - - private void sleep(long time) { - try { - Thread.sleep(time); - } catch (InterruptedException e) { - Log.e(TAG, "Sleep InterruptedException " + e.toString()); - } - } - - @LargeTest - public void testShotToShotLatency() { - long sigmaOfDiffFromMeanSquared = 0; - double mean = 0; - double standardDeviation = 0; - ArrayList<Long> captureTimes = new ArrayList<Long>(); - ArrayList<Long> latencyTimes = new ArrayList<Long>(); - - Log.v(TAG, "start testShotToShotLatency test"); - Instrumentation inst = getInstrumentation(); - - // Generate data points - for (int i = 0; i < TOTAL_NUMBER_OF_SNAPSHOTS; i++) { - inst.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER); - sleep(SNAPSHOT_WAIT); - CameraActivity c = getActivity(); - if (c.getCaptureStartTime() > 0) { - captureTimes.add(c.getCaptureStartTime()); - } - } - - // Calculate latencies - for (int j = 1; j < captureTimes.size(); j++) { - latencyTimes.add(captureTimes.get(j) - captureTimes.get(j - 1)); - } - - // Crunch numbers - for (long dataPoint : latencyTimes) { - mean += (double) dataPoint; - } - mean /= latencyTimes.size(); - - for (long dataPoint : latencyTimes) { - sigmaOfDiffFromMeanSquared += (dataPoint - mean) * (dataPoint - mean); - } - standardDeviation = Math.sqrt(sigmaOfDiffFromMeanSquared / latencyTimes.size()); - - // Report statistics - File outFile = new File(CAMERA_TEST_OUTPUT_FILE); - BufferedWriter output = null; - try { - output = new BufferedWriter(new FileWriter(outFile, true)); - output.write("Shot to shot latency - mean: " + mean + "\n"); - output.write("Shot to shot latency - standard deviation: " + standardDeviation + "\n"); - cleanupLatencyImages(); - } catch (IOException e) { - Log.e(TAG, "testShotToShotLatency IOException writing to log " + e.toString()); - } finally { - try { - if (output != null) { - output.close(); - } - } catch (IOException e) { - Log.e(TAG, "Error closing file: " + e.toString()); - } - } - } -} diff --git a/tests_camera/src/com/android/camera/stress/SwitchPreview.java b/tests_camera/src/com/android/camera/stress/SwitchPreview.java deleted file mode 100755 index 86b1b5d99..000000000 --- a/tests_camera/src/com/android/camera/stress/SwitchPreview.java +++ /dev/null @@ -1,117 +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.stress; - -import com.android.camera.CameraActivity; - -import android.app.Instrumentation; -import android.content.Intent; -import android.provider.MediaStore; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.os.Environment; -import android.util.Log; - -import java.io.BufferedWriter; -import java.io.FileWriter; - -/** - * Junit / Instrumentation test case for camera test - * - * Running the test suite: - * - * adb shell am instrument \ - * -e class com.android.camera.stress.SwitchPreview \ - * -w com.android.camera.tests/com.android.camera.stress.CameraStressTestRunner - * - */ -public class SwitchPreview extends ActivityInstrumentationTestCase2 <CameraActivity>{ - private String TAG = "SwitchPreview"; - private static final int TOTAL_NUMBER_OF_SWITCHING = 200; - private static final long WAIT_FOR_PREVIEW = 4000; - - private static final String CAMERA_TEST_OUTPUT_FILE = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - private BufferedWriter mOut; - private FileWriter mfstream; - - public SwitchPreview() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - getActivity(); - prepareOutputFile(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - getActivity().finish(); - closeOutputFile(); - super.tearDown(); - } - - private void prepareOutputFile(){ - try{ - mfstream = new FileWriter(CAMERA_TEST_OUTPUT_FILE, true); - mOut = new BufferedWriter(mfstream); - } catch (Exception e){ - assertTrue("Camera Switch Mode", false); - } - } - - private void closeOutputFile() { - try { - mOut.write("\n"); - mOut.close(); - mfstream.close(); - } catch (Exception e) { - assertTrue("CameraSwitchMode close output", false); - } - } - - @LargeTest - public void testSwitchMode() { - //Switching the video and the video recorder mode - Instrumentation inst = getInstrumentation(); - try{ - mOut.write("Camera Switch Mode:\n"); - mOut.write("No of loops :" + TOTAL_NUMBER_OF_SWITCHING + "\n"); - mOut.write("loop: "); - for (int i=0; i< TOTAL_NUMBER_OF_SWITCHING; i++) { - Thread.sleep(WAIT_FOR_PREVIEW); - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.setClass(getInstrumentation().getTargetContext(), - CameraActivity.class); - getActivity().startActivity(intent); - Thread.sleep(WAIT_FOR_PREVIEW); - intent = new Intent(); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.setClass(getInstrumentation().getTargetContext(), - CameraActivity.class); - getActivity().startActivity(intent); - mOut.write(" ," + i); - mOut.flush(); - } - } catch (Exception e){ - Log.v(TAG, "Got exception", e); - } - } -} diff --git a/tests_camera/src/com/android/camera/stress/TestUtil.java b/tests_camera/src/com/android/camera/stress/TestUtil.java deleted file mode 100644 index 64e2039f2..000000000 --- a/tests_camera/src/com/android/camera/stress/TestUtil.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.stress; - -import android.os.Environment; -import java.io.FileWriter; -import java.io.BufferedWriter; - - -/** - * Collection of utility functions used for the test. - */ -public class TestUtil { - public BufferedWriter mOut; - public FileWriter mfstream; - - public TestUtil() { - } - - public void prepareOutputFile() throws Exception { - String camera_test_output_file = - Environment.getExternalStorageDirectory().toString() + "/mediaStressOut.txt"; - mfstream = new FileWriter(camera_test_output_file, true); - mOut = new BufferedWriter(mfstream); - } - - public void closeOutputFile() throws Exception { - mOut.write("\n"); - mOut.close(); - mfstream.close(); - } - - public void writeReportHeader(String reportTag, int iteration) throws Exception { - mOut.write(reportTag); - mOut.write("No of loops :" + iteration + "\n"); - mOut.write("loop: "); - } - - public void writeResult(int iteration) throws Exception { - mOut.write(" ," + iteration); - mOut.flush(); - } -} diff --git a/tests_camera/src/com/android/camera/stress/VideoCapture.java b/tests_camera/src/com/android/camera/stress/VideoCapture.java deleted file mode 100755 index ec55ccce2..000000000 --- a/tests_camera/src/com/android/camera/stress/VideoCapture.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2010 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.stress; - -import com.android.camera.CameraActivity; -import com.android.camera.stress.TestUtil; - -import android.app.Activity; -import android.app.Instrumentation; -import android.content.Intent; -import android.provider.MediaStore; -import android.test.ActivityInstrumentationTestCase2; -import android.test.suitebuilder.annotation.LargeTest; -import android.view.KeyEvent; - -import com.android.camera.stress.CameraStressTestRunner; - -/** - * Junit / Instrumentation test case for camera test - * - * Running the test suite: - * - * adb shell am instrument \ - * -e class com.android.camera.stress.VideoCapture \ - * -w com.google.android.camera.tests/android.test.InstrumentationTestRunner - * - */ - -public class VideoCapture extends ActivityInstrumentationTestCase2 <CameraActivity> { - private static final long WAIT_FOR_PREVIEW = 1500; //1.5 seconds - private static final long WAIT_FOR_SWITCH_CAMERA = 3000; //2 seconds - - // Private intent extras which control the camera facing. - private final static String EXTRAS_CAMERA_FACING = - "android.intent.extras.CAMERA_FACING"; - - private TestUtil testUtil = new TestUtil(); - - public VideoCapture() { - super(CameraActivity.class); - } - - @Override - protected void setUp() throws Exception { - testUtil.prepareOutputFile(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - testUtil.closeOutputFile(); - super.tearDown(); - } - - @LargeTest - public void captureVideos(String reportTag, Instrumentation inst) throws Exception{ - boolean memoryResult = false; - int total_num_of_videos = CameraStressTestRunner.mVideoIterations; - int video_duration = CameraStressTestRunner.mVideoDuration; - testUtil.writeReportHeader(reportTag, total_num_of_videos); - - for (int i = 0; i < total_num_of_videos; i++) { - Thread.sleep(WAIT_FOR_PREVIEW); - // record a video - inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - Thread.sleep(video_duration); - inst.sendCharacterSync(KeyEvent.KEYCODE_CAMERA); - testUtil.writeResult(i); - } - } - - @LargeTest - public void testBackVideoCapture() throws Exception { - Instrumentation inst = getInstrumentation(); - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(EXTRAS_CAMERA_FACING, - android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK); - Activity act = inst.startActivitySync(intent); - Thread.sleep(WAIT_FOR_SWITCH_CAMERA); - captureVideos("Back Camera Video Capture\n", inst); - act.finish(); - } - - @LargeTest - public void testFrontVideoCapture() throws Exception { - Instrumentation inst = getInstrumentation(); - Intent intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA); - - intent.setClass(getInstrumentation().getTargetContext(), CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(EXTRAS_CAMERA_FACING, - android.hardware.Camera.CameraInfo.CAMERA_FACING_FRONT); - Activity act = inst.startActivitySync(intent); - Thread.sleep(WAIT_FOR_SWITCH_CAMERA); - captureVideos("Front Camera Video Capture\n", inst); - act.finish(); - } -} diff --git a/tests_camera/src/com/android/camera/unittest/CameraUnitTest.java b/tests_camera/src/com/android/camera/unittest/CameraUnitTest.java deleted file mode 100644 index 0b4fc80f6..000000000 --- a/tests_camera/src/com/android/camera/unittest/CameraUnitTest.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2010 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.unittest; - -import com.android.camera.Util; - -import android.graphics.Matrix; -import android.test.suitebuilder.annotation.SmallTest; - -import junit.framework.TestCase; - -@SmallTest -public class CameraUnitTest extends TestCase { - public void testRoundOrientation() { - int h = Util.ORIENTATION_HYSTERESIS; - assertEquals(0, Util.roundOrientation(0, 0)); - assertEquals(0, Util.roundOrientation(359, 0)); - assertEquals(0, Util.roundOrientation(0 + 44 + h, 0)); - assertEquals(90, Util.roundOrientation(0 + 45 + h, 0)); - assertEquals(0, Util.roundOrientation(360 - 44 - h, 0)); - assertEquals(270, Util.roundOrientation(360 - 45 - h, 0)); - - assertEquals(90, Util.roundOrientation(90, 90)); - assertEquals(90, Util.roundOrientation(90 + 44 + h, 90)); - assertEquals(180, Util.roundOrientation(90 + 45 + h, 90)); - assertEquals(90, Util.roundOrientation(90 - 44 - h, 90)); - assertEquals(0, Util.roundOrientation(90 - 45 - h, 90)); - - assertEquals(180, Util.roundOrientation(180, 180)); - assertEquals(180, Util.roundOrientation(180 + 44 + h, 180)); - assertEquals(270, Util.roundOrientation(180 + 45 + h, 180)); - assertEquals(180, Util.roundOrientation(180 - 44 - h, 180)); - assertEquals(90, Util.roundOrientation(180 - 45 - h, 180)); - - assertEquals(270, Util.roundOrientation(270, 270)); - assertEquals(270, Util.roundOrientation(270 + 44 + h, 270)); - assertEquals(0, Util.roundOrientation(270 + 45 + h, 270)); - assertEquals(270, Util.roundOrientation(270 - 44 - h, 270)); - assertEquals(180, Util.roundOrientation(270 - 45 - h, 270)); - - assertEquals(90, Util.roundOrientation(90, 0)); - assertEquals(180, Util.roundOrientation(180, 0)); - assertEquals(270, Util.roundOrientation(270, 0)); - - assertEquals(0, Util.roundOrientation(0, 90)); - assertEquals(180, Util.roundOrientation(180, 90)); - assertEquals(270, Util.roundOrientation(270, 90)); - - assertEquals(0, Util.roundOrientation(0, 180)); - assertEquals(90, Util.roundOrientation(90, 180)); - assertEquals(270, Util.roundOrientation(270, 180)); - - assertEquals(0, Util.roundOrientation(0, 270)); - assertEquals(90, Util.roundOrientation(90, 270)); - assertEquals(180, Util.roundOrientation(180, 270)); - } - - public void testPrepareMatrix() { - Matrix matrix = new Matrix(); - float[] points; - int[] expected; - - Util.prepareMatrix(matrix, false, 0, 800, 480); - points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; - expected = new int[] {0, 0, 400, 240, 800, 480, 400, 480, 100, 300}; - matrix.mapPoints(points); - assertEquals(expected, points); - - Util.prepareMatrix(matrix, false, 90, 800, 480); - points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; - expected = new int[] {800, 0, 400, 240, 0, 480, 0, 240, 300, 60}; - matrix.mapPoints(points); - assertEquals(expected, points); - - Util.prepareMatrix(matrix, false, 180, 800, 480); - points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; - expected = new int[] {800, 480, 400, 240, 0, 0, 400, 0, 700, 180}; - matrix.mapPoints(points); - assertEquals(expected, points); - - Util.prepareMatrix(matrix, true, 180, 800, 480); - points = new float[] {-1000, -1000, 0, 0, 1000, 1000, 0, 1000, -750, 250}; - expected = new int[] {0, 480, 400, 240, 800, 0, 400, 0, 100, 180}; - matrix.mapPoints(points); - assertEquals(expected, points); - } - - private void assertEquals(int expected[], float[] actual) { - for (int i = 0; i < expected.length; i++) { - assertEquals("Array index " + i + " mismatch", expected[i], Math.round(actual[i])); - } - } -} |