From 685b8e30b5c031e3d10b78143cc160eb204ca891 Mon Sep 17 00:00:00 2001 From: Doris Liu Date: Thu, 25 Apr 2013 13:41:12 -0700 Subject: Remove new camera activity code from Bryce Bug: 8722017 Change-Id: Ife3f45511f6724c61fb01c4753078df14571fc4a --- src/com/android/camera/NewCameraActivity.java | 346 --- src/com/android/camera/NewCameraModule.java | 76 - src/com/android/camera/NewPhotoMenu.java | 247 --- src/com/android/camera/NewPhotoModule.java | 2005 ----------------- src/com/android/camera/NewPhotoUI.java | 879 -------- src/com/android/camera/NewPreviewGestures.java | 358 --- src/com/android/camera/NewVideoMenu.java | 190 -- src/com/android/camera/NewVideoModule.java | 2344 -------------------- src/com/android/camera/NewVideoUI.java | 724 ------ src/com/android/camera/data/CameraDataAdapter.java | 424 ---- src/com/android/camera/ui/FaceView.java | 9 +- .../camera/ui/FilmStripGestureRecognizer.java | 107 - src/com/android/camera/ui/FilmStripView.java | 830 ------- src/com/android/camera/ui/NewCameraRootView.java | 91 - 14 files changed, 1 insertion(+), 8629 deletions(-) delete mode 100644 src/com/android/camera/NewCameraActivity.java delete mode 100644 src/com/android/camera/NewCameraModule.java delete mode 100644 src/com/android/camera/NewPhotoMenu.java delete mode 100644 src/com/android/camera/NewPhotoModule.java delete mode 100644 src/com/android/camera/NewPhotoUI.java delete mode 100644 src/com/android/camera/NewPreviewGestures.java delete mode 100644 src/com/android/camera/NewVideoMenu.java delete mode 100644 src/com/android/camera/NewVideoModule.java delete mode 100644 src/com/android/camera/NewVideoUI.java delete mode 100644 src/com/android/camera/data/CameraDataAdapter.java delete mode 100644 src/com/android/camera/ui/FilmStripGestureRecognizer.java delete mode 100644 src/com/android/camera/ui/FilmStripView.java delete mode 100644 src/com/android/camera/ui/NewCameraRootView.java (limited to 'src/com/android/camera') diff --git a/src/com/android/camera/NewCameraActivity.java b/src/com/android/camera/NewCameraActivity.java deleted file mode 100644 index e8d2157da..000000000 --- a/src/com/android/camera/NewCameraActivity.java +++ /dev/null @@ -1,346 +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.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.os.Bundle; -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 com.android.camera.data.CameraDataAdapter; -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 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 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; - }}; - - public MediaSaveService getMediaSaveService() { - return mMediaSaveService; - } - - 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() { - mMediaSaveService.setListener(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; - // Use a new album when this is started from the lock screen. - //TODO: sSecureAlbumId++; - } 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); - // 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); - mCurrentModule = new NewPhotoModule(); - mCurrentModule.init(this, mRootView); - mOrientationListener = new MyOrientationEventListener(this); - 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. - mDataAdapter.requestLoad(getContentResolver()); - } - - @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) { - //if (mFilmStripView.isInCameraFullscreen()) { - // return mCurrentModule.dispatchTouchEvent(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 PANORAMA_MODULE_INDEX: - mCurrentModule = new PanoramaModule(); - break; - case LIGHTCYCLE_MODULE_INDEX: - mCurrentModule = LightCycleHelper.createPanoramaModule(); - 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(); - ((NewCameraRootView) mRootView).cameraModuleChanged(); - } - - private void closeModule(NewCameraModule module) { - module.onPauseBeforeSuper(); - module.onPauseAfterSuper(); - ((ViewGroup) mRootView).removeAllViews(); - } - - @Override - public void onShowSwitcherPopup() { - } -} diff --git a/src/com/android/camera/NewCameraModule.java b/src/com/android/camera/NewCameraModule.java deleted file mode 100644 index 061cc6cca..000000000 --- a/src/com/android/camera/NewCameraModule.java +++ /dev/null @@ -1,76 +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 onFullScreenChanged(boolean full); - - 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 boolean dispatchTouchEvent(MotionEvent m); - - 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 962df0f9a..000000000 --- a/src/com/android/camera/NewPhotoMenu.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.content.Context; -import android.hardware.Camera.Parameters; -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.TimerSettingPopup; -import com.android.gallery3d.R; - -public class NewPhotoMenu extends PieController - implements MoreSettingPopup.Listener, - TimerSettingPopup.Listener, - ListPrefSettingPopup.Listener { - private static String TAG = "CAM_photomenu"; - - private static final int POS_HDR = 0; - private static final int POS_EXP = 1; - private static final int POS_MORE = 2; - private static final int POS_FLASH = 3; - private static final int POS_SWITCH = 4; - private static final int POS_WB = 1; - private static final int POS_SET = 2; - - private final String mSettingOff; - - private NewPhotoUI mUI; - private String[] mOtherKeys; - // First level popup - private MoreSettingPopup mPopup; - // Second level popup - private AbstractSettingPopup mSecondPopup; - 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; - mSecondPopup = null; - PieItem item = null; - // flash - if (group.findPreference(CameraSettings.KEY_FLASH_MODE) != null) { - item = makeItem(CameraSettings.KEY_FLASH_MODE, POS_FLASH, 5); - mRenderer.addItem(item); - } - // exposure compensation - item = makeItem(CameraSettings.KEY_EXPOSURE, POS_EXP, 5); - mRenderer.addItem(item); - // camera switcher - if (group.findPreference(CameraSettings.KEY_CAMERA_ID) != null) { - item = makeItem(R.drawable.ic_switch_photo_facing_holo_light); - item.setPosition(POS_SWITCH, 5); - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - // Find the index of next camera. - ListPreference camPref = mPreferenceGroup - .findPreference(CameraSettings.KEY_CAMERA_ID); - if (camPref != null) { - int index = camPref.findIndexOfValue(camPref.getValue()); - CharSequence[] values = camPref.getEntryValues(); - index = (index + 1) % values.length; - int newCameraId = Integer - .parseInt((String) values[index]); - mListener.onCameraPickerClicked(newCameraId); - } - } - }); - mRenderer.addItem(item); - } - // hdr - if (group.findPreference(CameraSettings.KEY_CAMERA_HDR) != null) { - item = makeItem(R.drawable.ic_hdr); - item.setPosition(POS_HDR, 5); - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - // Find the index of next camera. - ListPreference pref = mPreferenceGroup - .findPreference(CameraSettings.KEY_CAMERA_HDR); - if (pref != null) { - // toggle hdr value - int index = (pref.findIndexOfValue(pref.getValue()) + 1) % 2; - pref.setValueIndex(index); - onSettingChanged(pref); - } - } - }); - mRenderer.addItem(item); - } - - // more settings - PieItem more = makeItem(R.drawable.ic_settings_holo_light); - more.setPosition(POS_MORE, 5); - mRenderer.addItem(more); - // white balance - item = makeItem(CameraSettings.KEY_WHITE_BALANCE, POS_WB, 5); - more.addItem(item); - // settings popup - mOtherKeys = new String[] { - CameraSettings.KEY_SCENE_MODE, - CameraSettings.KEY_RECORD_LOCATION, - CameraSettings.KEY_PICTURE_SIZE, - CameraSettings.KEY_FOCUS_MODE, - CameraSettings.KEY_TIMER, - CameraSettings.KEY_TIMER_SOUND_EFFECTS, - }; - item = makeItem(R.drawable.ic_settings_holo_light); - item.setPosition(POS_SET, 5); - item.setOnClickListener(new OnClickListener() { - @Override - public void onClick(PieItem item) { - if (mPopup == null) { - initializePopup(); - } - mUI.showPopup(mPopup); - } - }); - more.addItem(item); - } - - @Override - public void reloadPreferences() { - super.reloadPreferences(); - if (mPopup != null) { - mPopup.reloadPreference(); - } - } - - @Override - // Hit when an item in the second-level popup gets selected - public void onListPrefChanged(ListPreference pref) { - if (mPopup != null && mSecondPopup != null) { - mUI.dismissPopup(true); - mPopup.reloadPreference(); - } - onSettingChanged(pref); - } - - @Override - public void overrideSettings(final String ... keyvalues) { - super.overrideSettings(keyvalues); - if (mPopup == null) initializePopup(); - mPopup.overrideSettings(keyvalues); - } - - 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 (mSecondPopup != null) { - mSecondPopup = null; - if (topPopupOnly) mUI.showPopup(mPopup); - } - } - - // 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); - } - - @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 (mSecondPopup != null) return; - - LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - if (CameraSettings.KEY_TIMER.equals(pref.getKey())) { - TimerSettingPopup timerPopup = (TimerSettingPopup) inflater.inflate( - R.layout.timer_setting_popup, null, false); - timerPopup.initialize(pref); - timerPopup.setSettingChangedListener(this); - mUI.dismissPopup(true); - mSecondPopup = timerPopup; - } else { - ListPrefSettingPopup basic = (ListPrefSettingPopup) inflater.inflate( - R.layout.list_pref_setting_popup, null, false); - basic.initialize(pref); - basic.setSettingChangedListener(this); - mUI.dismissPopup(true); - mSecondPopup = basic; - } - mUI.showPopup(mSecondPopup); - } -} diff --git a/src/com/android/camera/NewPhotoModule.java b/src/com/android/camera/NewPhotoModule.java deleted file mode 100644 index 659e2be19..000000000 --- a/src/com/android/camera/NewPhotoModule.java +++ /dev/null @@ -1,2005 +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.CropExtras; -import com.android.gallery3d.filtershow.FilterShowActivity; -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; - - // 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; - - // -1 means camera is not switching. - protected int mPendingSwitchCameraId = -1; - private boolean mOpenCameraFail; - private boolean mCameraDisabled; - - // When setCameraParametersWhenIdle() is called, we accumulate the subsets - // needed to be updated in mUpdateSet. - private int mUpdateSet; - - private static final int SCREEN_DELAY = 2 * 60 * 1000; - - private int mZoomValue; // The current zoom value. - - private Parameters mInitialParams; - private boolean mFocusAreaSupported; - private boolean mMeteringAreaSupported; - private boolean mAeLockSupported; - private boolean mAwbLockSupported; - private boolean mContinousFocusSupported; - - // The degrees of the device rotated clockwise from its natural orientation. - private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; - private ComboPreferences mPreferences; - - private static final String sTempCropFilename = "crop-temp"; - - private ContentProviderClient mMediaProviderClient; - private boolean mFaceDetectionStarted = false; - - // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true. - private String mCropValue; - private Uri mSaveUri; - - // We use a queue to generated names of the images to be used later - // when the image is ready to be saved. - private NamedImages mNamedImages; - - private Runnable mDoSnapRunnable = new Runnable() { - @Override - public void run() { - onShutterButtonClick(); - } - }; - - private final StringBuilder mBuilder = new StringBuilder(); - private final Formatter mFormatter = new Formatter(mBuilder); - private final Object[] mFormatterArgs = new Object[1]; - - /** - * An unpublished intent flag requesting to return as soon as capturing - * is completed. - * - * TODO: consider publishing by moving into MediaStore. - */ - private static final String EXTRA_QUICK_CAPTURE = - "android.intent.extra.quickCapture"; - - // The display rotation in degrees. This is only valid when mCameraState is - // not PREVIEW_STOPPED. - private int mDisplayRotation; - // The value for android.hardware.Camera.setDisplayOrientation. - private int mCameraDisplayOrientation; - // The value for UI components like indicators. - private int mDisplayOrientation; - // The value for android.hardware.Camera.Parameters.setRotation. - private int mJpegRotation; - private boolean mFirstTimeInitialized; - private boolean mIsImageCaptureIntent; - - private int mCameraState = PREVIEW_STOPPED; - private boolean mSnapshotOnIdle = false; - - private ContentResolver mContentResolver; - - private LocationManager mLocationManager; - - private final ShutterCallback mShutterCallback = new ShutterCallback(); - 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) { - // TODO: Commenting out the line below for now. need to get it working - // mActivity.addSecureAlbumItemIfNeeded(false, uri); - Util.broadcastNewPicture(mActivity, uri); - } - } - }; - - // The purpose is not to block the main thread in onCreate and onResume. - private class CameraStartUpThread extends Thread { - private volatile boolean mCancelled; - - public void cancel() { - mCancelled = true; - interrupt(); - } - - public boolean isCanceled() { - return mCancelled; - } - - @Override - public void run() { - try { - // We need to check whether the activity is paused before long - // operations to ensure that onPause() can be done ASAP. - if (mCancelled) return; - mCameraDevice = Util.openCamera(mActivity, mCameraId); - mParameters = mCameraDevice.getParameters(); - // Wait until all the initialization needed by startPreview are - // done. - mStartPreviewPrerequisiteReady.block(); - - initializeCapabilities(); - if (mFocusManager == null) initializeFocusManager(); - if (mCancelled) return; - setCameraParameters(UPDATE_PARAM_ALL); - mHandler.sendEmptyMessage(CAMERA_OPEN_DONE); - if (mCancelled) return; - startPreview(); - mHandler.sendEmptyMessage(START_PREVIEW_DONE); - mOnResumeTime = SystemClock.uptimeMillis(); - mHandler.sendEmptyMessage(CHECK_DISPLAY_ROTATION); - } catch (CameraHardwareException e) { - mHandler.sendEmptyMessage(OPEN_CAMERA_FAIL); - } catch (CameraDisabledException e) { - mHandler.sendEmptyMessage(CAMERA_DISABLED); - } - } - } - - /** - * This Handler is used to post message back onto the main thread of the - * application - */ - private class MainHandler extends Handler { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case SETUP_PREVIEW: { - setupPreview(); - break; - } - - case CLEAR_SCREEN_DELAY: { - mActivity.getWindow().clearFlags( - WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); - break; - } - - case FIRST_TIME_INIT: { - initializeFirstTime(); - break; - } - - case SET_CAMERA_PARAMETERS_WHEN_IDLE: { - setCameraParametersWhenIdle(0); - break; - } - - case CHECK_DISPLAY_ROTATION: { - // Set the display orientation if display rotation has changed. - // Sometimes this happens when the device is held upside - // down and camera app is opened. Rotation animation will - // take some time and the rotation value we have got may be - // wrong. Framework does not have a callback for this now. - if (Util.getDisplayRotation(mActivity) != mDisplayRotation) { - setDisplayOrientation(); - } - if (SystemClock.uptimeMillis() - mOnResumeTime < 5000) { - mHandler.sendEmptyMessageDelayed(CHECK_DISPLAY_ROTATION, 100); - } - break; - } - - case SHOW_TAP_TO_FOCUS_TOAST: { - showTapToFocusToast(); - break; - } - - case SWITCH_CAMERA: { - switchCamera(); - break; - } - - case SWITCH_CAMERA_START_ANIMATION: { - // TODO: Need to revisit - // ((CameraScreenNail) mActivity.mCameraScreenNail).animateSwitchCamera(); - break; - } - - case CAMERA_OPEN_DONE: { - onCameraOpened(); - break; - } - - case START_PREVIEW_DONE: { - onPreviewStarted(); - break; - } - - case OPEN_CAMERA_FAIL: { - mCameraStartUpThread = null; - mOpenCameraFail = true; - Util.showErrorAndFinish(mActivity, - R.string.cannot_connect_camera); - break; - } - - case CAMERA_DISABLED: { - mCameraStartUpThread = null; - mCameraDisabled = true; - Util.showErrorAndFinish(mActivity, - R.string.camera_disabled); - break; - } - } - } - } - - @Override - public void init(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(); - - 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(); - } - } - - @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 { - @Override - public void onShutter() { - mShutterCallbackTime = System.currentTimeMillis(); - mShutterLag = mShutterCallbackTime - mCaptureStartTime; - Log.v(TAG, "mShutterLag = " + mShutterLag + "ms"); - } - } - - 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; - } - if (mSceneMode == Util.SCENE_MODE_HDR) { - mUI.showSwitcher(); - //TODO: mActivity.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 - ((CameraScreenNail) mActivity.mCameraScreenNail).animateSlide(); - } */ - 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 mQueue; - private boolean mStop; - private NamedEntity mNamedEntity; - - public NamedImages() { - mQueue = new ArrayList(); - } - - 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.FOCUSING: - 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); - } */ - } - - @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 = (360 - mDisplayRotation) % 360; - // 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(mShutterCallback, mRawPictureCallback, - mPostViewPictureCallback, new JpegPictureCallback(loc), - mCameraState, mFocusManager.getFocusState()); - - if (!animateBefore) { - animateFlash(); - } - - mNamedImages.nameNewImage(mContentResolver, mCaptureStartTime); - - mFaceDetectionStarted = false; - setCameraState(SNAPSHOT_IN_PROGRESS); - 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(FilterShowActivity.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) { - if (mSceneMode == Util.SCENE_MODE_HDR) { - mUI.hideSwitcher(); - //TODO: mActivity.setSwipingEnabled(false); - } - 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 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 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. - List frameRates = mParameters.getSupportedPreviewFrameRates(); - if (frameRates != null) { - Integer max = Collections.max(frameRates); - mParameters.setPreviewFrameRate(max); - } - - 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 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 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 - 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 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, 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; - } - } -/* 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() {} - - @Override - public void onFullScreenChanged(boolean full) { - /* //TODO: - mUI.onFullScreenChanged(full); - if (ApiHelper.HAS_SURFACE_TEXTURE) { - if (mActivity.mCameraScreenNail != null) { - ((CameraScreenNail) mActivity.mCameraScreenNail).setFullScreen(full); - } - return; - } */ - } - -} diff --git a/src/com/android/camera/NewPhotoUI.java b/src/com/android/camera/NewPhotoUI.java deleted file mode 100644 index d1470b2b6..000000000 --- a/src/com/android/camera/NewPhotoUI.java +++ /dev/null @@ -1,879 +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.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.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, - NewPreviewGestures.CancelEventListener, - FocusUI, TextureView.SurfaceTextureListener, - LocationManager.Listener, - FaceDetectionListener, - NewPreviewGestures.SwipeListener { - - 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 View mCameraControls; - - // Small indicators which show the camera settings in the viewfinder. - private ImageView mExposureIndicator; - private ImageView mFlashIndicator; - private ImageView mSceneIndicator; - private ImageView mHdrIndicator; - // A view group that contains all the small indicators. - private View mOnScreenIndicators; - - private PieRenderer mPieRenderer; - private ZoomRenderer mZoomRenderer; - private Toast mNotSelectableToast; - - private int mZoomMax; - private List mZoomRatios; - - private int mPreviewWidth = 0; - private int mPreviewHeight = 0; - private float mSurfaceTextureUncroppedWidth; - private float mSurfaceTextureUncroppedHeight; - - 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 = mRootView.findViewById(R.id.camera_controls); - } - - 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 = mRootView.findViewById(R.id.on_screen_indicators); - mExposureIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_exposure_indicator); - mFlashIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_flash_indicator); - mSceneIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_scenemode_indicator); - mHdrIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_hdr_indicator); - } - - public void onCameraOpened(PreferenceGroup prefGroup, ComboPreferences prefs, - Camera.Parameters params, OnPreferenceChangedListener listener) { - if (mPieRenderer == null) { - mPieRenderer = new PieRenderer(mActivity); - mPieRenderer.setPieListener(this); - } - - if (mMenu == null) { - mMenu = new NewPhotoMenu(mActivity, this, mPieRenderer); - mMenu.setListener(listener); - } - mMenu.initialize(prefGroup); - - if (mZoomRenderer == null) { - mZoomRenderer = new ZoomRenderer(mActivity); - } - mRenderOverlay.addRenderer(mPieRenderer); - mRenderOverlay.addRenderer(mZoomRenderer); - - if (mGestures == null) { - // this will handle gesture disambiguation and dispatching - mGestures = new NewPreviewGestures(mActivity, this, mZoomRenderer, mPieRenderer, - this); - mGestures.setCancelEventListener(this); - } - mGestures.clearTouchReceivers(); - mGestures.setRenderOverlay(mRenderOverlay); - mGestures.addTouchReceiver(mMenuButton); - mGestures.addTouchReceiver(mBlocker); - // 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); - updateOnScreenIndicators(params, 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); - 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); - hideSwitcher(); - mShutterButton.setVisibility(View.GONE); - } - - public void showUI() { - mCameraControls.setVisibility(View.VISIBLE); - showSwitcher(); - mShutterButton.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, - ComboPreferences prefs) { - if (params == null) return; - updateSceneOnScreenIndicator(params.getSceneMode()); - updateExposureOnScreenIndicator(params, - CameraSettings.readExposure(prefs)); - updateFlashOnScreenIndicator(params.getFlashMode()); - updateHdrOnScreenIndicator(params.getSceneMode()); - } - - private void updateExposureOnScreenIndicator(Camera.Parameters params, int value) { - if (mExposureIndicator == null) { - return; - } - int id = 0; - float step = params.getExposureCompensationStep(); - value = (int) Math.round(value * step); - switch(value) { - case -3: - id = R.drawable.ic_indicator_ev_n3; - break; - case -2: - id = R.drawable.ic_indicator_ev_n2; - break; - case -1: - id = R.drawable.ic_indicator_ev_n1; - break; - case 0: - id = R.drawable.ic_indicator_ev_0; - break; - case 1: - id = R.drawable.ic_indicator_ev_p1; - break; - case 2: - id = R.drawable.ic_indicator_ev_p2; - break; - case 3: - id = R.drawable.ic_indicator_ev_p3; - break; - } - mExposureIndicator.setImageResource(id); - } - - private void updateFlashOnScreenIndicator(String value) { - if (mFlashIndicator == null) { - return; - } - if (value == null || Parameters.FLASH_MODE_OFF.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off); - } else { - if (Parameters.FLASH_MODE_AUTO.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_auto); - } else if (Parameters.FLASH_MODE_ON.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_on); - } else { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off); - } - } - } - - private void updateSceneOnScreenIndicator(String value) { - if (mSceneIndicator == null) { - return; - } - if ((value == null) || Parameters.SCENE_MODE_AUTO.equals(value) - || Parameters.SCENE_MODE_HDR.equals(value)) { - mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_off); - } else { - mSceneIndicator.setImageResource(R.drawable.ic_indicator_sce_on); - } - } - - private void updateHdrOnScreenIndicator(String value) { - if (mHdrIndicator == null) { - return; - } - if ((value != null) && Parameters.SCENE_MODE_HDR.equals(value)) { - mHdrIndicator.setImageResource(R.drawable.ic_indicator_hdr_on); - } else { - mHdrIndicator.setImageResource(R.drawable.ic_indicator_hdr_off); - } - } - - public void setCameraState(int state) { - } - - // Gestures and touch events - - public boolean dispatchTouchEvent(MotionEvent m) { - if (mPopup != null || mSwitcher.showsPopup()) { - boolean handled = mRootView.dispatchTouchEvent(m); - if (!handled && mPopup != null) { - dismissPopup(false); - } - return handled; - } else if (mGestures != null && mRenderOverlay != null) { - if (mGestures.dispatchTouch(m)) { - return true; - } else { - return mRootView.dispatchTouchEvent(m); - } - } - return true; - } - - @Override - public void onTouchEventCancelled(MotionEvent cancelEvent) { - mRootView.dispatchTouchEvent(cancelEvent); - } - - 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 onFullScreenChanged(boolean full) { - if (mFaceView != null) { - mFaceView.setBlockDraw(!full); - } - if (mPopup != null) { - dismissPopup(false, full); - } - if (mGestures != null) { - mGestures.setEnabled(full); - } - if (mRenderOverlay != null) { - // this can not happen in capture mode - mRenderOverlay.setVisibility(full ? View.VISIBLE : View.GONE); - } - if (mPieRenderer != null) { - mPieRenderer.setBlockFocus(!full); - } - setShowMenu(full); - if (mBlocker != null) { - mBlocker.setVisibility(full ? View.VISIBLE : View.GONE); - } - if (!full && mCountDownView != null) mCountDownView.cancelCountDown(); - } - - public boolean removeTopLevelPopup() { - // Remove the top level popup or dialog box and return true if there's any - if (mPopup != null) { - dismissPopup(true); - 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(boolean topPopupOnly) { - dismissPopup(topPopupOnly, true); - } - - private void dismissPopup(boolean topOnly, boolean fullScreen) { - if (fullScreen) { - showUI(); - mBlocker.setVisibility(View.VISIBLE); - } - setShowMenu(fullScreen); - if (mPopup != null) { - ((FrameLayout) mRootView).removeView(mPopup); - mPopup = null; - } - mMenu.popupDismissed(topOnly); - } - - 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(false); - ret = true; - } - return ret; - } - - protected void showPostCaptureAlert() { - mOnScreenIndicators.setVisibility(View.GONE); - mMenuButton.setVisibility(View.GONE); - Util.fadeIn(mReviewDoneButton); - mShutterButton.setVisibility(View.INVISIBLE); - Util.fadeIn(mReviewRetakeButton); - } - - protected void hidePostCaptureAlert() { - mOnScreenIndicators.setVisibility(View.VISIBLE); - mMenuButton.setVisibility(View.VISIBLE); - Util.fadeOut(mReviewDoneButton); - mShutterButton.setVisibility(View.VISIBLE); - Util.fadeOut(mReviewRetakeButton); - } - - 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) { - //TODO: mActivity.cancelActivityTouchHandling(); - //TODO: mActivity.setSwipingEnabled(false); - if (mFaceView != null) { - mFaceView.setBlockDraw(true); - } - } - - @Override - public void onPieClosed() { - //TODO: mActivity.setSwipingEnabled(true); - if (mFaceView != null) { - mFaceView.setBlockDraw(false); - } - } - - 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); - } - - @Override - public void onSwipe(int direction) { - if (direction == PreviewGestures.DIR_UP) { - openMenu(); - } - } -} diff --git a/src/com/android/camera/NewPreviewGestures.java b/src/com/android/camera/NewPreviewGestures.java deleted file mode 100644 index 2718e55ae..000000000 --- a/src/com/android/camera/NewPreviewGestures.java +++ /dev/null @@ -1,358 +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.MotionEvent; -import android.view.ScaleGestureDetector; -import android.view.View; -import android.view.ViewConfiguration; - -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; - -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 CancelEventListener mCancelEventListener; - private RenderOverlay mOverlay; - private PieRenderer mPie; - private ZoomRenderer mZoom; - private MotionEvent mDown; - private MotionEvent mCurrent; - private ScaleGestureDetector mScale; - private List mReceivers; - private int mMode; - private int mSlop; - private int mTapTimeout; - private boolean mEnabled; - private boolean mZoomOnly; - private int mOrientation; - private int[] mLocation; - private SwipeListener mSwipeListener; - - private Handler mHandler = new Handler() { - public void handleMessage(Message msg) { - if (msg.what == MSG_PIE) { - mMode = MODE_PIE; - openPie(); - cancelActivityTouchHandling(mDown); - } - } - }; - - public interface SingleTapListener { - public void onSingleTapUp(View v, int x, int y); - } - - public interface CancelEventListener { - public void onTouchEventCancelled(MotionEvent cancelEvent); - } - - interface SwipeListener { - public void onSwipe(int direction); - } - - public NewPreviewGestures(NewCameraActivity ctx, SingleTapListener tapListener, - ZoomRenderer zoom, PieRenderer pie, SwipeListener swipe) { - 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; - mLocation = new int[2]; - mSwipeListener = swipe; - } - - public void setCancelEventListener(CancelEventListener listener) { - mCancelEventListener = listener; - } - - public void setRenderOverlay(RenderOverlay overlay) { - mOverlay = overlay; - } - - public void setOrientation(int orientation) { - mOrientation = orientation; - } - - 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(); - } - mReceivers.add(v); - } - - public void clearTouchReceivers() { - if (mReceivers != null) { - mReceivers.clear(); - } - } - - public boolean dispatchTouch(MotionEvent m) { - if (!mEnabled) { - return false; - } - mCurrent = m; - if (MotionEvent.ACTION_DOWN == m.getActionMasked()) { - if (checkReceivers(m)) { - mMode = MODE_MODULE; - return false; - } else { - mMode = MODE_ALL; - mDown = MotionEvent.obtain(m); - if (mPie != null && mPie.showsItems()) { - mMode = MODE_PIE; - return sendToPie(m); - } - if (mPie != null && !mZoomOnly) { - mHandler.sendEmptyMessageDelayed(MSG_PIE, TIMEOUT_PIE); - } - if (mZoom != null) { - mScale.onTouchEvent(m); - } - // make sure this is ok - return false; - } - } 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 false; - } 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(); - cancelActivityTouchHandling(m); - // must have been tap - if (m.getEventTime() - mDown.getEventTime() < mTapTimeout) { - mTapListener.onSingleTapUp(null, - (int) mDown.getX() - mOverlay.getWindowPositionX(), - (int) mDown.getY() - mOverlay.getWindowPositionY()); - return true; - } else { - return false; - } - } 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 false; - } else { - cancelActivityTouchHandling(m); - mMode = MODE_NONE; - } - } - } - return false; - } - } - - private boolean checkReceivers(MotionEvent m) { - if (mReceivers != null) { - for (View receiver : mReceivers) { - if (isInside(m, receiver)) { - return true; - } - } - } - return false; - } - - // 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 boolean isInside(MotionEvent evt, View v) { - v.getLocationInWindow(mLocation); - 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) { - if (mCancelEventListener != null) { - mCancelEventListener.onTouchEventCancelled(makeCancelEvent(m)); - } - } - - private MotionEvent makeCancelEvent(MotionEvent m) { - MotionEvent c = MotionEvent.obtain(m); - c.setAction(MotionEvent.ACTION_CANCEL); - return c; - } - - private void openPie() { - mDown.offsetLocation(-mOverlay.getWindowPositionX(), - -mOverlay.getWindowPositionY()); - 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); - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - return mZoom.onScale(detector); - } - - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - if (mMode != MODE_ZOOM) { - mMode = MODE_ZOOM; - cancelActivityTouchHandling(mCurrent); - } - if (mCurrent.getActionMasked() != MotionEvent.ACTION_MOVE) { - return mZoom.onScaleBegin(detector); - } else { - return true; - } - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - if (mCurrent.getActionMasked() != MotionEvent.ACTION_MOVE) { - mZoom.onScaleEnd(detector); - } - } -} - diff --git a/src/com/android/camera/NewVideoMenu.java b/src/com/android/camera/NewVideoMenu.java deleted file mode 100644 index 1dec27a47..000000000 --- a/src/com/android/camera/NewVideoMenu.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera; - -import android.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 static final int POS_WB = 1; - private static final int POS_SET = 2; - private static final int POS_FLASH = 3; - private static final int POS_SWITCH = 4; - - 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 = makeItem(CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE, POS_FLASH, 5); - mRenderer.addItem(item); - item = makeItem(CameraSettings.KEY_WHITE_BALANCE, POS_WB, 5); - mRenderer.addItem(item); - // camera switcher - item = makeItem(R.drawable.ic_switch_video_facing_holo_light); - item.setPosition(POS_SWITCH, 5); - 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]); - mListener.onCameraPickerClicked(newCameraId); - } - } - }); - 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.setPosition(POS_SET, 5); - 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); - } - - @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 6ff8bbf18..000000000 --- a/src/com/android/camera/NewVideoModule.java +++ /dev/null @@ -1,2344 +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.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 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 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 VideoNamer mVideoNamer; - 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 MediaSaveService.OnMediaSavedListener mOnMediaSavedListener = - 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; - } - - 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); - - // 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) { - doReturnToCaller(true); - } - - @OnClickAttr - public void onReviewCancelClicked(View v) { - stopVideoRecording(); - doReturnToCaller(false); - } - - 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); - } - } - } - - 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 sizes = mParameters.getSupportedPreviewSizes(); - Size preferred = mParameters.getPreferredPreviewSizeForVideo(); - int product = preferred.width * preferred.height; - Iterator 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); - - mVideoNamer = new VideoNamer(); - 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 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(); - clearVideoNamer(); - } - - 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(7); - mCurrentVideoValues.put(Video.Media.TITLE, title); - mCurrentVideoValues.put(Video.Media.DISPLAY_NAME, filename); - mCurrentVideoValues.put(Video.Media.DATE_TAKEN, dateTaken); - 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()); - } - mVideoNamer.prepareUri(mContentResolver, mCurrentVideoValues); - mVideoFilename = tmpPath; - Log.v(TAG, "New video filename: " + mVideoFilename); - } - - private boolean addVideoToMediaStore() { - boolean fail = false; - if (mVideoFileDescriptor == null) { - mCurrentVideoValues.put(Video.Media.SIZE, - new File(mCurrentVideoFilename).length()); - long duration = SystemClock.uptimeMillis() - mRecordingStartTime; - if (duration > 0) { - if (mCaptureTimeLapse) { - duration = getTimeLapseVideoLength(duration); - } - mCurrentVideoValues.put(Video.Media.DURATION, duration); - } else { - Log.w(TAG, "Video duration <= 0 : " + duration); - } - try { - mCurrentVideoUri = mVideoNamer.getUri(); - //TODO: mActivity.addSecureAlbumItemIfNeeded(true, mCurrentVideoUri); - - // Rename the video file to the final name. This avoids other - // apps reading incomplete data. We need to do it after the - // above mVideoNamer.getUri() call, so we are certain that the - // previous insert to MediaProvider is completed. - String finalName = mCurrentVideoValues.getAsString( - Video.Media.DATA); - if (new File(mCurrentVideoFilename).renameTo(new File(finalName))) { - mCurrentVideoFilename = finalName; - } - - mContentResolver.update(mCurrentVideoUri, mCurrentVideoValues - , null, null); - mActivity.sendBroadcast(new Intent(Util.ACTION_NEW_VIDEO, - mCurrentVideoUri)); - } catch (Exception e) { - // We failed to insert into the database. This can happen if - // the SD card is unmounted. - Log.e(TAG, "failed to add video to media store", e); - mCurrentVideoUri = null; - mCurrentVideoFilename = null; - fail = true; - } finally { - Log.v(TAG, "Current video URI: " + mCurrentVideoUri); - } - } - mCurrentVideoValues = null; - return fail; - } - - private void deleteCurrentVideo() { - // Remove the video and the uri if the uri is not passed in by intent. - if (mCurrentVideoFilename != null) { - deleteVideoFile(mCurrentVideoFilename); - mCurrentVideoFilename = null; - if (mCurrentVideoUri != null) { - mContentResolver.delete(mCurrentVideoUri, null, null); - mCurrentVideoUri = null; - } - } - mActivity.updateStorageSpaceAndHint(); - } - - 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"); - // TODO: mActivity.setSwipingEnabled(false); - - mActivity.updateStorageSpaceAndHint(); - if (mActivity.getStorageSpace() <= Storage.LOW_STORAGE_THRESHOLD) { - Log.v(TAG, "Storage issue, ignore the start request"); - 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() { - 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"); - //TODO: 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 addVideoToMediaStore 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) { - if (addVideoToMediaStore()) fail = true; - } - } - // 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 supported) { - return supported == null ? false : supported.indexOf(value) >= 0; - } - - @SuppressWarnings("deprecation") - private void setCameraParameters() { - mParameters.setPreviewSize(mDesiredPreviewWidth, mDesiredPreviewHeight); - 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 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 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 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 && !addVideoToMediaStore()) { - 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(); - clearVideoNamer(); - } - } 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); - } - } - - 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 - 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); - } - - // 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(); - } - - @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) { - // 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 onFullScreenChanged(boolean full) { - mUI.onFullScreenChanged(full); - } - - 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, mOnMediaSavedListener, 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(); - } - - private void clearVideoNamer() { - if (mVideoNamer != null) { - mVideoNamer.finish(); - mVideoNamer = null; - } - } - - private static class VideoNamer extends Thread { - private boolean mRequestPending; - private ContentResolver mResolver; - private ContentValues mValues; - private boolean mStop; - private Uri mUri; - - // Runs in main thread - public VideoNamer() { - start(); - } - - // Runs in main thread - public synchronized void prepareUri( - ContentResolver resolver, ContentValues values) { - mRequestPending = true; - mResolver = resolver; - mValues = new ContentValues(values); - notifyAll(); - } - - // Runs in main thread - public synchronized Uri getUri() { - // wait until the request is done. - while (mRequestPending) { - try { - wait(); - } catch (InterruptedException ex) { - // ignore. - } - } - Uri uri = mUri; - mUri = null; - return uri; - } - - // Runs in namer thread - @Override - public synchronized void run() { - while (true) { - if (mStop) break; - if (!mRequestPending) { - try { - wait(); - } catch (InterruptedException ex) { - // ignore. - } - continue; - } - cleanOldUri(); - generateUri(); - mRequestPending = false; - notifyAll(); - } - cleanOldUri(); - } - - // Runs in main thread - public synchronized void finish() { - mStop = true; - notifyAll(); - } - - // Runs in namer thread - private void generateUri() { - Uri videoTable = Uri.parse("content://media/external/video/media"); - mUri = mResolver.insert(videoTable, mValues); - } - - // Runs in namer thread - private void cleanOldUri() { - if (mUri == null) return; - mResolver.delete(mUri, null, null); - mUri = null; - } - } - - @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 a14dae3d3..000000000 --- a/src/com/android/camera/NewVideoUI.java +++ /dev/null @@ -1,724 +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.CameraSwitcher; -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, - NewPreviewGestures.SwipeListener, 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 View mCameraControls; - private AbstractSettingPopup mPopup; - private ZoomRenderer mZoomRenderer; - private NewPreviewGestures mGestures; - private View mMenuButton; - private View mBlocker; - private View mOnScreenIndicators; - private ImageView mFlashIndicator; - private RotateLayout mRecordingTimeRect; - private final Object mLock = new Object(); - private SurfaceTexture mSurfaceTexture; - private VideoController mController; - private int mZoomMax; - private List mZoomRatios; - - 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); - 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 = mActivity.findViewById(R.id.camera_controls); - mOnScreenIndicators = mActivity.findViewById(R.id.on_screen_indicators); - mFlashIndicator = (ImageView) mActivity.findViewById(R.id.menu_flash_indicator); - 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); - hideSwitcher(); - mShutterButton.setVisibility(View.GONE); - } - - public void showUI() { - mCameraControls.setVisibility(View.VISIBLE); - showSwitcher(); - mShutterButton.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, this); - } - mGestures.setRenderOverlay(mRenderOverlay); - mGestures.clearTouchReceivers(); - mGestures.addTouchReceiver(mMenuButton); - mGestures.addTouchReceiver(mBlocker); - if (mController.isVideoCaptureIntent()) { - if (mReviewCancelButton != null) { - mGestures.addTouchReceiver(mReviewCancelButton); - } - if (mReviewDoneButton != null) { - mGestures.addTouchReceiver(mReviewDoneButton); - } - if (mReviewPlayButton != null) { - mGestures.addTouchReceiver(mReviewPlayButton); - } - } - } - - 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) { - if (param == null) return; - String value = param.getFlashMode(); - if (mFlashIndicator == null) return; - if (value == null || Parameters.FLASH_MODE_OFF.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off); - } else { - if (Parameters.FLASH_MODE_AUTO.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_auto); - } else if (Parameters.FLASH_MODE_ON.equals(value) - || Parameters.FLASH_MODE_TORCH.equals(value)) { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_on); - } else { - mFlashIndicator.setImageResource(R.drawable.ic_indicator_flash_off); - } - } - } - - 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) { - 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) { - // TODO: mActivity.cancelActivityTouchHandling(); - // mActivity.setSwipingEnabled(false); - } - - @Override - public void onPieClosed() { - // TODO: mActivity.setSwipingEnabled(true); - } - - 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 onFullScreenChanged(boolean full) { - if (mGestures != null) { - mGestures.setEnabled(full); - } - if (mPopup != null) { - dismissPopup(false, full); - } - 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); - } - } - - public void initializePopup(PreferenceGroup pref) { - mVideoMenu.initialize(pref); - } - - public void initializeZoom(Parameters param) { - if (param == null || !param.isZoomSupported()) return; - 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; - } - - // Gestures and touch events - - public boolean dispatchTouchEvent(MotionEvent m) { - if (mPopup != null || mSwitcher.showsPopup()) { - boolean handled = mRootView.dispatchTouchEvent(m); - if (!handled && mPopup != null) { - dismissPopup(false); - } - return handled; - } else if (mGestures != null && mRenderOverlay != null) { - if (mGestures.dispatchTouch(m)) { - return true; - } else { - return mRootView.dispatchTouchEvent(m); - } - } - return true; - } - public void setRecordingTime(String text) { - mRecordingTimeView.setText(text); - } - - public void setRecordingTimeTextColor(int color) { - mRecordingTimeView.setTextColor(color); - } - - public boolean isVisible() { - return mTextureView.getVisibility() == View.VISIBLE; - } - - 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() { - } - } - - @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; - } - - // 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/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java deleted file mode 100644 index d1dad3ffb..000000000 --- a/src/com/android/camera/data/CameraDataAdapter.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.data; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Matrix; -import android.graphics.drawable.Drawable; -import android.os.AsyncTask; -import android.provider.MediaStore; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.util.Log; -import android.view.View; -import android.widget.ImageView; - -import com.android.camera.Storage; -import com.android.camera.ui.FilmStripView; -import com.android.camera.ui.FilmStripView.ImageData; - -import java.util.ArrayList; -import java.util.List; - -/** - * A FilmStripDataProvider that provide data in the camera folder. - * - * The given view for camera preview won't be added until the preview info - * has been set by setCameraPreviewInfo(int, int). - */ -public class CameraDataAdapter implements FilmStripView.DataAdapter { - private static final String TAG = CameraDataAdapter.class.getSimpleName(); - - private static final int DEFAULT_DECODE_SIZE = 3000; - private static final String[] CAMERA_PATH = { Storage.DIRECTORY + "%" }; - - private List mImages; - - private Listener mListener; - private View mCameraPreviewView; - private Drawable mPlaceHolder; - - private int mSuggestedWidth = DEFAULT_DECODE_SIZE; - private int mSuggestedHeight = DEFAULT_DECODE_SIZE; - - public CameraDataAdapter(Drawable placeHolder) { - mPlaceHolder = placeHolder; - } - - public void setCameraPreviewInfo(View cameraPreview, int width, int height) { - mCameraPreviewView = cameraPreview; - addOrReplaceCameraData(buildCameraImageData(width, height)); - } - - public void requestLoad(ContentResolver resolver) { - QueryTask qtask = new QueryTask(); - qtask.execute(resolver); - } - - @Override - public int getTotalNumber() { - return mImages.size(); - } - - @Override - public ImageData getImageData(int id) { - if (id >= mImages.size()) return null; - return mImages.get(id); - } - - @Override - public void suggestSize(int w, int h) { - if (w <= 0 || h <= 0) { - mSuggestedWidth = mSuggestedHeight = DEFAULT_DECODE_SIZE; - } else { - mSuggestedWidth = (w < DEFAULT_DECODE_SIZE ? w : DEFAULT_DECODE_SIZE); - mSuggestedHeight = (h < DEFAULT_DECODE_SIZE ? h : DEFAULT_DECODE_SIZE); - } - } - - @Override - public View getView(Context c, int dataID) { - if (dataID >= mImages.size() || dataID < 0) { - return null; - } - - return mImages.get(dataID).getView( - c, mSuggestedWidth, mSuggestedHeight, mPlaceHolder); - } - - @Override - public void setListener(Listener listener) { - mListener = listener; - if (mImages != null) mListener.onDataLoaded(); - } - - private LocalData buildCameraImageData(int width, int height) { - LocalData d = new CameraPreviewData(width, height); - return d; - } - - private void addOrReplaceCameraData(LocalData data) { - if (mImages == null) mImages = new ArrayList(); - if (mImages.size() == 0) { - // No data at all. - mImages.add(0, data); - if (mListener != null) mListener.onDataLoaded(); - return; - } - - LocalData first = mImages.get(0); - if (first.getType() == ImageData.TYPE_CAMERA_PREVIEW) { - // Replace the old camera data. - mImages.set(0, data); - if (mListener != null) { - mListener.onDataUpdated(new StatusReporter() { - @Override - public boolean isDataRemoved(int id) { - return false; - } - - @Override - public boolean isDataUpdated(int id) { - if (id == 0) return true; - return false; - } - }); - } - } else { - // Add a new camera data. - mImages.add(0, data); - if (mListener != null) { - mListener.onDataLoaded(); - } - } - } - - private class QueryTask extends AsyncTask> { - @Override - protected List doInBackground(ContentResolver... resolver) { - List l = null; - Cursor c = resolver[0].query( - Images.Media.EXTERNAL_CONTENT_URI, - LocalPhotoData.QUERY_PROJECTION, - MediaStore.Images.Media.DATA + " like ? ", CAMERA_PATH, - LocalPhotoData.QUERY_ORDER); - if (c == null) return null; - - // build up the list. - l = new ArrayList(); - c.moveToFirst(); - while (!c.isLast()) { - LocalData data = LocalPhotoData.buildFromCursor(c); - if (data != null) { - l.add(data); - } else { - Log.e(TAG, "Error decoding file:" - + c.getString(LocalPhotoData.COL_DATA)); - } - c.moveToNext(); - } - c.close(); - return l; - } - - @Override - protected void onPostExecute(List l) { - boolean changed = (l != mImages); - LocalData cameraData = null; - if (mImages != null && mImages.size() > 0) { - cameraData = mImages.get(0); - if (cameraData.getType() != ImageData.TYPE_CAMERA_PREVIEW) cameraData = null; - } - - mImages = l; - if (cameraData != null) { - l.add(0, cameraData); - if (mListener != null) { - mListener.onDataUpdated(new StatusReporter() { - @Override - public boolean isDataRemoved(int id) { - return false; - } - - @Override - public boolean isDataUpdated(int id) { - if (id == 0) return false; - return true; - } - }); - } - } else { - // both might be null. - if (changed) mListener.onDataLoaded(); - } - } - } - - private abstract static class LocalData implements FilmStripView.ImageData { - public int id; - public String title; - public String mimeType; - public String path; - // width and height should be adjusted according to orientation. - public int width; - public int height; - public int supportedAction; - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public boolean isActionSupported(int action) { - return false; - } - - @Override - public abstract int getType(); - - abstract View getView(Context c, int width, int height, Drawable placeHolder); - } - - private class CameraPreviewData extends LocalData { - CameraPreviewData(int w, int h) { - width = w; - height = h; - } - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public int getType() { - return ImageData.TYPE_CAMERA_PREVIEW; - } - - @Override - View getView(Context c, int width, int height, Drawable placeHolder) { - return mCameraPreviewView; - } - } - - private static class LocalPhotoData extends LocalData { - static final String QUERY_ORDER = ImageColumns.DATE_TAKEN + " DESC, " - + ImageColumns._ID + " DESC"; - static final String[] QUERY_PROJECTION = { - ImageColumns._ID, // 0, int - ImageColumns.TITLE, // 1, string - ImageColumns.MIME_TYPE, // 2, tring - ImageColumns.DATE_TAKEN, // 3, int - ImageColumns.DATE_MODIFIED, // 4, int - ImageColumns.DATA, // 5, string - ImageColumns.ORIENTATION, // 6, int, 0, 90, 180, 270 - ImageColumns.WIDTH, // 7, int - ImageColumns.HEIGHT, // 8, int - ImageColumns.SIZE // 9, int - }; - - private static final int COL_ID = 0; - private static final int COL_TITLE = 1; - private static final int COL_MIME_TYPE = 2; - private static final int COL_DATE_TAKEN = 3; - private static final int COL_DATE_MODIFIED = 4; - private static final int COL_DATA = 5; - private static final int COL_ORIENTATION = 6; - private static final int COL_WIDTH = 7; - private static final int COL_HEIGHT = 8; - private static final int COL_SIZE = 9; - - - // 32K buffer. - private static final byte[] DECODE_TEMP_STORAGE = new byte[32 * 1024]; - - // from MediaStore, can only be 0, 90, 180, 270; - public int orientation; - - static LocalPhotoData buildFromCursor(Cursor c) { - LocalPhotoData d = new LocalPhotoData(); - d.id = c.getInt(COL_ID); - d.title = c.getString(COL_TITLE); - d.mimeType = c.getString(COL_MIME_TYPE); - d.path = c.getString(COL_DATA); - d.orientation = c.getInt(COL_ORIENTATION); - d.width = c.getInt(COL_WIDTH); - d.height = c.getInt(COL_HEIGHT); - if (d.width <= 0 || d.height <= 0) { - Log.v(TAG, "warning! zero dimension for " - + d.path + ":" + d.width + "x" + d.height); - Dimension dim = decodeDimension(d.path); - if (dim != null) { - d.width = dim.width; - d.height = dim.height; - } else { - Log.v(TAG, "warning! dimension decode failed for " + d.path); - Bitmap b = BitmapFactory.decodeFile(d.path); - if (b == null) return null; - d.width = b.getWidth(); - d.height = b.getHeight(); - } - } - if (d.orientation == 90 || d.orientation == 270) { - int b = d.width; - d.width = d.height; - d.height = b; - } - return d; - } - - @Override - View getView(Context c, - int decodeWidth, int decodeHeight, Drawable placeHolder) { - ImageView v = new ImageView(c); - v.setImageDrawable(placeHolder); - - v.setScaleType(ImageView.ScaleType.FIT_XY); - LoadBitmapTask task = new LoadBitmapTask(v, decodeWidth, decodeHeight); - task.execute(); - return v; - } - - - @Override - public String toString() { - return "LocalPhotoData:" + ",data=" + path + ",mimeType=" + mimeType - + "," + width + "x" + height + ",orientation=" + orientation; - } - - @Override - public int getType() { - return TYPE_PHOTO; - } - - private static Dimension decodeDimension(String path) { - BitmapFactory.Options opts = new BitmapFactory.Options(); - opts.inJustDecodeBounds = true; - Bitmap b = BitmapFactory.decodeFile(path, opts); - if (b == null) return null; - Dimension d = new Dimension(); - d.width = opts.outWidth; - d.height = opts.outHeight; - return d; - } - - private static class Dimension { - public int width; - public int height; - } - - private class LoadBitmapTask extends AsyncTask { - private ImageView mView; - private int mDecodeWidth; - private int mDecodeHeight; - - public LoadBitmapTask(ImageView v, int decodeWidth, int decodeHeight) { - mView = v; - mDecodeWidth = decodeWidth; - mDecodeHeight = decodeHeight; - } - - @Override - protected Bitmap doInBackground(Void... v) { - BitmapFactory.Options opts = null; - Bitmap b; - int sample = 1; - while (mDecodeWidth * sample < width - || mDecodeHeight * sample < height) { - sample *= 2; - } - opts = new BitmapFactory.Options(); - opts.inSampleSize = sample; - opts.inTempStorage = DECODE_TEMP_STORAGE; - if (isCancelled()) return null; - b = BitmapFactory.decodeFile(path, opts); - if (orientation != 0) { - if (isCancelled()) return null; - Matrix m = new Matrix(); - m.setRotate((float) orientation); - b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, false); - } - return b; - } - - @Override - protected void onPostExecute(Bitmap bitmap) { - if (bitmap == null) { - Log.e(TAG, "Cannot decode bitmap file:" + path); - return; - } - mView.setScaleType(ImageView.ScaleType.FIT_XY); - mView.setImageBitmap(bitmap); - } - } - } -} diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java index 9840b1544..f4dd823d1 100644 --- a/src/com/android/camera/ui/FaceView.java +++ b/src/com/android/camera/ui/FaceView.java @@ -33,15 +33,13 @@ import android.view.View; import com.android.camera.CameraActivity; import com.android.camera.CameraScreenNail; -import com.android.camera.NewPhotoUI; import com.android.camera.Util; import com.android.gallery3d.R; import com.android.gallery3d.common.ApiHelper; @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) public class FaceView extends View - implements FocusIndicator, Rotatable, - NewPhotoUI.SurfaceTextureSizeChangedListener { + implements FocusIndicator, Rotatable { private static final String TAG = "CAM FaceView"; private final boolean LOGV = false; // The value for android.hardware.Camera.setDisplayOrientation. @@ -97,11 +95,6 @@ public class FaceView extends View mPaint.setStrokeWidth(res.getDimension(R.dimen.face_circle_stroke)); } - public void onSurfaceTextureSizeChanged(int uncroppedWidth, int uncroppedHeight) { - mUncroppedWidth = uncroppedWidth; - mUncroppedHeight = uncroppedHeight; - } - public void setFaces(Face[] faces) { if (LOGV) Log.v(TAG, "Num of faces=" + faces.length); if (mPause) return; diff --git a/src/com/android/camera/ui/FilmStripGestureRecognizer.java b/src/com/android/camera/ui/FilmStripGestureRecognizer.java deleted file mode 100644 index f0e2534d3..000000000 --- a/src/com/android/camera/ui/FilmStripGestureRecognizer.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.content.Context; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; - -// This class aggregates three gesture detectors: GestureDetector, -// ScaleGestureDetector. -public class FilmStripGestureRecognizer { - @SuppressWarnings("unused") - private static final String TAG = "FilmStripGestureRecognizer"; - - public interface Listener { - boolean onSingleTapUp(float x, float y); - boolean onDoubleTap(float x, float y); - boolean onScroll(float x, float y, float dx, float dy); - boolean onFling(float velocityX, float velocityY); - boolean onScaleBegin(float focusX, float focusY); - boolean onScale(float focusX, float focusY, float scale); - boolean onDown(float x, float y); - void onScaleEnd(); - } - - private final GestureDetector mGestureDetector; - private final ScaleGestureDetector mScaleDetector; - private final Listener mListener; - - public FilmStripGestureRecognizer(Context context, Listener listener) { - mListener = listener; - mGestureDetector = new GestureDetector(context, new MyGestureListener(), - null, true /* ignoreMultitouch */); - mScaleDetector = new ScaleGestureDetector( - context, new MyScaleListener()); - } - - public boolean onTouchEvent(MotionEvent event) { - return mGestureDetector.onTouchEvent(event) || mScaleDetector.onTouchEvent(event); - } - - private class MyGestureListener - extends GestureDetector.SimpleOnGestureListener { - @Override - public boolean onSingleTapUp(MotionEvent e) { - return mListener.onSingleTapUp(e.getX(), e.getY()); - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - return mListener.onDoubleTap(e.getX(), e.getY()); - } - - @Override - public boolean onScroll( - MotionEvent e1, MotionEvent e2, float dx, float dy) { - return mListener.onScroll(e2.getX(), e2.getY(), dx, dy); - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - return mListener.onFling(velocityX, velocityY); - } - - @Override - public boolean onDown(MotionEvent e) { - mListener.onDown(e.getX(), e.getY()); - return super.onDown(e); - } - } - - private class MyScaleListener - extends ScaleGestureDetector.SimpleOnScaleGestureListener { - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - return mListener.onScaleBegin( - detector.getFocusX(), detector.getFocusY()); - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - return mListener.onScale(detector.getFocusX(), - detector.getFocusY(), detector.getScaleFactor()); - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - mListener.onScaleEnd(); - } - } -} diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java deleted file mode 100644 index 0a19effb2..000000000 --- a/src/com/android/camera/ui/FilmStripView.java +++ /dev/null @@ -1,830 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.animation.Animator; -import android.animation.ValueAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.DecelerateInterpolator; -import android.widget.Scroller; - -public class FilmStripView extends ViewGroup { - private static final String TAG = FilmStripView.class.getSimpleName(); - private static final int BUFFER_SIZE = 5; - // Horizontal padding of children. - private static final int H_PADDING = 50; - // Duration to go back to the first. - private static final int DURATION_BACK_ANIM = 500; - private static final int DURATION_SCROLL_TO_FILMSTRIP = 350; - private static final int DURATION_GEOMETRY_ADJUST = 200; - private static final float FILM_STRIP_SCALE = 0.6f; - private static final float MAX_SCALE = 1f; - - private Context mContext; - private FilmStripGestureRecognizer mGestureRecognizer; - private DataAdapter mDataAdapter; - private final Rect mDrawArea = new Rect(); - - private int mCurrentInfo; - private float mScale; - private GeometryAnimator mGeometryAnimator; - private int mCenterPosition = -1; - private ViewInfo[] mViewInfo = new ViewInfo[BUFFER_SIZE]; - - // This is used to resolve the misalignment problem when the device - // orientation is changed. If the current item is in fullscreen, it might - // be shifted because mCenterPosition is not adjusted with the orientation. - // Set this to true when onSizeChanged is called to make sure we adjust - // mCenterPosition accordingly. - private boolean mAnchorPending; - - public interface ImageData { - public static final int TYPE_NONE = 0; - public static final int TYPE_CAMERA_PREVIEW = 1; - public static final int TYPE_PHOTO = 2; - public static final int TYPE_VIDEO = 3; - public static final int TYPE_PHOTOSPHERE = 4; - - // The actions are defined bit-wise so we can use bit operations like - // | and &. - public static final int ACTION_NONE = 0; - public static final int ACTION_PROMOTE = 1; - public static final int ACTION_DEMOTE = 2; - - // SIZE_FULL means disgard the width or height when deciding the view size - // of this ImageData, just use full screen size. - public static final int SIZE_FULL = -2; - - // The values returned by getWidth() and getHeight() will be used for layout. - public int getWidth(); - public int getHeight(); - public int getType(); - public boolean isActionSupported(int action); - } - - public interface DataAdapter { - public interface StatusReporter { - public boolean isDataRemoved(int id); - public boolean isDataUpdated(int id); - } - - public interface Listener { - // Called when the whole data loading is done. No any assumption - // on previous data. - public void onDataLoaded(); - // Only some of the data is changed. The listener should check - // if any thing needs to be updated. - public void onDataUpdated(StatusReporter reporter); - public void onDataInserted(int dataID); - public void onDataRemoved(int dataID); - } - - public int getTotalNumber(); - public View getView(Context context, int id); - public ImageData getImageData(int id); - public void suggestSize(int w, int h); - - public void setListener(Listener listener); - } - - // A helper class to tract and calculate the view coordination. - private static class ViewInfo { - private int mDataID; - // the position of the left of the view in the whole filmstrip. - private int mLeftPosition; - private View mView; - private float mOffsetY; - - public ViewInfo(int id, View v) { - v.setPivotX(0f); - v.setPivotY(0f); - mDataID = id; - mView = v; - mLeftPosition = -1; - mOffsetY = 0; - } - - public int getID() { - return mDataID; - } - - public void setLeftPosition(int pos) { - mLeftPosition = pos; - } - - public int getLeftPosition() { - return mLeftPosition; - } - - public float getOffsetY() { - return mOffsetY; - } - - public void setOffsetY(float offset) { - mOffsetY = offset; - } - - public int getCenterX() { - return mLeftPosition + mView.getWidth() / 2; - } - - public View getView() { - return mView; - } - - private void layoutAt(int left, int top) { - mView.layout(left, top, left + mView.getMeasuredWidth(), - top + mView.getMeasuredHeight()); - } - - public void layoutIn(Rect drawArea, int refCenter, float scale) { - // drawArea is where to layout in. - // refCenter is the absolute horizontal position of the center of drawArea. - int left = (int) (drawArea.centerX() + (mLeftPosition - refCenter) * scale); - int top = (int) (drawArea.centerY() - (mView.getMeasuredHeight() / 2) * scale - + mOffsetY); - layoutAt(left, top); - mView.setScaleX(scale); - mView.setScaleY(scale); - } - } - - public FilmStripView(Context context) { - super(context); - init(context); - } - - public FilmStripView(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - public FilmStripView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(context); - } - - private void init(Context context) { - mCurrentInfo = (BUFFER_SIZE - 1) / 2; - // This is for positioning camera controller at the same place in - // different orientations. - setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - - setWillNotDraw(false); - mContext = context; - mScale = 1.0f; - mGeometryAnimator = new GeometryAnimator(context); - mGestureRecognizer = - new FilmStripGestureRecognizer(context, new MyGestureReceiver()); - } - - public float getScale() { - return mScale; - } - - public boolean isAnchoredTo(int id) { - if (mViewInfo[mCurrentInfo].getID() == id - && mViewInfo[mCurrentInfo].getCenterX() == mCenterPosition) { - return true; - } - return false; - } - - public int getCurrentType() { - if (mDataAdapter == null) return ImageData.TYPE_NONE; - ViewInfo curr = mViewInfo[mCurrentInfo]; - if (curr == null) return ImageData.TYPE_NONE; - return mDataAdapter.getImageData(curr.getID()).getType(); - } - - @Override - public void onDraw(Canvas c) { - if (mGeometryAnimator.hasNewGeometry()) { - layoutChildren(); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - int boundWidth = MeasureSpec.getSize(widthMeasureSpec); - int boundHeight = MeasureSpec.getSize(heightMeasureSpec); - if (mDataAdapter != null) { - mDataAdapter.suggestSize(boundWidth / 2, boundHeight / 2); - } - - int wMode = View.MeasureSpec.EXACTLY; - int hMode = View.MeasureSpec.EXACTLY; - - for (int i = 0; i < mViewInfo.length; i++) { - ViewInfo info = mViewInfo[i]; - if (mViewInfo[i] == null) continue; - - int imageWidth = mDataAdapter.getImageData(info.getID()).getWidth(); - int imageHeight = mDataAdapter.getImageData(info.getID()).getHeight(); - if (imageWidth == ImageData.SIZE_FULL) imageWidth = boundWidth; - if (imageHeight == ImageData.SIZE_FULL) imageHeight = boundHeight; - - int scaledWidth = boundWidth; - int scaledHeight = boundHeight; - - if (imageWidth * scaledHeight > scaledWidth * imageHeight) { - scaledHeight = imageHeight * scaledWidth / imageWidth; - } else { - scaledWidth = imageWidth * scaledHeight / imageHeight; - } - scaledWidth += H_PADDING * 2; - mViewInfo[i].getView().measure( - View.MeasureSpec.makeMeasureSpec(scaledWidth, wMode) - , View.MeasureSpec.makeMeasureSpec(scaledHeight, hMode)); - } - setMeasuredDimension(boundWidth, boundHeight); - } - - private int findTheNearestView(int pointX) { - - int nearest = 0; - // find the first non-null ViewInfo. - for (; nearest < BUFFER_SIZE - && (mViewInfo[nearest] == null || mViewInfo[nearest].getLeftPosition() == -1); - nearest++); - // no existing available ViewInfo - if (nearest == BUFFER_SIZE) return -1; - int min = Math.abs(pointX - mViewInfo[nearest].getCenterX()); - - for (int infoID = nearest + 1; - infoID < BUFFER_SIZE && mViewInfo[infoID] != null; infoID++) { - // not measured yet. - if (mViewInfo[infoID].getLeftPosition() == -1) continue; - - int c = mViewInfo[infoID].getCenterX(); - int dist = Math.abs(pointX - c); - if (dist < min) { - min = dist; - nearest = infoID; - } - } - return nearest; - } - - private ViewInfo buildInfoFromData(int dataID) { - View v = mDataAdapter.getView(mContext, dataID); - if (v == null) return null; - v.setPadding(H_PADDING, 0, H_PADDING, 0); - ViewInfo info = new ViewInfo(dataID, v); - addView(info.getView()); - return info; - } - - // We try to keep the one closest to the center of the screen at position mCurrentInfo. - private void stepIfNeeded() { - int nearest = findTheNearestView(mCenterPosition); - // no change made. - if (nearest == -1 || nearest == mCurrentInfo) return; - - int adjust = nearest - mCurrentInfo; - if (adjust > 0) { - for (int k = 0; k < adjust; k++) { - if (mViewInfo[k] != null) { - removeView(mViewInfo[k].getView()); - } - } - for (int k = 0; k + adjust < BUFFER_SIZE; k++) { - mViewInfo[k] = mViewInfo[k + adjust]; - } - for (int k = BUFFER_SIZE - adjust; k < BUFFER_SIZE; k++) { - mViewInfo[k] = null; - if (mViewInfo[k - 1] != null) - mViewInfo[k] = buildInfoFromData(mViewInfo[k - 1].getID() + 1); - } - } else { - for (int k = BUFFER_SIZE - 1; k >= BUFFER_SIZE + adjust; k--) { - if (mViewInfo[k] != null) { - removeView(mViewInfo[k].getView()); - } - } - for (int k = BUFFER_SIZE - 1; k + adjust >= 0; k--) { - mViewInfo[k] = mViewInfo[k + adjust]; - } - for (int k = -1 - adjust; k >= 0; k--) { - mViewInfo[k] = null; - if (mViewInfo[k + 1] != null) - mViewInfo[k] = buildInfoFromData(mViewInfo[k + 1].getID() - 1); - } - } - } - - // Don't go out of bound. - private void adjustCenterPosition() { - ViewInfo curr = mViewInfo[mCurrentInfo]; - if (curr == null) return; - - if (curr.getID() == 0 && mCenterPosition < curr.getCenterX()) { - mCenterPosition = curr.getCenterX(); - mGeometryAnimator.stopScroll(); - } - if (curr.getID() == mDataAdapter.getTotalNumber() - 1 - && mCenterPosition > curr.getCenterX()) { - mCenterPosition = curr.getCenterX(); - mGeometryAnimator.stopScroll(); - } - } - - private void layoutChildren() { - if (mAnchorPending) { - mCenterPosition = mViewInfo[mCurrentInfo].getCenterX(); - mAnchorPending = false; - } - - if (mGeometryAnimator.hasNewGeometry()) { - mCenterPosition = mGeometryAnimator.getNewPosition(); - mScale = mGeometryAnimator.getNewScale(); - } - - adjustCenterPosition(); - - mViewInfo[mCurrentInfo].layoutIn(mDrawArea, mCenterPosition, mScale); - - // images on the left - for (int infoID = mCurrentInfo - 1; infoID >= 0; infoID--) { - ViewInfo curr = mViewInfo[infoID]; - if (curr != null) { - ViewInfo next = mViewInfo[infoID + 1]; - curr.setLeftPosition( - next.getLeftPosition() - curr.getView().getMeasuredWidth()); - curr.layoutIn(mDrawArea, mCenterPosition, mScale); - } - } - - // images on the right - for (int infoID = mCurrentInfo + 1; infoID < BUFFER_SIZE; infoID++) { - ViewInfo curr = mViewInfo[infoID]; - if (curr != null) { - ViewInfo prev = mViewInfo[infoID - 1]; - curr.setLeftPosition( - prev.getLeftPosition() + prev.getView().getMeasuredWidth()); - curr.layoutIn(mDrawArea, mCenterPosition, mScale); - } - } - - stepIfNeeded(); - invalidate(); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - if (mViewInfo[mCurrentInfo] == null) return; - - mDrawArea.left = l; - mDrawArea.top = t; - mDrawArea.right = r; - mDrawArea.bottom = b; - - layoutChildren(); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - if (w == oldw && h == oldh) return; - if (mViewInfo[mCurrentInfo] != null && mScale == 1f - && isAnchoredTo(mViewInfo[mCurrentInfo].getID())) { - mAnchorPending = true; - } - } - - public void setDataAdapter(DataAdapter adapter) { - mDataAdapter = adapter; - mDataAdapter.suggestSize(getMeasuredWidth(), getMeasuredHeight()); - mDataAdapter.setListener(new DataAdapter.Listener() { - @Override - public void onDataLoaded() { - reload(); - } - - @Override - public void onDataUpdated(DataAdapter.StatusReporter reporter) { - update(reporter); - } - - @Override - public void onDataInserted(int dataID) { - } - - @Override - public void onDataRemoved(int dataID) { - } - }); - } - - public boolean isInCameraFullscreen() { - return (isAnchoredTo(0) && mScale == 1f - && getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (isInCameraFullscreen()) return false; - return true; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - mGestureRecognizer.onTouchEvent(ev); - return true; - } - - private void updateViewInfo(int infoID) { - ViewInfo info = mViewInfo[infoID]; - removeView(info.getView()); - mViewInfo[infoID] = buildInfoFromData(info.getID()); - } - - // Some of the data is changed. - private void update(DataAdapter.StatusReporter reporter) { - // No data yet. - if (mViewInfo[mCurrentInfo] == null) { - reload(); - return; - } - - // Check the current one. - ViewInfo curr = mViewInfo[mCurrentInfo]; - int dataID = curr.getID(); - if (reporter.isDataRemoved(dataID)) { - mCenterPosition = -1; - reload(); - return; - } - if (reporter.isDataUpdated(dataID)) { - updateViewInfo(mCurrentInfo); - } - - // Check left - for (int i = mCurrentInfo - 1; i >= 0; i--) { - curr = mViewInfo[i]; - if (curr != null) { - dataID = curr.getID(); - if (reporter.isDataRemoved(dataID) || reporter.isDataUpdated(dataID)) { - updateViewInfo(i); - } - } else { - ViewInfo next = mViewInfo[i + 1]; - if (next != null) mViewInfo[i] = buildInfoFromData(next.getID() - 1); - } - } - - // Check right - for (int i = mCurrentInfo + 1; i < BUFFER_SIZE; i++) { - curr = mViewInfo[i]; - if (curr != null) { - dataID = curr.getID(); - if (reporter.isDataRemoved(dataID) || reporter.isDataUpdated(dataID)) { - updateViewInfo(i); - } - } else { - ViewInfo prev = mViewInfo[i - 1]; - if (prev != null) mViewInfo[i] = buildInfoFromData(prev.getID() + 1); - } - } - } - - // The whole data might be totally different. Flush all and load from the start. - private void reload() { - removeAllViews(); - int dataNumber = mDataAdapter.getTotalNumber(); - if (dataNumber == 0) return; - - int currentData = 0; - int currentLeft = 0; - mViewInfo[mCurrentInfo] = buildInfoFromData(currentData); - mViewInfo[mCurrentInfo].setLeftPosition(currentLeft); - if (getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW - && currentLeft == 0) { - // we are in camera mode by default. - mGeometryAnimator.lockPosition(currentLeft); - } - for (int i = 1; mCurrentInfo + i < BUFFER_SIZE || mCurrentInfo - i >= 0; i++) { - int infoID = mCurrentInfo + i; - if (infoID < BUFFER_SIZE && mViewInfo[infoID - 1] != null) { - mViewInfo[infoID] = buildInfoFromData(mViewInfo[infoID - 1].getID() + 1); - } - infoID = mCurrentInfo - i; - if (infoID >= 0 && mViewInfo[infoID + 1] != null) { - mViewInfo[infoID] = buildInfoFromData(mViewInfo[infoID + 1].getID() - 1); - } - } - layoutChildren(); - } - - // GeometryAnimator controls all the geometry animations. It passively - // tells the geometry information on demand. - private class GeometryAnimator implements - ValueAnimator.AnimatorUpdateListener, - Animator.AnimatorListener { - - private ValueAnimator mScaleAnimator; - private boolean mHasNewScale; - private float mNewScale; - - private Scroller mScroller; - private boolean mHasNewPosition; - private DecelerateInterpolator mDecelerateInterpolator; - - private boolean mCanStopScroll; - private boolean mCanStopScale; - - private boolean mIsPositionLocked; - private int mLockedPosition; - - private Runnable mPostAction; - - GeometryAnimator(Context context) { - mScroller = new Scroller(context); - mHasNewPosition = false; - mScaleAnimator = new ValueAnimator(); - mScaleAnimator.addUpdateListener(GeometryAnimator.this); - mScaleAnimator.addListener(GeometryAnimator.this); - mDecelerateInterpolator = new DecelerateInterpolator(); - mCanStopScroll = true; - mCanStopScale = true; - mHasNewScale = false; - } - - boolean hasNewGeometry() { - mHasNewPosition = mScroller.computeScrollOffset(); - if (!mHasNewPosition) { - mCanStopScroll = true; - } - // If the position is locked, then we always return true to force - // the position value to use the locked value. - return (mHasNewPosition || mHasNewScale || mIsPositionLocked); - } - - // Always call hasNewGeometry() before getting the new scale value. - float getNewScale() { - if (!mHasNewScale) return mScale; - mHasNewScale = false; - return mNewScale; - } - - // Always call hasNewGeometry() before getting the new position value. - int getNewPosition() { - if (mIsPositionLocked) return mLockedPosition; - if (!mHasNewPosition) return mCenterPosition; - return mScroller.getCurrX(); - } - - void lockPosition(int pos) { - mIsPositionLocked = true; - mLockedPosition = pos; - } - - void unlockPosition() { - if (mIsPositionLocked) { - // only when the position is previously locked we set the current - // position to make it consistent. - mCenterPosition = mLockedPosition; - mIsPositionLocked = false; - } - } - - void fling(int velocityX, int minX, int maxX) { - if (!stopScroll() || mIsPositionLocked) return; - mScroller.fling(mCenterPosition, 0, velocityX, 0, minX, maxX, 0, 0); - } - - boolean stopScroll() { - if (!mCanStopScroll) return false; - mScroller.forceFinished(true); - mHasNewPosition = false; - return true; - } - - boolean stopScale() { - if (!mCanStopScale) return false; - mScaleAnimator.cancel(); - mHasNewScale = false; - return true; - } - - void stop() { - stopScroll(); - stopScale(); - } - - void scrollTo(int position, int duration, boolean interruptible) { - if (!stopScroll() || mIsPositionLocked) return; - mCanStopScroll = interruptible; - stopScroll(); - mScroller.startScroll(mCenterPosition, 0, position - mCenterPosition, - 0, duration); - } - - void scrollTo(int position, int duration) { - scrollTo(position, duration, true); - } - - void scaleTo(float scale, int duration, boolean interruptible) { - if (!stopScale()) return; - mCanStopScale = interruptible; - mScaleAnimator.setDuration(duration); - mScaleAnimator.setFloatValues(mScale, scale); - mScaleAnimator.setInterpolator(mDecelerateInterpolator); - mScaleAnimator.start(); - mHasNewScale = true; - } - - void scaleTo(float scale, int duration) { - scaleTo(scale, duration, true); - } - - void setPostAction(Runnable act) { - mPostAction = act; - } - - @Override - public void onAnimationUpdate(ValueAnimator animation) { - mHasNewScale = true; - mNewScale = (Float) animation.getAnimatedValue(); - layoutChildren(); - } - - @Override - public void onAnimationStart(Animator anim) { - } - - @Override - public void onAnimationEnd(Animator anim) { - if (mPostAction != null) { - mPostAction.run(); - mPostAction = null; - } - mCanStopScale = true; - } - - @Override - public void onAnimationCancel(Animator anim) { - mPostAction = null; - } - - @Override - public void onAnimationRepeat(Animator anim) { - } - } - - private class MyGestureReceiver implements FilmStripGestureRecognizer.Listener { - // Indicating the current trend of scaling is up (>1) or down (<1). - private float mScaleTrend; - - @Override - public boolean onSingleTapUp(float x, float y) { - return false; - } - - @Override - public boolean onDoubleTap(float x, float y) { - return false; - } - - @Override - public boolean onDown(float x, float y) { - mGeometryAnimator.stop(); - return true; - } - - @Override - public boolean onScroll(float x, float y, float dx, float dy) { - int deltaX = (int) (dx / mScale); - if (deltaX > 0 && isInCameraFullscreen()) { - mGeometryAnimator.unlockPosition(); - mGeometryAnimator.scaleTo(FILM_STRIP_SCALE, DURATION_GEOMETRY_ADJUST, false); - } - - mCenterPosition += deltaX; - - // Vertical part. Promote or demote. - int scaledDeltaY = (int) (dy / mScale); - - for (int i = 0; i < BUFFER_SIZE; i++) { - if (mViewInfo[i] == null) continue; - Rect hitRect = new Rect(); - View v = mViewInfo[i].getView(); - v.getHitRect(hitRect); - if (hitRect.contains((int) x, (int) y)) { - ImageData data = mDataAdapter.getImageData(mViewInfo[i].getID()); - if ((data.isActionSupported(ImageData.ACTION_DEMOTE) && dy > 0) - || (data.isActionSupported(ImageData.ACTION_PROMOTE) && dy < 0)) { - mViewInfo[i].setOffsetY(mViewInfo[i].getOffsetY() - dy); - } - break; - } - } - - layoutChildren(); - return true; - } - - @Override - public boolean onFling(float velocityX, float velocityY) { - float scaledVelocityX = velocityX / mScale; - if (isInCameraFullscreen() && scaledVelocityX < 0) { - mGeometryAnimator.unlockPosition(); - mGeometryAnimator.scaleTo(FILM_STRIP_SCALE, DURATION_GEOMETRY_ADJUST, false); - } - ViewInfo info = mViewInfo[mCurrentInfo]; - int w = getWidth(); - if (info == null) return true; - mGeometryAnimator.fling((int) -scaledVelocityX, - // estimation of possible length on the left - info.getLeftPosition() - info.getID() * w * 2, - // estimation of possible length on the right - info.getLeftPosition() - + (mDataAdapter.getTotalNumber() - info.getID()) * w * 2); - layoutChildren(); - return true; - } - - @Override - public boolean onScaleBegin(float focusX, float focusY) { - if (isInCameraFullscreen()) return false; - mScaleTrend = 1f; - return true; - } - - @Override - public boolean onScale(float focusX, float focusY, float scale) { - if (isInCameraFullscreen()) return false; - - mScaleTrend = mScaleTrend * 0.5f + scale * 0.5f; - mScale *= scale; - if (mScale <= FILM_STRIP_SCALE) mScale = FILM_STRIP_SCALE; - if (mScale >= MAX_SCALE) mScale = MAX_SCALE; - layoutChildren(); - return true; - } - - @Override - public void onScaleEnd() { - if (mScaleTrend >= 1f) { - if (mScale != 1f) { - mGeometryAnimator.scaleTo(1f, DURATION_GEOMETRY_ADJUST, false); - } - - if (getCurrentType() == ImageData.TYPE_CAMERA_PREVIEW) { - if (isAnchoredTo(0)) { - mGeometryAnimator.lockPosition(mViewInfo[mCurrentInfo].getCenterX()); - } else { - mGeometryAnimator.scrollTo( - mViewInfo[mCurrentInfo].getCenterX(), - DURATION_GEOMETRY_ADJUST, false); - mGeometryAnimator.setPostAction(mLockPositionRunnable); - } - } - } else { - // Scale down to film strip mode. - if (mScale == FILM_STRIP_SCALE) { - mGeometryAnimator.unlockPosition(); - return; - } - mGeometryAnimator.scaleTo(FILM_STRIP_SCALE, DURATION_GEOMETRY_ADJUST, false); - mGeometryAnimator.setPostAction(mUnlockPositionRunnable); - } - } - - private Runnable mLockPositionRunnable = new Runnable() { - @Override - public void run() { - mGeometryAnimator.lockPosition(mViewInfo[mCurrentInfo].getCenterX()); - } - }; - - private Runnable mUnlockPositionRunnable = new Runnable() { - @Override - public void run() { - mGeometryAnimator.unlockPosition(); - } - }; - } -} diff --git a/src/com/android/camera/ui/NewCameraRootView.java b/src/com/android/camera/ui/NewCameraRootView.java deleted file mode 100644 index a507b147c..000000000 --- a/src/com/android/camera/ui/NewCameraRootView.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camera.ui; - -import android.app.Activity; -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.view.Gravity; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.camera.Util; -import com.android.gallery3d.R; - -public class NewCameraRootView extends FrameLayout - implements RotatableLayout.RotationListener { - - private int mOffset = 0; - public NewCameraRootView(Context context, AttributeSet attrs) { - super(context, attrs); - setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); - } - - @Override - protected boolean fitSystemWindows(Rect insets) { - super.fitSystemWindows(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; - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); - if (insets.bottom > 0) { - mOffset = insets.bottom; - } else if (insets.right > 0) { - mOffset = insets.right; - } - Configuration config = getResources().getConfiguration(); - if (config.orientation == Configuration.ORIENTATION_PORTRAIT) { - lp.setMargins(0, 0, 0, mOffset); - } else if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) { - lp.setMargins(0, 0, mOffset, 0); - } - CameraControls controls = (CameraControls) findViewById(R.id.camera_controls); - if (controls != null) { - controls.setRotationListener(this); - controls.adjustControlsToRightPosition(); - } - return true; - } - - public void cameraModuleChanged() { - CameraControls controls = (CameraControls) findViewById(R.id.camera_controls); - if (controls != null) { - controls.setRotationListener(this); - controls.adjustControlsToRightPosition(); - } - } - - @Override - public void onRotation(int rotation) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); - int b = lp.bottomMargin; - int t = lp.topMargin; - int l = lp.leftMargin; - int r = lp.rightMargin; - rotation = (rotation + 360) % 360; - if (rotation == 90) { - lp.setMargins(b, l, t, r); - } else if (rotation == 270) { - lp.setMargins(t, r, b, l); - } else if (rotation == 180) { - lp.setMargins(r, b, l, t); - } - } -} -- cgit v1.2.3