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