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