summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/camera/CameraActivity.java650
-rw-r--r--src/com/android/camera/CameraModule.java10
-rw-r--r--src/com/android/camera/NewCameraActivity.java456
-rw-r--r--src/com/android/camera/NewCameraModule.java74
-rw-r--r--src/com/android/camera/NewPhotoMenu.java200
-rw-r--r--src/com/android/camera/NewPhotoModule.java2037
-rw-r--r--src/com/android/camera/NewPhotoUI.java793
-rw-r--r--src/com/android/camera/NewPreviewGestures.java263
-rw-r--r--src/com/android/camera/NewVideoMenu.java205
-rw-r--r--src/com/android/camera/NewVideoModule.java2261
-rw-r--r--src/com/android/camera/NewVideoUI.java713
-rw-r--r--src/com/android/camera/PanoramaModule.java1304
-rw-r--r--src/com/android/camera/PhotoMenu.java2
-rw-r--r--src/com/android/camera/PhotoModule.java214
-rw-r--r--src/com/android/camera/PhotoUI.java366
-rw-r--r--src/com/android/camera/PreviewGestures.java293
-rw-r--r--src/com/android/camera/VideoMenu.java3
-rw-r--r--src/com/android/camera/VideoModule.java307
-rw-r--r--src/com/android/camera/VideoUI.java387
-rw-r--r--src/com/android/camera/ui/CameraRootView.java67
-rw-r--r--src/com/android/camera/ui/FaceView.java18
-rw-r--r--src/com/android/camera/ui/NewCameraRootView.java184
-rw-r--r--src/com/android/camera/ui/RenderOverlay.java6
-rw-r--r--src/com/android/gallery3d/app/StateManager.java12
-rw-r--r--src_pd/com/android/gallery3d/util/LightCycleHelper.java5
25 files changed, 1137 insertions, 9693 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 5ba769a62..baa1e7e19 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -16,146 +16,78 @@
package com.android.camera;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
+import android.app.Activity;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
-import android.graphics.drawable.Drawable;
+import android.graphics.drawable.ColorDrawable;
+import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
-import android.provider.MediaStore;
import android.provider.Settings;
import android.view.KeyEvent;
+import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
-import android.widget.FrameLayout;
+import android.widget.ImageView;
-import com.android.camera.ui.CameraSwitcher;
+import com.android.camera.data.CameraDataAdapter;
+import com.android.camera.data.LocalData;
+import com.android.camera.ui.CameraSwitcher.CameraSwitchListener;
+import com.android.camera.ui.FilmStripView;
import com.android.gallery3d.R;
-import com.android.gallery3d.app.PhotoPage;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.util.LightCycleHelper;
-public class CameraActivity extends ActivityBase
- implements CameraSwitcher.CameraSwitchListener {
+public class CameraActivity extends Activity
+ implements CameraSwitchListener {
+
+ private static final String TAG = "CAM_Activity";
+
public static final int PHOTO_MODULE_INDEX = 0;
public static final int VIDEO_MODULE_INDEX = 1;
public static final int PANORAMA_MODULE_INDEX = 2;
public static final int LIGHTCYCLE_MODULE_INDEX = 3;
- CameraModule mCurrentModule;
- private FrameLayout mFrame;
- private ShutterButton mShutter;
- private CameraSwitcher mSwitcher;
- private View mCameraControls;
- private View mControlsBackground;
- private View mPieMenuButton;
- private Drawable[] mDrawables;
+ 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";
+
+ private CameraDataAdapter mDataAdapter;
private int mCurrentModuleIndex;
- private MotionEvent mDown;
+ private CameraModule mCurrentModule;
+ private View mRootView;
+ private FilmStripView mFilmStripView;
+ private int mResultCodeForTesting;
+ private Intent mResultDataForTesting;
+ private OnScreenHint mStorageHint;
+ private long mStorageSpace = Storage.LOW_STORAGE_THRESHOLD;
+ private PhotoModule mController;
private boolean mAutoRotateScreen;
- private int mHeightOrWidth = -1;
-
+ private boolean mSecureCamera;
+ private boolean mShowCameraPreview;
+ private int mLastRawOrientation;
private MyOrientationEventListener mOrientationListener;
- // The degrees of the device rotated clockwise from its natural orientation.
- private int mLastRawOrientation = OrientationEventListener.ORIENTATION_UNKNOWN;
-
- 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;
- }};
-
- private static final String TAG = "CAM_activity";
-
- private static final int[] DRAW_IDS = {
- R.drawable.ic_switch_camera,
- R.drawable.ic_switch_video,
- R.drawable.ic_switch_pan,
- R.drawable.ic_switch_photosphere
- };
-
- @Override
- public void onCreate(Bundle state) {
- super.onCreate(state);
- setContentView(R.layout.camera_main);
- mFrame = (FrameLayout) findViewById(R.id.camera_app_root);
- mDrawables = new Drawable[DRAW_IDS.length];
- for (int i = 0; i < DRAW_IDS.length; i++) {
- mDrawables[i] = getResources().getDrawable(DRAW_IDS[i]);
- }
- init();
- if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent().getAction())
- || MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())) {
- mCurrentModule = new VideoModule();
- mCurrentModuleIndex = VIDEO_MODULE_INDEX;
- } else {
- mCurrentModule = new PhotoModule();
- mCurrentModuleIndex = PHOTO_MODULE_INDEX;
- }
- mCurrentModule.init(this, mFrame, true);
- mSwitcher.setCurrentIndex(mCurrentModuleIndex);
- mOrientationListener = new MyOrientationEventListener(this);
- bindMediaSaveService();
- }
-
- public void init() {
- boolean landscape = Util.getDisplayRotation(this) % 180 == 90;
- mControlsBackground = findViewById(R.id.blocker);
- mCameraControls = findViewById(R.id.camera_controls);
- mShutter = (ShutterButton) findViewById(R.id.shutter_button);
- mSwitcher = (CameraSwitcher) findViewById(R.id.camera_switcher);
- mPieMenuButton = findViewById(R.id.menu);
- int totaldrawid = (LightCycleHelper.hasLightCycleCapture(this)
- ? DRAW_IDS.length : DRAW_IDS.length - 1);
- if (!ApiHelper.HAS_OLD_PANORAMA) totaldrawid--;
-
- int[] drawids = new int[totaldrawid];
- int[] moduleids = new int[totaldrawid];
- int ix = 0;
- for (int i = 0; i < mDrawables.length; i++) {
- if (i == PANORAMA_MODULE_INDEX && !ApiHelper.HAS_OLD_PANORAMA) {
- continue; // not enabled, so don't add to UI
- }
- if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(this)) {
- continue; // not enabled, so don't add to UI
- }
- moduleids[ix] = i;
- drawids[ix++] = DRAW_IDS[i];
- }
- mSwitcher.setIds(moduleids, drawids);
- mSwitcher.setSwitchListener(this);
- mSwitcher.setCurrentIndex(mCurrentModuleIndex);
- }
-
- @Override
- public void onDestroy() {
- unbindMediaSaveService();
- super.onDestroy();
- }
-
- // Return whether the auto-rotate screen in system settings
- // is turned on.
- public boolean isAutoRotateScreen() {
- return mAutoRotateScreen;
- }
+ private Handler mMainHandler;
private class MyOrientationEventListener
- extends OrientationEventListener {
+ extends OrientationEventListener {
public MyOrientationEventListener(Context context) {
super(context);
}
@@ -171,155 +103,149 @@ public class CameraActivity extends ActivityBase
}
}
- private ObjectAnimator mCameraSwitchAnimator;
-
- @Override
- public void onCameraSelected(final int i) {
- if (mPaused) return;
- if (i != mCurrentModuleIndex) {
- mPaused = true;
- CameraScreenNail screenNail = getCameraScreenNail();
- if (screenNail != null) {
- if (mCameraSwitchAnimator != null && mCameraSwitchAnimator.isRunning()) {
- mCameraSwitchAnimator.cancel();
- }
- mCameraSwitchAnimator = ObjectAnimator.ofFloat(
- screenNail, "alpha", screenNail.getAlpha(), 0f);
- mCameraSwitchAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- doChangeCamera(i);
- }
- });
- mCameraSwitchAnimator.start();
- } else {
- doChangeCamera(i);
+ private MediaSaveService mMediaSaveService;
+ private ServiceConnection mConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder b) {
+ mMediaSaveService = ((MediaSaveService.LocalBinder) b).getService();
+ mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
}
- }
- }
-
- private void doChangeCamera(int i) {
- boolean canReuse = canReuseScreenNail();
- CameraHolder.instance().keep();
- closeModule(mCurrentModule);
- mCurrentModuleIndex = i;
- switch (i) {
- case VIDEO_MODULE_INDEX:
- mCurrentModule = new VideoModule();
- break;
- case PHOTO_MODULE_INDEX:
- mCurrentModule = new PhotoModule();
- break;
- case PANORAMA_MODULE_INDEX:
- mCurrentModule = new PanoramaModule();
- break;
- case LIGHTCYCLE_MODULE_INDEX:
- mCurrentModule = LightCycleHelper.createPanoramaModule();
- break;
- }
- showPieMenuButton(mCurrentModule.needsPieMenu());
-
- openModule(mCurrentModule, canReuse);
- mCurrentModule.onOrientationChanged(mLastRawOrientation);
- if (mMediaSaveService != null) {
- mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
- }
- getCameraScreenNail().setAlpha(0f);
- getCameraScreenNail().setOnFrameDrawnOneShot(mOnFrameDrawn);
- }
-
- public void showPieMenuButton(boolean show) {
- if (show) {
- findViewById(R.id.blocker).setVisibility(View.VISIBLE);
- findViewById(R.id.menu).setVisibility(View.VISIBLE);
- findViewById(R.id.on_screen_indicators).setVisibility(View.VISIBLE);
- } else {
- findViewById(R.id.blocker).setVisibility(View.INVISIBLE);
- findViewById(R.id.menu).setVisibility(View.INVISIBLE);
- findViewById(R.id.on_screen_indicators).setVisibility(View.INVISIBLE);
- }
- }
-
- private Runnable mOnFrameDrawn = new Runnable() {
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ mMediaSaveService = null;
+ }};
- @Override
- public void run() {
- runOnUiThread(mFadeInCameraScreenNail);
- }
- };
+ private FilmStripView.Listener mFilmStripListener = new FilmStripView.Listener() {
+ @Override
+ public void onDataPromoted(int dataID) {
+ removeData(dataID);
+ }
- private Runnable mFadeInCameraScreenNail = new Runnable() {
+ @Override
+ public void onDataDemoted(int dataID) {
+ removeData(dataID);
+ }
- @Override
- public void run() {
- mCameraSwitchAnimator = ObjectAnimator.ofFloat(
- getCameraScreenNail(), "alpha", 0f, 1f);
- mCameraSwitchAnimator.setStartDelay(50);
- mCameraSwitchAnimator.start();
- }
- };
+ @Override
+ public void onDataFullScreenChange(int dataID, boolean full) {
+ }
- @Override
- public void onShowSwitcherPopup() {
- mCurrentModule.onShowSwitcherPopup();
- }
+ @Override
+ public void onSwitchMode(boolean toCamera) {
+ mCurrentModule.onSwitchMode(toCamera);
+ }
+ };
- private void openModule(CameraModule module, boolean canReuse) {
- module.init(this, mFrame, canReuse && canReuseScreenNail());
- mPaused = false;
- module.onResumeBeforeSuper();
- module.onResumeAfterSuper();
- }
+ private Runnable mDeletionRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mDataAdapter.executeDeletion(CameraActivity.this);
+ }
+ };
- private void closeModule(CameraModule module) {
- module.onPauseBeforeSuper();
- module.onPauseAfterSuper();
- mFrame.removeAllViews();
+ public MediaSaveService getMediaSaveService() {
+ return mMediaSaveService;
}
- public ShutterButton getShutterButton() {
- return mShutter;
+ 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 {
+ android.util.Log.w(TAG, "Unknown new media with MIME type:"
+ + mimeType + ", uri:" + uri);
+ }
}
- public void hideUI() {
- mCameraControls.setVisibility(View.INVISIBLE);
- hideSwitcher();
- mShutter.setVisibility(View.GONE);
+ private void removeData(int dataID) {
+ mDataAdapter.removeData(CameraActivity.this, dataID);
+ mMainHandler.removeCallbacks(mDeletionRunnable);
+ mMainHandler.postDelayed(mDeletionRunnable, 3000);
}
- public void showUI() {
- mCameraControls.setVisibility(View.VISIBLE);
- showSwitcher();
- mShutter.setVisibility(View.VISIBLE);
- // Force a layout change to show shutter button
- mShutter.requestLayout();
+ 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);
}
- public void hideSwitcher() {
- mSwitcher.closePopup();
- mSwitcher.setVisibility(View.INVISIBLE);
+ private void unbindMediaSaveService() {
+ if (mMediaSaveService != null) {
+ mMediaSaveService.setListener(null);
+ }
+ if (mConnection != null) {
+ unbindService(mConnection);
+ }
}
- public void showSwitcher() {
- if (mCurrentModule.needsSwitcher()) {
- mSwitcher.setVisibility(View.VISIBLE);
+ @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)) {
+ mSecureCamera = true;
+ } else if (ACTION_IMAGE_CAPTURE_SECURE.equals(action)) {
+ mSecureCamera = true;
+ } else {
+ mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false);
}
+ /*TODO: if (mSecureCamera) {
+ IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
+ registerReceiver(mScreenOffReceiver, filter);
+ if (sScreenOffReceiver == null) {
+ sScreenOffReceiver = new ScreenOffReceiver();
+ getApplicationContext().registerReceiver(sScreenOffReceiver, filter);
+ }
+ }*/
+ LayoutInflater inflater = getLayoutInflater();
+ View rootLayout = inflater.inflate(R.layout.camera, null, false);
+ mRootView = rootLayout.findViewById(R.id.camera_app_root);
+ mDataAdapter = new CameraDataAdapter(
+ new ColorDrawable(getResources().getColor(R.color.photo_placeholder)));
+ mFilmStripView = (FilmStripView) findViewById(R.id.filmstrip_view);
+ mFilmStripView.setViewGap(
+ getResources().getDimensionPixelSize(R.dimen.camera_film_strip_gap));
+ // Set up the camera preview first so the preview shows up ASAP.
+ mDataAdapter.setCameraPreviewInfo(rootLayout,
+ FilmStripView.ImageData.SIZE_FULL, FilmStripView.ImageData.SIZE_FULL);
+ mFilmStripView.setDataAdapter(mDataAdapter);
+ mFilmStripView.setListener(mFilmStripListener);
+ mCurrentModule = new PhotoModule();
+ mCurrentModule.init(this, mRootView);
+ mOrientationListener = new MyOrientationEventListener(this);
+ mMainHandler = new Handler(getMainLooper());
+ bindMediaSaveService();
}
- public boolean isInCameraApp() {
- return mShowCameraAppView;
+ 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 onConfigurationChanged(Configuration config) {
- super.onConfigurationChanged(config);
- mCurrentModule.onConfigurationChanged(config);
+ public void onUserInteraction() {
+ super.onUserInteraction();
+ mCurrentModule.onUserInteraction();
}
@Override
public void onPause() {
- mPaused = true;
mOrientationListener.disable();
mCurrentModule.onPauseBeforeSuper();
super.onPause();
@@ -328,7 +254,6 @@ public class CameraActivity extends ActivityBase
@Override
public void onResume() {
- mPaused = false;
if (Settings.System.getInt(getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION, 0) == 0) {// auto-rotate off
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
@@ -341,180 +266,185 @@ public class CameraActivity extends ActivityBase
mCurrentModule.onResumeBeforeSuper();
super.onResume();
mCurrentModule.onResumeAfterSuper();
- }
- private void bindMediaSaveService() {
- Intent intent = new Intent(this, MediaSaveService.class);
- bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- }
-
- private void unbindMediaSaveService() {
- if (mMediaSaveService != null) {
- mMediaSaveService.setListener(null);
- }
- if (mConnection != null) {
- unbindService(mConnection);
- }
- }
-
- @Override
- protected void onFullScreenChanged(boolean full) {
- if (full) {
- showUI();
+ // The loading is done in background and will update the filmstrip later.
+ if (!mSecureCamera) {
+ mDataAdapter.requestLoad(getContentResolver());
} else {
- hideUI();
+ // Flush out all the original data first.
+ mDataAdapter.flush();
+ ImageView v = (ImageView) getLayoutInflater().inflate(
+ R.layout.secure_album_placeholder, null);
+ // Put a lock placeholder as the last image by setting its date to 0.
+ mDataAdapter.addLocalData(
+ new LocalData.LocalViewData(
+ v,
+ v.getDrawable().getIntrinsicWidth(),
+ v.getDrawable().getIntrinsicHeight(),
+ 0, 0));
}
- super.onFullScreenChanged(full);
- if (ApiHelper.HAS_ROTATION_ANIMATION) {
- setRotationAnimation(full);
- }
- mCurrentModule.onFullScreenChanged(full);
- }
-
- private void setRotationAnimation(boolean fullscreen) {
- int rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
- if (fullscreen) {
- rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
- }
- Window win = getWindow();
- WindowManager.LayoutParams winParams = win.getAttributes();
- winParams.rotationAnimation = rotationAnimation;
- win.setAttributes(winParams);
+ setSwipingEnabled(true);
}
@Override
- protected void onStop() {
- super.onStop();
- mCurrentModule.onStop();
- getStateManager().clearTasks();
+ public void onDestroy() {
+ unbindMediaSaveService();
+ super.onDestroy();
}
@Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- getStateManager().clearActivityResult();
+ public void onConfigurationChanged(Configuration config) {
+ super.onConfigurationChanged(config);
+ mCurrentModule.onConfigurationChanged(config);
}
@Override
- protected void installIntentFilter() {
- super.installIntentFilter();
- mCurrentModule.installIntentFilter();
+ 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
- protected void onActivityResult(
- int requestCode, int resultCode, Intent data) {
- // Only PhotoPage understands ProxyLauncher.RESULT_USER_CANCELED
- if (resultCode == ProxyLauncher.RESULT_USER_CANCELED
- && !(getStateManager().getTopState() instanceof PhotoPage)) {
- resultCode = RESULT_CANCELED;
- }
- super.onActivityResult(requestCode, resultCode, data);
- // Unmap cancel vs. reset
- if (resultCode == ProxyLauncher.RESULT_USER_CANCELED) {
- resultCode = RESULT_CANCELED;
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (mCurrentModule.onKeyUp(keyCode, event)) return true;
+ if (keyCode == KeyEvent.KEYCODE_MENU && mShowCameraPreview) {
+ return true;
}
- mCurrentModule.onActivityResult(requestCode, resultCode, data);
+ return super.onKeyUp(keyCode, event);
}
- // Preview area is touched. Handle touch focus.
- // Touch to focus is handled by PreviewGestures, this function call
- // is no longer needed. TODO: Clean it up in the next refactor
@Override
- protected void onSingleTapUp(View view, int x, int y) {
+ public boolean dispatchTouchEvent(MotionEvent m) {
+ return mFilmStripView.dispatchTouchEvent(m);
+ }
+ public boolean isAutoRotateScreen() {
+ return mAutoRotateScreen;
}
- @Override
- public void onBackPressed() {
- if (!mCurrentModule.onBackPressed()) {
- super.onBackPressed();
- }
+ protected void updateStorageSpace() {
+ mStorageSpace = Storage.getAvailableSpace();
}
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return mCurrentModule.onKeyDown(keyCode, event)
- || super.onKeyDown(keyCode, event);
+ protected long getStorageSpace() {
+ return mStorageSpace;
}
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return mCurrentModule.onKeyUp(keyCode, event)
- || super.onKeyUp(keyCode, event);
+ protected void updateStorageSpaceAndHint() {
+ updateStorageSpace();
+ updateStorageHint(mStorageSpace);
}
- public void cancelActivityTouchHandling() {
- if (mDown != null) {
- MotionEvent cancel = MotionEvent.obtain(mDown);
- cancel.setAction(MotionEvent.ACTION_CANCEL);
- super.dispatchTouchEvent(cancel);
- }
+ protected void updateStorageHint() {
+ updateStorageHint(mStorageSpace);
}
- @Override
- public boolean dispatchTouchEvent(MotionEvent m) {
- if (m.getActionMasked() == MotionEvent.ACTION_DOWN) {
- mDown = m;
+ 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 ((mSwitcher != null) && mSwitcher.showsPopup() && !mSwitcher.isInsidePopup(m)) {
- return mSwitcher.onTouch(null, m);
- } else if ((mSwitcher != null) && mSwitcher.isInsidePopup(m)) {
- return superDispatchTouchEvent(m);
- } else {
- return mCurrentModule.dispatchTouchEvent(m);
+
+ 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;
}
}
- @Override
- public void startActivityForResult(Intent intent, int requestCode) {
- Intent proxyIntent = new Intent(this, ProxyLauncher.class);
- proxyIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
- proxyIntent.putExtra(Intent.EXTRA_INTENT, intent);
- super.startActivityForResult(proxyIntent, requestCode);
+ protected void setResultEx(int resultCode) {
+ mResultCodeForTesting = resultCode;
+ setResult(resultCode);
}
- public boolean superDispatchTouchEvent(MotionEvent m) {
- return super.dispatchTouchEvent(m);
+ protected void setResultEx(int resultCode, Intent data) {
+ mResultCodeForTesting = resultCode;
+ mResultDataForTesting = data;
+ setResult(resultCode, data);
}
- // Preview texture has been copied. Now camera can be released and the
- // animation can be started.
- @Override
- public void onPreviewTextureCopied() {
- mCurrentModule.onPreviewTextureCopied();
+ public int getResultCode() {
+ return mResultCodeForTesting;
}
- @Override
- public void onCaptureTextureCopied() {
- mCurrentModule.onCaptureTextureCopied();
+ public Intent getResultData() {
+ return mResultDataForTesting;
}
- @Override
- public void onUserInteraction() {
- super.onUserInteraction();
- mCurrentModule.onUserInteraction();
+ public boolean isSecureCamera() {
+ return mSecureCamera;
}
@Override
- protected boolean updateStorageHintOnResume() {
- return mCurrentModule.updateStorageHintOnResume();
+ public void onCameraSelected(int i) {
+ if (mCurrentModuleIndex == i) return;
+
+ CameraHolder.instance().keep();
+ closeModule(mCurrentModule);
+ mCurrentModuleIndex = i;
+ switch (i) {
+ case VIDEO_MODULE_INDEX:
+ mCurrentModule = new VideoModule();
+ break;
+ case PHOTO_MODULE_INDEX:
+ mCurrentModule = new PhotoModule();
+ break;
+ case LIGHTCYCLE_MODULE_INDEX:
+ mCurrentModule = LightCycleHelper.createPanoramaModule();
+ break;
+ default:
+ break;
+ }
+
+ openModule(mCurrentModule);
+ mCurrentModule.onOrientationChanged(mLastRawOrientation);
+ if (mMediaSaveService != null) {
+ mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
+ }
}
- @Override
- public void updateCameraAppView() {
- super.updateCameraAppView();
- mCurrentModule.updateCameraAppView();
+ private void openModule(CameraModule module) {
+ module.init(this, mRootView);
+ module.onResumeBeforeSuper();
+ module.onResumeAfterSuper();
}
- private boolean canReuseScreenNail() {
- return mCurrentModuleIndex == PHOTO_MODULE_INDEX
- || mCurrentModuleIndex == VIDEO_MODULE_INDEX
- || mCurrentModuleIndex == LIGHTCYCLE_MODULE_INDEX;
+ private void closeModule(CameraModule module) {
+ module.onPauseBeforeSuper();
+ module.onPauseAfterSuper();
+ ((ViewGroup) mRootView).removeAllViews();
}
@Override
- public boolean isPanoramaActivity() {
- return (mCurrentModuleIndex == PANORAMA_MODULE_INDEX);
+ public void onShowSwitcherPopup() {
+ }
+
+ public void setSwipingEnabled(boolean enable) {
+ mDataAdapter.setCameraPreviewLock(!enable);
}
// Accessor methods for getting latency times used in performance testing
@@ -552,12 +482,4 @@ public class CameraActivity extends ActivityBase
return (mCurrentModule instanceof VideoModule) ?
((VideoModule) mCurrentModule).isRecording() : false;
}
-
- public CameraScreenNail getCameraScreenNail() {
- return (CameraScreenNail) mCameraScreenNail;
- }
-
- public MediaSaveService getMediaSaveService() {
- return mMediaSaveService;
- }
}
diff --git a/src/com/android/camera/CameraModule.java b/src/com/android/camera/CameraModule.java
index 3275d5f51..bcfe98d65 100644
--- a/src/com/android/camera/CameraModule.java
+++ b/src/com/android/camera/CameraModule.java
@@ -24,9 +24,9 @@ import android.view.View;
public interface CameraModule {
- public void init(CameraActivity activity, View frame, boolean reuseScreenNail);
+ public void init(CameraActivity activity, View frame);
- public void onFullScreenChanged(boolean full);
+ public void onSwitchMode(boolean toCamera);
public void onPauseBeforeSuper();
@@ -52,8 +52,6 @@ public interface CameraModule {
public void onSingleTapUp(View view, int x, int y);
- public boolean dispatchTouchEvent(MotionEvent m);
-
public void onPreviewTextureCopied();
public void onCaptureTextureCopied();
@@ -64,10 +62,6 @@ public interface CameraModule {
public void updateCameraAppView();
- public boolean needsSwitcher();
-
- public boolean needsPieMenu();
-
public void onOrientationChanged(int orientation);
public void onShowSwitcherPopup();
diff --git a/src/com/android/camera/NewCameraActivity.java b/src/com/android/camera/NewCameraActivity.java
deleted file mode 100644
index 8985f7f58..000000000
--- a/src/com/android/camera/NewCameraActivity.java
+++ /dev/null
@@ -1,456 +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.Activity;
-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.view.LayoutInflater;
-import android.view.MotionEvent;
-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 com.android.camera.data.CameraDataAdapter;
-import com.android.camera.data.LocalData;
-import com.android.camera.ui.CameraSwitcher.CameraSwitchListener;
-import com.android.camera.ui.FilmStripView;
-import com.android.camera.ui.NewCameraRootView;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-import com.android.gallery3d.util.LightCycleHelper;
-
-public class NewCameraActivity extends Activity
- implements CameraSwitchListener {
- public static final int PHOTO_MODULE_INDEX = 0;
- public static final int VIDEO_MODULE_INDEX = 1;
- public static final int PANORAMA_MODULE_INDEX = 2;
- public static final int LIGHTCYCLE_MODULE_INDEX = 3;
- 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";
-
- private static final String TAG = "CAM_Activity";
- private CameraDataAdapter mDataAdapter;
- private int mCurrentModuleIndex;
- private NewCameraModule mCurrentModule;
- private View mRootView;
- private FilmStripView mFilmStripView;
- private int mResultCodeForTesting;
- private Intent mResultDataForTesting;
- private OnScreenHint mStorageHint;
- private long mStorageSpace = Storage.LOW_STORAGE_THRESHOLD;
- private PhotoModule mController;
- private boolean mAutoRotateScreen;
- private boolean mSecureCamera;
- private int mLastRawOrientation;
- private MyOrientationEventListener mOrientationListener;
- private Handler mMainHandler;
- 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;
- }};
-
- 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);
- }
- };
-
- private Runnable mDeletionRunnable = new Runnable() {
- @Override
- public void run() {
- mDataAdapter.executeDeletion(NewCameraActivity.this);
- }
- };
-
- 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 {
- android.util.Log.w(TAG, "Unknown new media with MIME type:"
- + mimeType + ", uri:" + uri);
- }
- }
-
- private void removeData(int dataID) {
- mDataAdapter.removeData(NewCameraActivity.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)) {
- mSecureCamera = true;
- } else if (ACTION_IMAGE_CAPTURE_SECURE.equals(action)) {
- mSecureCamera = true;
- } else {
- mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false);
- }
- /*TODO: if (mSecureCamera) {
- IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
- registerReceiver(mScreenOffReceiver, filter);
- if (sScreenOffReceiver == null) {
- sScreenOffReceiver = new ScreenOffReceiver();
- getApplicationContext().registerReceiver(sScreenOffReceiver, filter);
- }
- }*/
- LayoutInflater inflater = getLayoutInflater();
- View rootLayout = inflater.inflate(R.layout.camera, null, false);
- mRootView = rootLayout.findViewById(R.id.camera_app_root);
- mDataAdapter = new CameraDataAdapter(
- new ColorDrawable(getResources().getColor(R.color.photo_placeholder)));
- mFilmStripView = (FilmStripView) findViewById(R.id.filmstrip_view);
- mFilmStripView.setViewGap(
- getResources().getDimensionPixelSize(R.dimen.camera_film_strip_gap));
- // Set up the camera preview first so the preview shows up ASAP.
- mDataAdapter.setCameraPreviewInfo(rootLayout,
- FilmStripView.ImageData.SIZE_FULL, FilmStripView.ImageData.SIZE_FULL);
- mFilmStripView.setDataAdapter(mDataAdapter);
- mFilmStripView.setListener(mFilmStripListener);
- mCurrentModule = new NewPhotoModule();
- mCurrentModule.init(this, mRootView);
- mOrientationListener = new MyOrientationEventListener(this);
- mMainHandler = new Handler(getMainLooper());
- bindMediaSaveService();
- }
-
- 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();
-
- // The loading is done in background and will update the filmstrip later.
- if (!mSecureCamera) {
- mDataAdapter.requestLoad(getContentResolver());
- } else {
- // Flush out all the original data first.
- mDataAdapter.flush();
- ImageView v = (ImageView) getLayoutInflater().inflate(
- R.layout.secure_album_placeholder, null);
- // Put a lock placeholder as the last image by setting its date to 0.
- mDataAdapter.addLocalData(
- new LocalData.LocalViewData(
- v,
- v.getDrawable().getIntrinsicWidth(),
- v.getDrawable().getIntrinsicHeight(),
- 0, 0));
- }
- setSwipingEnabled(true);
- }
-
- @Override
- public void onDestroy() {
- unbindMediaSaveService();
- super.onDestroy();
- }
-
- @Override
- public void onConfigurationChanged(Configuration config) {
- super.onConfigurationChanged(config);
- mCurrentModule.onConfigurationChanged(config);
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent m) {
- return mFilmStripView.dispatchTouchEvent(m);
- }
- 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 VIDEO_MODULE_INDEX:
- mCurrentModule = new NewVideoModule();
- break;
- case PHOTO_MODULE_INDEX:
- mCurrentModule = new NewPhotoModule();
- break;
- /* TODO:
- case LIGHTCYCLE_MODULE_INDEX:
- mCurrentModule = LightCycleHelper.createNewPanoramaModule();
- break; */
- default:
- break;
- }
-
- openModule(mCurrentModule);
- mCurrentModule.onOrientationChanged(mLastRawOrientation);
- if (mMediaSaveService != null) {
- mCurrentModule.onMediaSaveServiceConnected(mMediaSaveService);
- }
- }
-
- private void openModule(NewCameraModule module) {
- module.init(this, mRootView);
- module.onResumeBeforeSuper();
- module.onResumeAfterSuper();
- }
-
- private void closeModule(NewCameraModule module) {
- module.onPauseBeforeSuper();
- module.onPauseAfterSuper();
- ((ViewGroup) mRootView).removeAllViews();
- }
-
- @Override
- public void onShowSwitcherPopup() {
- }
-
- public void setSwipingEnabled(boolean enable) {
- mDataAdapter.setCameraPreviewLock(!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/NewCameraModule.java b/src/com/android/camera/NewCameraModule.java
deleted file mode 100644
index a98c95247..000000000
--- a/src/com/android/camera/NewCameraModule.java
+++ /dev/null
@@ -1,74 +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.Intent;
-import android.content.res.Configuration;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-
-public interface NewCameraModule {
-
- public void init(NewCameraActivity 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 boolean needsSwitcher();
-
- public boolean needsPieMenu();
-
- public void onOrientationChanged(int orientation);
-
- public void onShowSwitcherPopup();
-
- public void onMediaSaveServiceConnected(MediaSaveService s);
-}
diff --git a/src/com/android/camera/NewPhotoMenu.java b/src/com/android/camera/NewPhotoMenu.java
deleted file mode 100644
index c63aff458..000000000
--- a/src/com/android/camera/NewPhotoMenu.java
+++ /dev/null
@@ -1,200 +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.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 NewPhotoMenu extends PieController
- implements CountdownTimerPopup.Listener,
- ListPrefSettingPopup.Listener {
- private static String TAG = "CAM_photomenu";
-
- private final String mSettingOff;
-
- private NewPhotoUI mUI;
- private AbstractSettingPopup mPopup;
- private NewCameraActivity mActivity;
-
- public NewPhotoMenu(NewCameraActivity activity, NewPhotoUI 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(NewPhotoMenu.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(NewPhotoMenu.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/NewPhotoModule.java b/src/com/android/camera/NewPhotoModule.java
deleted file mode 100644
index 6e306e48f..000000000
--- a/src/com/android/camera/NewPhotoModule.java
+++ /dev/null
@@ -1,2037 +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.annotation.TargetApi;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.ContentProviderClient;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-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.PictureCallback;
-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.MotionEvent;
-import android.view.OrientationEventListener;
-import android.view.SurfaceHolder;
-import android.view.View;
-import android.view.WindowManager;
-
-import com.android.camera.CameraManager.CameraProxy;
-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.Collections;
-import java.util.Formatter;
-import java.util.List;
-
-public class NewPhotoModule
- implements NewCameraModule,
- 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;
- private static final int CAPTURE_ANIMATION_DONE = 13;
-
- // 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 NewCameraActivity mActivity;
- private CameraProxy mCameraDevice;
- private int mCameraId;
- private Parameters mParameters;
- private boolean mPaused;
-
- private NewPhotoUI 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 Runnable mFlashRunnable = new Runnable() {
- @Override
- public void run() {
- animateFlash();
- }
- };
-
- 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;
- }
- case CAPTURE_ANIMATION_DONE: {
- mUI.enablePreviewThumb(false);
- break;
- }
- }
- }
- }
-
- @Override
- public void init(NewCameraActivity activity, View parent) {
- mActivity = activity;
- mUI = new NewPhotoUI(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;
- }
-
- 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) {
- setLocationPreference(RecordLocationPreference.VALUE_ON);
- }
- })
- .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) {
- setLocationPreference(RecordLocationPreference.VALUE_OFF);
- }
- })
- .show();
- }
-
- 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.setPreviewDisplayAsync(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.setFaceDetectionListener(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.setFaceDetectionListener(null);
- mCameraDevice.stopFaceDetection();
- mUI.clearFaces();
- }
- }
-
- private final class ShutterCallback
- implements android.hardware.Camera.ShutterCallback {
-
- private boolean mAnimateFlash;
-
- public ShutterCallback(boolean animateFlash) {
- mAnimateFlash = animateFlash;
- }
-
- @Override
- public void onShutter() {
- mShutterCallbackTime = System.currentTimeMillis();
- mShutterLag = mShutterCallbackTime - mCaptureStartTime;
- Log.v(TAG, "mShutterLag = " + mShutterLag + "ms");
- if (mAnimateFlash) {
- mActivity.runOnUiThread(mFlashRunnable);
- }
- }
- }
-
- private final class PostViewPictureCallback implements PictureCallback {
- @Override
- public void onPictureTaken(
- byte [] data, android.hardware.Camera camera) {
- mPostViewPictureCallbackTime = System.currentTimeMillis();
- Log.v(TAG, "mShutterToPostViewCallbackTime = "
- + (mPostViewPictureCallbackTime - mShutterCallbackTime)
- + "ms");
- }
- }
-
- private final class RawPictureCallback implements PictureCallback {
- @Override
- public void onPictureTaken(
- byte [] rawData, android.hardware.Camera camera) {
- mRawPictureCallbackTime = System.currentTimeMillis();
- Log.v(TAG, "mShutterToRawCallbackTime = "
- + (mRawPictureCallbackTime - mShutterCallbackTime) + "ms");
- }
- }
-
- private final class JpegPictureCallback implements PictureCallback {
- Location mLocation;
-
- public JpegPictureCallback(Location loc) {
- mLocation = loc;
- }
-
- @Override
- public void onPictureTaken(
- final byte [] jpegData, final android.hardware.Camera camera) {
- if (mPaused) {
- return;
- }
- //TODO: We should show the picture taken rather than frozen preview here
- if (mIsImageCaptureIntent) {
- stopPreview();
- }
- 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");
-
- /*TODO:
- // 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 (ApiHelper.HAS_SURFACE_TEXTURE && !mIsImageCaptureIntent
- && mActivity.mShowCameraAppView) {
- // Finish capture animation
- mHandler.removeMessages(CAPTURE_ANIMATION_DONE);
- ((CameraScreenNail) mActivity.mCameraScreenNail).animateSlide();
- mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE,
- CaptureAnimManager.getAnimationDuration());
- } */
- 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 android.hardware.Camera.AutoFocusCallback {
- @Override
- public void onAutoFocus(
- boolean focused, android.hardware.Camera 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 android.hardware.Camera.AutoFocusMoveCallback {
- @Override
- public void onAutoFocusMoving(
- boolean moving, android.hardware.Camera 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 animateFlash() {
- /* //TODO:
- // 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 (ApiHelper.HAS_SURFACE_TEXTURE && !mIsImageCaptureIntent
- && mActivity.mShowCameraAppView) {
- // Start capture animation.
- ((CameraScreenNail) mActivity.mCameraScreenNail).animateFlash(mDisplayRotation);
- mUI.enablePreviewThumb(true);
- mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE,
- CaptureAnimManager.getAnimationDuration());
- } */
- }
-
- @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) {
- animateFlash();
- }
-
- // 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.takePicture2(new ShutterCallback(!animateBefore),
- mRawPictureCallback, mPostViewPictureCallback,
- new JpegPictureCallback(loc), mCameraState,
- mFocusManager.getFocusState());
-
- 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()
- && ActivityBase.isFirstStartAfterScreenOn()) {
- ActivityBase.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(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.setFaceDetectionListener(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.setPreviewTextureAsync((SurfaceTexture) st);
- }
-
- Log.v(TAG, "startPreview");
- mCameraDevice.startPreviewAsync();
- 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(
- (AutoFocusMoveCallback) mAutoFocusMoveCallback);
- } else {
- mCameraDevice.setAutoFocusMoveCallback(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)
- || ActivityBase.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 boolean needsSwitcher() {
- return !mIsImageCaptureIntent;
- }
-
- @Override
- public boolean needsPieMenu() {
- return true;
- }
-
- @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/NewPhotoUI.java b/src/com/android/camera/NewPhotoUI.java
deleted file mode 100644
index a049787b1..000000000
--- a/src/com/android/camera/NewPhotoUI.java
+++ /dev/null
@@ -1,793 +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.graphics.Matrix;
-import android.graphics.SurfaceTexture;
-import android.hardware.Camera;
-import android.hardware.Camera.Face;
-import android.hardware.Camera.FaceDetectionListener;
-import android.hardware.Camera.Parameters;
-import android.hardware.Camera.Size;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.MotionEvent;
-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.CameraSwitcher.CameraSwitchListener;
-import com.android.camera.ui.CountDownView;
-import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
-import com.android.camera.ui.CameraSwitcher;
-import com.android.camera.ui.FaceView;
-import com.android.camera.ui.FocusIndicator;
-import com.android.camera.ui.NewCameraRootView;
-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.io.IOException;
-import java.util.List;
-
-public class NewPhotoUI implements PieListener,
- NewPreviewGestures.SingleTapListener,
- FocusUI, TextureView.SurfaceTextureListener,
- LocationManager.Listener, NewCameraRootView.MyDisplayListener,
- FaceDetectionListener {
-
- private static final String TAG = "CAM_UI";
- private static final int UPDATE_TRANSFORM_MATRIX = 1;
- private NewCameraActivity mActivity;
- private PhotoController mController;
- private NewPreviewGestures 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 NewPhotoMenu mMenu;
- private CameraSwitcher mSwitcher;
- private CameraControls mCameraControls;
-
- // 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 View mPreviewThumb;
-
- 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);
- }
- }
- };
-
- public NewPhotoUI(NewCameraActivity activity, PhotoController controller, View parent) {
- mActivity = activity;
- mController = controller;
- mRootView = parent;
-
- mActivity.getLayoutInflater().inflate(R.layout.new_photo_module,
- (ViewGroup) mRootView, true);
- mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_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(0);
- 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);
- ((NewCameraRootView) mRootView).setDisplayChangeListener(this);
- }
-
- 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 NewPhotoMenu(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 NewPreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer);
- mRenderOverlay.setGestures(mGestures);
- }
- mGestures.setZoomEnabled(params.isZoomSupported());
- mGestures.setRenderOverlay(mRenderOverlay);
- mRenderOverlay.requestLayout();
-
- initializeZoom(params);
- updateOnScreenIndicators(params, prefGroup, prefs);
- }
-
- 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 = mActivity.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 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 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 void enablePreviewThumb(boolean enabled) {
- if (enabled) {
- mPreviewThumb.setVisibility(View.VISIBLE);
- } else {
- mPreviewThumb.setVisibility(View.GONE);
- }
- }
-
- 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();
-
- 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, android.hardware.Camera camera) {
- mFaceView.setFaces(faces);
- }
-
- public void onDisplayChanged() {
- mCameraControls.checkLayoutFlip();
- mController.updateCameraOrientation();
- }
-
-}
diff --git a/src/com/android/camera/NewPreviewGestures.java b/src/com/android/camera/NewPreviewGestures.java
deleted file mode 100644
index 339c4b33f..000000000
--- a/src/com/android/camera/NewPreviewGestures.java
+++ /dev/null
@@ -1,263 +0,0 @@
-package com.android.camera;
-
-/*
- * 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.
- */
-
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-import com.android.camera.PreviewGestures.SingleTapListener;
-import com.android.camera.PreviewGestures.SwipeListener;
-import com.android.camera.ui.PieRenderer;
-import com.android.camera.ui.RenderOverlay;
-import com.android.camera.ui.ZoomRenderer;
-import com.android.gallery3d.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/* NewPreviewGestures 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 NewPreviewGestures
- implements ScaleGestureDetector.OnScaleGestureListener {
-
- private static final String TAG = "CAM_gestures";
-
- private static final long TIMEOUT_PIE = 200;
- private static final int MSG_PIE = 1;
- private static final int MODE_NONE = 0;
- private static final int MODE_PIE = 1;
- private static final int MODE_ZOOM = 2;
- private static final int MODE_MODULE = 3;
- private static final int MODE_ALL = 4;
- private static final int MODE_SWIPE = 5;
-
- 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 NewCameraActivity mActivity;
- 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 int mSlop;
- private int mTapTimeout;
- private boolean mZoomEnabled;
- private boolean mEnabled;
- private boolean mZoomOnly;
- private int mOrientation;
- private GestureDetector mGestureDetector;
-
- private GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {
- @Override
- public void onLongPress (MotionEvent e) {
- // Open pie
- if (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 (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;
- }
- };
-
- private Handler mHandler = new Handler() {
- public void handleMessage(Message msg) {
- if (msg.what == MSG_PIE) {
- mMode = MODE_PIE;
- openPie();
- }
- }
- };
-
- public interface SingleTapListener {
- public void onSingleTapUp(View v, int x, int y);
- }
-
- public NewPreviewGestures(NewCameraActivity ctx, SingleTapListener tapListener,
- ZoomRenderer zoom, PieRenderer pie) {
- mActivity = ctx;
- mTapListener = tapListener;
- mPie = pie;
- mZoom = zoom;
- mMode = MODE_ALL;
- mScale = new ScaleGestureDetector(ctx, this);
- mSlop = (int) ctx.getResources().getDimension(R.dimen.pie_touch_slop);
- mTapTimeout = ViewConfiguration.getTapTimeout();
- mEnabled = true;
- mGestureDetector = new GestureDetector(mGestureListener);
- }
-
- public void setRenderOverlay(RenderOverlay overlay) {
- mOverlay = overlay;
- }
-
- public void setOrientation(int orientation) {
- mOrientation = orientation;
- }
-
- 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;
- }
-
- // left tests for finger moving right to left
- private int getSwipeDirection(MotionEvent m) {
- float dx = 0;
- float dy = 0;
- switch (mOrientation) {
- case 0:
- dx = m.getX() - mDown.getX();
- dy = m.getY() - mDown.getY();
- break;
- case 90:
- dx = - (m.getY() - mDown.getY());
- dy = m.getX() - mDown.getX();
- break;
- case 180:
- dx = -(m.getX() - mDown.getX());
- dy = m.getY() - mDown.getY();
- break;
- case 270:
- dx = m.getY() - mDown.getY();
- dy = m.getX() - mDown.getX();
- break;
- }
- if (dx < 0 && (Math.abs(dy) / -dx < 2)) return DIR_LEFT;
- if (dx > 0 && (Math.abs(dy) / dx < 2)) return DIR_RIGHT;
- if (dy > 0) return DIR_DOWN;
- return DIR_UP;
- }
-
- 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/NewVideoMenu.java b/src/com/android/camera/NewVideoMenu.java
deleted file mode 100644
index 70f73ec39..000000000
--- a/src/com/android/camera/NewVideoMenu.java
+++ /dev/null
@@ -1,205 +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.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 NewVideoMenu extends PieController
- implements MoreSettingPopup.Listener,
- ListPrefSettingPopup.Listener,
- TimeIntervalPopup.Listener {
-
- private static String TAG = "CAM_VideoMenu";
-
- private NewVideoUI 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 NewCameraActivity mActivity;
-
- public NewVideoMenu(NewCameraActivity activity, NewVideoUI 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/NewVideoModule.java b/src/com/android/camera/NewVideoModule.java
deleted file mode 100644
index 9b6f59ba8..000000000
--- a/src/com/android/camera/NewVideoModule.java
+++ /dev/null
@@ -1,2261 +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.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.PictureCallback;
-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.MotionEvent;
-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.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 NewVideoModule implements NewCameraModule,
- 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 HIDE_SURFACE_VIEW = 10;
- private static final int CAPTURE_ANIMATION_DONE = 11;
-
- 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";
-
- private static final int MIN_THUMB_SIZE = 64;
- // module fields
- private NewCameraActivity mActivity;
- private boolean mPaused;
- private int mCameraId;
- private Parameters mParameters;
-
- private Boolean mCameraOpened = false;
- 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;
-
- 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 NewVideoUI 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.sendBroadcast(
- new Intent(Util.ACTION_NEW_VIDEO, uri));
- Util.broadcastNewPicture(mActivity, uri);
- }
- }
- };
-
- private final MediaSaveService.OnMediaSavedListener mOnPhotoSavedListener =
- new MediaSaveService.OnMediaSavedListener() {
- @Override
- public void onMediaSaved(Uri uri) {
- if (uri != null) {
- Util.broadcastNewPicture(mActivity, uri);
- }
- }
- };
-
-
- protected class CameraOpenThread extends Thread {
- @Override
- public void run() {
- openCamera();
- }
- }
-
- private void openCamera() {
- try {
- synchronized(mCameraOpened) {
- if (!mCameraOpened) {
- mCameraDevice = Util.openCamera(mActivity, mCameraId);
- mCameraOpened = true;
- }
- }
- 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;
- }
-
- case CAPTURE_ANIMATION_DONE: {
- mUI.enablePreviewThumb(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(NewCameraActivity activity, View root) {
- mActivity = activity;
- mUI = new NewVideoUI(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);
- new Thread(new Runnable() {
- @Override
- public void run() {
- startPreview();
- }
- }).start();
-
- 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(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(getLowVideoQuality()));
- }
- }
-
- @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
- private static int getLowVideoQuality() {
- if (ApiHelper.HAS_FINE_RESOLUTION_QUALITY_LEVELS) {
- return CamcorderProfile.QUALITY_480P;
- } else {
- return CamcorderProfile.QUALITY_LOW;
- }
- }
-
-
- @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.
- // TODO: need to get the capture animation to work
- // ((CameraScreenNail) mActivity.mCameraScreenNail).animateCapture(mDisplayRotation);
-
- mUI.enablePreviewThumb(true);
-
- // Make sure to disable the thumbnail preview after the
- // animation is done to disable the click target.
- mHandler.removeMessages(CAPTURE_ANIMATION_DONE);
- mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE,
- CaptureAnimManager.getAnimationDuration());
- }
- }
- }
-
- 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 defaultQuality = CameraSettings.getDefaultVideoQuality(mCameraId,
- mActivity.getResources().getString(R.string.pref_video_quality_default));
- String videoQuality =
- mPreferences.getString(CameraSettings.KEY_VIDEO_QUALITY,
- defaultQuality);
- 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 = getLowVideoQuality();
- }
- } 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();
- }
-
- 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();
- new Thread(new Runnable() {
- @Override
- public void run() {
- startPreview();
- }
- }).start();
- } 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");
-
- mCameraDevice.setErrorCallback(mErrorCallback);
- if (mPreviewing == true) {
- stopPreview();
- if (effectsActive() && mEffectsRecorder != null) {
- mEffectsRecorder.release();
- mEffectsRecorder = null;
- }
- }
-
- setDisplayOrientation();
- mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation);
- setCameraParameters();
-
- try {
- if (!effectsActive()) {
- SurfaceTexture surfaceTexture = mUI.getSurfaceTexture();
- if (surfaceTexture == null) {
- return; // The texture has been destroyed (pause, etc)
- }
- mCameraDevice.setPreviewTextureAsync(surfaceTexture);
- mCameraDevice.startPreviewAsync();
- mPreviewing = true;
- onPreviewStarted();
- } else {
- initializeEffectsPreview();
- mEffectsRecorder.startPreview();
- mPreviewing = true;
- onPreviewStarted();
- }
- } catch (Throwable ex) {
- closeCamera();
- throw new RuntimeException("startPreview failed", ex);
- } finally {
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- 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);
- synchronized(mCameraOpened) {
- if (mCameraOpened) {
- CameraHolder.instance().release();
- }
- mCameraOpened = false;
- }
- 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;
- // 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.setPreviewDisplayAsync(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.startPreviewAsync();
- 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();
- mCameraDevice.waitDone();
- 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.enablePreviewThumb(false);
- 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 void showCaptureResult() {
- mIsInReviewMode = true;
- 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);
- 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();
- mCameraDevice.waitDone();
- 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) {
- // TODO: ((CameraScreenNail) mActivity.mCameraScreenNail).animateCapture(mDisplayRotation);
- } 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 PictureCallback {
- Location mLocation;
-
- public JpegPictureCallback(Location loc) {
- mLocation = loc;
- }
-
- @Override
- public void onPictureTaken(byte [] jpegData, android.hardware.Camera 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 boolean needsSwitcher() {
- return !mIsVideoCaptureIntent;
- }
-
- @Override
- public boolean needsPieMenu() {
- return true;
- }
-
- @Override
- public void onShowSwitcherPopup() {
- mUI.onShowSwitcherPopup();
- }
-
- @Override
- public void onMediaSaveServiceConnected(MediaSaveService s) {
- // do nothing.
- }
-}
diff --git a/src/com/android/camera/NewVideoUI.java b/src/com/android/camera/NewVideoUI.java
deleted file mode 100644
index b0c9c507f..000000000
--- a/src/com/android/camera/NewVideoUI.java
+++ /dev/null
@@ -1,713 +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.graphics.Bitmap;
-import android.graphics.Matrix;
-import android.graphics.SurfaceTexture;
-import android.hardware.Camera.Parameters;
-import android.hardware.Camera.Size;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.MotionEvent;
-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.CameraSwitcher;
-import com.android.camera.ui.NewCameraRootView;
-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.camera.ui.CameraSwitcher.CameraSwitchListener;
-import com.android.gallery3d.R;
-import com.android.gallery3d.common.ApiHelper;
-
-import java.util.List;
-
-public class NewVideoUI implements PieRenderer.PieListener,
- NewPreviewGestures.SingleTapListener,
- NewCameraRootView.MyDisplayListener,
- SurfaceTextureListener, SurfaceHolder.Callback {
- private final static String TAG = "CAM_VideoUI";
- private static final int UPDATE_TRANSFORM_MATRIX = 1;
- // module fields
- private NewCameraActivity 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 NewVideoMenu mVideoMenu;
- private CameraControls mCameraControls;
- private AbstractSettingPopup mPopup;
- private ZoomRenderer mZoomRenderer;
- private NewPreviewGestures 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 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 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 NewVideoUI(NewCameraActivity activity, VideoController controller, View parent) {
- mActivity = activity;
- mController = controller;
- mRootView = parent;
- mActivity.getLayoutInflater().inflate(R.layout.new_video_module, (ViewGroup) mRootView, true);
- mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content);
- mTextureView.setSurfaceTextureListener(this);
- mRootView.addOnLayoutChangeListener(mLayoutListener);
- ((NewCameraRootView) mRootView).setDisplayChangeListener(this);
- mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
- mSwitcher = (CameraSwitcher) mRootView.findViewById(R.id.camera_switcher);
- mSwitcher.setCurrentIndex(1);
- mSwitcher.setSwitchListener((CameraSwitchListener) mActivity);
- initializeMiscControls();
- initializeControlByIntent();
- initializeOverlay();
- }
-
-
- 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();
- }
- }
-
- 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) {
- if (mGestures != null) {
- mGestures.setOrientation(orientation);
- }
- // 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 NewVideoMenu(mActivity, this, mPieRenderer);
- mPieRenderer.setPieListener(this);
- }
- mRenderOverlay.addRenderer(mPieRenderer);
- if (mZoomRenderer == null) {
- mZoomRenderer = new ZoomRenderer(mActivity);
- }
- mRenderOverlay.addRenderer(mZoomRenderer);
- if (mGestures == null) {
- mGestures = new NewPreviewGestures(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();
- }
-
- /**
- * Enable or disable the preview thumbnail for click events.
- */
- public void enablePreviewThumb(boolean enabled) {
- if (enabled) {
- mPreviewThumb.setVisibility(View.VISIBLE);
- } else {
- mPreviewThumb.setVisibility(View.GONE);
- }
- }
-
- 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() {
- synchronized (mLock) {
- if (mSurfaceTexture == null) {
- try {
- mLock.wait();
- } catch (InterruptedException e) {
- Log.w(TAG, "Unexpected interruption when waiting to get surface texture");
- }
- }
- }
- return mSurfaceTexture;
- }
-
- // SurfaceTexture callbacks
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- synchronized (mLock) {
- mSurfaceTexture = surface;
- mLock.notifyAll();
- }
- }
-
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- mSurfaceTexture = null;
- mController.stopPreview();
- 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/PanoramaModule.java b/src/com/android/camera/PanoramaModule.java
deleted file mode 100644
index 007ea7a4c..000000000
--- a/src/com/android/camera/PanoramaModule.java
+++ /dev/null
@@ -1,1304 +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.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.ImageFormat;
-import android.graphics.Matrix;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.SurfaceTexture;
-import android.graphics.YuvImage;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.hardware.Camera.Parameters;
-import android.hardware.Camera.Size;
-import android.location.Location;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.os.Message;
-import android.os.PowerManager;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.OrientationEventListener;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.camera.CameraManager.CameraProxy;
-import com.android.camera.ui.LayoutChangeNotifier;
-import com.android.camera.ui.LayoutNotifyView;
-import com.android.camera.ui.PopupManager;
-import com.android.camera.ui.Rotatable;
-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.ui.GLRootView;
-import com.android.gallery3d.util.UsageStatistics;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import java.util.TimeZone;
-
-/**
- * Activity to handle panorama capturing.
- */
-@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) // uses SurfaceTexture
-public class PanoramaModule implements CameraModule,
- SurfaceTexture.OnFrameAvailableListener,
- ShutterButton.OnShutterButtonListener,
- LayoutChangeNotifier.Listener {
-
- public static final int DEFAULT_SWEEP_ANGLE = 160;
- public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL;
- public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720;
-
- private static final int MSG_LOW_RES_FINAL_MOSAIC_READY = 1;
- private static final int MSG_GENERATE_FINAL_MOSAIC_ERROR = 2;
- private static final int MSG_END_DIALOG_RESET_TO_PREVIEW = 3;
- private static final int MSG_CLEAR_SCREEN_DELAY = 4;
- private static final int MSG_CONFIG_MOSAIC_PREVIEW = 5;
- private static final int MSG_RESET_TO_PREVIEW = 6;
-
- private static final int SCREEN_DELAY = 2 * 60 * 1000;
-
- private static final String TAG = "CAM PanoModule";
- private static final int PREVIEW_STOPPED = 0;
- private static final int PREVIEW_ACTIVE = 1;
- private static final int CAPTURE_STATE_VIEWFINDER = 0;
- private static final int CAPTURE_STATE_MOSAIC = 1;
- // The unit of speed is degrees per frame.
- private static final float PANNING_SPEED_THRESHOLD = 2.5f;
-
- private ContentResolver mContentResolver;
-
- private GLRootView mGLRootView;
- private ViewGroup mPanoLayout;
- private LinearLayout mCaptureLayout;
- private View mReviewLayout;
- private ImageView mReview;
- private View mCaptureIndicator;
- private PanoProgressBar mPanoProgressBar;
- private PanoProgressBar mSavingProgressBar;
- private Matrix mProgressDirectionMatrix = new Matrix();
- private float[] mProgressAngle = new float[2];
- private LayoutNotifyView mPreviewArea;
- private View mLeftIndicator;
- private View mRightIndicator;
- private MosaicPreviewRenderer mMosaicPreviewRenderer;
- private Object mRendererLock = new Object();
- private TextView mTooFastPrompt;
- private ShutterButton mShutterButton;
- private Object mWaitObject = new Object();
-
- private String mPreparePreviewString;
- private String mDialogTitle;
- private String mDialogOkString;
- private String mDialogPanoramaFailedString;
- private String mDialogWaitingPreviousString;
-
- private int mIndicatorColor;
- private int mIndicatorColorFast;
- private int mReviewBackground;
-
- private boolean mUsingFrontCamera;
- private int mPreviewWidth;
- private int mPreviewHeight;
- private int mCameraState;
- private int mCaptureState;
- private PowerManager.WakeLock mPartialWakeLock;
- private MosaicFrameProcessor mMosaicFrameProcessor;
- private boolean mMosaicFrameProcessorInitialized;
- private AsyncTask <Void, Void, Void> mWaitProcessorTask;
- private long mTimeTaken;
- private Handler mMainHandler;
- private SurfaceTexture mCameraTexture;
- private boolean mThreadRunning;
- private boolean mCancelComputation;
- private float mHorizontalViewAngle;
- private float mVerticalViewAngle;
-
- // Prefer FOCUS_MODE_INFINITY to FOCUS_MODE_CONTINUOUS_VIDEO because of
- // getting a better image quality by the former.
- private String mTargetFocusMode = Parameters.FOCUS_MODE_INFINITY;
-
- private PanoOrientationEventListener mOrientationEventListener;
- // The value could be 0, 90, 180, 270 for the 4 different orientations measured in clockwise
- // respectively.
- private int mDeviceOrientation;
- private int mDeviceOrientationAtCapture;
- private int mCameraOrientation;
- private int mOrientationCompensation;
-
- private RotateDialogController mRotateDialog;
-
- private SoundClips.Player mSoundPlayer;
-
- private Runnable mOnFrameAvailableRunnable;
-
- private CameraActivity mActivity;
- private View mRootView;
- private CameraProxy mCameraDevice;
- private boolean mPaused;
- private boolean mIsCreatingRenderer;
-
- private LocationManager mLocationManager;
- private ComboPreferences mPreferences;
-
- private class MosaicJpeg {
- public MosaicJpeg(byte[] data, int width, int height) {
- this.data = data;
- this.width = width;
- this.height = height;
- this.isValid = true;
- }
-
- public MosaicJpeg() {
- this.data = null;
- this.width = 0;
- this.height = 0;
- this.isValid = false;
- }
-
- public final byte[] data;
- public final int width;
- public final int height;
- public final boolean isValid;
- }
-
- private class PanoOrientationEventListener extends OrientationEventListener {
- public PanoOrientationEventListener(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;
- mDeviceOrientation = Util.roundOrientation(orientation, mDeviceOrientation);
- // When the screen is unlocked, display rotation may change. Always
- // calculate the up-to-date orientationCompensation.
- int orientationCompensation = mDeviceOrientation
- + Util.getDisplayRotation(mActivity) % 360;
- if (mOrientationCompensation != orientationCompensation) {
- mOrientationCompensation = orientationCompensation;
- mActivity.getGLRoot().requestLayoutContentPane();
- }
- }
- }
-
- @Override
- public void init(CameraActivity activity, View parent, boolean reuseScreenNail) {
- mActivity = activity;
- mRootView = parent;
-
- createContentView();
-
- mContentResolver = mActivity.getContentResolver();
- if (reuseScreenNail) {
- mActivity.reuseCameraScreenNail(true);
- } else {
- mActivity.createCameraScreenNail(true);
- }
-
- // This runs in UI thread.
- mOnFrameAvailableRunnable = new Runnable() {
- @Override
- public void run() {
- // Frames might still be available after the activity is paused.
- // If we call onFrameAvailable after pausing, the GL thread will crash.
- if (mPaused) return;
-
- MosaicPreviewRenderer renderer = null;
- synchronized (mRendererLock) {
- if (mMosaicPreviewRenderer == null) {
- return;
- }
- renderer = mMosaicPreviewRenderer;
- }
- if (mGLRootView.getVisibility() != View.VISIBLE) {
- renderer.showPreviewFrameSync();
- mGLRootView.setVisibility(View.VISIBLE);
- } else {
- if (mCaptureState == CAPTURE_STATE_VIEWFINDER) {
- renderer.showPreviewFrame();
- } else {
- renderer.alignFrameSync();
- mMosaicFrameProcessor.processFrame();
- }
- }
- }
- };
-
- PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE);
- mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Panorama");
-
- mOrientationEventListener = new PanoOrientationEventListener(mActivity);
-
- mMosaicFrameProcessor = MosaicFrameProcessor.getInstance();
-
- Resources appRes = mActivity.getResources();
- mPreparePreviewString = appRes.getString(R.string.pano_dialog_prepare_preview);
- mDialogTitle = appRes.getString(R.string.pano_dialog_title);
- mDialogOkString = appRes.getString(R.string.dialog_ok);
- mDialogPanoramaFailedString = appRes.getString(R.string.pano_dialog_panorama_failed);
- mDialogWaitingPreviousString = appRes.getString(R.string.pano_dialog_waiting_previous);
-
- mGLRootView = (GLRootView) mActivity.getGLRoot();
-
- mPreferences = new ComboPreferences(mActivity);
- CameraSettings.upgradeGlobalPreferences(mPreferences.getGlobal());
- mLocationManager = new LocationManager(mActivity, null);
-
- mMainHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_LOW_RES_FINAL_MOSAIC_READY:
- onBackgroundThreadFinished();
- showFinalMosaic((Bitmap) msg.obj);
- saveHighResMosaic();
- break;
- case MSG_GENERATE_FINAL_MOSAIC_ERROR:
- onBackgroundThreadFinished();
- if (mPaused) {
- resetToPreview();
- } else {
- mRotateDialog.showAlertDialog(
- mDialogTitle, mDialogPanoramaFailedString,
- mDialogOkString, new Runnable() {
- @Override
- public void run() {
- resetToPreview();
- }},
- null, null);
- }
- clearMosaicFrameProcessorIfNeeded();
- break;
- case MSG_END_DIALOG_RESET_TO_PREVIEW:
- onBackgroundThreadFinished();
- resetToPreview();
- clearMosaicFrameProcessorIfNeeded();
- break;
- case MSG_CLEAR_SCREEN_DELAY:
- mActivity.getWindow().clearFlags(WindowManager.LayoutParams.
- FLAG_KEEP_SCREEN_ON);
- break;
- case MSG_CONFIG_MOSAIC_PREVIEW:
- configMosaicPreview(msg.arg1, msg.arg2);
- break;
- case MSG_RESET_TO_PREVIEW:
- resetToPreview();
- break;
- }
- }
- };
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent m) {
- return mActivity.superDispatchTouchEvent(m);
- }
-
- private void setupCamera() throws CameraHardwareException, CameraDisabledException {
- openCamera();
- Parameters parameters = mCameraDevice.getParameters();
- setupCaptureParams(parameters);
- configureCamera(parameters);
- }
-
- private void releaseCamera() {
- if (mCameraDevice != null) {
- mCameraDevice.setPreviewCallbackWithBuffer(null);
- CameraHolder.instance().release();
- mCameraDevice = null;
- mCameraState = PREVIEW_STOPPED;
- }
- }
-
- private void openCamera() throws CameraHardwareException, CameraDisabledException {
- int cameraId = CameraHolder.instance().getBackCameraId();
- // If there is no back camera, use the first camera. Camera id starts
- // from 0. Currently if a camera is not back facing, it is front facing.
- // This is also forward compatible if we have a new facing other than
- // back or front in the future.
- if (cameraId == -1) cameraId = 0;
- mCameraDevice = Util.openCamera(mActivity, cameraId);
- mCameraOrientation = Util.getCameraOrientation(cameraId);
- if (cameraId == CameraHolder.instance().getFrontCameraId()) mUsingFrontCamera = true;
- }
-
- private boolean findBestPreviewSize(List<Size> supportedSizes, boolean need4To3,
- boolean needSmaller) {
- int pixelsDiff = DEFAULT_CAPTURE_PIXELS;
- boolean hasFound = false;
- for (Size size : supportedSizes) {
- int h = size.height;
- int w = size.width;
- // we only want 4:3 format.
- int d = DEFAULT_CAPTURE_PIXELS - h * w;
- if (needSmaller && d < 0) { // no bigger preview than 960x720.
- continue;
- }
- if (need4To3 && (h * 4 != w * 3)) {
- continue;
- }
- d = Math.abs(d);
- if (d < pixelsDiff) {
- mPreviewWidth = w;
- mPreviewHeight = h;
- pixelsDiff = d;
- hasFound = true;
- }
- }
- return hasFound;
- }
-
- private void setupCaptureParams(Parameters parameters) {
- List<Size> supportedSizes = parameters.getSupportedPreviewSizes();
- if (!findBestPreviewSize(supportedSizes, true, true)) {
- Log.w(TAG, "No 4:3 ratio preview size supported.");
- if (!findBestPreviewSize(supportedSizes, false, true)) {
- Log.w(TAG, "Can't find a supported preview size smaller than 960x720.");
- findBestPreviewSize(supportedSizes, false, false);
- }
- }
- Log.v(TAG, "preview h = " + mPreviewHeight + " , w = " + mPreviewWidth);
- parameters.setPreviewSize(mPreviewWidth, mPreviewHeight);
-
- List<int[]> frameRates = parameters.getSupportedPreviewFpsRange();
- int last = frameRates.size() - 1;
- int minFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MIN_INDEX];
- int maxFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MAX_INDEX];
- parameters.setPreviewFpsRange(minFps, maxFps);
- Log.v(TAG, "preview fps: " + minFps + ", " + maxFps);
-
- List<String> supportedFocusModes = parameters.getSupportedFocusModes();
- if (supportedFocusModes.indexOf(mTargetFocusMode) >= 0) {
- parameters.setFocusMode(mTargetFocusMode);
- } else {
- // Use the default focus mode and log a message
- Log.w(TAG, "Cannot set the focus mode to " + mTargetFocusMode +
- " becuase the mode is not supported.");
- }
-
- parameters.set(Util.RECORDING_HINT, Util.FALSE);
-
- mHorizontalViewAngle = parameters.getHorizontalViewAngle();
- mVerticalViewAngle = parameters.getVerticalViewAngle();
- }
-
- public int getPreviewBufSize() {
- PixelFormat pixelInfo = new PixelFormat();
- PixelFormat.getPixelFormatInfo(mCameraDevice.getParameters().getPreviewFormat(), pixelInfo);
- // TODO: remove this extra 32 byte after the driver bug is fixed.
- return (mPreviewWidth * mPreviewHeight * pixelInfo.bitsPerPixel / 8) + 32;
- }
-
- private void configureCamera(Parameters parameters) {
- mCameraDevice.setParameters(parameters);
- }
-
- private void configMosaicPreview(final int w, final int h) {
- synchronized (mRendererLock) {
- if (mIsCreatingRenderer) {
- mMainHandler.removeMessages(MSG_CONFIG_MOSAIC_PREVIEW);
- mMainHandler.obtainMessage(MSG_CONFIG_MOSAIC_PREVIEW, w, h).sendToTarget();
- return;
- }
- mIsCreatingRenderer = true;
- }
- stopCameraPreview();
- CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
- screenNail.setSize(w, h);
- synchronized (mRendererLock) {
- if (mMosaicPreviewRenderer != null) {
- mMosaicPreviewRenderer.release();
- }
- mMosaicPreviewRenderer = null;
- screenNail.releaseSurfaceTexture();
- screenNail.acquireSurfaceTexture();
- }
- mActivity.notifyScreenNailChanged();
- final boolean isLandscape = (mActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
- new Thread(new Runnable() {
- @Override
- public void run() {
- CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
- SurfaceTexture surfaceTexture = screenNail.getSurfaceTexture();
- if (surfaceTexture == null) {
- synchronized (mRendererLock) {
- mIsCreatingRenderer = false;
- mRendererLock.notifyAll();
- return;
- }
- }
- MosaicPreviewRenderer renderer = new MosaicPreviewRenderer(
- screenNail.getSurfaceTexture(), w, h, isLandscape);
- synchronized (mRendererLock) {
- mMosaicPreviewRenderer = renderer;
- mCameraTexture = mMosaicPreviewRenderer.getInputSurfaceTexture();
-
- if (!mPaused && !mThreadRunning && mWaitProcessorTask == null) {
- mMainHandler.sendEmptyMessage(MSG_RESET_TO_PREVIEW);
- }
- mIsCreatingRenderer = false;
- mRendererLock.notifyAll();
- }
- }
- }).start();
- }
-
- // Receives the layout change event from the preview area. So we can set
- // the camera preview screennail to the same size and initialize the mosaic
- // preview renderer.
- @Override
- public void onLayoutChange(View v, int l, int t, int r, int b) {
- Log.i(TAG, "layout change: "+(r - l) + "/" +(b - t));
- mActivity.onLayoutChange(v, l, t, r, b);
- configMosaicPreview(r - l, b - t);
- }
-
- @Override
- public void onFrameAvailable(SurfaceTexture surface) {
- /* This function may be called by some random thread,
- * so let's be safe and jump back to ui thread.
- * No OpenGL calls can be done here. */
- mActivity.runOnUiThread(mOnFrameAvailableRunnable);
- }
-
- private void hideDirectionIndicators() {
- mLeftIndicator.setVisibility(View.GONE);
- mRightIndicator.setVisibility(View.GONE);
- }
-
- private void showDirectionIndicators(int direction) {
- switch (direction) {
- case PanoProgressBar.DIRECTION_NONE:
- mLeftIndicator.setVisibility(View.VISIBLE);
- mRightIndicator.setVisibility(View.VISIBLE);
- break;
- case PanoProgressBar.DIRECTION_LEFT:
- mLeftIndicator.setVisibility(View.VISIBLE);
- mRightIndicator.setVisibility(View.GONE);
- break;
- case PanoProgressBar.DIRECTION_RIGHT:
- mLeftIndicator.setVisibility(View.GONE);
- mRightIndicator.setVisibility(View.VISIBLE);
- break;
- }
- }
-
- public void startCapture() {
- // Reset values so we can do this again.
- mCancelComputation = false;
- mTimeTaken = System.currentTimeMillis();
- mActivity.setSwipingEnabled(false);
- mActivity.hideSwitcher();
- mShutterButton.setImageResource(R.drawable.btn_shutter_recording);
- mCaptureState = CAPTURE_STATE_MOSAIC;
- mCaptureIndicator.setVisibility(View.VISIBLE);
- showDirectionIndicators(PanoProgressBar.DIRECTION_NONE);
-
- mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() {
- @Override
- public void onProgress(boolean isFinished, float panningRateX, float panningRateY,
- float progressX, float progressY) {
- float accumulatedHorizontalAngle = progressX * mHorizontalViewAngle;
- float accumulatedVerticalAngle = progressY * mVerticalViewAngle;
- if (isFinished
- || (Math.abs(accumulatedHorizontalAngle) >= DEFAULT_SWEEP_ANGLE)
- || (Math.abs(accumulatedVerticalAngle) >= DEFAULT_SWEEP_ANGLE)) {
- stopCapture(false);
- } else {
- float panningRateXInDegree = panningRateX * mHorizontalViewAngle;
- float panningRateYInDegree = panningRateY * mVerticalViewAngle;
- updateProgress(panningRateXInDegree, panningRateYInDegree,
- accumulatedHorizontalAngle, accumulatedVerticalAngle);
- }
- }
- });
-
- mPanoProgressBar.reset();
- // TODO: calculate the indicator width according to different devices to reflect the actual
- // angle of view of the camera device.
- mPanoProgressBar.setIndicatorWidth(20);
- mPanoProgressBar.setMaxProgress(DEFAULT_SWEEP_ANGLE);
- mPanoProgressBar.setVisibility(View.VISIBLE);
- mDeviceOrientationAtCapture = mDeviceOrientation;
- keepScreenOn();
- mActivity.getOrientationManager().lockOrientation();
- setupProgressDirectionMatrix();
- }
-
- void setupProgressDirectionMatrix() {
- int degrees = Util.getDisplayRotation(mActivity);
- int cameraId = CameraHolder.instance().getBackCameraId();
- int orientation = Util.getDisplayOrientation(degrees, cameraId);
- mProgressDirectionMatrix.reset();
- mProgressDirectionMatrix.postRotate(orientation);
- }
-
- private void stopCapture(boolean aborted) {
- mCaptureState = CAPTURE_STATE_VIEWFINDER;
- mCaptureIndicator.setVisibility(View.GONE);
- hideTooFastIndication();
- hideDirectionIndicators();
-
- mMosaicFrameProcessor.setProgressListener(null);
- stopCameraPreview();
-
- mCameraTexture.setOnFrameAvailableListener(null);
-
- if (!aborted && !mThreadRunning) {
- mRotateDialog.showWaitingDialog(mPreparePreviewString);
- // Hide shutter button, shutter icon, etc when waiting for
- // panorama to stitch
- mActivity.hideUI();
- runBackgroundThread(new Thread() {
- @Override
- public void run() {
- MosaicJpeg jpeg = generateFinalMosaic(false);
-
- if (jpeg != null && jpeg.isValid) {
- Bitmap bitmap = null;
- bitmap = BitmapFactory.decodeByteArray(jpeg.data, 0, jpeg.data.length);
- mMainHandler.sendMessage(mMainHandler.obtainMessage(
- MSG_LOW_RES_FINAL_MOSAIC_READY, bitmap));
- } else {
- mMainHandler.sendMessage(mMainHandler.obtainMessage(
- MSG_END_DIALOG_RESET_TO_PREVIEW));
- }
- }
- });
- }
- keepScreenOnAwhile();
- }
-
- private void showTooFastIndication() {
- mTooFastPrompt.setVisibility(View.VISIBLE);
- // The PreviewArea also contains the border for "too fast" indication.
- mPreviewArea.setVisibility(View.VISIBLE);
- mPanoProgressBar.setIndicatorColor(mIndicatorColorFast);
- mLeftIndicator.setEnabled(true);
- mRightIndicator.setEnabled(true);
- }
-
- private void hideTooFastIndication() {
- mTooFastPrompt.setVisibility(View.GONE);
- // We set "INVISIBLE" instead of "GONE" here because we need mPreviewArea to have layout
- // information so we can know the size and position for mCameraScreenNail.
- mPreviewArea.setVisibility(View.INVISIBLE);
- mPanoProgressBar.setIndicatorColor(mIndicatorColor);
- mLeftIndicator.setEnabled(false);
- mRightIndicator.setEnabled(false);
- }
-
- private void updateProgress(float panningRateXInDegree, float panningRateYInDegree,
- float progressHorizontalAngle, float progressVerticalAngle) {
- mGLRootView.requestRender();
-
- if ((Math.abs(panningRateXInDegree) > PANNING_SPEED_THRESHOLD)
- || (Math.abs(panningRateYInDegree) > PANNING_SPEED_THRESHOLD)) {
- showTooFastIndication();
- } else {
- hideTooFastIndication();
- }
-
- // progressHorizontalAngle and progressVerticalAngle are relative to the
- // camera. Convert them to UI direction.
- mProgressAngle[0] = progressHorizontalAngle;
- mProgressAngle[1] = progressVerticalAngle;
- mProgressDirectionMatrix.mapPoints(mProgressAngle);
-
- int angleInMajorDirection =
- (Math.abs(mProgressAngle[0]) > Math.abs(mProgressAngle[1]))
- ? (int) mProgressAngle[0]
- : (int) mProgressAngle[1];
- mPanoProgressBar.setProgress((angleInMajorDirection));
- }
-
- private void setViews(Resources appRes) {
- mCaptureState = CAPTURE_STATE_VIEWFINDER;
- mPanoProgressBar = (PanoProgressBar) mRootView.findViewById(R.id.pano_pan_progress_bar);
- mPanoProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty));
- mPanoProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_done));
- mPanoProgressBar.setIndicatorColor(mIndicatorColor);
- mPanoProgressBar.setOnDirectionChangeListener(
- new PanoProgressBar.OnDirectionChangeListener () {
- @Override
- public void onDirectionChange(int direction) {
- if (mCaptureState == CAPTURE_STATE_MOSAIC) {
- showDirectionIndicators(direction);
- }
- }
- });
-
- mLeftIndicator = mRootView.findViewById(R.id.pano_pan_left_indicator);
- mRightIndicator = mRootView.findViewById(R.id.pano_pan_right_indicator);
- mLeftIndicator.setEnabled(false);
- mRightIndicator.setEnabled(false);
- mTooFastPrompt = (TextView) mRootView.findViewById(R.id.pano_capture_too_fast_textview);
- // This mPreviewArea also shows the border for visual "too fast" indication.
- mPreviewArea = (LayoutNotifyView) mRootView.findViewById(R.id.pano_preview_area);
- mPreviewArea.setOnLayoutChangeListener(this);
-
- mSavingProgressBar = (PanoProgressBar) mRootView.findViewById(R.id.pano_saving_progress_bar);
- mSavingProgressBar.setIndicatorWidth(0);
- mSavingProgressBar.setMaxProgress(100);
- mSavingProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty));
- mSavingProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_indication));
-
- mCaptureIndicator = mRootView.findViewById(R.id.pano_capture_indicator);
-
- mReviewLayout = mRootView.findViewById(R.id.pano_review_layout);
- mReview = (ImageView) mRootView.findViewById(R.id.pano_reviewarea);
- mReview.setBackgroundColor(mReviewBackground);
- View cancelButton = mRootView.findViewById(R.id.pano_review_cancel_button);
- cancelButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- if (mPaused || mCameraTexture == null) return;
- cancelHighResComputation();
- }
- });
-
- mShutterButton = mActivity.getShutterButton();
- mShutterButton.setImageResource(R.drawable.btn_new_shutter);
- mShutterButton.setOnShutterButtonListener(this);
-
- if (mActivity.getResources().getConfiguration().orientation
- == Configuration.ORIENTATION_PORTRAIT) {
- Rotatable view = (Rotatable) mRootView.findViewById(R.id.pano_rotate_reviewarea);
- view.setOrientation(270, false);
- }
- }
-
- private void createContentView() {
- mActivity.getLayoutInflater().inflate(R.layout.panorama_module, (ViewGroup) mRootView, true);
- Resources appRes = mActivity.getResources();
- mCaptureLayout = (LinearLayout) mRootView.findViewById(R.id.camera_app);
- mIndicatorColor = appRes.getColor(R.color.pano_progress_indication);
- mReviewBackground = appRes.getColor(R.color.review_background);
- mIndicatorColorFast = appRes.getColor(R.color.pano_progress_indication_fast);
- mPanoLayout = (ViewGroup) mRootView.findViewById(R.id.camera_app_root);
- mRotateDialog = new RotateDialogController(mActivity, R.layout.rotate_dialog);
- setViews(appRes);
- }
-
- @Override
- public void onShutterButtonClick() {
- // If mCameraTexture == null then GL setup is not finished yet.
- // No buttons can be pressed.
- if (mPaused || mThreadRunning || mCameraTexture == null) return;
- // Since this button will stay on the screen when capturing, we need to check the state
- // right now.
- switch (mCaptureState) {
- case CAPTURE_STATE_VIEWFINDER:
- if(mActivity.getStorageSpace() <= Storage.LOW_STORAGE_THRESHOLD) return;
- mSoundPlayer.play(SoundClips.START_VIDEO_RECORDING);
- startCapture();
- break;
- case CAPTURE_STATE_MOSAIC:
- mSoundPlayer.play(SoundClips.STOP_VIDEO_RECORDING);
- stopCapture(false);
- }
- }
-
- @Override
- public void onShutterButtonFocus(boolean pressed) {
- }
-
- public void reportProgress() {
- mSavingProgressBar.reset();
- mSavingProgressBar.setRightIncreasing(true);
- Thread t = new Thread() {
- @Override
- public void run() {
- while (mThreadRunning) {
- final int progress = mMosaicFrameProcessor.reportProgress(
- true, mCancelComputation);
-
- try {
- synchronized (mWaitObject) {
- mWaitObject.wait(50);
- }
- } catch (InterruptedException e) {
- throw new RuntimeException("Panorama reportProgress failed", e);
- }
- // Update the progress bar
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mSavingProgressBar.setProgress(progress);
- }
- });
- }
- }
- };
- t.start();
- }
-
- private int getCaptureOrientation() {
- // The panorama image returned from the library is oriented based on the
- // natural orientation of a camera. We need to set an orientation for the image
- // in its EXIF header, so the image can be displayed correctly.
- // The orientation is calculated from compensating the
- // device orientation at capture and the camera orientation respective to
- // the natural orientation of the device.
- int orientation;
- if (mUsingFrontCamera) {
- // mCameraOrientation is negative with respect to the front facing camera.
- // See document of android.hardware.Camera.Parameters.setRotation.
- orientation = (mDeviceOrientationAtCapture - mCameraOrientation + 360) % 360;
- } else {
- orientation = (mDeviceOrientationAtCapture + mCameraOrientation) % 360;
- }
- return orientation;
- }
-
- public void saveHighResMosaic() {
- runBackgroundThread(new Thread() {
- @Override
- public void run() {
- mPartialWakeLock.acquire();
- MosaicJpeg jpeg;
- try {
- jpeg = generateFinalMosaic(true);
- } finally {
- mPartialWakeLock.release();
- }
-
- if (jpeg == null) { // Cancelled by user.
- mMainHandler.sendEmptyMessage(MSG_END_DIALOG_RESET_TO_PREVIEW);
- } else if (!jpeg.isValid) { // Error when generating mosaic.
- mMainHandler.sendEmptyMessage(MSG_GENERATE_FINAL_MOSAIC_ERROR);
- } else {
- int orientation = getCaptureOrientation();
- Uri uri = savePanorama(jpeg.data, jpeg.width, jpeg.height, orientation);
- if (uri != null) {
- mActivity.addSecureAlbumItemIfNeeded(false, uri);
- Util.broadcastNewPicture(mActivity, uri);
- }
- mMainHandler.sendMessage(
- mMainHandler.obtainMessage(MSG_END_DIALOG_RESET_TO_PREVIEW));
- }
- }
- });
- reportProgress();
- }
-
- private void runBackgroundThread(Thread thread) {
- mThreadRunning = true;
- thread.start();
- }
-
- private void onBackgroundThreadFinished() {
- mThreadRunning = false;
- mRotateDialog.dismissDialog();
- }
-
- private void cancelHighResComputation() {
- mCancelComputation = true;
- synchronized (mWaitObject) {
- mWaitObject.notify();
- }
- }
-
- // This function will be called upon the first camera frame is available.
- private void reset() {
- mCaptureState = CAPTURE_STATE_VIEWFINDER;
-
- mActivity.getOrientationManager().unlockOrientation();
- // We should set mGLRootView visible too. However, since there might be no
- // frame available yet, setting mGLRootView visible should be done right after
- // the first camera frame is available and therefore it is done by
- // mOnFirstFrameAvailableRunnable.
- mActivity.setSwipingEnabled(true);
- mShutterButton.setImageResource(R.drawable.btn_new_shutter);
- mReviewLayout.setVisibility(View.GONE);
- mPanoProgressBar.setVisibility(View.GONE);
- mGLRootView.setVisibility(View.VISIBLE);
- // Orientation change will trigger onLayoutChange->configMosaicPreview->
- // resetToPreview. Do not show the capture UI in film strip.
- if (mActivity.mShowCameraAppView) {
- mCaptureLayout.setVisibility(View.VISIBLE);
- mActivity.showUI();
- }
- mMosaicFrameProcessor.reset();
- }
-
- private void resetToPreview() {
- reset();
- if (!mPaused) startCameraPreview();
- }
-
- private static class FlipBitmapDrawable extends BitmapDrawable {
-
- public FlipBitmapDrawable(Resources res, Bitmap bitmap) {
- super(res, bitmap);
- }
-
- @Override
- public void draw(Canvas canvas) {
- Rect bounds = getBounds();
- int cx = bounds.centerX();
- int cy = bounds.centerY();
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- canvas.rotate(180, cx, cy);
- super.draw(canvas);
- canvas.restore();
- }
- }
-
- private void showFinalMosaic(Bitmap bitmap) {
- if (bitmap != null) {
- int orientation = getCaptureOrientation();
- if (orientation >= 180) {
- // We need to flip the drawable to compensate
- mReview.setImageDrawable(new FlipBitmapDrawable(
- mActivity.getResources(), bitmap));
- } else {
- mReview.setImageBitmap(bitmap);
- }
- }
-
- mCaptureLayout.setVisibility(View.GONE);
- mReviewLayout.setVisibility(View.VISIBLE);
- }
-
- private Uri savePanorama(byte[] jpegData, int width, int height, int orientation) {
- if (jpegData != null) {
- String filename = PanoUtil.createName(
- mActivity.getResources().getString(R.string.pano_file_name_format), mTimeTaken);
- String filepath = Storage.generateFilepath(filename);
-
- Location loc = mLocationManager.getCurrentLocation();
- ExifInterface exif = new ExifInterface();
- try {
- exif.readExif(jpegData);
- exif.addGpsDateTimeStampTag(mTimeTaken);
- exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, mTimeTaken,
- TimeZone.getDefault());
- exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION,
- ExifInterface.getOrientationValueForRotation(orientation)));
- writeLocation(loc, exif);
- exif.writeExif(jpegData, filepath);
- } catch (IOException e) {
- Log.e(TAG, "Cannot set exif for " + filepath, e);
- Storage.writeFile(filepath, jpegData);
- }
- int jpegLength = (int) (new File(filepath).length());
- return Storage.addImage(mContentResolver, filename, mTimeTaken,
- loc, orientation, jpegLength, filepath, width, height);
- }
- return null;
- }
-
- private static void writeLocation(Location location, ExifInterface exif) {
- if (location == null) {
- return;
- }
- exif.addGpsTags(location.getLatitude(), location.getLongitude());
- exif.setTag(exif.buildTag(ExifInterface.TAG_GPS_PROCESSING_METHOD, location.getProvider()));
- }
-
- private void clearMosaicFrameProcessorIfNeeded() {
- if (!mPaused || mThreadRunning) return;
- // Only clear the processor if it is initialized by this activity
- // instance. Other activity instances may be using it.
- if (mMosaicFrameProcessorInitialized) {
- mMosaicFrameProcessor.clear();
- mMosaicFrameProcessorInitialized = false;
- }
- }
-
- private void initMosaicFrameProcessorIfNeeded() {
- if (mPaused || mThreadRunning) return;
- mMosaicFrameProcessor.initialize(
- mPreviewWidth, mPreviewHeight, getPreviewBufSize());
- mMosaicFrameProcessorInitialized = true;
- }
-
- @Override
- public void onPauseBeforeSuper() {
- mPaused = true;
- if (mLocationManager != null) mLocationManager.recordLocation(false);
- }
-
- @Override
- public void onPauseAfterSuper() {
- mOrientationEventListener.disable();
- if (mCameraDevice == null) {
- // Camera open failed. Nothing should be done here.
- return;
- }
- // Stop the capturing first.
- if (mCaptureState == CAPTURE_STATE_MOSAIC) {
- stopCapture(true);
- reset();
- }
-
- releaseCamera();
- synchronized (mRendererLock) {
- mCameraTexture = null;
-
- // The preview renderer might not have a chance to be initialized
- // before onPause().
- if (mMosaicPreviewRenderer != null) {
- mMosaicPreviewRenderer.release();
- mMosaicPreviewRenderer = null;
- }
- }
-
- clearMosaicFrameProcessorIfNeeded();
- if (mWaitProcessorTask != null) {
- mWaitProcessorTask.cancel(true);
- mWaitProcessorTask = null;
- }
- resetScreenOn();
- if (mSoundPlayer != null) {
- mSoundPlayer.release();
- mSoundPlayer = null;
- }
- CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
- screenNail.releaseSurfaceTexture();
- System.gc();
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- Drawable lowResReview = null;
- if (mThreadRunning) lowResReview = mReview.getDrawable();
-
- // Change layout in response to configuration change
- mCaptureLayout.setOrientation(
- newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
- ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
- mCaptureLayout.removeAllViews();
- LayoutInflater inflater = mActivity.getLayoutInflater();
- inflater.inflate(R.layout.preview_frame_pano, mCaptureLayout);
-
- mPanoLayout.removeView(mReviewLayout);
- inflater.inflate(R.layout.pano_review, mPanoLayout);
-
- setViews(mActivity.getResources());
- if (mThreadRunning) {
- mReview.setImageDrawable(lowResReview);
- mCaptureLayout.setVisibility(View.GONE);
- mReviewLayout.setVisibility(View.VISIBLE);
- }
- }
-
- @Override
- public void onOrientationChanged(int orientation) {
- }
-
- @Override
- public void onResumeBeforeSuper() {
- mPaused = false;
- }
-
- @Override
- public void onResumeAfterSuper() {
- mOrientationEventListener.enable();
-
- mCaptureState = CAPTURE_STATE_VIEWFINDER;
-
- try {
- setupCamera();
- } catch (CameraHardwareException e) {
- Util.showErrorAndFinish(mActivity, R.string.cannot_connect_camera);
- return;
- } catch (CameraDisabledException e) {
- Util.showErrorAndFinish(mActivity, R.string.camera_disabled);
- return;
- }
-
- // Set up sound playback for shutter button
- mSoundPlayer = SoundClips.getPlayer(mActivity);
-
- // Check if another panorama instance is using the mosaic frame processor.
- mRotateDialog.dismissDialog();
- if (!mThreadRunning && mMosaicFrameProcessor.isMosaicMemoryAllocated()) {
- mGLRootView.setVisibility(View.GONE);
- mRotateDialog.showWaitingDialog(mDialogWaitingPreviousString);
- // If stitching is still going on, make sure switcher and shutter button
- // are not showing
- mActivity.hideUI();
- mWaitProcessorTask = new WaitProcessorTask().execute();
- } else {
- mGLRootView.setVisibility(View.VISIBLE);
- // Camera must be initialized before MosaicFrameProcessor is
- // initialized. The preview size has to be decided by camera device.
- initMosaicFrameProcessorIfNeeded();
- int w = mPreviewArea.getWidth();
- int h = mPreviewArea.getHeight();
- if (w != 0 && h != 0) { // The layout has been calculated.
- configMosaicPreview(w, h);
- }
- }
- keepScreenOnAwhile();
-
- // Initialize location service.
- boolean recordLocation = RecordLocationPreference.get(mPreferences,
- mContentResolver);
- mLocationManager.recordLocation(recordLocation);
-
- // Dismiss open menu if exists.
- PopupManager.getInstance(mActivity).notifyShowPopup(null);
- mRootView.requestLayout();
- UsageStatistics.onContentViewChanged(
- UsageStatistics.COMPONENT_CAMERA, "PanoramaModule");
- }
-
- /**
- * Generate the final mosaic image.
- *
- * @param highRes flag to indicate whether we want to get a high-res version.
- * @return a MosaicJpeg with its isValid flag set to true if successful; null if the generation
- * process is cancelled; and a MosaicJpeg with its isValid flag set to false if there
- * is an error in generating the final mosaic.
- */
- public MosaicJpeg generateFinalMosaic(boolean highRes) {
- int mosaicReturnCode = mMosaicFrameProcessor.createMosaic(highRes);
- if (mosaicReturnCode == Mosaic.MOSAIC_RET_CANCELLED) {
- return null;
- } else if (mosaicReturnCode == Mosaic.MOSAIC_RET_ERROR) {
- return new MosaicJpeg();
- }
-
- byte[] imageData = mMosaicFrameProcessor.getFinalMosaicNV21();
- if (imageData == null) {
- Log.e(TAG, "getFinalMosaicNV21() returned null.");
- return new MosaicJpeg();
- }
-
- int len = imageData.length - 8;
- int width = (imageData[len + 0] << 24) + ((imageData[len + 1] & 0xFF) << 16)
- + ((imageData[len + 2] & 0xFF) << 8) + (imageData[len + 3] & 0xFF);
- int height = (imageData[len + 4] << 24) + ((imageData[len + 5] & 0xFF) << 16)
- + ((imageData[len + 6] & 0xFF) << 8) + (imageData[len + 7] & 0xFF);
- Log.v(TAG, "ImLength = " + (len) + ", W = " + width + ", H = " + height);
-
- if (width <= 0 || height <= 0) {
- // TODO: pop up an error message indicating that the final result is not generated.
- Log.e(TAG, "width|height <= 0!!, len = " + (len) + ", W = " + width + ", H = " +
- height);
- return new MosaicJpeg();
- }
-
- YuvImage yuvimage = new YuvImage(imageData, ImageFormat.NV21, width, height, null);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- yuvimage.compressToJpeg(new Rect(0, 0, width, height), 100, out);
- try {
- out.close();
- } catch (Exception e) {
- Log.e(TAG, "Exception in storing final mosaic", e);
- return new MosaicJpeg();
- }
- return new MosaicJpeg(out.toByteArray(), width, height);
- }
-
- private void startCameraPreview() {
- if (mCameraDevice == null) {
- // Camera open failed. Return.
- return;
- }
-
- // This works around a driver issue. startPreview may fail if
- // stopPreview/setPreviewTexture/startPreview are called several times
- // in a row. mCameraTexture can be null after pressing home during
- // mosaic generation and coming back. Preview will be started later in
- // onLayoutChange->configMosaicPreview. This also reduces the latency.
- synchronized (mRendererLock) {
- if (mCameraTexture == null) return;
-
- // If we're previewing already, stop the preview first (this will
- // blank the screen).
- if (mCameraState != PREVIEW_STOPPED) stopCameraPreview();
-
- // Set the display orientation to 0, so that the underlying mosaic
- // library can always get undistorted mPreviewWidth x mPreviewHeight
- // image data from SurfaceTexture.
- mCameraDevice.setDisplayOrientation(0);
-
- mCameraTexture.setOnFrameAvailableListener(this);
- mCameraDevice.setPreviewTextureAsync(mCameraTexture);
- }
- mCameraDevice.startPreviewAsync();
- mCameraState = PREVIEW_ACTIVE;
- }
-
- private void stopCameraPreview() {
- if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
- Log.v(TAG, "stopPreview");
- mCameraDevice.stopPreview();
- }
- mCameraState = PREVIEW_STOPPED;
- }
-
- @Override
- public void onUserInteraction() {
- if (mCaptureState != CAPTURE_STATE_MOSAIC) keepScreenOnAwhile();
- }
-
- @Override
- public boolean onBackPressed() {
- // If panorama is generating low res or high res mosaic, ignore back
- // key. So the activity will not be destroyed.
- if (mThreadRunning) return true;
- return false;
- }
-
- private void resetScreenOn() {
- mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY);
- mActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
-
- private void keepScreenOnAwhile() {
- mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY);
- mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- mMainHandler.sendEmptyMessageDelayed(MSG_CLEAR_SCREEN_DELAY, SCREEN_DELAY);
- }
-
- private void keepScreenOn() {
- mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY);
- mActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
- }
-
- private class WaitProcessorTask extends AsyncTask<Void, Void, Void> {
- @Override
- protected Void doInBackground(Void... params) {
- synchronized (mMosaicFrameProcessor) {
- while (!isCancelled() && mMosaicFrameProcessor.isMosaicMemoryAllocated()) {
- try {
- mMosaicFrameProcessor.wait();
- } catch (Exception e) {
- // ignore
- }
- }
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- mWaitProcessorTask = null;
- mRotateDialog.dismissDialog();
- mGLRootView.setVisibility(View.VISIBLE);
- initMosaicFrameProcessorIfNeeded();
- int w = mPreviewArea.getWidth();
- int h = mPreviewArea.getHeight();
- if (w != 0 && h != 0) { // The layout has been calculated.
- configMosaicPreview(w, h);
- }
- resetToPreview();
- }
- }
-
- @Override
- public void onFullScreenChanged(boolean full) {
- }
-
-
- @Override
- public void onStop() {
- }
-
- @Override
- public void installIntentFilter() {
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- }
-
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- public void onSingleTapUp(View view, int x, int y) {
- }
-
- @Override
- public void onPreviewTextureCopied() {
- }
-
- @Override
- public void onCaptureTextureCopied() {
- }
-
- @Override
- public boolean updateStorageHintOnResume() {
- return false;
- }
-
- @Override
- public void updateCameraAppView() {
- }
-
- @Override
- public boolean needsSwitcher() {
- return true;
- }
-
- @Override
- public boolean needsPieMenu() {
- return false;
- }
-
- @Override
- public void onShowSwitcherPopup() {
- }
-
- @Override
- public void onMediaSaveServiceConnected(MediaSaveService s) {
- // do nothing.
- }
-}
diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java
index d0f21ed68..6c1e2d085 100644
--- a/src/com/android/camera/PhotoMenu.java
+++ b/src/com/android/camera/PhotoMenu.java
@@ -168,7 +168,6 @@ public class PhotoMenu extends PieController
}
public void popupDismissed() {
- // the popup gets dismissed
if (mPopup != null) {
mPopup = null;
}
@@ -198,5 +197,4 @@ public class PhotoMenu extends PieController
}
super.onSettingChanged(pref);
}
-
}
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index ecda6c6e3..49b209d34 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -64,7 +64,6 @@ 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.FilterShowActivity;
import com.android.gallery3d.filtershow.crop.CropActivity;
import com.android.gallery3d.filtershow.crop.CropExtras;
import com.android.gallery3d.util.UsageStatistics;
@@ -127,8 +126,6 @@ public class PhotoModule
private PhotoUI mUI;
- // these are only used by Camera
-
// 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.
@@ -252,23 +249,21 @@ public class PhotoModule
private PreferenceGroup mPreferenceGroup;
private boolean mQuickCapture;
-
- CameraStartUpThread mCameraStartUpThread;
- ConditionVariable mStartPreviewPrerequisiteReady = new ConditionVariable();
-
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.addSecureAlbumItemIfNeeded(false, uri);
- Util.broadcastNewPicture(mActivity, uri);
+ mActivity.notifyNewMedia(uri);
}
}
};
@@ -371,7 +366,8 @@ public class PhotoModule
}
case SWITCH_CAMERA_START_ANIMATION: {
- ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera();
+ // TODO: Need to revisit
+ // ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera();
break;
}
@@ -409,7 +405,7 @@ public class PhotoModule
}
@Override
- public void init(CameraActivity activity, View parent, boolean reuseNail) {
+ public void init(CameraActivity activity, View parent) {
mActivity = activity;
mUI = new PhotoUI(activity, this, parent);
mPreferences = new ComboPreferences(mActivity);
@@ -423,15 +419,9 @@ public class PhotoModule
mCameraStartUpThread = new CameraStartUpThread();
mCameraStartUpThread.start();
-
// Surface texture is from camera screen nail and startPreview needs it.
// This must be done before startPreview.
mIsImageCaptureIntent = isImageCaptureIntent();
- if (reuseNail) {
- mActivity.reuseCameraScreenNail(!mIsImageCaptureIntent);
- } else {
- mActivity.createCameraScreenNail(!mIsImageCaptureIntent);
- }
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
@@ -445,7 +435,6 @@ public class PhotoModule
mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
mLocationManager = new LocationManager(mActivity, mUI);
mSensorManager = (SensorManager)(mActivity.getSystemService(Context.SENSOR_SERVICE));
-
}
private void initializeControlByIntent() {
@@ -458,10 +447,6 @@ public class PhotoModule
private void onPreviewStarted() {
mCameraStartUpThread = null;
setCameraState(IDLE);
- if (!ApiHelper.HAS_SURFACE_TEXTURE) {
- // This may happen if surfaceCreated has arrived.
- mCameraDevice.setPreviewDisplayAsync(mUI.getSurfaceHolder());
- }
startFaceDetection();
locationFirstRun();
}
@@ -520,16 +505,7 @@ public class PhotoModule
int width = root.getWidth();
int height = root.getHeight();
mFocusManager.setPreviewSize(width, height);
- // Full-screen screennail
- if (Util.getDisplayRotation(mActivity) % 180 == 0) {
- ((CameraScreenNail) mActivity.mCameraScreenNail).setPreviewFrameLayoutSize(width, height);
- } else {
- ((CameraScreenNail) mActivity.mCameraScreenNail).setPreviewFrameLayoutSize(height, width);
- }
- // Set touch focus listener.
- mActivity.setSingleTapUpListener(root);
openCameraCommon();
- onFullScreenChanged(mActivity.isInCameraApp());
}
private void switchCamera() {
@@ -566,6 +542,8 @@ public class PhotoModule
mFocusManager.setParameters(mInitialParams);
setupPreview();
+ // reset zoom value index
+ mZoomValue = 0;
openCameraCommon();
if (ApiHelper.HAS_SURFACE_TEXTURE) {
@@ -592,11 +570,7 @@ public class PhotoModule
}
public void onScreenSizeChanged(int width, int height, int previewWidth, int previewHeight) {
- Log.d(TAG, "Preview size changed.");
if (mFocusManager != null) mFocusManager.setPreviewSize(width, height);
- ((CameraScreenNail) mActivity.mCameraScreenNail).setPreviewFrameLayoutSize(
- previewWidth, previewHeight);
- mActivity.notifyScreenNailChanged();
}
private void resetExposureCompensation() {
@@ -726,12 +700,6 @@ public class PhotoModule
}
}
- @Override
- public boolean dispatchTouchEvent(MotionEvent m) {
- if (mCameraState == SWITCHING_CAMERA) return true;
- return mUI.dispatchTouchEvent(m);
- }
-
private final class ShutterCallback
implements android.hardware.Camera.ShutterCallback {
@@ -786,9 +754,13 @@ public class PhotoModule
if (mPaused) {
return;
}
+ //TODO: We should show the picture taken rather than frozen preview here
+ if (mIsImageCaptureIntent) {
+ stopPreview();
+ }
if (mSceneMode == Util.SCENE_MODE_HDR) {
- mActivity.showSwitcher();
- mActivity.setSwipingEnabled(true);
+ mUI.showSwitcher();
+ mUI.setSwipingEnabled(true);
}
mJpegPictureCallbackTime = System.currentTimeMillis();
@@ -809,6 +781,7 @@ public class PhotoModule
Log.v(TAG, "mPictureDisplayedToJpegCallbackTime = "
+ mPictureDisplayedToJpegCallbackTime + "ms");
+ /*TODO:
// 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
@@ -819,7 +792,7 @@ public class PhotoModule
((CameraScreenNail) mActivity.mCameraScreenNail).animateSlide();
mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE,
CaptureAnimManager.getAnimationDuration());
- }
+ } */
mFocusManager.updateFocusUI(); // Ensure focus indicator is hidden.
if (!mIsImageCaptureIntent) {
if (ApiHelper.CAN_START_PREVIEW_IN_JPEG_CALLBACK) {
@@ -957,19 +930,17 @@ public class PhotoModule
switch (state) {
case PhotoController.PREVIEW_STOPPED:
case PhotoController.SNAPSHOT_IN_PROGRESS:
- case PhotoController.FOCUSING:
case PhotoController.SWITCHING_CAMERA:
mUI.enableGestures(false);
break;
case PhotoController.IDLE:
- if (mActivity.isInCameraApp()) {
- mUI.enableGestures(true);
- }
+ mUI.enableGestures(true);
break;
}
}
private void animateFlash() {
+ /* //TODO:
// 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
@@ -980,7 +951,7 @@ public class PhotoModule
mUI.enablePreviewThumb(true);
mHandler.sendEmptyMessageDelayed(CAPTURE_ANIMATION_DONE,
CaptureAnimManager.getAnimationDuration());
- }
+ } */
}
@Override
@@ -1047,17 +1018,6 @@ public class PhotoModule
}
}
- @Override
- public void onFullScreenChanged(boolean full) {
- mUI.onFullScreenChanged(full);
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- if (mActivity.mCameraScreenNail != null) {
- ((CameraScreenNail) mActivity.mCameraScreenNail).setFullScreen(full);
- }
- return;
- }
- }
-
private void updateSceneMode() {
// If scene mode is set, we cannot set flash mode, white balance, and
// focus mode, instead, we read it from driver
@@ -1236,8 +1196,8 @@ public class PhotoModule
Log.v(TAG, "onShutterButtonClick: mCameraState=" + mCameraState);
if (mSceneMode == Util.SCENE_MODE_HDR) {
- mActivity.hideSwitcher();
- mActivity.setSwipingEnabled(false);
+ 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
@@ -1295,7 +1255,6 @@ public class PhotoModule
mJpegPictureCallbackTime = 0;
mZoomValue = 0;
-
// Start the preview if it is not started.
if (mCameraState == PREVIEW_STOPPED && mCameraStartUpThread == null) {
resetExposureCompensation();
@@ -1375,8 +1334,6 @@ public class PhotoModule
mCameraDevice.cancelAutoFocus();
}
stopPreview();
- // Release surface texture.
- ((CameraScreenNail) mActivity.mCameraScreenNail).releaseSurfaceTexture();
mNamedImages = null;
@@ -1438,6 +1395,13 @@ public class PhotoModule
}
@Override
+ public void updateCameraOrientation() {
+ if (mDisplayRotation != Util.getDisplayRotation(mActivity)) {
+ setDisplayOrientation();
+ }
+ }
+
+ @Override
public void onActivityResult(
int requestCode, int resultCode, Intent data) {
switch (requestCode) {
@@ -1507,7 +1471,7 @@ public class PhotoModule
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_FOCUS:
- if (mActivity.isInCameraApp() && mFirstTimeInitialized) {
+ if (/*TODO: mActivity.isInCameraApp() &&*/ mFirstTimeInitialized) {
if (event.getRepeatCount() == 0) {
onShutterButtonFocus(true);
}
@@ -1540,7 +1504,7 @@ public class PhotoModule
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
- if (mActivity.isInCameraApp() && mFirstTimeInitialized) {
+ if (/*mActivity.isInCameraApp() && */ mFirstTimeInitialized) {
onShutterButtonClick();
return true;
}
@@ -1573,13 +1537,15 @@ public class PhotoModule
private void setDisplayOrientation() {
mDisplayRotation = Util.getDisplayRotation(mActivity);
mDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, mCameraId);
- mCameraDisplayOrientation = Util.getDisplayOrientation(0, mCameraId);
+ mCameraDisplayOrientation = mDisplayOrientation;
mUI.setDisplayOrientation(mDisplayOrientation);
if (mFocusManager != null) {
mFocusManager.setDisplayOrientation(mDisplayOrientation);
}
- // GLRoot also uses the DisplayRotation, and needs to be told to layout to update
- mActivity.getGLRoot().requestLayoutContentPane();
+ // Change the camera display orientation
+ if (mCameraDevice != null) {
+ mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation);
+ }
}
// Only called by UI thread.
@@ -1611,40 +1577,15 @@ public class PhotoModule
mFocusManager.setAeAwbLock(false); // Unlock AE and AWB.
}
setCameraParameters(UPDATE_PARAM_ALL);
-
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
- if (mUI.getSurfaceTexture() == null) {
- Size size = mParameters.getPreviewSize();
- if (mCameraDisplayOrientation % 180 == 0) {
- screenNail.setSize(size.width, size.height);
- } else {
- screenNail.setSize(size.height, size.width);
- }
- screenNail.enableAspectRatioClamping();
- mActivity.notifyScreenNailChanged();
- screenNail.acquireSurfaceTexture();
- CameraStartUpThread t = mCameraStartUpThread;
- if (t != null && t.isCanceled()) {
- return; // Exiting, so no need to get the surface texture.
- }
- mUI.setSurfaceTexture(screenNail.getSurfaceTexture());
- } else {
- updatePreviewSize(screenNail);
- }
- mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation);
- Object st = mUI.getSurfaceTexture();
- if (st != null) {
- mCameraDevice.setPreviewTextureAsync((SurfaceTexture) st);
- }
- } else {
- mCameraDevice.setDisplayOrientation(mDisplayOrientation);
- mCameraDevice.setPreviewDisplayAsync(mUI.getSurfaceHolder());
+ // Let UI set its expected aspect ratio
+ mUI.setPreviewSize(mParameters.getPreviewSize());
+ Object st = mUI.getSurfaceTexture();
+ if (st != null) {
+ mCameraDevice.setPreviewTextureAsync((SurfaceTexture) st);
}
Log.v(TAG, "startPreview");
mCameraDevice.startPreviewAsync();
-
mFocusManager.onPreviewStarted();
if (mSnapshotOnIdle) {
@@ -1652,21 +1593,6 @@ public class PhotoModule
}
}
- private void updatePreviewSize(CameraScreenNail snail) {
- Size size = mParameters.getPreviewSize();
- int w = size.width;
- int h = size.height;
- if (mCameraDisplayOrientation % 180 != 0) {
- w = size.height;
- h = size.width;
- }
- if (snail.getWidth() != w || snail.getHeight() != h) {
- snail.setSize(w, h);
- }
- snail.enableAspectRatioClamping();
- mActivity.notifyScreenNailChanged();
- }
-
@Override
public void stopPreview() {
if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
@@ -1682,10 +1608,11 @@ public class PhotoModule
private void updateCameraParametersInitialize() {
// Reset preview frame rate to the maximum because it may be lowered by
// video camera application.
- List<Integer> frameRates = mParameters.getSupportedPreviewFrameRates();
- if (frameRates != null) {
- Integer max = Collections.max(frameRates);
- mParameters.setPreviewFrameRate(max);
+ 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);
@@ -1760,6 +1687,7 @@ public class PhotoModule
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()) {
@@ -1950,16 +1878,12 @@ public class PhotoModule
if (mPaused || mPendingSwitchCameraId != -1) return;
mPendingSwitchCameraId = cameraId;
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- Log.v(TAG, "Start to copy texture. cameraId=" + cameraId);
- // We need to keep a preview frame for the animation before
- // releasing the camera. This will trigger onPreviewTextureCopied.
- ((CameraScreenNail) mActivity.mCameraScreenNail).copyTexture();
- // Disable all camera controls.
- setCameraState(SWITCHING_CAMERA);
- } else {
- switchCamera();
- }
+
+ 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
@@ -1975,7 +1899,7 @@ public class PhotoModule
@Override
public void onUserInteraction() {
- if (!mActivity.isFinishing()) keepScreenOnAwhile();
+ if (!mActivity.isFinishing()) keepScreenOnAwhile();
}
private void resetScreenOn() {
@@ -1989,11 +1913,6 @@ public class PhotoModule
mHandler.sendEmptyMessageDelayed(CLEAR_SCREEN_DELAY, SCREEN_DELAY);
}
- // TODO: Delete this function after old camera code is removed
- @Override
- public void onRestorePreferencesClicked() {
- }
-
@Override
public void onOverriddenPreferencesClicked() {
if (mPaused) return;
@@ -2027,16 +1946,6 @@ public class PhotoModule
}
@Override
- public boolean needsSwitcher() {
- return !mIsImageCaptureIntent;
- }
-
- @Override
- public boolean needsPieMenu() {
- return true;
- }
-
- @Override
public void onShowSwitcherPopup() {
mUI.onShowSwitcherPopup();
}
@@ -2101,5 +2010,18 @@ public class PhotoModule
mHeading += 360;
}
}
- public void updateCameraOrientation() {}
+
+ @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
index a364d797e..1468a3ce4 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -17,13 +17,19 @@
package com.android.camera;
+import android.graphics.Matrix;
+import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.Face;
import android.hardware.Camera.FaceDetectionListener;
+import android.hardware.Camera.Parameters;
+import android.hardware.Camera.Size;
+import android.os.Handler;
+import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
-import android.view.SurfaceHolder;
+import android.view.TextureView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLayoutChangeListener;
@@ -31,15 +37,20 @@ 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.CameraSwitcher.CameraSwitchListener;
import com.android.camera.ui.CountDownView;
import com.android.camera.ui.CountDownView.OnCountDownFinishedListener;
+import com.android.camera.ui.CameraSwitcher;
import com.android.camera.ui.FaceView;
import com.android.camera.ui.FocusIndicator;
+import com.android.camera.ui.CameraRootView;
import com.android.camera.ui.PieRenderer;
import com.android.camera.ui.PieRenderer.PieListener;
import com.android.camera.ui.RenderOverlay;
@@ -47,25 +58,23 @@ import com.android.camera.ui.ZoomRenderer;
import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
+import java.io.IOException;
import java.util.List;
public class PhotoUI implements PieListener,
- SurfaceHolder.Callback,
PreviewGestures.SingleTapListener,
- FocusUI,
- LocationManager.Listener,
- FaceDetectionListener,
- PreviewGestures.SwipeListener {
+ FocusUI, TextureView.SurfaceTextureListener,
+ LocationManager.Listener, CameraRootView.MyDisplayListener,
+ FaceDetectionListener {
private static final String TAG = "CAM_UI";
-
+ private static final int UPDATE_TRANSFORM_MATRIX = 1;
private CameraActivity mActivity;
private PhotoController mController;
private PreviewGestures mGestures;
private View mRootView;
private Object mSurfaceTexture;
- private volatile SurfaceHolder mSurfaceHolder;
private AbstractSettingPopup mPopup;
private ShutterButton mShutterButton;
@@ -80,7 +89,10 @@ public class PhotoUI implements PieListener,
private View mMenuButton;
private View mBlocker;
private PhotoMenu mMenu;
+ private CameraSwitcher mSwitcher;
+ private CameraControls mCameraControls;
+ // Small indicators which show the camera settings in the viewfinder.
private OnScreenIndicators mOnScreenIndicators;
private PieRenderer mPieRenderer;
@@ -92,8 +104,33 @@ public class PhotoUI implements PieListener,
private int mPreviewWidth = 0;
private int mPreviewHeight = 0;
+ private float mSurfaceTextureUncroppedWidth;
+ private float mSurfaceTextureUncroppedHeight;
+
private View mPreviewThumb;
+ 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,
@@ -107,9 +144,10 @@ public class PhotoUI implements PieListener,
w = height;
h = width;
}
- if (mPreviewWidth != w || mPreviewHeight != h) {
- mPreviewWidth = w;
- mPreviewHeight = h;
+ if (mPreviewWidth != width || mPreviewHeight != height) {
+ mPreviewWidth = width;
+ mPreviewHeight = height;
+ onScreenSizeChanged(width, height, w, h);
mController.onScreenSizeChanged(width, height, w, h);
}
}
@@ -123,20 +161,106 @@ public class PhotoUI implements PieListener,
mActivity.getLayoutInflater().inflate(R.layout.photo_module,
(ViewGroup) mRootView, true);
mRenderOverlay = (RenderOverlay) mRootView.findViewById(R.id.render_overlay);
-
+ // display the view
+ mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content);
+ mTextureView.setSurfaceTextureListener(this);
+ mTextureView.addOnLayoutChangeListener(mLayoutListener);
initIndicators();
- mCountDownView = (CountDownView) (mRootView.findViewById(R.id.count_down_to_capture));
- mCountDownView.setCountDownFinishedListener((OnCountDownFinishedListener) mController);
+ mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
+ mSwitcher = (CameraSwitcher) mRootView.findViewById(R.id.camera_switcher);
+ mSwitcher.setCurrentIndex(0);
+ 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);
+ }
+
+ 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() {
@@ -145,7 +269,7 @@ public class PhotoUI implements PieListener,
private void initIndicators() {
mOnScreenIndicators = new OnScreenIndicators(mActivity,
- mActivity.findViewById(R.id.on_screen_indicators));
+ mRootView.findViewById(R.id.on_screen_indicators));
}
public void onCameraOpened(PreferenceGroup prefGroup, ComboPreferences prefs,
@@ -155,6 +279,7 @@ public class PhotoUI implements PieListener,
mPieRenderer.setPieListener(this);
mRenderOverlay.addRenderer(mPieRenderer);
}
+
if (mMenu == null) {
mMenu = new PhotoMenu(mActivity, this, mPieRenderer);
mMenu.setListener(listener);
@@ -165,25 +290,14 @@ public class PhotoUI implements PieListener,
mZoomRenderer = new ZoomRenderer(mActivity);
mRenderOverlay.addRenderer(mZoomRenderer);
}
+
if (mGestures == null) {
// this will handle gesture disambiguation and dispatching
- mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer,
- this);
+ mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer);
+ mRenderOverlay.setGestures(mGestures);
}
- mGestures.reset();
+ mGestures.setZoomEnabled(params.isZoomSupported());
mGestures.setRenderOverlay(mRenderOverlay);
- mGestures.addTouchReceiver(mMenuButton);
- mGestures.addUnclickableArea(mBlocker);
- enablePreviewThumb(false);
- // make sure to add touch targets for image capture
- if (mController.isImageCaptureIntent()) {
- if (mReviewCancelButton != null) {
- mGestures.addTouchReceiver(mReviewCancelButton);
- }
- if (mReviewDoneButton != null) {
- mGestures.addTouchReceiver(mReviewDoneButton);
- }
- }
mRenderOverlay.requestLayout();
initializeZoom(params);
@@ -202,15 +316,16 @@ public class PhotoUI implements PieListener,
}
public void initializeControlByIntent() {
- mBlocker = mActivity.findViewById(R.id.blocker);
+ mBlocker = mRootView.findViewById(R.id.blocker);
mPreviewThumb = mActivity.findViewById(R.id.preview_thumb);
mPreviewThumb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- mActivity.gotoGallery();
+ // TODO: go to filmstrip
+ // mActivity.gotoGallery();
}
});
- mMenuButton = mActivity.findViewById(R.id.menu);
+ mMenuButton = mRootView.findViewById(R.id.menu);
mMenuButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -218,13 +333,13 @@ public class PhotoUI implements PieListener,
}
});
if (mController.isImageCaptureIntent()) {
- mActivity.hideSwitcher();
- ViewGroup cameraControls = (ViewGroup) mActivity.findViewById(R.id.camera_controls);
+ hideSwitcher();
+ ViewGroup cameraControls = (ViewGroup) mRootView.findViewById(R.id.camera_controls);
mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls);
- mReviewDoneButton = mActivity.findViewById(R.id.btn_done);
- mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel);
- mReviewRetakeButton = mActivity.findViewById(R.id.btn_retake);
+ 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() {
@@ -249,14 +364,29 @@ public class PhotoUI implements PieListener,
}
}
+ 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 = mActivity.getShutterButton();
mShutterButton.setImageResource(R.drawable.btn_new_shutter);
mShutterButton.setOnShutterButtonListener(mController);
mShutterButton.setVisibility(View.VISIBLE);
- mRootView.addOnLayoutChangeListener(mLayoutListener);
}
// called from onResume every other time
@@ -268,7 +398,6 @@ public class PhotoUI implements PieListener,
if (mMenu != null) {
mMenu.reloadPreferences();
}
- mRootView.addOnLayoutChangeListener(mLayoutListener);
}
public void initializeZoom(Camera.Parameters params) {
@@ -286,16 +415,8 @@ public class PhotoUI implements PieListener,
}
}
- public void enableGestures(boolean enable) {
- if (mGestures != null) {
- mGestures.setEnabled(enable);
- }
- }
-
- @Override
public void showGpsOnScreenIndicator(boolean hasSignal) { }
- @Override
public void hideGpsOnScreenIndicator() { }
public void overrideSettings(final String ... keyvalues) {
@@ -323,11 +444,16 @@ public class PhotoUI implements PieListener,
public void setCameraState(int state) {
}
- public boolean dispatchTouchEvent(MotionEvent m) {
- if (mGestures != null && mRenderOverlay != null) {
- return mGestures.dispatchTouch(m);
+ public void enableGestures(boolean enable) {
+ if (mGestures != null) {
+ mGestures.setEnabled(enable);
}
- return false;
+ }
+
+ // forward from preview gestures to controller
+ @Override
+ public void onSingleTapUp(View view, int x, int y) {
+ mController.onSingleTapUp(view, x, y);
}
public boolean onBackPressed() {
@@ -352,36 +478,36 @@ public class PhotoUI implements PieListener,
}
}
- public void onFullScreenChanged(boolean full) {
+ public void onSwitchMode(boolean toCamera) {
+ if (toCamera) {
+ showUI();
+ } else {
+ hideUI();
+ }
if (mFaceView != null) {
- mFaceView.setBlockDraw(!full);
+ mFaceView.setBlockDraw(!toCamera);
}
if (mPopup != null) {
- dismissPopup(full);
+ dismissPopup(toCamera);
}
if (mGestures != null) {
- mGestures.setEnabled(full);
+ mGestures.setEnabled(toCamera);
}
if (mRenderOverlay != null) {
// this can not happen in capture mode
- mRenderOverlay.setVisibility(full ? View.VISIBLE : View.GONE);
+ mRenderOverlay.setVisibility(toCamera ? View.VISIBLE : View.GONE);
}
if (mPieRenderer != null) {
- mPieRenderer.setBlockFocus(!full);
+ mPieRenderer.setBlockFocus(!toCamera);
}
- setShowMenu(full);
- if (mBlocker != null) {
- mBlocker.setVisibility(full ? View.VISIBLE : View.GONE);
- }
- if (!full && mCountDownView != null) mCountDownView.cancelCountDown();
+ setShowMenu(toCamera);
+ if (!toCamera && mCountDownView != null) mCountDownView.cancelCountDown();
}
public void enablePreviewThumb(boolean enabled) {
if (enabled) {
- mGestures.addTouchReceiver(mPreviewThumb);
mPreviewThumb.setVisibility(View.VISIBLE);
} else {
- mGestures.removeTouchReceiver(mPreviewThumb);
mPreviewThumb.setVisibility(View.GONE);
}
}
@@ -396,7 +522,7 @@ public class PhotoUI implements PieListener,
}
public void showPopup(AbstractSettingPopup popup) {
- mActivity.hideUI();
+ hideUI();
mBlocker.setVisibility(View.INVISIBLE);
setShowMenu(false);
mPopup = popup;
@@ -405,7 +531,6 @@ public class PhotoUI implements PieListener,
LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.CENTER;
((FrameLayout) mRootView).addView(mPopup, lp);
- mGestures.addTouchReceiver(mPopup);
}
public void dismissPopup() {
@@ -414,12 +539,11 @@ public class PhotoUI implements PieListener,
private void dismissPopup(boolean fullScreen) {
if (fullScreen) {
- mActivity.showUI();
+ showUI();
mBlocker.setVisibility(View.VISIBLE);
}
setShowMenu(fullScreen);
if (mPopup != null) {
- mGestures.removeTouchReceiver(mPopup);
((FrameLayout) mRootView).removeView(mPopup);
mPopup = null;
}
@@ -482,8 +606,20 @@ public class PhotoUI implements PieListener,
return mShutterButton.isPressed();
}
- // focus handling
+ 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
@@ -511,9 +647,8 @@ public class PhotoUI implements PieListener,
@Override
public void onPieOpened(int centerX, int centerY) {
+ setSwipingEnabled(false);
dismissPopup();
- mActivity.cancelActivityTouchHandling();
- mActivity.setSwipingEnabled(false);
if (mFaceView != null) {
mFaceView.setBlockDraw(true);
}
@@ -521,55 +656,49 @@ public class PhotoUI implements PieListener,
@Override
public void onPieClosed() {
- mActivity.setSwipingEnabled(true);
+ setSwipingEnabled(true);
if (mFaceView != null) {
mFaceView.setBlockDraw(false);
}
}
- // Surface Listener
-
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- Log.v(TAG, "surfaceChanged:" + holder + " width=" + width + ". height="
- + height);
- }
-
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- Log.v(TAG, "surfaceCreated: " + holder);
- mSurfaceHolder = holder;
- mController.onSurfaceCreated(holder);
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- Log.v(TAG, "surfaceDestroyed: " + holder);
- mSurfaceHolder = null;
- mController.stopPreview();
+ 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;
}
- public void setSurfaceTexture(Object st) {
- mSurfaceTexture = st;
- }
+ // Countdown timer
- public SurfaceHolder getSurfaceHolder() {
- return mSurfaceHolder;
+ 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.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);
}
@@ -582,41 +711,16 @@ public class PhotoUI implements PieListener,
}
public void onPause() {
- mCountDownView.cancelCountDown();
- // Close the camera now because other activities may need to use it.
- mSurfaceTexture = null;
+ cancelCountDown();
// Clear UI.
collapseCameraControls();
if (mFaceView != null) mFaceView.clear();
-
- mRootView.removeOnLayoutChangeListener(mLayoutListener);
mPreviewWidth = 0;
mPreviewHeight = 0;
}
- 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);
- }
-
- // forward from preview gestures to controller
- @Override
- public void onSingleTapUp(View view, int x, int y) {
- mController.onSingleTapUp(view, x, y);
- }
-
// focus UI implementation
private FocusIndicator getFocusIndicator() {
@@ -681,11 +785,9 @@ public class PhotoUI implements PieListener,
mFaceView.setFaces(faces);
}
- @Override
- public void onSwipe(int direction) {
- if (direction == PreviewGestures.DIR_UP) {
- openMenu();
- }
+ public void onDisplayChanged() {
+ mCameraControls.checkLayoutFlip();
+ mController.updateCameraOrientation();
}
}
diff --git a/src/com/android/camera/PreviewGestures.java b/src/com/android/camera/PreviewGestures.java
index 0b80ff688..925607e80 100644
--- a/src/com/android/camera/PreviewGestures.java
+++ b/src/com/android/camera/PreviewGestures.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -18,6 +18,7 @@ package com.android.camera;
import android.os.Handler;
import android.os.Message;
+import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
@@ -28,9 +29,10 @@ import com.android.camera.ui.RenderOverlay;
import com.android.camera.ui.ZoomRenderer;
import com.android.gallery3d.R;
-import java.util.ArrayList;
-import java.util.List;
-
+/* 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 {
@@ -58,23 +60,55 @@ public class PreviewGestures
private MotionEvent mDown;
private MotionEvent mCurrent;
private ScaleGestureDetector mScale;
- private List<View> mReceivers;
- private List<View> mUnclickableAreas;
private int mMode;
private int mSlop;
private int mTapTimeout;
+ private boolean mZoomEnabled;
private boolean mEnabled;
private boolean mZoomOnly;
private int mOrientation;
- private int[] mLocation;
- private SwipeListener mSwipeListener;
+ private GestureDetector mGestureDetector;
+
+ private GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public void onLongPress (MotionEvent e) {
+ // Open pie
+ if (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 (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;
+ }
+ };
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if (msg.what == MSG_PIE) {
mMode = MODE_PIE;
openPie();
- cancelActivityTouchHandling(mDown);
}
}
};
@@ -83,12 +117,8 @@ public class PreviewGestures
public void onSingleTapUp(View v, int x, int y);
}
- interface SwipeListener {
- public void onSwipe(int direction);
- }
-
public PreviewGestures(CameraActivity ctx, SingleTapListener tapListener,
- ZoomRenderer zoom, PieRenderer pie, SwipeListener swipe) {
+ ZoomRenderer zoom, PieRenderer pie) {
mActivity = ctx;
mTapListener = tapListener;
mPie = pie;
@@ -98,8 +128,7 @@ public class PreviewGestures
mSlop = (int) ctx.getResources().getDimension(R.dimen.pie_touch_slop);
mTapTimeout = ViewConfiguration.getTapTimeout();
mEnabled = true;
- mLocation = new int[2];
- mSwipeListener = swipe;
+ mGestureDetector = new GestureDetector(mGestureListener);
}
public void setRenderOverlay(RenderOverlay overlay) {
@@ -112,184 +141,51 @@ public class PreviewGestures
public void setEnabled(boolean enabled) {
mEnabled = enabled;
- if (!enabled) {
- cancelPie();
- }
- }
-
- public void setZoomOnly(boolean zoom) {
- mZoomOnly = zoom;
- }
-
- public void addTouchReceiver(View v) {
- if (mReceivers == null) {
- mReceivers = new ArrayList<View>();
- }
- mReceivers.add(v);
- }
-
- public void removeTouchReceiver(View v) {
- if (mReceivers == null || v == null) return;
- mReceivers.remove(v);
- }
-
- public void addUnclickableArea(View v) {
- if (mUnclickableAreas == null) {
- mUnclickableAreas = new ArrayList<View>();
- }
- mUnclickableAreas.add(v);
- }
-
- public void clearTouchReceivers() {
- if (mReceivers != null) {
- mReceivers.clear();
- }
}
- public void clearUnclickableAreas() {
- if (mUnclickableAreas != null) {
- mUnclickableAreas.clear();
- }
+ public void setZoomEnabled(boolean enable) {
+ mZoomEnabled = enable;
}
- private boolean checkClickable(MotionEvent m) {
- if (mUnclickableAreas != null) {
- for (View v : mUnclickableAreas) {
- if (isInside(m, v)) {
- return false;
- }
- }
- }
- return true;
+ public void setZoomOnly(boolean zoom) {
+ mZoomOnly = zoom;
}
- public void reset() {
- clearTouchReceivers();
- clearUnclickableAreas();
+ public boolean isEnabled() {
+ return mEnabled;
}
public boolean dispatchTouch(MotionEvent m) {
if (!mEnabled) {
- return mActivity.superDispatchTouchEvent(m);
+ return false;
}
mCurrent = m;
if (MotionEvent.ACTION_DOWN == m.getActionMasked()) {
- if (checkReceivers(m)) {
- mMode = MODE_MODULE;
- return mActivity.superDispatchTouchEvent(m);
- } else {
- mMode = MODE_ALL;
- mDown = MotionEvent.obtain(m);
- if (mPie != null && mPie.showsItems()) {
- mMode = MODE_PIE;
- return sendToPie(m);
- }
- if (mPie != null && !mZoomOnly && checkClickable(m)) {
- mHandler.sendEmptyMessageDelayed(MSG_PIE, TIMEOUT_PIE);
- }
- if (mZoom != null) {
- mScale.onTouchEvent(m);
- }
- // make sure this is ok
- return mActivity.superDispatchTouchEvent(m);
- }
- } else if (mMode == MODE_NONE) {
- return false;
- } else if (mMode == MODE_SWIPE) {
- if (MotionEvent.ACTION_UP == m.getActionMasked()) {
- mSwipeListener.onSwipe(getSwipeDirection(m));
- }
- return true;
- } else if (mMode == MODE_PIE) {
- if (MotionEvent.ACTION_POINTER_DOWN == m.getActionMasked()) {
- sendToPie(makeCancelEvent(m));
- if (mZoom != null) {
- onScaleBegin(mScale);
- }
- } else {
- return sendToPie(m);
- }
- return true;
- } else if (mMode == MODE_ZOOM) {
- mScale.onTouchEvent(m);
- if (!mScale.isInProgress() && MotionEvent.ACTION_POINTER_UP == m.getActionMasked()) {
- mMode = MODE_NONE;
- onScaleEnd(mScale);
- }
- return true;
- } else if (mMode == MODE_MODULE) {
- return mActivity.superDispatchTouchEvent(m);
- } else {
- // didn't receive down event previously;
- // assume module wasn't initialzed and ignore this event.
- if (mDown == null) {
- return true;
- }
- if (MotionEvent.ACTION_POINTER_DOWN == m.getActionMasked()) {
- if (!mZoomOnly) {
- cancelPie();
- sendToPie(makeCancelEvent(m));
- }
- if (mZoom != null) {
- mScale.onTouchEvent(m);
- onScaleBegin(mScale);
- }
- } else if ((mMode == MODE_ZOOM) && !mScale.isInProgress()
- && MotionEvent.ACTION_POINTER_UP == m.getActionMasked()) {
- // user initiated and stopped zoom gesture without zooming
- mScale.onTouchEvent(m);
- onScaleEnd(mScale);
- }
- // not zoom or pie mode and no timeout yet
- if (mZoom != null) {
- boolean res = mScale.onTouchEvent(m);
- if (mScale.isInProgress()) {
- cancelPie();
- cancelActivityTouchHandling(m);
- return res;
- }
- }
- if (MotionEvent.ACTION_UP == m.getActionMasked()) {
- cancelPie();
- // must have been tap
- if (m.getEventTime() - mDown.getEventTime() < mTapTimeout
- && checkClickable(m)) {
- cancelActivityTouchHandling(m);
- mTapListener.onSingleTapUp(null,
- (int) mDown.getX() - mOverlay.getWindowPositionX(),
- (int) mDown.getY() - mOverlay.getWindowPositionY());
- return true;
- } else {
- return mActivity.superDispatchTouchEvent(m);
- }
- } else if (MotionEvent.ACTION_MOVE == m.getActionMasked()) {
- if ((Math.abs(m.getX() - mDown.getX()) > mSlop)
- || Math.abs(m.getY() - mDown.getY()) > mSlop) {
- // moved too far and no timeout yet, no focus or pie
- cancelPie();
- int dir = getSwipeDirection(m);
- if (dir == DIR_LEFT) {
- mMode = MODE_MODULE;
- return mActivity.superDispatchTouchEvent(m);
- } else {
- cancelActivityTouchHandling(m);
- mMode = MODE_NONE;
- }
- }
- }
- return false;
+ mMode = MODE_NONE;
+ mDown = MotionEvent.obtain(m);
}
- }
- private boolean checkReceivers(MotionEvent m) {
- if (mReceivers != null) {
- for (View receiver : mReceivers) {
- if (isInside(m, receiver)) {
- return true;
+ // 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 false;
+ return true;
}
// left tests for finger moving right to left
@@ -320,25 +216,6 @@ public class PreviewGestures
return DIR_UP;
}
- private boolean isInside(MotionEvent evt, View v) {
- v.getLocationInWindow(mLocation);
- // when view is flipped horizontally
- if ((int) v.getRotationY() == 180) {
- mLocation[0] -= v.getWidth();
- }
- // when view is flipped vertically
- if ((int) v.getRotationX() == 180) {
- mLocation[1] -= v.getHeight();
- }
- return (v.getVisibility() == View.VISIBLE
- && evt.getX() >= mLocation[0] && evt.getX() < mLocation[0] + v.getWidth()
- && evt.getY() >= mLocation[1] && evt.getY() < mLocation[1] + v.getHeight());
- }
-
- public void cancelActivityTouchHandling(MotionEvent m) {
- mActivity.superDispatchTouchEvent(makeCancelEvent(m));
- }
-
private MotionEvent makeCancelEvent(MotionEvent m) {
MotionEvent c = MotionEvent.obtain(m);
c.setAction(MotionEvent.ACTION_CANCEL);
@@ -346,21 +223,16 @@ public class PreviewGestures
}
private void openPie() {
- mDown.offsetLocation(-mOverlay.getWindowPositionX(),
- -mOverlay.getWindowPositionY());
+ mGestureDetector.onTouchEvent(makeCancelEvent(mDown));
+ mScale.onTouchEvent(makeCancelEvent(mDown));
mOverlay.directDispatchTouch(mDown, mPie);
}
- private void cancelPie() {
- mHandler.removeMessages(MSG_PIE);
- }
-
private boolean sendToPie(MotionEvent m) {
- m.offsetLocation(-mOverlay.getWindowPositionX(),
- -mOverlay.getWindowPositionY());
return mOverlay.directDispatchTouch(m, mPie);
}
+ // OnScaleGestureListener implementation
@Override
public boolean onScale(ScaleGestureDetector detector) {
return mZoom.onScale(detector);
@@ -368,21 +240,18 @@ public class PreviewGestures
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
- if (mMode != MODE_ZOOM) {
+ if (mPie == null || !mPie.isOpen()) {
mMode = MODE_ZOOM;
- cancelActivityTouchHandling(mCurrent);
- }
- if (mCurrent.getActionMasked() != MotionEvent.ACTION_MOVE) {
+ mGestureDetector.onTouchEvent(makeCancelEvent(mCurrent));
+ if (!mZoomEnabled) return false;
return mZoom.onScaleBegin(detector);
- } else {
- return true;
}
+ return false;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
- if (mCurrent.getActionMasked() != MotionEvent.ACTION_MOVE) {
- mZoom.onScaleEnd(detector);
- }
+ mZoom.onScaleEnd(detector);
}
}
+
diff --git a/src/com/android/camera/VideoMenu.java b/src/com/android/camera/VideoMenu.java
index 9bfcdea5d..da0bde10e 100644
--- a/src/com/android/camera/VideoMenu.java
+++ b/src/com/android/camera/VideoMenu.java
@@ -16,6 +16,7 @@
package com.android.camera;
+import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
@@ -51,6 +52,7 @@ public class VideoMenu extends PieController
mActivity = activity;
}
+
public void initialize(PreferenceGroup group) {
super.initialize(group);
mPopup = null;
@@ -200,5 +202,4 @@ public class VideoMenu extends PieController
mUI.showPopup(mPopup);
mPopupStatus = POPUP_SECOND_LEVEL;
}
-
}
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index 977986d1f..839037fc0 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -51,13 +51,16 @@ import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
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.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;
@@ -113,7 +116,7 @@ public class VideoModule implements CameraModule,
private Parameters mParameters;
private Boolean mCameraOpened = false;
-
+ private boolean mIsInReviewMode;
private boolean mSnapshotInProgress = false;
private static final String EFFECT_BG_FROM_GALLERY = "gallery";
@@ -123,11 +126,8 @@ public class VideoModule implements CameraModule,
private ComboPreferences mPreferences;
private PreferenceGroup mPreferenceGroup;
- private CameraScreenNail.OnFrameDrawnListener mFrameDrawnListener;
-
private boolean mIsVideoCaptureIntent;
private boolean mQuickCapture;
- private boolean mIsInReviewMode = false;
private MediaRecorder mMediaRecorder;
private EffectsRecorder mEffectsRecorder;
@@ -176,11 +176,16 @@ public class VideoModule implements CameraModule,
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;
@@ -194,7 +199,6 @@ public class VideoModule implements CameraModule,
@Override
public void onMediaSaved(Uri uri) {
if (uri != null) {
- mActivity.addSecureAlbumItemIfNeeded(true, uri);
mActivity.sendBroadcast(
new Intent(Util.ACTION_NEW_VIDEO, uri));
Util.broadcastNewPicture(mActivity, uri);
@@ -224,15 +228,15 @@ public class VideoModule implements CameraModule,
try {
synchronized(mCameraOpened) {
if (!mCameraOpened) {
- mActivity.mCameraDevice = Util.openCamera(mActivity, mCameraId);
+ mCameraDevice = Util.openCamera(mActivity, mCameraId);
mCameraOpened = true;
}
}
- mParameters = mActivity.mCameraDevice.getParameters();
+ mParameters = mCameraDevice.getParameters();
} catch (CameraHardwareException e) {
- mActivity.mOpenCameraFail = true;
+ mOpenCameraFail = true;
} catch (CameraDisabledException e) {
- mActivity.mCameraDisabled = true;
+ mCameraDisabled = true;
}
}
@@ -285,18 +289,14 @@ public class VideoModule implements CameraModule,
}
case SWITCH_CAMERA_START_ANIMATION: {
- ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera();
+ //TODO:
+ //((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera();
// Enable all camera controls.
mSwitchingCamera = false;
break;
}
- case HIDE_SURFACE_VIEW: {
- mUI.hideSurfaceView();
- break;
- }
-
case CAPTURE_ANIMATION_DONE: {
mUI.enablePreviewThumb(false);
break;
@@ -345,18 +345,12 @@ public class VideoModule implements CameraModule,
private void initializeSurfaceView() {
if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) { // API level < 16
- mFrameDrawnListener = new CameraScreenNail.OnFrameDrawnListener() {
- @Override
- public void onFrameDrawn(CameraScreenNail c) {
- mHandler.sendEmptyMessage(HIDE_SURFACE_VIEW);
- }
- };
- mUI.getSurfaceHolder().addCallback(mUI);
+ mUI.initializeSurfaceView();
}
}
@Override
- public void init(CameraActivity activity, View root, boolean reuseScreenNail) {
+ public void init(CameraActivity activity, View root) {
mActivity = activity;
mUI = new VideoUI(activity, this, root);
mPreferences = new ComboPreferences(mActivity);
@@ -366,9 +360,9 @@ public class VideoModule implements CameraModule,
mPreferences.setLocalId(mActivity, mCameraId);
CameraSettings.upgradeLocalPreferences(mPreferences.getLocal());
- mActivity.mNumberOfCameras = CameraHolder.instance().getNumberOfCameras();
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.
@@ -382,20 +376,15 @@ public class VideoModule implements CameraModule,
// Surface texture is from camera screen nail and startPreview needs it.
// This must be done before startPreview.
mIsVideoCaptureIntent = isVideoCaptureIntent();
- if (reuseScreenNail) {
- mActivity.reuseCameraScreenNail(!mIsVideoCaptureIntent);
- } else {
- mActivity.createCameraScreenNail(!mIsVideoCaptureIntent);
- }
initializeSurfaceView();
// Make sure camera device is opened.
try {
cameraOpenThread.join();
- if (mActivity.mOpenCameraFail) {
+ if (mOpenCameraFail) {
Util.showErrorAndFinish(mActivity, R.string.cannot_connect_camera);
return;
- } else if (mActivity.mCameraDisabled) {
+ } else if (mCameraDisabled) {
Util.showErrorAndFinish(mActivity, R.string.camera_disabled);
return;
}
@@ -463,10 +452,10 @@ public class VideoModule implements CameraModule,
mParameters.setRotation(rotation);
Location loc = mLocationManager.getCurrentLocation();
Util.setGpsParameters(mParameters, loc);
- mActivity.mCameraDevice.setParameters(mParameters);
+ mCameraDevice.setParameters(mParameters);
Log.v(TAG, "Video snapshot start");
- mActivity.mCameraDevice.takePicture(null, null, null, new JpegPictureCallback(loc));
+ mCameraDevice.takePicture(null, null, null, new JpegPictureCallback(loc));
showVideoSnapshotUI(true);
mSnapshotInProgress = true;
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
@@ -583,7 +572,8 @@ public class VideoModule implements CameraModule,
// 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.
- ((CameraScreenNail) mActivity.mCameraScreenNail).animateCapture(mDisplayRotation);
+ // TODO: need to get the capture animation to work
+ // ((CameraScreenNail) mActivity.mCameraScreenNail).animateCapture(mDisplayRotation);
mUI.enablePreviewThumb(true);
@@ -694,7 +684,7 @@ public class VideoModule implements CameraModule,
@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB)
private void getDesiredPreviewSize() {
- mParameters = mActivity.mCameraDevice.getParameters();
+ mParameters = mCameraDevice.getParameters();
if (ApiHelper.HAS_GET_SUPPORTED_VIDEO_SIZE) {
if (mParameters.getSupportedVideoSizes() == null || effectsActive()) {
mDesiredPreviewWidth = mProfile.videoFrameWidth;
@@ -720,6 +710,7 @@ public class VideoModule implements CameraModule,
mDesiredPreviewWidth = mProfile.videoFrameWidth;
mDesiredPreviewHeight = mProfile.videoFrameHeight;
}
+ mUI.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight);
Log.v(TAG, "mDesiredPreviewWidth=" + mDesiredPreviewWidth +
". mDesiredPreviewHeight=" + mDesiredPreviewHeight);
}
@@ -747,7 +738,7 @@ public class VideoModule implements CameraModule,
@Override
public void onResumeAfterSuper() {
- if (mActivity.mOpenCameraFail || mActivity.mCameraDisabled)
+ if (mOpenCameraFail || mCameraDisabled)
return;
mUI.enableShutter(false);
mZoomValue = 0;
@@ -757,11 +748,11 @@ public class VideoModule implements CameraModule,
if (!mPreviewing) {
resetEffect();
openCamera();
- if (mActivity.mOpenCameraFail) {
+ if (mOpenCameraFail) {
Util.showErrorAndFinish(mActivity,
R.string.cannot_connect_camera);
return;
- } else if (mActivity.mCameraDisabled) {
+ } else if (mCameraDisabled) {
Util.showErrorAndFinish(mActivity, R.string.camera_disabled);
return;
}
@@ -801,15 +792,19 @@ public class VideoModule implements CameraModule,
private void setDisplayOrientation() {
mDisplayRotation = Util.getDisplayRotation(mActivity);
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- // The display rotation is handled by gallery.
- mCameraDisplayOrientation = Util.getDisplayOrientation(0, mCameraId);
- } else {
- // We need to consider display rotation ourselves.
- mCameraDisplayOrientation = Util.getDisplayOrientation(mDisplayRotation, mCameraId);
+ 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();
}
- // GLRoot also uses the DisplayRotation, and needs to be told to layout to update
- mActivity.getGLRoot().requestLayoutContentPane();
}
@Override
@@ -817,18 +812,18 @@ public class VideoModule implements CameraModule,
// Not useful to change zoom value when the activity is paused.
if (mPaused) return index;
mZoomValue = index;
- if (mParameters == null || mActivity.mCameraDevice == null) return index;
+ if (mParameters == null || mCameraDevice == null) return index;
// Set zoom parameters asynchronously
mParameters.setZoom(mZoomValue);
- mActivity.mCameraDevice.setParameters(mParameters);
- Parameters p = mActivity.mCameraDevice.getParameters();
+ mCameraDevice.setParameters(mParameters);
+ Parameters p = mCameraDevice.getParameters();
if (p != null) return p.getZoom();
return index;
}
private void startPreview() {
Log.v(TAG, "startPreview");
- mActivity.mCameraDevice.setErrorCallback(mErrorCallback);
+ mCameraDevice.setErrorCallback(mErrorCallback);
if (mPreviewing == true) {
stopPreview();
if (effectsActive() && mEffectsRecorder != null) {
@@ -838,22 +833,17 @@ public class VideoModule implements CameraModule,
}
setDisplayOrientation();
- mActivity.mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation);
+ mCameraDevice.setDisplayOrientation(mCameraDisplayOrientation);
setCameraParameters();
try {
if (!effectsActive()) {
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- SurfaceTexture surfaceTexture = ((CameraScreenNail) mActivity.mCameraScreenNail)
- .getSurfaceTexture();
- if (surfaceTexture == null) {
- return; // The texture has been destroyed (pause, etc)
- }
- mActivity.mCameraDevice.setPreviewTextureAsync(surfaceTexture);
- } else {
- mActivity.mCameraDevice.setPreviewDisplayAsync(mUI.getSurfaceHolder());
+ SurfaceTexture surfaceTexture = mUI.getSurfaceTexture();
+ if (surfaceTexture == null) {
+ return; // The texture has been destroyed (pause, etc)
}
- mActivity.mCameraDevice.startPreviewAsync();
+ mCameraDevice.setPreviewTextureAsync(surfaceTexture);
+ mCameraDevice.startPreviewAsync();
mPreviewing = true;
onPreviewStarted();
} else {
@@ -869,9 +859,9 @@ public class VideoModule implements CameraModule,
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
- if (mActivity.mOpenCameraFail) {
+ if (mOpenCameraFail) {
Util.showErrorAndFinish(mActivity, R.string.cannot_connect_camera);
- } else if (mActivity.mCameraDisabled) {
+ } else if (mCameraDisabled) {
Util.showErrorAndFinish(mActivity, R.string.camera_disabled);
}
}
@@ -886,7 +876,8 @@ public class VideoModule implements CameraModule,
@Override
public void stopPreview() {
- mActivity.mCameraDevice.stopPreview();
+ if (!mPreviewing) return;
+ mCameraDevice.stopPreview();
mPreviewing = false;
}
@@ -922,7 +913,7 @@ public class VideoModule implements CameraModule,
// effects also along with the camera.
private void closeCamera(boolean closeEffectsAlso) {
Log.v(TAG, "closeCamera");
- if (mActivity.mCameraDevice == null) {
+ if (mCameraDevice == null) {
Log.d(TAG, "already stopped.");
return;
}
@@ -933,27 +924,22 @@ public class VideoModule implements CameraModule,
mEffectsRecorder.disconnectCamera();
}
if (closeEffectsAlso) closeEffects();
- mActivity.mCameraDevice.setZoomChangeListener(null);
- mActivity.mCameraDevice.setErrorCallback(null);
+ mCameraDevice.setZoomChangeListener(null);
+ mCameraDevice.setErrorCallback(null);
synchronized(mCameraOpened) {
if (mCameraOpened) {
CameraHolder.instance().release();
}
mCameraOpened = false;
}
- mActivity.mCameraDevice = null;
+ mCameraDevice = null;
mPreviewing = false;
mSnapshotInProgress = false;
}
private void releasePreviewResources() {
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
- screenNail.releaseSurfaceTexture();
- if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) {
- mHandler.removeMessages(HIDE_SURFACE_VIEW);
- mUI.hideSurfaceView();
- }
+ if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) {
+ mUI.hideSurfaceView();
}
}
@@ -1096,13 +1082,11 @@ public class VideoModule implements CameraModule,
private void setupMediaRecorderPreviewDisplay() {
// Nothing to do here if using SurfaceTexture.
- if (!ApiHelper.HAS_SURFACE_TEXTURE) {
- mMediaRecorder.setPreviewDisplay(mUI.getSurfaceHolder().getSurface());
- } else if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) {
+ 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();
- mActivity.mCameraDevice.setPreviewDisplayAsync(mUI.getSurfaceHolder());
+ mCameraDevice.setPreviewDisplayAsync(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
@@ -1110,9 +1094,9 @@ public class VideoModule implements CameraModule,
// Gallery will handle the orientation for the preview. For
// SurfaceView we will have to take everything into account so the
// display rotation is considered.
- mActivity.mCameraDevice.setDisplayOrientation(
+ mCameraDevice.setDisplayOrientation(
Util.getDisplayOrientation(mDisplayRotation, mCameraId));
- mActivity.mCameraDevice.startPreviewAsync();
+ mCameraDevice.startPreviewAsync();
mPreviewing = true;
mMediaRecorder.setPreviewDisplay(mUI.getSurfaceHolder().getSurface());
}
@@ -1122,15 +1106,14 @@ public class VideoModule implements CameraModule,
private void initializeRecorder() {
Log.v(TAG, "initializeRecorder");
// If the mCameraDevice is null, then this activity is going to finish
- if (mActivity.mCameraDevice == null) return;
+ if (mCameraDevice == null) return;
- if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING && ApiHelper.HAS_SURFACE_TEXTURE) {
+ 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();
- if (!mUI.isSurfaceViewReady()) return;
}
Intent intent = mActivity.getIntent();
@@ -1156,9 +1139,9 @@ public class VideoModule implements CameraModule,
setupMediaRecorderPreviewDisplay();
// Unlock the camera object before passing it to media recorder.
- mActivity.mCameraDevice.unlock();
- mActivity.mCameraDevice.waitDone();
- mMediaRecorder.setCamera(mActivity.mCameraDevice.getCamera());
+ mCameraDevice.unlock();
+ mCameraDevice.waitDone();
+ mMediaRecorder.setCamera(mCameraDevice.getCamera());
if (!mCaptureTimeLapse) {
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
}
@@ -1244,7 +1227,7 @@ public class VideoModule implements CameraModule,
private void initializeEffectsPreview() {
Log.v(TAG, "initializeEffectsPreview");
// If the mCameraDevice is null, then this activity is going to finish
- if (mActivity.mCameraDevice == null) return;
+ if (mCameraDevice == null) return;
boolean inLandscape = (mActivity.getResources().getConfiguration().orientation
== Configuration.ORIENTATION_LANDSCAPE);
@@ -1257,7 +1240,7 @@ public class VideoModule implements CameraModule,
// 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(mActivity.mCameraDevice);
+ mEffectsRecorder.setCamera(mCameraDevice);
mEffectsRecorder.setCameraFacing(info.facing);
mEffectsRecorder.setProfile(mProfile);
mEffectsRecorder.setEffectsListener(this);
@@ -1274,9 +1257,8 @@ public class VideoModule implements CameraModule,
}
mEffectsRecorder.setOrientationHint(orientation);
- CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
- mEffectsRecorder.setPreviewSurfaceTexture(screenNail.getSurfaceTexture(),
- screenNail.getWidth(), screenNail.getHeight());
+ mEffectsRecorder.setPreviewSurfaceTexture(mUI.getSurfaceTexture(),
+ mUI.getPreviewWidth(), mUI.getPreviewHeight());
if (mEffectType == EffectsRecorder.EFFECT_BACKDROPPER &&
((String) mEffectParameter).equals(EFFECT_BG_FROM_GALLERY)) {
@@ -1472,7 +1454,7 @@ public class VideoModule implements CameraModule,
private void startVideoRecording() {
Log.v(TAG, "startVideoRecording");
mUI.enablePreviewThumb(false);
- mActivity.setSwipingEnabled(false);
+ mUI.setSwipingEnabled(false);
mActivity.updateStorageSpaceAndHint();
if (mActivity.getStorageSpace() <= Storage.LOW_STORAGE_THRESHOLD) {
@@ -1480,7 +1462,7 @@ public class VideoModule implements CameraModule,
return;
}
- if (!mActivity.mCameraDevice.waitDone()) return;
+ if (!mCameraDevice.waitDone()) return;
mCurrentVideoUri = null;
if (effectsActive()) {
initializeEffectsRecording();
@@ -1513,31 +1495,31 @@ public class VideoModule implements CameraModule,
Log.e(TAG, "Could not start media recorder. ", e);
releaseMediaRecorder();
// If start fails, frameworks will not lock the camera for us.
- mActivity.mCameraDevice.lock();
+ mCameraDevice.lock();
return;
}
}
// Make sure the video recording has started before announcing
// this in accessibility.
- AccessibilityUtils.makeAnnouncement(mActivity.getShutterButton(),
+ 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.
- mActivity.mCameraDevice.refreshParameters();
+ 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 = mActivity.mCameraDevice.getParameters();
+ mParameters = mCameraDevice.getParameters();
}
mUI.enableCameraControls(false);
mMediaRecorderRecording = true;
- mActivity.getOrientationManager().lockOrientation();
+ mOrientationManager.lockOrientation();
mRecordingStartTime = SystemClock.uptimeMillis();
mUI.showRecordingUI(true, mParameters.isZoomSupported());
@@ -1581,8 +1563,8 @@ public class VideoModule implements CameraModule,
private boolean stopVideoRecording() {
Log.v(TAG, "stopVideoRecording");
- mActivity.setSwipingEnabled(true);
- mActivity.showSwitcher();
+ mUI.setSwipingEnabled(true);
+ mUI.showSwitcher();
boolean fail = false;
if (mMediaRecorderRecording) {
@@ -1604,7 +1586,7 @@ public class VideoModule implements CameraModule,
mCurrentVideoFilename = mVideoFilename;
Log.v(TAG, "stopVideoRecording: Setting current video filename: "
+ mCurrentVideoFilename);
- AccessibilityUtils.makeAnnouncement(mActivity.getShutterButton(),
+ AccessibilityUtils.makeAnnouncement(mUI.getShutterButton(),
mActivity.getString(R.string.video_recording_stopped));
} catch (RuntimeException e) {
Log.e(TAG, "stop fail", e);
@@ -1612,7 +1594,7 @@ public class VideoModule implements CameraModule,
fail = true;
}
mMediaRecorderRecording = false;
- mActivity.getOrientationManager().unlockOrientation();
+ mOrientationManager.unlockOrientation();
// If the activity is paused, this means activity is interrupted
// during recording. Release the camera as soon as possible because
@@ -1646,21 +1628,19 @@ public class VideoModule implements CameraModule,
if (!effectsActive()) {
releaseMediaRecorder();
if (!mPaused) {
- mActivity.mCameraDevice.lock();
- mActivity.mCameraDevice.waitDone();
- if (ApiHelper.HAS_SURFACE_TEXTURE &&
- !ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) {
+ mCameraDevice.lock();
+ mCameraDevice.waitDone();
+ if (!ApiHelper.HAS_SURFACE_TEXTURE_RECORDING) {
stopPreview();
+ mUI.hideSurfaceView();
// Switch back to use SurfaceTexture for preview.
- ((CameraScreenNail) mActivity.mCameraScreenNail).setOneTimeOnFrameDrawnListener(
- mFrameDrawnListener);
startPreview();
}
}
}
// Update the parameters here because the parameters might have been altered
// by MediaRecorder.
- if (!mPaused) mParameters = mActivity.mCameraDevice.getParameters();
+ if (!mPaused) mParameters = mCameraDevice.getParameters();
UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
fail ? UsageStatistics.ACTION_CAPTURE_FAIL :
UsageStatistics.ACTION_CAPTURE_DONE, "Video",
@@ -1792,11 +1772,18 @@ public class VideoModule implements CameraModule,
@SuppressWarnings("deprecation")
private void setCameraParameters() {
mParameters.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight);
- mParameters.setPreviewFrameRate(mProfile.videoFrameRate);
+ 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 (mActivity.mShowCameraAppView) {
+ if (mUI.isVisible()) {
flashMode = mPreferences.getString(
CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE,
mActivity.getString(R.string.pref_camera_video_flashmode_default));
@@ -1867,35 +1854,9 @@ public class VideoModule implements CameraModule,
CameraProfile.QUALITY_HIGH);
mParameters.setJpegQuality(jpegQuality);
- mActivity.mCameraDevice.setParameters(mParameters);
+ mCameraDevice.setParameters(mParameters);
// Keep preview size up to date.
- mParameters = mActivity.mCameraDevice.getParameters();
-
- updateCameraScreenNailSize(mDesiredPreviewWidth, mDesiredPreviewHeight);
- }
-
- private void updateCameraScreenNailSize(int width, int height) {
- if (!ApiHelper.HAS_SURFACE_TEXTURE) return;
-
- if (mCameraDisplayOrientation % 180 != 0) {
- int tmp = width;
- width = height;
- height = tmp;
- }
-
- CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
- int oldWidth = screenNail.getWidth();
- int oldHeight = screenNail.getHeight();
-
- if (oldWidth != width || oldHeight != height) {
- screenNail.setSize(width, height);
- screenNail.enableAspectRatioClamping();
- mActivity.notifyScreenNailChanged();
- }
-
- if (screenNail.getSurfaceTexture() == null) {
- screenNail.acquireSurfaceTexture();
- }
+ mParameters = mCameraDevice.getParameters();
}
@Override
@@ -2006,7 +1967,7 @@ public class VideoModule implements CameraModule,
synchronized (mPreferences) {
// If mCameraDevice is not ready then we can set the parameter in
// startPreview().
- if (mActivity.mCameraDevice == null) return;
+ if (mCameraDevice == null) return;
boolean recordLocation = RecordLocationPreference.get(
mPreferences, mContentResolver);
@@ -2062,14 +2023,13 @@ public class VideoModule implements CameraModule,
initializeVideoControl();
// From onResume
+ mZoomValue = 0;
mUI.initializeZoom(mParameters);
mUI.setOrientationIndicator(0, false);
- 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);
- }
+ // 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);
}
@@ -2138,32 +2098,23 @@ public class VideoModule implements CameraModule,
startPreview();
}
- @Override
- public boolean dispatchTouchEvent(MotionEvent m) {
- if (mSwitchingCamera) return true;
- return mUI.dispatchTouchEvent(m);
- }
-
private void initializeVideoSnapshot() {
if (mParameters == null) return;
if (Util.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) {
- mActivity.setSingleTapUpListener(mUI.getPreview());
// 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);
}
- } else {
- mActivity.setSingleTapUpListener(null);
}
}
void showVideoSnapshotUI(boolean enabled) {
if (mParameters == null) return;
if (Util.isVideoSnapshotSupported(mParameters) && !mIsVideoCaptureIntent) {
- if (ApiHelper.HAS_SURFACE_TEXTURE && enabled) {
- ((CameraScreenNail) mActivity.mCameraScreenNail).animateCapture(mDisplayRotation);
+ if (enabled) {
+ // TODO: ((CameraScreenNail) mActivity.mCameraScreenNail).animateCapture(mDisplayRotation);
} else {
mUI.showPreviewBorder(enabled);
}
@@ -2176,7 +2127,7 @@ public class VideoModule implements CameraModule,
if (!mPreviewing || mParameters.getFlashMode() == null) return;
// When going to and back from gallery, we need to turn off/on the flash.
- if (!mActivity.mShowCameraAppView) {
+ if (!mUI.isVisible()) {
if (mParameters.getFlashMode().equals(Parameters.FLASH_MODE_OFF)) {
mRestoreFlash = false;
return;
@@ -2190,14 +2141,8 @@ public class VideoModule implements CameraModule,
}
@Override
- public void onFullScreenChanged(boolean full) {
- mUI.onFullScreenChanged(full);
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- if (mActivity.mCameraScreenNail != null) {
- ((CameraScreenNail) mActivity.mCameraScreenNail).setFullScreen(full);
- }
- return;
- }
+ public void onSwitchMode(boolean toCamera) {
+ mUI.onSwitchMode(toCamera);
}
private final class JpegPictureCallback implements PictureCallback {
@@ -2285,26 +2230,13 @@ public class VideoModule implements CameraModule,
if (mPaused || mPendingSwitchCameraId != -1) return;
mPendingSwitchCameraId = cameraId;
- if (ApiHelper.HAS_SURFACE_TEXTURE) {
- 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.
- ((CameraScreenNail) mActivity.mCameraScreenNail).copyTexture();
- // Disable all camera controls.
- mSwitchingCamera = true;
- } else {
- switchCamera();
- }
- }
+ 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 boolean needsSwitcher() {
- return !mIsVideoCaptureIntent;
- }
-
- @Override
- public boolean needsPieMenu() {
- return true;
}
@Override
@@ -2316,7 +2248,4 @@ public class VideoModule implements CameraModule,
public void onMediaSaveServiceConnected(MediaSaveService s) {
// do nothing.
}
-
- @Override
- public void updateCameraOrientation() {}
}
diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java
index 9fc05769f..c446b9778 100644
--- a/src/com/android/camera/VideoUI.java
+++ b/src/com/android/camera/VideoUI.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -17,13 +17,20 @@
package com.android.camera;
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.MotionEvent;
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;
@@ -33,8 +40,11 @@ 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.PreviewSurfaceView;
import com.android.camera.ui.RenderOverlay;
import com.android.camera.ui.RotateLayout;
import com.android.camera.ui.ZoomRenderer;
@@ -43,16 +53,16 @@ import com.android.gallery3d.common.ApiHelper;
import java.util.List;
-public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
+public class VideoUI implements PieRenderer.PieListener,
PreviewGestures.SingleTapListener,
- PreviewGestures.SwipeListener {
+ CameraRootView.MyDisplayListener,
+ SurfaceTextureListener, SurfaceHolder.Callback {
private final static String TAG = "CAM_VideoUI";
+ private static final int UPDATE_TRANSFORM_MATRIX = 1;
// module fields
private CameraActivity mActivity;
private View mRootView;
- private PreviewFrameLayout mPreviewFrameLayout;
- private boolean mSurfaceViewReady;
- private PreviewSurfaceView mPreviewSurfaceView;
+ private TextureView mTextureView;
// An review image having same size as preview. It is displayed when
// recording is stopped in capture intent.
private ImageView mReviewImage;
@@ -60,40 +70,97 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
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 mMenu;
+ 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 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 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);
- mPreviewSurfaceView = (PreviewSurfaceView) mRootView
- .findViewById(R.id.preview_surface_view);
+ mTextureView = (TextureView) mRootView.findViewById(R.id.preview_content);
+ mTextureView.setSurfaceTextureListener(this);
+ mRootView.addOnLayoutChangeListener(mLayoutListener);
+ ((CameraRootView) mRootView).setDisplayChangeListener(this);
+ mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
+ mSwitcher = (CameraSwitcher) mRootView.findViewById(R.id.camera_switcher);
+ mSwitcher.setCurrentIndex(1);
+ mSwitcher.setSwitchListener((CameraSwitchListener) mActivity);
initializeMiscControls();
initializeControlByIntent();
initializeOverlay();
}
+
+ 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);
- mMenu = mActivity.findViewById(R.id.menu);
- mMenu.setOnClickListener(new OnClickListener() {
+ mMenuButton = mActivity.findViewById(R.id.menu);
+ mMenuButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mPieRenderer != null) {
@@ -101,13 +168,15 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
}
});
+
+ mCameraControls = (CameraControls) mActivity.findViewById(R.id.camera_controls);
mOnScreenIndicators = new OnScreenIndicators(mActivity,
mActivity.findViewById(R.id.on_screen_indicators));
mOnScreenIndicators.resetToDefault();
if (mController.isVideoCaptureIntent()) {
- mActivity.hideSwitcher();
- ViewGroup cameraControls = (ViewGroup) mActivity.findViewById(R.id.camera_controls);
- mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls);
+ 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.
@@ -136,6 +205,85 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
}
+ 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();
+ }
+ }
+
+ 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) {
@@ -166,10 +314,6 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
mVideoMenu.overrideSettings(keyvalues);
}
- public View getPreview() {
- return mPreviewFrameLayout;
- }
-
public void setOrientationIndicator(int orientation, boolean animation) {
if (mGestures != null) {
mGestures.setOrientation(orientation);
@@ -187,15 +331,19 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
public SurfaceHolder getSurfaceHolder() {
- return mPreviewSurfaceView.getHolder();
+ return mSurfaceView.getHolder();
}
public void hideSurfaceView() {
- mPreviewSurfaceView.setVisibility(View.GONE);
+ mSurfaceView.setVisibility(View.GONE);
+ mTextureView.setVisibility(View.VISIBLE);
+ setTransformMatrix(mPreviewWidth, mPreviewHeight);
}
public void showSurfaceView() {
- mPreviewSurfaceView.setVisibility(View.VISIBLE);
+ mSurfaceView.setVisibility(View.VISIBLE);
+ mTextureView.setVisibility(View.GONE);
+ setTransformMatrix(mPreviewWidth, mPreviewHeight);
}
private void initializeOverlay() {
@@ -211,29 +359,16 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
mRenderOverlay.addRenderer(mZoomRenderer);
if (mGestures == null) {
- mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer, this);
+ mGestures = new PreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer);
+ mRenderOverlay.setGestures(mGestures);
}
mGestures.setRenderOverlay(mRenderOverlay);
- mGestures.reset();
- mGestures.addTouchReceiver(mMenu);
- mGestures.addUnclickableArea(mBlocker);
- if (mController.isVideoCaptureIntent()) {
- if (mReviewCancelButton != null) {
- mGestures.addTouchReceiver(mReviewCancelButton);
- }
- if (mReviewDoneButton != null) {
- mGestures.addTouchReceiver(mReviewDoneButton);
- }
- if (mReviewPlayButton != null) {
- mGestures.addTouchReceiver(mReviewPlayButton);
- }
- }
mPreviewThumb = mActivity.findViewById(R.id.preview_thumb);
mPreviewThumb.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- mActivity.gotoGallery();
+ // TODO: Go to filmstrip view
}
});
}
@@ -243,10 +378,7 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
private void initializeMiscControls() {
- mPreviewFrameLayout = (PreviewFrameLayout) mRootView.findViewById(R.id.frame);
- mPreviewFrameLayout.setOnLayoutChangeListener(mActivity);
mReviewImage = (ImageView) mRootView.findViewById(R.id.review_image);
- mShutterButton = mActivity.getShutterButton();
mShutterButton.setImageResource(R.drawable.btn_new_shutter_video);
mShutterButton.setOnShutterButtonListener(mController);
mShutterButton.setVisibility(View.VISIBLE);
@@ -269,7 +401,7 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
public void setAspectRatio(double ratio) {
- mPreviewFrameLayout.setAspectRatio(ratio);
+ // mPreviewFrameLayout.setAspectRatio(ratio);
}
public void showTimeLapseUI(boolean enable) {
@@ -285,7 +417,7 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
public void showPopup(AbstractSettingPopup popup) {
- mActivity.hideUI();
+ hideUI();
mBlocker.setVisibility(View.INVISIBLE);
setShowMenu(false);
mPopup = popup;
@@ -294,7 +426,6 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.CENTER;
((FrameLayout) mRootView).addView(mPopup, lp);
- mGestures.addTouchReceiver(mPopup);
}
public void dismissPopup(boolean topLevelOnly) {
@@ -306,12 +437,11 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
if (mController.isInReviewMode()) return;
if (fullScreen) {
- mActivity.showUI();
+ showUI();
mBlocker.setVisibility(View.VISIBLE);
}
setShowMenu(fullScreen);
if (mPopup != null) {
- mGestures.removeTouchReceiver(mPopup);
((FrameLayout) mRootView).removeView(mPopup);
mPopup = null;
}
@@ -345,18 +475,21 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
// PieListener
@Override
public void onPieOpened(int centerX, int centerY) {
+ setSwipingEnabled(false);
dismissPopup(false, true);
- mActivity.cancelActivityTouchHandling();
- mActivity.setSwipingEnabled(false);
}
@Override
public void onPieClosed() {
- mActivity.setSwipingEnabled(true);
+ setSwipingEnabled(true);
+ }
+
+ public void setSwipingEnabled(boolean enable) {
+ mActivity.setSwipingEnabled(enable);
}
public void showPreviewBorder(boolean enable) {
- mPreviewFrameLayout.showBorder(enable);
+ // TODO: mPreviewFrameLayout.showBorder(enable);
}
// SingleTapListener
@@ -366,35 +499,12 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
mController.onSingleTapUp(view, x, y);
}
- // SurfaceView callback
- @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");
- mSurfaceViewReady = true;
- }
-
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- Log.v(TAG, "Surface destroyed");
- mSurfaceViewReady = false;
- mController.stopPreview();
- }
-
- public boolean isSurfaceViewReady() {
- return mSurfaceViewReady;
- }
-
public void showRecordingUI(boolean recording, boolean zoomSupported) {
- mMenu.setVisibility(recording ? View.GONE : View.VISIBLE);
+ mMenuButton.setVisibility(recording ? View.GONE : View.VISIBLE);
mOnScreenIndicators.setVisibility(recording ? View.GONE : View.VISIBLE);
if (recording) {
mShutterButton.setImageResource(R.drawable.btn_shutter_video_recording);
- mActivity.hideSwitcher();
+ hideSwitcher();
mRecordingTimeView.setText("");
mRecordingTimeView.setVisibility(View.VISIBLE);
// The camera is not allowed to be accessed in older api levels during
@@ -407,7 +517,7 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
} else {
mShutterButton.setImageResource(R.drawable.btn_new_shutter_video);
- mActivity.showSwitcher();
+ showSwitcher();
mRecordingTimeView.setVisibility(View.GONE);
if (!ApiHelper.HAS_ZOOM_WHEN_RECORDING && zoomSupported) {
// TODO: enable zoom UI here.
@@ -425,14 +535,14 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
Util.fadeIn(mReviewDoneButton);
Util.fadeIn(mReviewPlayButton);
mReviewImage.setVisibility(View.VISIBLE);
- mMenu.setVisibility(View.GONE);
+ mMenuButton.setVisibility(View.GONE);
mOnScreenIndicators.setVisibility(View.GONE);
}
public void hideReviewUI() {
mReviewImage.setVisibility(View.GONE);
mShutterButton.setEnabled(true);
- mMenu.setVisibility(View.VISIBLE);
+ mMenuButton.setVisibility(View.VISIBLE);
mOnScreenIndicators.setVisibility(View.VISIBLE);
Util.fadeOut(mReviewDoneButton);
Util.fadeOut(mReviewPlayButton);
@@ -443,27 +553,28 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
if (mOnScreenIndicators != null) {
mOnScreenIndicators.setVisibility(show ? View.VISIBLE : View.GONE);
}
- if (mMenu != null) {
- mMenu.setVisibility(show ? View.VISIBLE : View.GONE);
+ if (mMenuButton != null) {
+ mMenuButton.setVisibility(show ? View.VISIBLE : View.GONE);
}
}
- public void onFullScreenChanged(boolean full) {
+ public void onSwitchMode(boolean toCamera) {
+ if (toCamera) {
+ showUI();
+ } else {
+ hideUI();
+ }
if (mGestures != null) {
- mGestures.setEnabled(full);
+ mGestures.setEnabled(toCamera);
}
if (mPopup != null) {
- dismissPopup(false, full);
+ dismissPopup(false, toCamera);
}
if (mRenderOverlay != null) {
// this can not happen in capture mode
- mRenderOverlay.setVisibility(full ? View.VISIBLE : View.GONE);
- }
- setShowMenu(full);
- if (mBlocker != null) {
- // this can not happen in capture mode
- mBlocker.setVisibility(full ? View.VISIBLE : View.GONE);
+ mRenderOverlay.setVisibility(toCamera ? View.VISIBLE : View.GONE);
}
+ setShowMenu(toCamera);
}
public void initializePopup(PreferenceGroup pref) {
@@ -471,7 +582,11 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
public void initializeZoom(Parameters param) {
- if (param == null || !param.isZoomSupported()) return;
+ 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
@@ -490,11 +605,8 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
mShutterButton.setPressed(pressed);
}
- public boolean dispatchTouchEvent(MotionEvent m) {
- if (mGestures != null && mRenderOverlay != null) {
- return mGestures.dispatchTouch(m);
- }
- return false;
+ public View getShutterButton() {
+ return mShutterButton;
}
public void setRecordingTime(String text) {
@@ -505,6 +617,26 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
mRecordingTimeView.setTextColor(color);
}
+ public boolean isVisible() {
+ return mTextureView.getVisibility() == View.VISIBLE;
+ }
+
+ public void onDisplayChanged() {
+ mCameraControls.checkLayoutFlip();
+ mController.updateCameraOrientation();
+ }
+
+ /**
+ * Enable or disable the preview thumbnail for click events.
+ */
+ public void enablePreviewThumb(boolean enabled) {
+ if (enabled) {
+ mPreviewThumb.setVisibility(View.VISIBLE);
+ } else {
+ mPreviewThumb.setVisibility(View.GONE);
+ }
+ }
+
private class ZoomChangeListener implements ZoomRenderer.OnZoomChangedListener {
@Override
public void onZoomValueChanged(int index) {
@@ -523,23 +655,58 @@ public class VideoUI implements SurfaceHolder.Callback, PieRenderer.PieListener,
}
}
- @Override
- public void onSwipe(int direction) {
- if (direction == PreviewGestures.DIR_UP) {
- openMenu();
+ public SurfaceTexture 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;
}
- /**
- * Enable or disable the preview thumbnail for click events.
- */
- public void enablePreviewThumb(boolean enabled) {
- if (enabled) {
- mGestures.addTouchReceiver(mPreviewThumb);
- mPreviewThumb.setVisibility(View.VISIBLE);
- } else {
- mGestures.removeTouchReceiver(mPreviewThumb);
- mPreviewThumb.setVisibility(View.GONE);
+ // SurfaceTexture callbacks
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ synchronized (mLock) {
+ mSurfaceTexture = surface;
+ mLock.notifyAll();
}
}
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ mSurfaceTexture = null;
+ mController.stopPreview();
+ 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/ui/CameraRootView.java b/src/com/android/camera/ui/CameraRootView.java
index 76fea2cfa..adda70697 100644
--- a/src/com/android/camera/ui/CameraRootView.java
+++ b/src/com/android/camera/ui/CameraRootView.java
@@ -20,28 +20,34 @@ 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.Gravity;
import android.view.View;
import android.widget.FrameLayout;
-import android.widget.RelativeLayout;
import com.android.camera.Util;
-import com.android.gallery3d.R;
+import com.android.gallery3d.common.ApiHelper;
-public class CameraRootView extends RelativeLayout {
+public class CameraRootView extends FrameLayout {
private int mTopMargin = 0;
private int mBottomMargin = 0;
private int mLeftMargin = 0;
private int mRightMargin = 0;
- private int mOffset = 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);
- // Layout the window as if we did not need navigation bar
- setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+ initDisplayListener();
+ setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
@Override
@@ -60,6 +66,46 @@ public class CameraRootView extends RelativeLayout {
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());
@@ -102,12 +148,15 @@ public class CameraRootView extends RelativeLayout {
// 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++) {
diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java
index 24150497c..7d66dc079 100644
--- a/src/com/android/camera/ui/FaceView.java
+++ b/src/com/android/camera/ui/FaceView.java
@@ -31,9 +31,7 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
-import com.android.camera.CameraActivity;
-import com.android.camera.CameraScreenNail;
-import com.android.camera.NewPhotoUI;
+import com.android.camera.PhotoUI;
import com.android.camera.Util;
import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
@@ -41,7 +39,7 @@ import com.android.gallery3d.common.ApiHelper;
@TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH)
public class FaceView extends View
implements FocusIndicator, Rotatable,
- NewPhotoUI.SurfaceTextureSizeChangedListener {
+ PhotoUI.SurfaceTextureSizeChangedListener {
private static final String TAG = "CAM FaceView";
private final boolean LOGV = false;
// The value for android.hardware.Camera.setDisplayOrientation.
@@ -190,16 +188,8 @@ public class FaceView extends View
protected void onDraw(Canvas canvas) {
if (!mBlocked && (mFaces != null) && (mFaces.length > 0)) {
int rw, rh;
- if (mUncroppedWidth == 0) {
- // TODO: This check is temporary. It needs to be removed after the
- // refactoring is fully functioning.
- final CameraScreenNail sn = ((CameraActivity) getContext()).getCameraScreenNail();
- rw = sn.getUncroppedRenderWidth();
- rh = sn.getUncroppedRenderHeight();
- } else {
- rw = mUncroppedWidth;
- rh = mUncroppedHeight;
- }
+ rw = mUncroppedWidth;
+ rh = mUncroppedHeight;
// Prepare the matrix.
if (((rh > rw) && ((mDisplayOrientation == 0) || (mDisplayOrientation == 180)))
|| ((rw > rh) && ((mDisplayOrientation == 90) || (mDisplayOrientation == 270)))) {
diff --git a/src/com/android/camera/ui/NewCameraRootView.java b/src/com/android/camera/ui/NewCameraRootView.java
deleted file mode 100644
index 07b6ec623..000000000
--- a/src/com/android/camera/ui/NewCameraRootView.java
+++ /dev/null
@@ -1,184 +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.Gravity;
-import android.view.MotionEvent;
-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 NewCameraRootView 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 NewCameraRootView(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/RenderOverlay.java b/src/com/android/camera/ui/RenderOverlay.java
index c61103018..d82ce18b6 100644
--- a/src/com/android/camera/ui/RenderOverlay.java
+++ b/src/com/android/camera/ui/RenderOverlay.java
@@ -23,7 +23,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
-import com.android.camera.NewPreviewGestures;
+import com.android.camera.PreviewGestures;
import java.util.ArrayList;
import java.util.List;
@@ -44,7 +44,7 @@ public class RenderOverlay extends FrameLayout {
private RenderView mRenderView;
private List<Renderer> mClients;
- private NewPreviewGestures mGestures;
+ private PreviewGestures mGestures;
// reverse list of touch clients
private List<Renderer> mTouchClients;
private int[] mPosition = new int[2];
@@ -59,7 +59,7 @@ public class RenderOverlay extends FrameLayout {
setWillNotDraw(false);
}
- public void setGestures(NewPreviewGestures gestures) {
+ public void setGestures(PreviewGestures gestures) {
mGestures = gestures;
}
diff --git a/src/com/android/gallery3d/app/StateManager.java b/src/com/android/gallery3d/app/StateManager.java
index c0c84c950..53c3fc228 100644
--- a/src/com/android/gallery3d/app/StateManager.java
+++ b/src/com/android/gallery3d/app/StateManager.java
@@ -64,14 +64,10 @@ public class StateManager {
StateTransitionAnimation.Transition.Incoming);
if (mIsResumed) top.onPause();
}
- // Ignore the filmstrip used for the root of the camera app
- boolean ignoreHit = (mActivity instanceof CameraActivity)
- && mStack.isEmpty();
- if (!ignoreHit) {
- UsageStatistics.onContentViewChanged(
- UsageStatistics.COMPONENT_GALLERY,
- klass.getSimpleName());
- }
+
+ UsageStatistics.onContentViewChanged(
+ UsageStatistics.COMPONENT_GALLERY,
+ klass.getSimpleName());
state.initialize(mActivity, data);
mStack.push(new StateEntry(data, state));
diff --git a/src_pd/com/android/gallery3d/util/LightCycleHelper.java b/src_pd/com/android/gallery3d/util/LightCycleHelper.java
index 742400ec3..bceeea6b4 100644
--- a/src_pd/com/android/gallery3d/util/LightCycleHelper.java
+++ b/src_pd/com/android/gallery3d/util/LightCycleHelper.java
@@ -22,7 +22,6 @@ import android.content.Intent;
import android.net.Uri;
import com.android.camera.CameraModule;
-import com.android.camera.NewCameraModule;
import com.android.gallery3d.app.GalleryApp;
import com.android.gallery3d.app.StitchingProgressManager;
@@ -80,10 +79,6 @@ public class LightCycleHelper {
return null;
}
- public static NewCameraModule createNewPanoramaModule() {
- return null;
- }
-
public static StitchingProgressManager createStitchingManagerInstance(GalleryApp app) {
return null;
}