diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/camera/CameraActivity.java | 40 | ||||
-rw-r--r-- | src/com/android/camera/CameraModule.java | 2 | ||||
-rw-r--r-- | src/com/android/camera/PanoramaModule.java | 11 | ||||
-rw-r--r-- | src/com/android/camera/PhotoModule.java | 156 | ||||
-rw-r--r-- | src/com/android/camera/PreviewFrameLayout.java | 9 | ||||
-rwxr-xr-x | src/com/android/camera/ShutterButton.java | 9 | ||||
-rw-r--r-- | src/com/android/camera/VideoModule.java | 92 | ||||
-rw-r--r-- | src/com/android/camera/ui/CameraSwitcher.java | 13 | ||||
-rw-r--r-- | src/com/android/camera/ui/RotatableLayout.java | 158 | ||||
-rw-r--r-- | src/com/android/photos/PhotoSetFragment.java | 6 | ||||
-rw-r--r-- | src/com/android/photos/drawables/AutoThumbnailDrawable.java | 133 | ||||
-rw-r--r-- | src/com/android/photos/drawables/DataUriThumbnailDrawable.java | 54 | ||||
-rw-r--r-- | src/com/android/photos/drawables/MtpThumbnailDrawable.java | 61 |
13 files changed, 485 insertions, 259 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index b5ff0114c..eed347079 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -41,6 +41,7 @@ import android.view.WindowManager; import android.widget.FrameLayout; import com.android.camera.ui.CameraSwitcher; +import com.android.camera.ui.RotatableLayout; import com.android.gallery3d.R; import com.android.gallery3d.app.PhotoPage; import com.android.gallery3d.common.ApiHelper; @@ -57,8 +58,10 @@ public class CameraActivity extends ActivityBase private FrameLayout mFrame; private ShutterButton mShutter; private CameraSwitcher mSwitcher; - private View mShutterSwitcher; + private View mCameraControls; private View mControlsBackground; + private View mPieMenuButton; + private View mSwitcherControl; private Drawable[] mDrawables; private int mCurrentModuleIndex; private MotionEvent mDown; @@ -94,7 +97,7 @@ public class CameraActivity extends ActivityBase public void onCreate(Bundle state) { super.onCreate(state); setContentView(R.layout.camera_main); - mFrame = (FrameLayout) findViewById(R.id.main_content); + mFrame = (FrameLayout) findViewById(R.id.camera_app_root); mDrawables = new Drawable[DRAW_IDS.length]; for (int i = 0; i < DRAW_IDS.length; i++) { mDrawables[i] = getResources().getDrawable(DRAW_IDS[i]); @@ -115,10 +118,12 @@ public class CameraActivity extends ActivityBase } public void init() { - mControlsBackground = findViewById(R.id.controls); - mShutterSwitcher = findViewById(R.id.camera_shutter_switcher); + mControlsBackground = findViewById(R.id.blocker); + mCameraControls = findViewById(R.id.camera_controls); mShutter = (ShutterButton) findViewById(R.id.shutter_button); mSwitcher = (CameraSwitcher) findViewById(R.id.camera_switcher); + mPieMenuButton = findViewById(R.id.menu_button); + mSwitcherControl = findViewById(R.id.switcher_control); int totaldrawid = (LightCycleHelper.hasLightCycleCapture(this) ? DRAW_IDS.length : DRAW_IDS.length - 1); if (!ApiHelper.HAS_OLD_PANORAMA) totaldrawid--; @@ -217,6 +222,11 @@ public class CameraActivity extends ActivityBase mCurrentModule = LightCycleHelper.createPanoramaModule(); break; } + if (mCurrentModule.needsPieMenu()) { + mPieMenuButton.setVisibility(View.VISIBLE); + } else { + mPieMenuButton.setVisibility(View.INVISIBLE); + } openModule(mCurrentModule, canReuse); mCurrentModule.onOrientationChanged(mLastRawOrientation); if (mMediaSaveService != null) { @@ -268,13 +278,13 @@ public class CameraActivity extends ActivityBase } public void hideUI() { - mControlsBackground.setVisibility(View.INVISIBLE); + mCameraControls.setVisibility(View.INVISIBLE); hideSwitcher(); mShutter.setVisibility(View.GONE); } public void showUI() { - mControlsBackground.setVisibility(View.VISIBLE); + mCameraControls.setVisibility(View.VISIBLE); showSwitcher(); mShutter.setVisibility(View.VISIBLE); // Force a layout change to show shutter button @@ -310,20 +320,10 @@ public class CameraActivity extends ActivityBase } appRoot.setLayoutParams(lp); - // remove old switcher, shutter and shutter icon - View cameraControlsView = findViewById(R.id.camera_shutter_switcher); - appRoot.removeView(cameraControlsView); - - // create new layout with the current orientation - LayoutInflater inflater = getLayoutInflater(); - inflater.inflate(R.layout.camera_shutter_switcher, appRoot); - init(); + // Reset the background after rotation + mControlsBackground.setBackgroundResource(0); // remove the current background + mControlsBackground.setBackgroundResource(R.drawable.switcher_bg); - if (mShowCameraAppView) { - showUI(); - } else { - hideUI(); - } mCurrentModule.onConfigurationChanged(config); } @@ -466,7 +466,7 @@ public class CameraActivity extends ActivityBase if ((mSwitcher != null) && mSwitcher.showsPopup() && !mSwitcher.isInsidePopup(m)) { return mSwitcher.onTouch(null, m); } else { - return mShutterSwitcher.dispatchTouchEvent(m) + return mSwitcherControl.dispatchTouchEvent(m) || mCurrentModule.dispatchTouchEvent(m); } } diff --git a/src/com/android/camera/CameraModule.java b/src/com/android/camera/CameraModule.java index 37eabd0a3..aa057b916 100644 --- a/src/com/android/camera/CameraModule.java +++ b/src/com/android/camera/CameraModule.java @@ -68,6 +68,8 @@ public interface CameraModule { public boolean needsSwitcher(); + public boolean needsPieMenu(); + public void onOrientationChanged(int orientation); public void onShowSwitcherPopup(); diff --git a/src/com/android/camera/PanoramaModule.java b/src/com/android/camera/PanoramaModule.java index 4edc68657..d12c8286e 100644 --- a/src/com/android/camera/PanoramaModule.java +++ b/src/com/android/camera/PanoramaModule.java @@ -714,13 +714,13 @@ public class PanoramaModule implements CameraModule, } private void createContentView() { - mActivity.getLayoutInflater().inflate(R.layout.panorama_module, (ViewGroup) mRootView); + mActivity.getLayoutInflater().inflate(R.layout.panorama_module, (ViewGroup) mRootView, true); Resources appRes = mActivity.getResources(); - mCaptureLayout = (LinearLayout) mRootView.findViewById(R.id.camera_app_root); + mCaptureLayout = (LinearLayout) mRootView.findViewById(R.id.camera_app); mIndicatorColor = appRes.getColor(R.color.pano_progress_indication); mReviewBackground = appRes.getColor(R.color.review_background); mIndicatorColorFast = appRes.getColor(R.color.pano_progress_indication_fast); - mPanoLayout = (ViewGroup) mRootView.findViewById(R.id.pano_layout); + mPanoLayout = (ViewGroup) mRootView.findViewById(R.id.camera_app_root); mRotateDialog = new RotateDialogController(mActivity, R.layout.rotate_dialog); setViews(appRes); } @@ -1308,6 +1308,11 @@ public class PanoramaModule implements CameraModule, } @Override + public boolean needsPieMenu() { + return false; + } + + @Override public void onShowSwitcherPopup() { } diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index e244d6b88..664246a8a 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -52,6 +52,7 @@ import android.view.MotionEvent; import android.view.OrientationEventListener; import android.view.SurfaceHolder; import android.view.View; +import android.view.ViewStub; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; @@ -66,11 +67,8 @@ import com.android.camera.ui.CountDownView; import com.android.camera.ui.FaceView; import com.android.camera.ui.PieRenderer; import com.android.camera.ui.PopupManager; -import com.android.camera.ui.PreviewSurfaceView; import com.android.camera.ui.RenderOverlay; -import com.android.camera.ui.Rotatable; import com.android.camera.ui.RotateTextToast; -import com.android.camera.ui.TwoStateImageView; import com.android.camera.ui.ZoomRenderer; import com.android.gallery3d.R; import com.android.gallery3d.common.ApiHelper; @@ -92,7 +90,6 @@ public class PhotoModule FocusOverlayManager.Listener, CameraPreference.OnPreferenceChangedListener, LocationManager.Listener, - PreviewFrameLayout.OnSizeChangedListener, ShutterButton.OnShutterButtonListener, SurfaceHolder.Callback, PieRenderer.PieListener, @@ -172,18 +169,15 @@ public class PhotoModule private ShutterButton mShutterButton; private boolean mFaceDetectionStarted = false; - private PreviewFrameLayout mPreviewFrameLayout; private Object mSurfaceTexture; private CountDownView mCountDownView; - // for API level 10 - private PreviewSurfaceView mPreviewSurfaceView; private volatile SurfaceHolder mCameraSurfaceHolder; private FaceView mFaceView; private RenderOverlay mRenderOverlay; - private Rotatable mReviewCancelButton; - private Rotatable mReviewDoneButton; + private View mReviewCancelButton; + private View mReviewDoneButton; private View mReviewRetakeButton; // mCropValue and mSaveUri are used only if isImageCaptureIntent() is true. @@ -288,7 +282,6 @@ public class PhotoModule private PhotoController mPhotoControl; private ZoomRenderer mZoomRenderer; - private String mSceneMode; private Toast mNotSelectableToast; @@ -466,7 +459,16 @@ public class PhotoModule mCameraStartUpThread = new CameraStartUpThread(); mCameraStartUpThread.start(); - mActivity.getLayoutInflater().inflate(R.layout.photo_module, (ViewGroup) mRootView); + mActivity.getLayoutInflater().inflate(R.layout.photo_module, + (ViewGroup) mRootView, true); + if (ApiHelper.HAS_FACE_DETECTION) { + ViewStub faceViewStub = (ViewStub) mRootView + .findViewById(R.id.face_view_stub); + if (faceViewStub != null) { + faceViewStub.inflate(); + mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); + } + } // Surface texture is from camera screen nail and startPreview needs it. // This must be done before startPreview. @@ -487,7 +489,6 @@ public class PhotoModule initializeControlByIntent(); mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false); - initializeMiscControls(); mLocationManager = new LocationManager(mActivity, this); initOnScreenIndicator(); mCountDownView = (CountDownView) (mRootView.findViewById(R.id.count_down_to_capture)); @@ -557,10 +558,10 @@ public class PhotoModule if (isImageCaptureIntent()) { if (mReviewCancelButton != null) { - mGestures.addTouchReceiver((View) mReviewCancelButton); + mGestures.addTouchReceiver(mReviewCancelButton); } if (mReviewDoneButton != null) { - mGestures.addTouchReceiver((View) mReviewDoneButton); + mGestures.addTouchReceiver(mReviewDoneButton); } } } @@ -585,9 +586,17 @@ public class PhotoModule initializePhotoControl(); // These depend on camera parameters. - setPreviewFrameLayoutAspectRatio(); - mFocusManager.setPreviewSize(mPreviewFrameLayout.getWidth(), - mPreviewFrameLayout.getHeight()); + int width = mActivity.getWindowManager().getDefaultDisplay().getWidth(); + int height = mActivity.getWindowManager().getDefaultDisplay().getHeight(); + mFocusManager.setPreviewSize(width, height); + // Full-screen screennail + if (Util.getDisplayRotation(mActivity) % 180 == 0) { + ((CameraScreenNail) mActivity.mCameraScreenNail).setPreviewFrameLayoutSize(width, height); + } else { + ((CameraScreenNail) mActivity.mCameraScreenNail).setPreviewFrameLayoutSize(height, width); + } + // Set touch focus listener. + mActivity.setSingleTapUpListener(mRootView); loadCameraPreferences(); initializeZoom(); updateOnScreenIndicators(); @@ -795,7 +804,7 @@ public class PhotoModule } private void initOnScreenIndicator() { - mOnScreenIndicators = mRootView.findViewById(R.id.on_screen_indicators); + mOnScreenIndicators = mActivity.findViewById(R.id.on_screen_indicators); mExposureIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_exposure_indicator); mFlashIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_flash_indicator); mSceneIndicator = (ImageView) mOnScreenIndicators.findViewById(R.id.menu_scenemode_indicator); @@ -1217,11 +1226,6 @@ public class PhotoModule } return; } - if (full) { - mPreviewSurfaceView.expand(); - } else { - mPreviewSurfaceView.shrink(); - } } @Override @@ -1623,8 +1627,8 @@ public class PhotoModule } private void initializeControlByIntent() { - mBlocker = mRootView.findViewById(R.id.blocker); - mMenu = mRootView.findViewById(R.id.menu); + mBlocker = mActivity.findViewById(R.id.blocker); + mMenu = mActivity.findViewById(R.id.menu); mMenu.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -1637,23 +1641,22 @@ public class PhotoModule } }); if (mIsImageCaptureIntent) { - mActivity.hideSwitcher(); - // Cannot use RotateImageView for "done" and "cancel" button because - // the tablet layout uses RotateLayout, which cannot be cast to - // RotateImageView. - mReviewDoneButton = (Rotatable) mRootView.findViewById(R.id.btn_done); - mReviewCancelButton = (Rotatable) mRootView.findViewById(R.id.btn_cancel); - mReviewRetakeButton = mRootView.findViewById(R.id.btn_retake); - ((View) mReviewCancelButton).setVisibility(View.VISIBLE); - - ((View) mReviewDoneButton).setOnClickListener(new OnClickListener() { + ViewGroup cameraControls = (ViewGroup) mActivity.findViewById(R.id.camera_controls); + mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls); + + mReviewDoneButton = mActivity.findViewById(R.id.btn_done); + mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel); + mReviewRetakeButton = mActivity.findViewById(R.id.btn_retake); + mReviewCancelButton.setVisibility(View.VISIBLE); + + mReviewDoneButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewDoneClicked(v); } }); - ((View) mReviewCancelButton).setOnClickListener(new OnClickListener() { + mReviewCancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewCancelClicked(v); @@ -1667,13 +1670,6 @@ public class PhotoModule } }); - // Not grayed out upon disabled, to make the follow-up fade-out - // effect look smooth. Note that the review done button in tablet - // layout is not a TwoStateImageView. - if (mReviewDoneButton instanceof TwoStateImageView) { - ((TwoStateImageView) mReviewDoneButton).enableFilter(false); - } - setupCaptureParams(); } } @@ -1700,62 +1696,10 @@ public class PhotoModule } } - private void initializeMiscControls() { - // startPreview needs this. - mPreviewFrameLayout = (PreviewFrameLayout) mRootView.findViewById(R.id.frame); - // Set touch focus listener. - mActivity.setSingleTapUpListener(mPreviewFrameLayout); - - mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); - mPreviewFrameLayout.setOnSizeChangedListener(this); - mPreviewFrameLayout.setOnLayoutChangeListener(mActivity); - if (!ApiHelper.HAS_SURFACE_TEXTURE) { - mPreviewSurfaceView = - (PreviewSurfaceView) mRootView.findViewById(R.id.preview_surface_view); - mPreviewSurfaceView.setVisibility(View.VISIBLE); - mPreviewSurfaceView.getHolder().addCallback(this); - } - } - @Override public void onConfigurationChanged(Configuration newConfig) { Log.v(TAG, "onConfigurationChanged"); setDisplayOrientation(); - - // Only the views in photo_module_content need to be removed and recreated - // i.e. CountDownView won't be recreated - ViewGroup viewGroup = (ViewGroup) mRootView.findViewById(R.id.camera_app); - viewGroup.removeAllViews(); - LayoutInflater inflater = mActivity.getLayoutInflater(); - inflater.inflate(R.layout.photo_module_content, (ViewGroup) viewGroup); - - // from onCreate() - initializeControlByIntent(); - - initializeFocusManager(); - initializeMiscControls(); - loadCameraPreferences(); - - // from initializeFirstTime() - mShutterButton = mActivity.getShutterButton(); - mShutterButton.setOnShutterButtonListener(this); - initializeZoom(); - initOnScreenIndicator(); - updateOnScreenIndicators(); - if (mFaceView != null) { - mFaceView.clear(); - mFaceView.setVisibility(View.VISIBLE); - mFaceView.setDisplayOrientation(mDisplayOrientation); - CameraInfo info = CameraHolder.instance().getCameraInfo()[mCameraId]; - mFaceView.setMirror(info.facing == CameraInfo.CAMERA_FACING_FRONT); - mFaceView.resume(); - mFocusManager.setFaceView(mFaceView); - } - initializeRenderOverlay(); - onFullScreenChanged(mActivity.isInCameraApp()); - if (mJpegImageData != null) { // Jpeg data found, picture has been taken. - showPostCaptureAlert(); - } } @Override @@ -2258,7 +2202,7 @@ public class PhotoModule if (mIsImageCaptureIntent) { mOnScreenIndicators.setVisibility(View.GONE); mMenu.setVisibility(View.GONE); - Util.fadeIn((View) mReviewDoneButton); + Util.fadeIn(mReviewDoneButton); mShutterButton.setVisibility(View.INVISIBLE); Util.fadeIn(mReviewRetakeButton); } @@ -2268,7 +2212,7 @@ public class PhotoModule if (mIsImageCaptureIntent) { mOnScreenIndicators.setVisibility(View.VISIBLE); mMenu.setVisibility(View.VISIBLE); - Util.fadeOut((View) mReviewDoneButton); + Util.fadeOut(mReviewDoneButton); mShutterButton.setVisibility(View.VISIBLE); Util.fadeOut(mReviewRetakeButton); } @@ -2284,7 +2228,6 @@ public class PhotoModule mLocationManager.recordLocation(recordLocation); setCameraParametersWhenIdle(UPDATE_PARAM_PREFERENCE); - setPreviewFrameLayoutAspectRatio(); updateOnScreenIndicators(); } @@ -2431,12 +2374,6 @@ public class PhotoModule Util.FOCUS_MODE_CONTINUOUS_PICTURE); } - // PreviewFrameLayout size has changed. - @Override - public void onSizeChanged(int width, int height) { - if (mFocusManager != null) mFocusManager.setPreviewSize(width, height); - } - @Override public void onCountDownFinished() { mSnapshotOnIdle = false; @@ -2444,17 +2381,16 @@ public class PhotoModule mFocusManager.onShutterUp(); } - void setPreviewFrameLayoutAspectRatio() { - // Set the preview frame aspect ratio according to the picture size. - Size size = mParameters.getPictureSize(); - mPreviewFrameLayout.setAspectRatio((double) size.width / size.height); - } - @Override public boolean needsSwitcher() { return !mIsImageCaptureIntent; } + @Override + public boolean needsPieMenu() { + return true; + } + public void showPopup(AbstractSettingPopup popup) { mActivity.hideUI(); mBlocker.setVisibility(View.INVISIBLE); diff --git a/src/com/android/camera/PreviewFrameLayout.java b/src/com/android/camera/PreviewFrameLayout.java index 87e3c8dfc..03ef91c60 100644 --- a/src/com/android/camera/PreviewFrameLayout.java +++ b/src/com/android/camera/PreviewFrameLayout.java @@ -54,15 +54,6 @@ public class PreviewFrameLayout extends RelativeLayout implements LayoutChangeNo @Override protected void onFinishInflate() { mBorder = findViewById(R.id.preview_border); - if (ApiHelper.HAS_FACE_DETECTION) { - ViewStub faceViewStub = (ViewStub) findViewById(R.id.face_view_stub); - /* preview_frame_video.xml does not have face view stub, so we need to - * check that. - */ - if (faceViewStub != null) { - faceViewStub.inflate(); - } - } } public void setAspectRatio(double ratio) { diff --git a/src/com/android/camera/ShutterButton.java b/src/com/android/camera/ShutterButton.java index a1bbb1a0d..41775a186 100755 --- a/src/com/android/camera/ShutterButton.java +++ b/src/com/android/camera/ShutterButton.java @@ -17,11 +17,14 @@ package com.android.camera; import android.content.Context; +import android.content.res.Configuration; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; +import com.android.camera.ui.RotatableLayout; + /** * A button designed to be used for the on-screen shutter button. * It's currently an {@code ImageView} that can call a delegate when the @@ -127,4 +130,10 @@ public class ShutterButton extends ImageView { } return result; } + + @Override + public void onConfigurationChanged(Configuration config) { + super.onConfigurationChanged(config); + RotatableLayout.rotate(this, config.orientation == Configuration.ORIENTATION_PORTRAIT); + } } diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java index 245ef5990..7bda657a2 100644 --- a/src/com/android/camera/VideoModule.java +++ b/src/com/android/camera/VideoModule.java @@ -73,7 +73,6 @@ import com.android.camera.ui.Rotatable; import com.android.camera.ui.RotateImageView; import com.android.camera.ui.RotateLayout; import com.android.camera.ui.RotateTextToast; -import com.android.camera.ui.TwoStateImageView; import com.android.camera.ui.ZoomRenderer; import com.android.gallery3d.R; import com.android.gallery3d.common.ApiHelper; @@ -142,14 +141,13 @@ public class VideoModule implements CameraModule, private SurfaceHolder.Callback mSurfaceViewCallback; private PreviewSurfaceView mPreviewSurfaceView; private CameraScreenNail.OnFrameDrawnListener mFrameDrawnListener; - private View mReviewControl; // An review image having same size as preview. It is displayed when // recording is stopped in capture intent. private ImageView mReviewImage; - private Rotatable mReviewCancelButton; - private Rotatable mReviewDoneButton; - private RotateImageView mReviewPlayButton; + private View mReviewCancelButton; + private View mReviewDoneButton; + private View mReviewPlayButton; private ShutterButton mShutterButton; private TextView mRecordingTimeView; private RotateLayout mBgLearningMessageRotater; @@ -414,13 +412,13 @@ public class VideoModule implements CameraModule, if (isVideoCaptureIntent()) { if (mReviewCancelButton != null) { - mGestures.addTouchReceiver((View) mReviewCancelButton); + mGestures.addTouchReceiver(mReviewCancelButton); } if (mReviewDoneButton != null) { - mGestures.addTouchReceiver((View) mReviewDoneButton); + mGestures.addTouchReceiver(mReviewDoneButton); } if (mReviewPlayButton != null) { - mGestures.addTouchReceiver((View) mReviewPlayButton); + mGestures.addTouchReceiver(mReviewPlayButton); } } } @@ -449,7 +447,7 @@ public class VideoModule implements CameraModule, mContentResolver = mActivity.getContentResolver(); - mActivity.getLayoutInflater().inflate(R.layout.video_module, (ViewGroup) mRootView); + mActivity.getLayoutInflater().inflate(R.layout.video_module, (ViewGroup) mRootView, true); // Surface texture is from camera screen nail and startPreview needs it. // This must be done before startPreview. @@ -589,8 +587,7 @@ public class VideoModule implements CameraModule, private void setOrientationIndicator(int orientation, boolean animation) { Rotatable[] indicators = { - mBgLearningMessageRotater, - mReviewDoneButton, mReviewPlayButton}; + mBgLearningMessageRotater}; for (Rotatable indicator : indicators) { if (indicator != null) indicator.setOrientation(orientation, animation); } @@ -598,14 +595,6 @@ public class VideoModule implements CameraModule, mGestures.setOrientation(orientation); } - // We change the orientation of the review cancel button only for tablet - // UI because there's a label along with the X icon. For phone UI, we - // don't change the orientation because there's only a symmetrical X - // icon. - if (mReviewCancelButton instanceof RotateLayout) { - mReviewCancelButton.setOrientation(orientation, animation); - } - // We change the orientation of the linearlayout only for phone UI because when in portrait // the width is not enough. if (mLabelsLinearLayout != null) { @@ -1636,7 +1625,6 @@ public class VideoModule implements CameraModule, mActivity.hideSwitcher(); mRecordingTimeView.setText(""); mRecordingTimeView.setVisibility(View.VISIBLE); - if (mReviewControl != null) mReviewControl.setVisibility(View.GONE); // The camera is not allowed to be accessed in older api levels during // recording. It is therefore necessary to hide the zoom UI on older // platforms. @@ -1650,7 +1638,6 @@ public class VideoModule implements CameraModule, mShutterButton.setImageResource(R.drawable.btn_new_shutter_video); mActivity.showSwitcher(); mRecordingTimeView.setVisibility(View.GONE); - if (mReviewControl != null) mReviewControl.setVisibility(View.VISIBLE); if (!ApiHelper.HAS_ZOOM_WHEN_RECORDING && mParameters.isZoomSupported()) { // TODO: enable zoom UI here. @@ -1679,7 +1666,7 @@ public class VideoModule implements CameraModule, Util.fadeOut(mShutterButton); - Util.fadeIn((View) mReviewDoneButton); + Util.fadeIn(mReviewDoneButton); Util.fadeIn(mReviewPlayButton); mMenu.setVisibility(View.GONE); mOnScreenIndicators.setVisibility(View.GONE); @@ -1695,7 +1682,7 @@ public class VideoModule implements CameraModule, mOnScreenIndicators.setVisibility(View.VISIBLE); enableCameraControls(true); - Util.fadeOut((View) mReviewDoneButton); + Util.fadeOut(mReviewDoneButton); Util.fadeOut(mReviewPlayButton); Util.fadeIn(mShutterButton); @@ -2115,8 +2102,8 @@ public class VideoModule implements CameraModule, } private void initializeControlByIntent() { - mBlocker = mRootView.findViewById(R.id.blocker); - mMenu = mRootView.findViewById(R.id.menu); + mBlocker = mActivity.findViewById(R.id.blocker); + mMenu = mActivity.findViewById(R.id.menu); mMenu.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -2125,46 +2112,40 @@ public class VideoModule implements CameraModule, } } }); - mOnScreenIndicators = mRootView.findViewById(R.id.on_screen_indicators); - mFlashIndicator = (ImageView) mRootView.findViewById(R.id.menu_flash_indicator); + mOnScreenIndicators = mActivity.findViewById(R.id.on_screen_indicators); + mFlashIndicator = (ImageView) mActivity.findViewById(R.id.menu_flash_indicator); if (mIsVideoCaptureIntent) { mActivity.hideSwitcher(); + ViewGroup cameraControls = (ViewGroup) mActivity.findViewById(R.id.camera_controls); + mActivity.getLayoutInflater().inflate(R.layout.review_module_control, cameraControls); // Cannot use RotateImageView for "done" and "cancel" button because // the tablet layout uses RotateLayout, which cannot be cast to // RotateImageView. - mReviewDoneButton = (Rotatable) mRootView.findViewById(R.id.btn_done); - mReviewCancelButton = (Rotatable) mRootView.findViewById(R.id.btn_cancel); - mReviewPlayButton = (RotateImageView) mRootView.findViewById(R.id.btn_play); + mReviewDoneButton = mActivity.findViewById(R.id.btn_done); + mReviewCancelButton = mActivity.findViewById(R.id.btn_cancel); + mReviewPlayButton = mActivity.findViewById(R.id.btn_play); - ((View) mReviewCancelButton).setVisibility(View.VISIBLE); + mReviewCancelButton.setVisibility(View.VISIBLE); - ((View) mReviewDoneButton).setOnClickListener(new OnClickListener() { + mReviewDoneButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewDoneClicked(v); } }); - ((View) mReviewCancelButton).setOnClickListener(new OnClickListener() { + mReviewCancelButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewCancelClicked(v); } }); - ((View) mReviewPlayButton).setOnClickListener(new OnClickListener() { + mReviewPlayButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { onReviewPlayClicked(v); } }); - - - // Not grayed out upon disabled, to make the follow-up fade-out - // effect look smooth. Note that the review done button in tablet - // layout is not a TwoStateImageView. - if (mReviewDoneButton instanceof TwoStateImageView) { - ((TwoStateImageView) mReviewDoneButton).enableFilter(false); - } } } @@ -2203,28 +2184,8 @@ public class VideoModule implements CameraModule, @Override public void onConfigurationChanged(Configuration newConfig) { + Log.v(TAG, "onConfigurationChanged"); setDisplayOrientation(); - // Change layout in response to configuration change - LayoutInflater inflater = mActivity.getLayoutInflater(); - ((ViewGroup) mRootView).removeAllViews(); - inflater.inflate(R.layout.video_module, (ViewGroup) mRootView); - - // from onCreate() - initializeControlByIntent(); - initializeOverlay(); - initializeSurfaceView(); - initializeMiscControls(); - showTimeLapseUI(mCaptureTimeLapse); - initializeVideoSnapshot(); - - // from onResume() - showVideoSnapshotUI(false); - initializeZoom(); - onFullScreenChanged(mActivity.isInCameraApp()); - updateOnScreenIndicators(); - if (mIsVideoCaptureIntent && mVideoFileDescriptor != null) { - showCaptureResult(); - } } @Override @@ -2785,6 +2746,11 @@ public class VideoModule implements CameraModule, } @Override + public boolean needsPieMenu() { + return true; + } + + @Override public void onPieOpened(int centerX, int centerY) { mActivity.cancelActivityTouchHandling(); mActivity.setSwipingEnabled(false); diff --git a/src/com/android/camera/ui/CameraSwitcher.java b/src/com/android/camera/ui/CameraSwitcher.java index 8d2cd7117..3fa4a01d5 100644 --- a/src/com/android/camera/ui/CameraSwitcher.java +++ b/src/com/android/camera/ui/CameraSwitcher.java @@ -30,6 +30,7 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; +import android.widget.FrameLayout.LayoutParams; import android.widget.LinearLayout; import com.android.gallery3d.R; @@ -177,6 +178,16 @@ public class CameraSwitcher extends RotateImageView mParent.setOnTouchListener(null); } + @Override + public void onConfigurationChanged(Configuration config) { + if (showsPopup()) { + ((ViewGroup) mParent).removeView(mPopup); + mPopup = null; + initPopup(); + mPopup.setVisibility(View.VISIBLE); + } + } + private void showSwitcher() { mShowingPopup = true; if (mPopup == null) { @@ -245,6 +256,8 @@ public class CameraSwitcher extends RotateImageView // Verify that we weren't canceled if (!showsPopup()) { mPopup.setVisibility(View.INVISIBLE); + ((ViewGroup) mParent).removeView(mPopup); + mPopup = null; } } }; diff --git a/src/com/android/camera/ui/RotatableLayout.java b/src/com/android/camera/ui/RotatableLayout.java new file mode 100644 index 000000000..9c5ebd34d --- /dev/null +++ b/src/com/android/camera/ui/RotatableLayout.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.camera.ui; + +import android.content.Context; +import android.content.res.Configuration; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +/* RotatableLayout rotates itself as well as all its children when orientation + * changes. Specifically, when going from portrait to landscape, camera + * controls move from the bottom of the screen to right side of the screen + * (i.e. counter clockwise). Similarly, when the screen changes to portrait, we + * need to move the controls from right side to the bottom of the screen, which + * is a clockwise rotation. + */ + +public class RotatableLayout extends FrameLayout { + + public RotatableLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public RotatableLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RotatableLayout(Context context) { + super(context); + } + + @Override + public void onConfigurationChanged(Configuration config) { + super.onConfigurationChanged(config); + // rotate the layout itself and all its children + boolean clockwise = (config.orientation == Configuration.ORIENTATION_PORTRAIT); + rotate(this, clockwise); + int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = getChildAt(i); + rotate(child, clockwise); + } + } + + public static void rotate(View view, boolean isClockwise) { + if (isClockwise) { + rotateClockwise(view); + } else { + rotateCounterClockwise(view); + } + } + + private static boolean contains(int value, int mask) { + return (value & mask) == mask; + } + + public static void rotateClockwise(View view) { + if (view == null) return; + LayoutParams lp = (LayoutParams) view.getLayoutParams(); + int gravity = lp.gravity; + int ngravity = 0; + // rotate gravity + if (contains(gravity, Gravity.LEFT)) { + ngravity |= Gravity.TOP; + } + if (contains(gravity, Gravity.RIGHT)) { + ngravity |= Gravity.BOTTOM; + } + if (contains(gravity, Gravity.TOP)) { + ngravity |= Gravity.RIGHT; + } + if (contains(gravity, Gravity.BOTTOM)) { + ngravity |= Gravity.LEFT; + } + if (contains(gravity, Gravity.CENTER)) { + ngravity |= Gravity.CENTER; + } + if (contains(gravity, Gravity.CENTER_HORIZONTAL)) { + ngravity |= Gravity.CENTER_VERTICAL; + } + if (contains(gravity, Gravity.CENTER_VERTICAL)) { + ngravity |= Gravity.CENTER_HORIZONTAL; + } + lp.gravity = ngravity; + int ml = lp.leftMargin; + int mr = lp.rightMargin; + int mt = lp.topMargin; + int mb = lp.bottomMargin; + lp.leftMargin = mb; + lp.rightMargin = mt; + lp.topMargin = ml; + lp.bottomMargin = mr; + int width = lp.width; + int height = lp.height; + lp.width = height; + lp.height = width; + view.setLayoutParams(lp); + } + + public static void rotateCounterClockwise(View view) { + if (view == null) return; + LayoutParams lp = (LayoutParams) view.getLayoutParams(); + int gravity = lp.gravity; + int ngravity = 0; + // change gravity + if (contains(gravity, Gravity.RIGHT)) { + ngravity |= Gravity.TOP; + } + if (contains(gravity, Gravity.LEFT)) { + ngravity |= Gravity.BOTTOM; + } + if (contains(gravity, Gravity.TOP)) { + ngravity |= Gravity.LEFT; + } + if (contains(gravity, Gravity.BOTTOM)) { + ngravity |= Gravity.RIGHT; + } + if (contains(gravity, Gravity.CENTER)) { + ngravity |= Gravity.CENTER; + } + if (contains(gravity, Gravity.CENTER_HORIZONTAL)) { + ngravity |= Gravity.CENTER_VERTICAL; + } + if (contains(gravity, Gravity.CENTER_VERTICAL)) { + ngravity |= Gravity.CENTER_HORIZONTAL; + } + lp.gravity = ngravity; + int ml = lp.leftMargin; + int mr = lp.rightMargin; + int mt = lp.topMargin; + int mb = lp.bottomMargin; + lp.leftMargin = mt; + lp.rightMargin = mb; + lp.topMargin = mr; + lp.bottomMargin = ml; + int width = lp.width; + int height = lp.height; + lp.width = height; + lp.height = width; + view.setLayoutParams(lp); + } +}
\ No newline at end of file diff --git a/src/com/android/photos/PhotoSetFragment.java b/src/com/android/photos/PhotoSetFragment.java index 6c0e2e7c5..0e9efa4b1 100644 --- a/src/com/android/photos/PhotoSetFragment.java +++ b/src/com/android/photos/PhotoSetFragment.java @@ -33,7 +33,7 @@ import android.widget.ImageView; import com.android.gallery3d.R; import com.android.photos.data.PhotoSetLoader; -import com.android.photos.drawables.AutoThumbnailDrawable; +import com.android.photos.drawables.DataUriThumbnailDrawable; import com.android.photos.views.GalleryThumbnailView; import com.android.photos.views.GalleryThumbnailView.GalleryThumbnailAdapter; @@ -105,7 +105,7 @@ public class PhotoSetFragment extends Fragment implements LoaderCallbacks<Cursor @Override public void bindView(View view, Context context, Cursor cursor) { ImageView iv = (ImageView) view; - AutoThumbnailDrawable drawable = (AutoThumbnailDrawable) iv.getDrawable(); + DataUriThumbnailDrawable drawable = (DataUriThumbnailDrawable) iv.getDrawable(); int width = cursor.getInt(PhotoSetLoader.INDEX_WIDTH); int height = cursor.getInt(PhotoSetLoader.INDEX_HEIGHT); String path = cursor.getString(PhotoSetLoader.INDEX_DATA); @@ -116,7 +116,7 @@ public class PhotoSetFragment extends Fragment implements LoaderCallbacks<Cursor @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { ImageView iv = new ImageView(context); - AutoThumbnailDrawable drawable = new AutoThumbnailDrawable(); + DataUriThumbnailDrawable drawable = new DataUriThumbnailDrawable(); iv.setImageDrawable(drawable); int padding = (int) Math.ceil(2 * context.getResources().getDisplayMetrics().density); iv.setPadding(padding, padding, padding, padding); diff --git a/src/com/android/photos/drawables/AutoThumbnailDrawable.java b/src/com/android/photos/drawables/AutoThumbnailDrawable.java index 95283e16d..09b344147 100644 --- a/src/com/android/photos/drawables/AutoThumbnailDrawable.java +++ b/src/com/android/photos/drawables/AutoThumbnailDrawable.java @@ -25,26 +25,25 @@ import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.media.ExifInterface; -import android.text.TextUtils; import android.util.Log; -import java.io.FileDescriptor; -import java.io.FileInputStream; +import com.android.photos.data.GalleryBitmapPool; + +import java.io.InputStream; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -public class AutoThumbnailDrawable extends Drawable { +public abstract class AutoThumbnailDrawable<T> extends Drawable { - private static final String TAG = "AutoMipMapDrawable"; + private static final String TAG = "AutoThumbnailDrawable"; private static ExecutorService sThreadPool = Executors.newSingleThreadExecutor(); + private static GalleryBitmapPool sBitmapPool = GalleryBitmapPool.getInstance(); private static byte[] sTempStorage = new byte[64 * 1024]; // UI thread only private Paint mPaint = new Paint(); private Matrix mDrawMatrix = new Matrix(); - private int mSampleSize = 1; // Decoder thread only private BitmapFactory.Options mOptions = new BitmapFactory.Options(); @@ -52,10 +51,11 @@ public class AutoThumbnailDrawable extends Drawable { // Shared, guarded by mLock private Object mLock = new Object(); private Bitmap mBitmap; - private String mDataUri; + protected T mData; private boolean mIsQueued; private int mImageWidth, mImageHeight; private Rect mBounds = new Rect(); + private int mSampleSize = 1; public AutoThumbnailDrawable() { mPaint.setAntiAlias(true); @@ -64,18 +64,32 @@ public class AutoThumbnailDrawable extends Drawable { mOptions.inTempStorage = sTempStorage; } - public void setImage(String dataUri, int width, int height) { - if (TextUtils.equals(mDataUri, dataUri)) return; + protected abstract byte[] getPreferredImageBytes(T data); + protected abstract InputStream getFallbackImageStream(T data); + protected abstract boolean dataChangedLocked(T data); + + public void setImage(T data, int width, int height) { + if (!dataChangedLocked(data)) return; synchronized (mLock) { mImageWidth = width; mImageHeight = height; - mDataUri = dataUri; - mBitmap = null; + mData = data; + setBitmapLocked(null); refreshSampleSizeLocked(); } invalidateSelf(); } + private void setBitmapLocked(Bitmap b) { + if (b == mBitmap) { + return; + } + if (mBitmap != null) { + sBitmapPool.put(mBitmap); + } + mBitmap = b; + } + @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); @@ -148,7 +162,8 @@ public class AutoThumbnailDrawable extends Drawable { } else { scale = (float) dwidth / (float) vwidth; } - return (int) (scale + .5f); + int result = Math.round(scale); + return result > 0 ? result : 1; } private void refreshSampleSizeLocked() { @@ -208,62 +223,78 @@ public class AutoThumbnailDrawable extends Drawable { private final Runnable mLoadBitmap = new Runnable() { @Override public void run() { - // TODO: Use bitmap pool - String data; - int sampleSize; + T data; + synchronized (mLock) { + data = mData; + } + int preferredSampleSize = 1; + byte[] preferred = getPreferredImageBytes(data); + boolean hasPreferred = (preferred != null && preferred.length > 0); + if (hasPreferred) { + mOptions.inJustDecodeBounds = true; + BitmapFactory.decodeByteArray(preferred, 0, preferred.length, mOptions); + mOptions.inJustDecodeBounds = false; + } + int sampleSize, width, height; synchronized (mLock) { - data = mDataUri; - sampleSize = calculateSampleSizeLocked(mImageWidth, mImageHeight); - mSampleSize = sampleSize; + if (dataChangedLocked(data)) { + return; + } + width = mImageWidth; + height = mImageHeight; + if (hasPreferred) { + preferredSampleSize = calculateSampleSizeLocked( + mOptions.outWidth, mOptions.outHeight); + } + sampleSize = calculateSampleSizeLocked(width, height); mIsQueued = false; } - FileInputStream fis = null; + Bitmap b = null; + InputStream is = null; try { - ExifInterface exif = new ExifInterface(data); - if (exif.hasThumbnail()) { - byte[] thumbnail = exif.getThumbnail(); - mOptions.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(thumbnail, 0, - thumbnail.length, mOptions); - int exifThumbSampleSize = calculateSampleSizeLocked( - mOptions.outWidth, mOptions.outHeight); - mOptions.inJustDecodeBounds = false; - mOptions.inSampleSize = exifThumbSampleSize; - mBitmap = BitmapFactory.decodeByteArray(thumbnail, 0, - thumbnail.length, mOptions); - if (mBitmap != null) { - synchronized (mLock) { - if (TextUtils.equals(data, mDataUri)) { - scheduleSelf(mUpdateBitmap, 0); - } - } - return; + if (hasPreferred) { + mOptions.inSampleSize = preferredSampleSize; + mOptions.inBitmap = sBitmapPool.get( + mOptions.outWidth / preferredSampleSize, + mOptions.outHeight / preferredSampleSize); + b = BitmapFactory.decodeByteArray(preferred, 0, preferred.length, mOptions); + if (mOptions.inBitmap != null && b != mOptions.inBitmap) { + sBitmapPool.put(mOptions.inBitmap); + mOptions.inBitmap = null; + } + } + if (b == null) { + is = getFallbackImageStream(data); + mOptions.inSampleSize = sampleSize; + mOptions.inBitmap = sBitmapPool.get(width / sampleSize, height / sampleSize); + b = BitmapFactory.decodeStream(is, null, mOptions); + if (mOptions.inBitmap != null && b != mOptions.inBitmap) { + sBitmapPool.put(mOptions.inBitmap); + mOptions.inBitmap = null; } } - fis = new FileInputStream(data); - FileDescriptor fd = fis.getFD(); - mOptions.inSampleSize = sampleSize; - mBitmap = BitmapFactory.decodeFileDescriptor(fd, null, mOptions); } catch (Exception e) { - Log.d("AsyncBitmap", "Failed to fetch bitmap", e); + Log.d(TAG, "Failed to fetch bitmap", e); return; } finally { try { - if (fis != null) { - fis.close(); + if (is != null) { + is.close(); } } catch (Exception e) {} - } - synchronized (mLock) { - if (TextUtils.equals(data, mDataUri)) { - scheduleSelf(mUpdateBitmap, 0); + if (b != null) { + synchronized (mLock) { + if (!dataChangedLocked(data)) { + setBitmapLocked(b); + scheduleSelf(mUpdateBitmap, 0); + } + } } } } }; private final Runnable mUpdateBitmap = new Runnable() { - @Override public void run() { synchronized (AutoThumbnailDrawable.this) { diff --git a/src/com/android/photos/drawables/DataUriThumbnailDrawable.java b/src/com/android/photos/drawables/DataUriThumbnailDrawable.java new file mode 100644 index 000000000..c83b0c8fa --- /dev/null +++ b/src/com/android/photos/drawables/DataUriThumbnailDrawable.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.photos.drawables; + +import android.media.ExifInterface; +import android.text.TextUtils; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +public class DataUriThumbnailDrawable extends AutoThumbnailDrawable<String> { + + @Override + protected byte[] getPreferredImageBytes(String data) { + byte[] thumbnail = null; + try { + ExifInterface exif = new ExifInterface(data); + if (exif.hasThumbnail()) { + thumbnail = exif.getThumbnail(); + } + } catch (IOException e) { } + return thumbnail; + } + + @Override + protected InputStream getFallbackImageStream(String data) { + try { + return new FileInputStream(data); + } catch (FileNotFoundException e) { + return null; + } + } + + @Override + protected boolean dataChangedLocked(String data) { + return !TextUtils.equals(mData, data); + } +} diff --git a/src/com/android/photos/drawables/MtpThumbnailDrawable.java b/src/com/android/photos/drawables/MtpThumbnailDrawable.java new file mode 100644 index 000000000..e35e06943 --- /dev/null +++ b/src/com/android/photos/drawables/MtpThumbnailDrawable.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.photos.drawables; + +import android.mtp.MtpDevice; +import android.mtp.MtpObjectInfo; + +import com.android.gallery3d.ingest.MtpDeviceIndex; + +import java.io.InputStream; + +public class MtpThumbnailDrawable extends AutoThumbnailDrawable<MtpObjectInfo> { + public void setImage(MtpObjectInfo data) { + if (data == null) { + setImage(null, 0, 0); + } else { + setImage(data, data.getImagePixWidth(), data.getImagePixHeight()); + } + } + + @Override + protected byte[] getPreferredImageBytes(MtpObjectInfo data) { + if (data == null) { + return null; + } + MtpDevice device = MtpDeviceIndex.getInstance().getDevice(); + if (device != null) { + return device.getThumbnail(data.getObjectHandle()); + } else { + return null; + } + } + + @Override + protected InputStream getFallbackImageStream(MtpObjectInfo data) { + // No fallback + return null; + } + + @Override + protected boolean dataChangedLocked(MtpObjectInfo data) { + // We only fetch the MtpObjectInfo once when creating + // the index so checking the reference is enough + return mData == data; + } + +} |