CameraActivity.java revision d200be24670fe4e455abeef0e684af6370f85a79
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.camera; 18 19import android.content.Context; 20import android.content.Intent; 21import android.content.res.Configuration; 22import android.graphics.drawable.Drawable; 23import android.os.Bundle; 24import android.provider.MediaStore; 25import android.view.KeyEvent; 26import android.view.LayoutInflater; 27import android.view.MotionEvent; 28import android.view.OrientationEventListener; 29import android.view.View; 30import android.view.ViewGroup; 31import android.widget.FrameLayout; 32 33import com.android.camera.ui.CameraSwitcher; 34import com.android.gallery3d.util.LightCycleHelper; 35 36public class CameraActivity extends ActivityBase 37 implements CameraSwitcher.CameraSwitchListener { 38 public static final int PHOTO_MODULE_INDEX = 0; 39 public static final int VIDEO_MODULE_INDEX = 1; 40 public static final int PANORAMA_MODULE_INDEX = 2; 41 public static final int LIGHTCYCLE_MODULE_INDEX = 3; 42 43 CameraModule mCurrentModule; 44 private FrameLayout mFrame; 45 private ShutterButton mShutter; 46 private CameraSwitcher mSwitcher; 47 private View mShutterSwitcher; 48 private View mControlsBackground; 49 private Drawable[] mDrawables; 50 private int mCurrentModuleIndex; 51 private MotionEvent mDown; 52 53 private MyOrientationEventListener mOrientationListener; 54 // The degrees of the device rotated clockwise from its natural orientation. 55 private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; 56 // The orientation compensation for icons. Eg: if the value 57 // is 90, the UI components should be rotated 90 degrees counter-clockwise. 58 private int mOrientationCompensation = 0; 59 60 private static final String TAG = "CAM_activity"; 61 62 private static final int[] DRAW_IDS = { 63 R.drawable.ic_switch_camera, 64 R.drawable.ic_switch_video, 65 R.drawable.ic_switch_pan, 66 R.drawable.ic_switch_photosphere 67 }; 68 69 @Override 70 public void onCreate(Bundle state) { 71 super.onCreate(state); 72 setContentView(R.layout.camera_main); 73 mFrame =(FrameLayout) findViewById(R.id.main_content); 74 mDrawables = new Drawable[DRAW_IDS.length]; 75 for (int i = 0; i < DRAW_IDS.length; i++) { 76 mDrawables[i] = getResources().getDrawable(DRAW_IDS[i]); 77 } 78 init(); 79 if (MediaStore.INTENT_ACTION_VIDEO_CAMERA.equals(getIntent().getAction()) 80 || MediaStore.ACTION_VIDEO_CAPTURE.equals(getIntent().getAction())) { 81 mCurrentModule = new VideoModule(); 82 mCurrentModuleIndex = VIDEO_MODULE_INDEX; 83 } else { 84 mCurrentModule = new PhotoModule(); 85 mCurrentModuleIndex = PHOTO_MODULE_INDEX; 86 } 87 mCurrentModule.init(this, mFrame, true); 88 mSwitcher.setCurrentIndex(mCurrentModuleIndex); 89 mOrientationListener = new MyOrientationEventListener(this); 90 } 91 92 public void init() { 93 mControlsBackground = findViewById(R.id.controls); 94 mShutterSwitcher = findViewById(R.id.camera_shutter_switcher); 95 mShutter = (ShutterButton) findViewById(R.id.shutter_button); 96 mSwitcher = (CameraSwitcher) findViewById(R.id.camera_switcher); 97 mSwitcher.setDrawIds(DRAW_IDS); 98 int[] drawids = new int[LightCycleHelper.hasLightCycleCapture(this) 99 ? DRAW_IDS.length : DRAW_IDS.length - 1]; 100 int ix = 0; 101 for (int i = 0; i < mDrawables.length; i++) { 102 if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(this)) { 103 continue; // not enabled, so don't add to UI 104 } 105 drawids[ix++] = DRAW_IDS[i]; 106 } 107 mSwitcher.setDrawIds(drawids); 108 mSwitcher.setSwitchListener(this); 109 mSwitcher.setCurrentIndex(mCurrentModuleIndex); 110 } 111 112 private class MyOrientationEventListener 113 extends OrientationEventListener { 114 public MyOrientationEventListener(Context context) { 115 super(context); 116 } 117 118 @Override 119 public void onOrientationChanged(int orientation) { 120 // We keep the last known orientation. So if the user first orient 121 // the camera then point the camera to floor or sky, we still have 122 // the correct orientation. 123 if (orientation == ORIENTATION_UNKNOWN) return; 124 mOrientation = Util.roundOrientation(orientation, mOrientation); 125 // When the screen is unlocked, display rotation may change. Always 126 // calculate the up-to-date orientationCompensation. 127 int orientationCompensation = 128 (mOrientation + Util.getDisplayRotation(CameraActivity.this)) % 360; 129 // Rotate camera mode icons in the switcher 130 if (mOrientationCompensation != orientationCompensation) { 131 mOrientationCompensation = orientationCompensation; 132 } 133 mCurrentModule.onOrientationChanged(orientation); 134 } 135 } 136 137 @Override 138 public void onCameraSelected(int i) { 139 if (i != mCurrentModuleIndex) { 140 mPaused = true; 141 boolean canReuse = canReuseScreenNail(); 142 CameraHolder.instance().keep(); 143 closeModule(mCurrentModule); 144 mCurrentModuleIndex = i; 145 switch (i) { 146 case VIDEO_MODULE_INDEX: 147 mCurrentModule = new VideoModule(); 148 break; 149 case PHOTO_MODULE_INDEX: 150 mCurrentModule = new PhotoModule(); 151 break; 152 case PANORAMA_MODULE_INDEX: 153 mCurrentModule = new PanoramaModule(); 154 break; 155 case LIGHTCYCLE_MODULE_INDEX: 156 mCurrentModule = LightCycleHelper.createPanoramaModule(); 157 break; 158 } 159 openModule(mCurrentModule, canReuse); 160 mCurrentModule.onOrientationChanged(mOrientation); 161 } 162 } 163 164 @Override 165 public void onShowSwitcherPopup() { 166 mCurrentModule.onShowSwitcherPopup(); 167 } 168 169 private void openModule(CameraModule module, boolean canReuse) { 170 module.init(this, mFrame, canReuse && canReuseScreenNail()); 171 mPaused = false; 172 module.onResumeBeforeSuper(); 173 module.onResumeAfterSuper(); 174 } 175 176 private void closeModule(CameraModule module) { 177 module.onPauseBeforeSuper(); 178 module.onPauseAfterSuper(); 179 mFrame.removeAllViews(); 180 } 181 182 public ShutterButton getShutterButton() { 183 return mShutter; 184 } 185 186 public void hideUI() { 187 mControlsBackground.setVisibility(View.INVISIBLE); 188 hideSwitcher(); 189 mShutter.setVisibility(View.GONE); 190 } 191 192 public void showUI() { 193 mControlsBackground.setVisibility(View.VISIBLE); 194 showSwitcher(); 195 mShutter.setVisibility(View.VISIBLE); 196 } 197 198 public void hideSwitcher() { 199 mSwitcher.setVisibility(View.GONE); 200 } 201 202 public void showSwitcher() { 203 if (mCurrentModule.needsSwitcher()) { 204 mSwitcher.setVisibility(View.VISIBLE); 205 } 206 } 207 208 public boolean isInCameraApp() { 209 return mShowCameraAppView; 210 } 211 212 @Override 213 public void onConfigurationChanged(Configuration config) { 214 super.onConfigurationChanged(config); 215 216 ViewGroup appRoot = (ViewGroup) findViewById(R.id.content); 217 // remove old switcher, shutter and shutter icon 218 View cameraControlsView = findViewById(R.id.camera_shutter_switcher); 219 appRoot.removeView(cameraControlsView); 220 221 // create new layout with the current orientation 222 LayoutInflater inflater = getLayoutInflater(); 223 inflater.inflate(R.layout.camera_shutter_switcher, appRoot); 224 init(); 225 226 if (mShowCameraAppView) { 227 showUI(); 228 } else { 229 hideUI(); 230 } 231 mCurrentModule.onConfigurationChanged(config); 232 } 233 234 @Override 235 public void onPause() { 236 mPaused = true; 237 mOrientationListener.disable(); 238 mCurrentModule.onPauseBeforeSuper(); 239 super.onPause(); 240 mCurrentModule.onPauseAfterSuper(); 241 } 242 243 @Override 244 public void onResume() { 245 mPaused = false; 246 mOrientationListener.enable(); 247 mCurrentModule.onResumeBeforeSuper(); 248 super.onResume(); 249 mCurrentModule.onResumeAfterSuper(); 250 } 251 252 @Override 253 protected void onFullScreenChanged(boolean full) { 254 if (full) { 255 showUI(); 256 } else { 257 hideUI(); 258 } 259 super.onFullScreenChanged(full); 260 mCurrentModule.onFullScreenChanged(full); 261 } 262 263 @Override 264 protected void onStop() { 265 super.onStop(); 266 mCurrentModule.onStop(); 267 } 268 269 @Override 270 protected void onNewIntent(Intent intent) { 271 super.onNewIntent(intent); 272 getStateManager().clearActivityResult(); 273 } 274 275 @Override 276 protected void installIntentFilter() { 277 super.installIntentFilter(); 278 mCurrentModule.installIntentFilter(); 279 } 280 281 @Override 282 protected void onActivityResult( 283 int requestCode, int resultCode, Intent data) { 284 super.onActivityResult(requestCode, resultCode, data); 285 mCurrentModule.onActivityResult(requestCode, resultCode, data); 286 } 287 288 // Preview area is touched. Handle touch focus. 289 @Override 290 protected void onSingleTapUp(View view, int x, int y) { 291 mCurrentModule.onSingleTapUp(view, x, y); 292 } 293 294 @Override 295 public void onBackPressed() { 296 if (!mCurrentModule.onBackPressed()) { 297 super.onBackPressed(); 298 } 299 } 300 301 @Override 302 public boolean onKeyDown(int keyCode, KeyEvent event) { 303 return mCurrentModule.onKeyDown(keyCode, event) 304 || super.onKeyDown(keyCode, event); 305 } 306 307 @Override 308 public boolean onKeyUp(int keyCode, KeyEvent event) { 309 return mCurrentModule.onKeyUp(keyCode, event) 310 || super.onKeyUp(keyCode, event); 311 } 312 313 public void cancelActivityTouchHandling() { 314 if (mDown != null) { 315 MotionEvent cancel = MotionEvent.obtain(mDown); 316 cancel.setAction(MotionEvent.ACTION_CANCEL); 317 super.dispatchTouchEvent(cancel); 318 } 319 } 320 321 @Override 322 public boolean dispatchTouchEvent(MotionEvent m) { 323 if (m.getActionMasked() == MotionEvent.ACTION_DOWN) { 324 mDown = m; 325 } 326 if ((mSwitcher != null) && mSwitcher.showsPopup() && !mSwitcher.isInsidePopup(m)) { 327 return mSwitcher.onTouch(null, m); 328 } else { 329 return mShutterSwitcher.dispatchTouchEvent(m) 330 || mCurrentModule.dispatchTouchEvent(m); 331 } 332 } 333 334 public boolean superDispatchTouchEvent(MotionEvent m) { 335 return super.dispatchTouchEvent(m); 336 } 337 338 // Preview texture has been copied. Now camera can be released and the 339 // animation can be started. 340 @Override 341 public void onPreviewTextureCopied() { 342 mCurrentModule.onPreviewTextureCopied(); 343 } 344 345 @Override 346 public void onCaptureTextureCopied() { 347 mCurrentModule.onCaptureTextureCopied(); 348 } 349 350 @Override 351 public void onUserInteraction() { 352 super.onUserInteraction(); 353 mCurrentModule.onUserInteraction(); 354 } 355 356 @Override 357 protected boolean updateStorageHintOnResume() { 358 return mCurrentModule.updateStorageHintOnResume(); 359 } 360 361 @Override 362 public void updateCameraAppView() { 363 super.updateCameraAppView(); 364 mCurrentModule.updateCameraAppView(); 365 } 366 367 private boolean canReuseScreenNail() { 368 return mCurrentModuleIndex == PHOTO_MODULE_INDEX 369 || mCurrentModuleIndex == VIDEO_MODULE_INDEX; 370 } 371 372 @Override 373 public boolean isPanoramaActivity() { 374 return (mCurrentModuleIndex == PANORAMA_MODULE_INDEX); 375 } 376 377 // Accessor methods for getting latency times used in performance testing 378 public long getAutoFocusTime() { 379 return (mCurrentModule instanceof PhotoModule) ? 380 ((PhotoModule)mCurrentModule).mAutoFocusTime : -1; 381 } 382 383 public long getShutterLag() { 384 return (mCurrentModule instanceof PhotoModule) ? 385 ((PhotoModule)mCurrentModule).mShutterLag : -1; 386 } 387 388 public long getShutterToPictureDisplayedTime() { 389 return (mCurrentModule instanceof PhotoModule) ? 390 ((PhotoModule)mCurrentModule).mShutterToPictureDisplayedTime : -1; 391 } 392 393 public long getPictureDisplayedToJpegCallbackTime() { 394 return (mCurrentModule instanceof PhotoModule) ? 395 ((PhotoModule)mCurrentModule).mPictureDisplayedToJpegCallbackTime : -1; 396 } 397 398 public long getJpegCallbackFinishTime() { 399 return (mCurrentModule instanceof PhotoModule) ? 400 ((PhotoModule)mCurrentModule).mJpegCallbackFinishTime : -1; 401 } 402 403 public long getCaptureStartTime() { 404 return (mCurrentModule instanceof PhotoModule) ? 405 ((PhotoModule)mCurrentModule).mCaptureStartTime : -1; 406 } 407 408 public boolean isRecording() { 409 return (mCurrentModule instanceof VideoModule) ? 410 ((VideoModule) mCurrentModule).isRecording() : false; 411 } 412 413 public CameraScreenNail getCameraScreenNail() { 414 return (CameraScreenNail) mCameraScreenNail; 415 } 416} 417