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