ActivityBase.java revision d80b2cd48dd5958a0e9f370ce28c483b3a1dd166
1/* 2 * Copyright (C) 2009 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.BroadcastReceiver; 20import android.content.ContentResolver; 21import android.content.Context; 22import android.content.Intent; 23import android.content.IntentFilter; 24import android.graphics.Bitmap; 25import android.graphics.BitmapFactory; 26import android.graphics.Rect; 27import android.hardware.Camera.Parameters; 28import android.net.Uri; 29import android.os.AsyncTask; 30import android.os.Bundle; 31import android.os.Handler; 32import android.os.Message; 33import android.support.v4.content.LocalBroadcastManager; 34import android.util.Log; 35import android.view.KeyEvent; 36import android.view.View; 37import android.view.Window; 38import android.view.WindowManager; 39import android.view.animation.AlphaAnimation; 40import android.view.animation.Animation; 41import android.view.animation.DecelerateInterpolator; 42 43import com.android.camera.ui.CameraPicker; 44import com.android.camera.ui.LayoutChangeNotifier; 45import com.android.camera.ui.PopupManager; 46import com.android.camera.ui.RotateImageView; 47import com.android.gallery3d.app.AbstractGalleryActivity; 48import com.android.gallery3d.app.AppBridge; 49import com.android.gallery3d.app.GalleryActionBar; 50import com.android.gallery3d.app.PhotoPage; 51import com.android.gallery3d.common.ApiHelper; 52import com.android.gallery3d.ui.ScreenNail; 53import com.android.gallery3d.util.MediaSetUtils; 54 55import java.io.File; 56 57/** 58 * Superclass of Camera and VideoCamera activities. 59 */ 60public abstract class ActivityBase extends AbstractGalleryActivity 61 implements LayoutChangeNotifier.Listener { 62 63 private static final String TAG = "ActivityBase"; 64 private static final int CAMERA_APP_VIEW_TOGGLE_TIME = 100; // milliseconds 65 private static final String ACTION_DELETE_PICTURE = 66 "com.android.gallery3d.action.DELETE_PICTURE"; 67 private static final String INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE = 68 "android.media.action.STILL_IMAGE_CAMERA_SECURE"; 69 // The intent extra for camera from secure lock screen. True if the gallery 70 // should only show newly captured pictures. sSecureAlbumId does not 71 // increment. This is used when switching between camera, camcorder, and 72 // panorama. If the extra is not set, it is in the normal camera mode. 73 public static final String SECURE_CAMERA_EXTRA = "secure_camera"; 74 75 private int mResultCodeForTesting; 76 private Intent mResultDataForTesting; 77 private OnScreenHint mStorageHint; 78 private View mSingleTapArea; 79 80 // The bitmap of the last captured picture thumbnail and the URI of the 81 // original picture. 82 protected Thumbnail mThumbnail; 83 protected int mThumbnailViewWidth; // layout width of the thumbnail 84 protected AsyncTask<Void, Void, Thumbnail> mLoadThumbnailTask; 85 // An imageview showing the last captured picture thumbnail. 86 protected RotateImageView mThumbnailView; 87 protected CameraPicker mCameraPicker; 88 89 protected boolean mOpenCameraFail; 90 protected boolean mCameraDisabled; 91 protected CameraManager.CameraProxy mCameraDevice; 92 protected Parameters mParameters; 93 // The activity is paused. The classes that extend this class should set 94 // mPaused the first thing in onResume/onPause. 95 protected boolean mPaused; 96 protected GalleryActionBar mActionBar; 97 98 // multiple cameras support 99 protected int mNumberOfCameras; 100 protected int mCameraId; 101 // The activity is going to switch to the specified camera id. This is 102 // needed because texture copy is done in GL thread. -1 means camera is not 103 // switching. 104 protected int mPendingSwitchCameraId = -1; 105 106 protected MyAppBridge mAppBridge; 107 protected ScreenNail mCameraScreenNail; // This shows camera preview. 108 // The view containing only camera related widgets like control panel, 109 // indicator bar, focus indicator and etc. 110 protected View mCameraAppView; 111 protected boolean mShowCameraAppView = true; 112 private Animation mCameraAppViewFadeIn; 113 private Animation mCameraAppViewFadeOut; 114 // Secure album id. This should be incremented every time the camera is 115 // launched from the secure lock screen. The id should be the same when 116 // switching between camera, camcorder, and panorama. 117 protected static int sSecureAlbumId; 118 // True if the gallery should only show newly captured pictures or recorded 119 // videos. 120 protected boolean mSecureCamera; 121 122 private long mStorageSpace = Storage.LOW_STORAGE_THRESHOLD; 123 private static final int UPDATE_STORAGE_HINT = 0; 124 private final Handler mHandler = new Handler() { 125 @Override 126 public void handleMessage(Message msg) { 127 switch (msg.what) { 128 case UPDATE_STORAGE_HINT: 129 updateStorageHint(); 130 return; 131 } 132 } 133 }; 134 135 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 136 @Override 137 public void onReceive(Context context, Intent intent) { 138 String action = intent.getAction(); 139 if (action.equals(Intent.ACTION_MEDIA_MOUNTED) 140 || action.equals(Intent.ACTION_MEDIA_UNMOUNTED) 141 || action.equals(Intent.ACTION_MEDIA_CHECKING) 142 || action.equals(Intent.ACTION_MEDIA_SCANNER_FINISHED)) { 143 updateStorageSpaceAndHint(); 144 } 145 } 146 }; 147 148 private boolean mUpdateThumbnailDelayed; 149 private IntentFilter mDeletePictureFilter = 150 new IntentFilter(ACTION_DELETE_PICTURE); 151 private BroadcastReceiver mDeletePictureReceiver = 152 new BroadcastReceiver() { 153 @Override 154 public void onReceive(Context context, Intent intent) { 155 if (mShowCameraAppView) { 156 getLastThumbnailUncached(); 157 } else { 158 mUpdateThumbnailDelayed = true; 159 } 160 } 161 }; 162 163 // close activity when screen turns off 164 private BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { 165 @Override 166 public void onReceive(Context context, Intent intent) { 167 finish(); 168 } 169 }; 170 171 protected class CameraOpenThread extends Thread { 172 @Override 173 public void run() { 174 try { 175 mCameraDevice = Util.openCamera(ActivityBase.this, mCameraId); 176 mParameters = mCameraDevice.getParameters(); 177 } catch (CameraHardwareException e) { 178 mOpenCameraFail = true; 179 } catch (CameraDisabledException e) { 180 mCameraDisabled = true; 181 } 182 } 183 } 184 185 @Override 186 public void onCreate(Bundle icicle) { 187 // Setting the flag FLAG_SECURE causes white screen and flickering on Gingerbread, 188 // so we do not set the flag. 189 if (ApiHelper.CAN_USE_FLAG_SECURE) { 190 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); 191 } 192 super.disableToggleStatusBar(); 193 // Set a theme with action bar. It is not specified in manifest because 194 // we want to hide it by default. setTheme must happen before 195 // setContentView. 196 // 197 // This must be set before we call super.onCreate(), where the window's 198 // background is removed. 199 setTheme(R.style.Theme_Gallery); 200 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 201 if (ApiHelper.HAS_ACTION_BAR) { 202 requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); 203 } else { 204 requestWindowFeature(Window.FEATURE_NO_TITLE); 205 } 206 207 // Check if this is in the secure camera mode. 208 Intent intent = getIntent(); 209 if (INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE.equals(intent.getAction())) { 210 mSecureCamera = true; 211 // Use a new album when this is started from the lock screen. 212 sSecureAlbumId++; 213 } else { 214 mSecureCamera = intent.getBooleanExtra(SECURE_CAMERA_EXTRA, false); 215 } 216 if (mSecureCamera) { 217 IntentFilter intentFilter = new IntentFilter(); 218 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 219 registerReceiver(mScreenOffReceiver, intentFilter); 220 } 221 super.onCreate(icicle); 222 } 223 224 public boolean isPanoramaActivity() { 225 return false; 226 } 227 228 @Override 229 protected void onResume() { 230 super.onResume(); 231 LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this); 232 manager.registerReceiver(mDeletePictureReceiver, mDeletePictureFilter); 233 234 installIntentFilter(); 235 if(updateStorageHintOnResume()) { 236 updateStorageSpace(); 237 mHandler.sendEmptyMessageDelayed(UPDATE_STORAGE_HINT, 200); 238 } 239 } 240 241 @Override 242 protected void onPause() { 243 super.onPause(); 244 LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this); 245 manager.unregisterReceiver(mDeletePictureReceiver); 246 247 saveThumbnailToFile(); 248 249 if (mLoadThumbnailTask != null) { 250 mLoadThumbnailTask.cancel(true); 251 mLoadThumbnailTask = null; 252 } 253 254 if (mStorageHint != null) { 255 mStorageHint.cancel(); 256 mStorageHint = null; 257 } 258 259 unregisterReceiver(mReceiver); 260 } 261 262 @Override 263 public void setContentView(int layoutResID) { 264 super.setContentView(layoutResID); 265 // getActionBar() should be after setContentView 266 mActionBar = new GalleryActionBar(this); 267 mActionBar.hide(); 268 } 269 270 @Override 271 public boolean onSearchRequested() { 272 return false; 273 } 274 275 @Override 276 public boolean onKeyDown(int keyCode, KeyEvent event) { 277 // Prevent software keyboard or voice search from showing up. 278 if (keyCode == KeyEvent.KEYCODE_SEARCH 279 || keyCode == KeyEvent.KEYCODE_MENU) { 280 if (event.isLongPress()) return true; 281 } 282 if (keyCode == KeyEvent.KEYCODE_MENU && mShowCameraAppView) { 283 return true; 284 } 285 286 return super.onKeyDown(keyCode, event); 287 } 288 289 @Override 290 public boolean onKeyUp(int keyCode, KeyEvent event) { 291 if (keyCode == KeyEvent.KEYCODE_MENU && mShowCameraAppView) { 292 return true; 293 } 294 return super.onKeyUp(keyCode, event); 295 } 296 297 protected void setResultEx(int resultCode) { 298 mResultCodeForTesting = resultCode; 299 setResult(resultCode); 300 } 301 302 protected void setResultEx(int resultCode, Intent data) { 303 mResultCodeForTesting = resultCode; 304 mResultDataForTesting = data; 305 setResult(resultCode, data); 306 } 307 308 public int getResultCode() { 309 return mResultCodeForTesting; 310 } 311 312 public Intent getResultData() { 313 return mResultDataForTesting; 314 } 315 316 @Override 317 protected void onDestroy() { 318 PopupManager.removeInstance(this); 319 if (mSecureCamera) unregisterReceiver(mScreenOffReceiver); 320 super.onDestroy(); 321 } 322 323 protected void installIntentFilter() { 324 // install an intent filter to receive SD card related events. 325 IntentFilter intentFilter = 326 new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); 327 intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED); 328 intentFilter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED); 329 intentFilter.addAction(Intent.ACTION_MEDIA_CHECKING); 330 intentFilter.addDataScheme("file"); 331 registerReceiver(mReceiver, intentFilter); 332 } 333 334 protected void updateStorageSpace() { 335 mStorageSpace = Storage.getAvailableSpace(); 336 } 337 338 protected long getStorageSpace() { 339 return mStorageSpace; 340 } 341 342 protected void updateStorageSpaceAndHint() { 343 updateStorageSpace(); 344 updateStorageHint(mStorageSpace); 345 } 346 347 protected void updateStorageHint() { 348 updateStorageHint(mStorageSpace); 349 } 350 351 protected boolean updateStorageHintOnResume() { 352 return true; 353 } 354 355 protected void updateStorageHint(long storageSpace) { 356 String message = null; 357 if (storageSpace == Storage.UNAVAILABLE) { 358 message = getString(R.string.no_storage); 359 } else if (storageSpace == Storage.PREPARING) { 360 message = getString(R.string.preparing_sd); 361 } else if (storageSpace == Storage.UNKNOWN_SIZE) { 362 message = getString(R.string.access_sd_fail); 363 } else if (storageSpace <= Storage.LOW_STORAGE_THRESHOLD) { 364 message = getString(R.string.spaceIsLow_content); 365 } 366 367 if (message != null) { 368 if (mStorageHint == null) { 369 mStorageHint = OnScreenHint.makeText(this, message); 370 } else { 371 mStorageHint.setText(message); 372 } 373 mStorageHint.show(); 374 } else if (mStorageHint != null) { 375 mStorageHint.cancel(); 376 mStorageHint = null; 377 } 378 } 379 380 protected void updateThumbnailView() { 381 if (mThumbnail != null) { 382 mThumbnailView.setBitmap(mThumbnail.getBitmap()); 383 mThumbnailView.setVisibility(View.VISIBLE); 384 } else { 385 mThumbnailView.setBitmap(null); 386 mThumbnailView.setVisibility(View.GONE); 387 } 388 } 389 390 protected void getLastThumbnail() { 391 mThumbnail = ThumbnailHolder.getLastThumbnail(getContentResolver()); 392 // Suppose users tap the thumbnail view, go to the gallery, delete the 393 // image, and coming back to the camera. Thumbnail file will be invalid. 394 // Since the new thumbnail will be loaded in another thread later, the 395 // view should be set to gone to prevent from opening the invalid image. 396 updateThumbnailView(); 397 if (mThumbnail == null) { 398 mLoadThumbnailTask = new LoadThumbnailTask(true).execute(); 399 } 400 } 401 402 protected void getLastThumbnailUncached() { 403 if (mLoadThumbnailTask != null) mLoadThumbnailTask.cancel(true); 404 mLoadThumbnailTask = new LoadThumbnailTask(false).execute(); 405 } 406 407 private class LoadThumbnailTask extends AsyncTask<Void, Void, Thumbnail> { 408 private boolean mLookAtCache; 409 410 public LoadThumbnailTask(boolean lookAtCache) { 411 mLookAtCache = lookAtCache; 412 } 413 414 @Override 415 protected Thumbnail doInBackground(Void... params) { 416 // Load the thumbnail from the file. 417 ContentResolver resolver = getContentResolver(); 418 Thumbnail t = null; 419 if (mLookAtCache) { 420 t = Thumbnail.getLastThumbnailFromFile(getFilesDir(), resolver); 421 } 422 423 if (isCancelled()) return null; 424 425 if (t == null) { 426 Thumbnail result[] = new Thumbnail[1]; 427 // Load the thumbnail from the media provider. 428 int code = Thumbnail.getLastThumbnailFromContentResolver( 429 resolver, result); 430 switch (code) { 431 case Thumbnail.THUMBNAIL_FOUND: 432 return result[0]; 433 case Thumbnail.THUMBNAIL_NOT_FOUND: 434 return null; 435 case Thumbnail.THUMBNAIL_DELETED: 436 cancel(true); 437 return null; 438 } 439 } 440 return t; 441 } 442 443 @Override 444 protected void onPostExecute(Thumbnail thumbnail) { 445 if (isCancelled()) return; 446 mThumbnail = thumbnail; 447 updateThumbnailView(); 448 } 449 } 450 451 protected void gotoGallery() { 452 // Move the next picture with capture animation. "1" means next. 453 mAppBridge.switchWithCaptureAnimation(1); 454 } 455 456 protected void saveThumbnailToFile() { 457 if (mThumbnail != null && !mThumbnail.fromFile()) { 458 new SaveThumbnailTask().execute(mThumbnail); 459 } 460 } 461 462 private class SaveThumbnailTask extends AsyncTask<Thumbnail, Void, Void> { 463 @Override 464 protected Void doInBackground(Thumbnail... params) { 465 final int n = params.length; 466 final File filesDir = getFilesDir(); 467 for (int i = 0; i < n; i++) { 468 params[i].saveLastThumbnailToFile(filesDir); 469 } 470 return null; 471 } 472 } 473 474 // Call this after setContentView. 475 protected void createCameraScreenNail(boolean getPictures) { 476 mCameraAppView = findViewById(R.id.camera_app_root); 477 Bundle data = new Bundle(); 478 String path; 479 if (mSecureCamera) { 480 path = "/secure/all/" + sSecureAlbumId; 481 } else { 482 path = "/local/all/"; 483 // Intent mode does not show camera roll. Use 0 as a work around for 484 // invalid bucket id. 485 // TODO: add support of empty media set in gallery. 486 path += (getPictures ? MediaSetUtils.CAMERA_BUCKET_ID : "0"); 487 } 488 data.putString(PhotoPage.KEY_MEDIA_SET_PATH, path); 489 data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path); 490 491 // Send an AppBridge to gallery to enable the camera preview. 492 mAppBridge = new MyAppBridge(); 493 data.putParcelable(PhotoPage.KEY_APP_BRIDGE, mAppBridge); 494 getStateManager().startState(PhotoPage.class, data); 495 mCameraScreenNail = mAppBridge.getCameraScreenNail(); 496 } 497 498 private class HideCameraAppView implements Animation.AnimationListener { 499 @Override 500 public void onAnimationEnd(Animation animation) { 501 // We cannot set this as GONE because we want to receive the 502 // onLayoutChange() callback even when we are invisible. 503 mCameraAppView.setVisibility(View.INVISIBLE); 504 } 505 506 @Override 507 public void onAnimationRepeat(Animation animation) { 508 } 509 510 @Override 511 public void onAnimationStart(Animation animation) { 512 } 513 } 514 515 protected void updateCameraAppView() { 516 // Initialize the animation. 517 if (mCameraAppViewFadeIn == null) { 518 mCameraAppViewFadeIn = new AlphaAnimation(0f, 1f); 519 mCameraAppViewFadeIn.setDuration(CAMERA_APP_VIEW_TOGGLE_TIME); 520 mCameraAppViewFadeIn.setInterpolator(new DecelerateInterpolator()); 521 522 mCameraAppViewFadeOut = new AlphaAnimation(1f, 0f); 523 mCameraAppViewFadeOut.setDuration(CAMERA_APP_VIEW_TOGGLE_TIME); 524 mCameraAppViewFadeOut.setInterpolator(new DecelerateInterpolator()); 525 mCameraAppViewFadeOut.setAnimationListener(new HideCameraAppView()); 526 } 527 528 if (mShowCameraAppView) { 529 mCameraAppView.setVisibility(View.VISIBLE); 530 // The "transparent region" is not recomputed when a sibling of 531 // SurfaceView changes visibility (unless it involves GONE). It's 532 // been broken since 1.0. Call requestLayout to work around it. 533 mCameraAppView.requestLayout(); 534 mCameraAppView.startAnimation(mCameraAppViewFadeIn); 535 } else { 536 mCameraAppView.startAnimation(mCameraAppViewFadeOut); 537 } 538 } 539 540 protected void onFullScreenChanged(boolean full) { 541 if (mShowCameraAppView == full) return; 542 mShowCameraAppView = full; 543 if (mPaused || isFinishing()) return; 544 updateCameraAppView(); 545 546 // If we received DELETE_PICTURE broadcasts while the Camera UI is 547 // hidden, we update the thumbnail now. 548 if (full && mUpdateThumbnailDelayed) { 549 getLastThumbnailUncached(); 550 mUpdateThumbnailDelayed = false; 551 } 552 } 553 554 @Override 555 public GalleryActionBar getGalleryActionBar() { 556 return mActionBar; 557 } 558 559 // Preview frame layout has changed. 560 @Override 561 public void onLayoutChange(View v, int left, int top, int right, int bottom) { 562 if (mAppBridge == null) return; 563 564 int width = right - left; 565 int height = bottom - top; 566 if (ApiHelper.HAS_SURFACE_TEXTURE) { 567 CameraScreenNail screenNail = (CameraScreenNail) mCameraScreenNail; 568 if (Util.getDisplayRotation(this) % 180 == 0) { 569 screenNail.setPreviewFrameLayoutSize(width, height); 570 } else { 571 // Swap the width and height. Camera screen nail draw() is based on 572 // natural orientation, not the view system orientation. 573 screenNail.setPreviewFrameLayoutSize(height, width); 574 } 575 } 576 577 // Find out the coordinates of the preview frame relative to GL 578 // root view. 579 View root = (View) getGLRoot(); 580 int[] rootLocation = new int[2]; 581 int[] viewLocation = new int[2]; 582 root.getLocationInWindow(rootLocation); 583 v.getLocationInWindow(viewLocation); 584 585 int l = viewLocation[0] - rootLocation[0]; 586 int t = viewLocation[1] - rootLocation[1]; 587 int r = l + width; 588 int b = t + height; 589 Rect frame = new Rect(l, t, r, b); 590 Log.d(TAG, "set CameraRelativeFrame as " + frame); 591 mAppBridge.setCameraRelativeFrame(frame); 592 } 593 594 protected void setSingleTapUpListener(View singleTapArea) { 595 mSingleTapArea = singleTapArea; 596 } 597 598 private boolean onSingleTapUp(int x, int y) { 599 // Ignore if listener is null or the camera control is invisible. 600 if (mSingleTapArea == null || !mShowCameraAppView) return false; 601 602 int[] relativeLocation = Util.getRelativeLocation((View) getGLRoot(), 603 mSingleTapArea); 604 x -= relativeLocation[0]; 605 y -= relativeLocation[1]; 606 if (x >= 0 && x < mSingleTapArea.getWidth() && y >= 0 607 && y < mSingleTapArea.getHeight()) { 608 onSingleTapUp(mSingleTapArea, x, y); 609 return true; 610 } 611 return false; 612 } 613 614 protected void onSingleTapUp(View view, int x, int y) { 615 } 616 617 protected void setSwipingEnabled(boolean enabled) { 618 mAppBridge.setSwipingEnabled(enabled); 619 } 620 621 protected void notifyScreenNailChanged() { 622 mAppBridge.notifyScreenNailChanged(); 623 } 624 625 protected void onPreviewTextureCopied() { 626 } 627 628 protected void addSecureAlbumItemIfNeeded(boolean isVideo, Uri uri) { 629 if (mSecureCamera) { 630 int id = Integer.parseInt(uri.getLastPathSegment()); 631 mAppBridge.addSecureAlbumItem(isVideo, id); 632 } 633 } 634 635 ////////////////////////////////////////////////////////////////////////// 636 // The is the communication interface between the Camera Application and 637 // the Gallery PhotoPage. 638 ////////////////////////////////////////////////////////////////////////// 639 640 class MyAppBridge extends AppBridge implements CameraScreenNail.Listener { 641 @SuppressWarnings("hiding") 642 private ScreenNail mCameraScreenNail; 643 private Server mServer; 644 645 @Override 646 public ScreenNail attachScreenNail() { 647 if (mCameraScreenNail == null) { 648 if (ApiHelper.HAS_SURFACE_TEXTURE) { 649 mCameraScreenNail = new CameraScreenNail(this); 650 } else { 651 Bitmap b = BitmapFactory.decodeResource(getResources(), 652 R.drawable.wallpaper_picker_preview); 653 mCameraScreenNail = new StaticBitmapScreenNail(b); 654 } 655 } 656 return mCameraScreenNail; 657 } 658 659 @Override 660 public void detachScreenNail() { 661 mCameraScreenNail = null; 662 } 663 664 public ScreenNail getCameraScreenNail() { 665 return mCameraScreenNail; 666 } 667 668 // Return true if the tap is consumed. 669 @Override 670 public boolean onSingleTapUp(int x, int y) { 671 return ActivityBase.this.onSingleTapUp(x, y); 672 } 673 674 // This is used to notify that the screen nail will be drawn in full screen 675 // or not in next draw() call. 676 @Override 677 public void onFullScreenChanged(boolean full) { 678 ActivityBase.this.onFullScreenChanged(full); 679 } 680 681 @Override 682 public void requestRender() { 683 getGLRoot().requestRender(); 684 } 685 686 @Override 687 public void onPreviewTextureCopied() { 688 ActivityBase.this.onPreviewTextureCopied(); 689 } 690 691 @Override 692 public void setServer(Server s) { 693 mServer = s; 694 } 695 696 @Override 697 public boolean isPanorama() { 698 return ActivityBase.this.isPanoramaActivity(); 699 } 700 701 @Override 702 public boolean isStaticCamera() { 703 return !ApiHelper.HAS_SURFACE_TEXTURE; 704 } 705 706 public void addSecureAlbumItem(boolean isVideo, int id) { 707 if (mServer != null) mServer.addSecureAlbumItem(isVideo, id); 708 } 709 710 private void setCameraRelativeFrame(Rect frame) { 711 if (mServer != null) mServer.setCameraRelativeFrame(frame); 712 } 713 714 private void switchWithCaptureAnimation(int offset) { 715 if (mServer != null) mServer.switchWithCaptureAnimation(offset); 716 } 717 718 private void setSwipingEnabled(boolean enabled) { 719 if (mServer != null) mServer.setSwipingEnabled(enabled); 720 } 721 722 private void notifyScreenNailChanged() { 723 if (mServer != null) mServer.notifyScreenNailChanged(); 724 } 725 } 726} 727