summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorcretin45 <cretin45@gmail.com>2015-09-29 16:29:29 -0700
committerSteve Kondik <steve@cyngn.com>2016-11-09 00:33:10 -0800
commit5a82864e7cf42d3bd04bb167ebfa52d3e5deb1f6 (patch)
tree8c14729de11f59b21b8bc9237f84236b8f0ed41f /src/com
parentf549631a977d44b3cf378cf51de108ab022c7315 (diff)
downloadandroid_packages_apps_Snap-5a82864e7cf42d3bd04bb167ebfa52d3e5deb1f6.tar.gz
android_packages_apps_Snap-5a82864e7cf42d3bd04bb167ebfa52d3e5deb1f6.tar.bz2
android_packages_apps_Snap-5a82864e7cf42d3bd04bb167ebfa52d3e5deb1f6.zip
CameraNext: Use Glide for async bitmap loading
This is what Camera2 code uses. Addresses SAMBAR-766 CameraNext: Fix rotation not updated The thumbnail generated by Glide is not updated when user rotate the image manually. This is because exif is rewrite using nio mmap, however there is no nio unmap available in java. Even though the file channel is closed, the rotation modification is still in buffer, when Glide tries to dtermine the orientation of the image, it still reads the old data. Use force to ensure data is sync to disk and buffer flushed. HAM-1389 Fix memory leaks Two leaks were occuring. One was an unused Parameters in AndroidCameraManagerImpl that was holding onto excess PhotoModules. The second was Glide images for video previews that were never being cleared on recycle. issue-id: CYNGNOS-2731 CameraNext: don't call Glide to load image after Camera exits There is a race condition where the filmstrip can still be trying to load a new image just as the camera exit, and Glide gets upset if it is handed a destroyed activity context to work with. So just check for that condition and go home. Change-Id: I9e76ab40d23213c7a74c26779e345207d5fd7bae Ticket-Id: CRACKLING-1068
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/camera/AndroidCameraManagerImpl.java8
-rw-r--r--src/com/android/camera/CameraActivity.java15
-rwxr-xr-xsrc/com/android/camera/data/CameraDataAdapter.java11
-rw-r--r--src/com/android/camera/data/FixedFirstDataAdapter.java7
-rw-r--r--src/com/android/camera/data/FixedLastDataAdapter.java7
-rw-r--r--src/com/android/camera/data/InProgressDataWrapper.java5
-rw-r--r--src/com/android/camera/data/LocalData.java4
-rw-r--r--src/com/android/camera/data/LocalMediaData.java307
-rw-r--r--src/com/android/camera/data/SimpleViewData.java4
-rw-r--r--src/com/android/camera/exif/ExifInterface.java4
-rw-r--r--src/com/android/camera/ui/FilmStripView.java5
11 files changed, 164 insertions, 213 deletions
diff --git a/src/com/android/camera/AndroidCameraManagerImpl.java b/src/com/android/camera/AndroidCameraManagerImpl.java
index 521229951..b151c1914 100644
--- a/src/com/android/camera/AndroidCameraManagerImpl.java
+++ b/src/com/android/camera/AndroidCameraManagerImpl.java
@@ -106,9 +106,6 @@ class AndroidCameraManagerImpl implements CameraManager {
private CameraHandler mCameraHandler;
private android.hardware.Camera mCamera;
- // Used to retain a copy of Parameters for setting parameters.
- private Parameters mParamsToSet;
-
AndroidCameraManagerImpl() {
HandlerThread ht = new HandlerThread("Camera Handler Thread");
ht.start();
@@ -224,11 +221,6 @@ class AndroidCameraManagerImpl implements CameraManager {
if (mCamera != null) {
mParametersIsDirty = true;
-
- // Get a instance of Camera.Parameters for later use.
- if (mParamsToSet == null) {
- mParamsToSet = mCamera.getParameters();
- }
} else {
if (msg.obj != null) {
((CameraOpenErrorCallback) msg.obj).onDeviceOpenFailure(msg.arg1);
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 6b1d8d13f..87ebe60a4 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -116,6 +116,10 @@ import com.android.camera.util.PhotoSphereHelper;
import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper;
import com.android.camera.util.UsageStatistics;
import org.codeaurora.snapcam.R;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.GlideBuilder;
+import com.bumptech.glide.MemoryCategory;
+import com.bumptech.glide.load.engine.executor.FifoPriorityThreadPoolExecutor;
import java.io.File;
import java.io.IOException;
@@ -1539,8 +1543,7 @@ public class CameraActivity extends Activity
FilmStripView.ImageData.SIZE_FULL);
// Put a CameraPreviewData at the first position.
mWrappedDataAdapter = new FixedFirstDataAdapter(
- new CameraDataAdapter(new ColorDrawable(
- getResources().getColor(R.color.photo_placeholder))),
+ new CameraDataAdapter(R.color.photo_placeholder),
mCameraPreviewData);
mFilmStripView.setViewGap(
@@ -1610,13 +1613,17 @@ public class CameraActivity extends Activity
display.getSize(size);
int width = size.x;
int height = size.y;
-
int lower = Math.min(width, height);
-
int offset = lower * 7 / 100;
SETTING_LIST_WIDTH_1 = lower / 2 + offset;
SETTING_LIST_WIDTH_2 = lower / 2 - offset;
registerSDcardMountedReceiver();
+
+ if (!Glide.isSetup()) {
+ Glide.setup(new GlideBuilder(getApplicationContext())
+ .setResizeService(new FifoPriorityThreadPoolExecutor(2)));
+ Glide.get(getApplicationContext()).setMemoryCategory(MemoryCategory.HIGH);
+ }
}
private void setRotationAnimation() {
diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java
index 4b810a0fa..7059221b8 100755
--- a/src/com/android/camera/data/CameraDataAdapter.java
+++ b/src/com/android/camera/data/CameraDataAdapter.java
@@ -20,7 +20,6 @@ import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
-import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.MediaStore;
@@ -46,16 +45,16 @@ public class CameraDataAdapter implements LocalDataAdapter {
private LocalDataList mImages;
private Listener mListener;
- private Drawable mPlaceHolder;
+ private final int mPlaceHolderResourceId;
private int mSuggestedWidth = DEFAULT_DECODE_SIZE;
private int mSuggestedHeight = DEFAULT_DECODE_SIZE;
private LocalData mLocalDataToDelete;
- public CameraDataAdapter(Drawable placeHolder) {
+ public CameraDataAdapter(int placeholderResource) {
mImages = new LocalDataList();
- mPlaceHolder = placeHolder;
+ mPlaceHolderResourceId = placeholderResource;
}
@Override
@@ -94,14 +93,14 @@ public class CameraDataAdapter implements LocalDataAdapter {
}
@Override
- public View getView(Activity activity, int dataID) {
+ public View getView(Activity activity, int dataID, boolean inFullScreen) {
if (dataID >= mImages.size() || dataID < 0) {
return null;
}
return mImages.get(dataID).getView(
activity, mSuggestedWidth, mSuggestedHeight,
- mPlaceHolder.getConstantState().newDrawable(), this);
+ mPlaceHolderResourceId, this, inFullScreen);
}
@Override
diff --git a/src/com/android/camera/data/FixedFirstDataAdapter.java b/src/com/android/camera/data/FixedFirstDataAdapter.java
index aa2025234..a210cb00c 100644
--- a/src/com/android/camera/data/FixedFirstDataAdapter.java
+++ b/src/com/android/camera/data/FixedFirstDataAdapter.java
@@ -108,12 +108,13 @@ public class FixedFirstDataAdapter extends AbstractLocalDataAdapterWrapper
}
@Override
- public View getView(Activity activity, int dataID) {
+ public View getView(Activity activity, int dataID, boolean inFullScreen) {
if (dataID == 0) {
return mFirstData.getView(
- activity, mSuggestedWidth, mSuggestedHeight, null, null);
+ activity, mSuggestedWidth, mSuggestedHeight, R.color.photo_placeholder,
+ null, inFullScreen);
}
- return mAdapter.getView(activity, dataID - 1);
+ return mAdapter.getView(activity, dataID - 1, inFullScreen);
}
@Override
diff --git a/src/com/android/camera/data/FixedLastDataAdapter.java b/src/com/android/camera/data/FixedLastDataAdapter.java
index 4df0652e1..33fd20d75 100644
--- a/src/com/android/camera/data/FixedLastDataAdapter.java
+++ b/src/com/android/camera/data/FixedLastDataAdapter.java
@@ -111,14 +111,15 @@ public class FixedLastDataAdapter extends AbstractLocalDataAdapterWrapper {
}
@Override
- public View getView(Activity activity, int dataID) {
+ public View getView(Activity activity, int dataID, boolean inFullScreen) {
int totalNumber = mAdapter.getTotalNumber();
if (dataID < totalNumber) {
- return mAdapter.getView(activity, dataID);
+ return mAdapter.getView(activity, dataID, inFullScreen);
} else if (dataID == totalNumber) {
return mLastData.getView(activity,
- mSuggestedWidth, mSuggestedHeight, null, null);
+ mSuggestedWidth, mSuggestedHeight, R.color.photo_placeholder,
+ null, inFullScreen);
}
return null;
diff --git a/src/com/android/camera/data/InProgressDataWrapper.java b/src/com/android/camera/data/InProgressDataWrapper.java
index 9ce968e2f..f212b6929 100644
--- a/src/com/android/camera/data/InProgressDataWrapper.java
+++ b/src/com/android/camera/data/InProgressDataWrapper.java
@@ -50,8 +50,9 @@ public class InProgressDataWrapper implements LocalData {
@Override
public View getView(
Activity a, int width, int height,
- Drawable placeHolder, LocalDataAdapter adapter) {
- View v = mLocalData.getView(a, width, height, placeHolder, adapter);
+ int placeHolderResourceId, LocalDataAdapter adapter, boolean inFullScreen) {
+ View v = mLocalData.getView(a, width, height, placeHolderResourceId,
+ adapter, inFullScreen);
if (mHasProgressBar) {
// Return a framelayout with the progressbar and imageview.
diff --git a/src/com/android/camera/data/LocalData.java b/src/com/android/camera/data/LocalData.java
index da64fee30..c9d518d70 100644
--- a/src/com/android/camera/data/LocalData.java
+++ b/src/com/android/camera/data/LocalData.java
@@ -74,8 +74,8 @@ public interface LocalData extends FilmStripView.ImageData {
*/
public static final int LOCAL_IN_PROGRESS_DATA = 7;
- View getView(Activity a, int width, int height, Drawable placeHolder,
- LocalDataAdapter adapter);
+ View getView(Activity a, int width, int height, int placeHolderResourceId,
+ LocalDataAdapter adapter, boolean full);
/**
* Gets the date when this data is created. The returned date is also used
diff --git a/src/com/android/camera/data/LocalMediaData.java b/src/com/android/camera/data/LocalMediaData.java
index e77578b16..c32d6ccf9 100644
--- a/src/com/android/camera/data/LocalMediaData.java
+++ b/src/com/android/camera/data/LocalMediaData.java
@@ -18,19 +18,13 @@ package com.android.camera.data;
import android.app.Activity;
import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
-import android.os.AsyncTask;
import android.provider.MediaStore;
-import android.provider.MediaStore.Images;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
@@ -42,6 +36,9 @@ import com.android.camera.ui.FilmStripView;
import com.android.camera.util.CameraUtil;
import com.android.camera.util.PhotoSphereHelper;
import org.codeaurora.snapcam.R;
+import com.bumptech.glide.BitmapRequestBuilder;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.resource.bitmap.BitmapEncoder;
import java.io.File;
import java.text.DateFormat;
@@ -55,6 +52,13 @@ import java.util.Locale;
* return a bitmap.
*/
public abstract class LocalMediaData implements LocalData {
+
+ private static final int MEDIASTORE_THUMB_WIDTH = 512;
+ private static final int MEDIASTORE_THUMB_HEIGHT = 384;
+
+ // GL max texture size: keep bitmaps below this value.
+ private static final int MAXIMUM_TEXTURE_SIZE = 2048;
+
protected final long mContentId;
protected final String mTitle;
protected final String mMimeType;
@@ -68,12 +72,18 @@ public abstract class LocalMediaData implements LocalData {
protected final double mLatitude;
protected final double mLongitude;
+ protected ImageView mImageView;
+
/** The panorama metadata information of this media data. */
protected PhotoSphereHelper.PanoramaMetadata mPanoramaMetadata;
/** Used to load photo sphere metadata from image files. */
protected PanoramaMetadataLoader mPanoramaMetadataLoader = null;
+ private static final int JPEG_COMPRESS_QUALITY = 90;
+ private static final BitmapEncoder JPEG_ENCODER =
+ new BitmapEncoder(Bitmap.CompressFormat.JPEG, JPEG_COMPRESS_QUALITY);
+
/**
* Used for thumbnail loading optimization. True if this data has a
* corresponding visible view.
@@ -202,23 +212,25 @@ public abstract class LocalMediaData implements LocalData {
}
protected ImageView fillImageView(Context ctx, ImageView v,
- int decodeWidth, int decodeHeight, Drawable placeHolder,
- LocalDataAdapter adapter) {
- v.setScaleType(ImageView.ScaleType.FIT_XY);
- v.setImageDrawable(placeHolder);
-
- BitmapLoadTask task = getBitmapLoadTask(v, decodeWidth, decodeHeight,
- ctx.getContentResolver(), adapter);
- task.execute();
+ int decodeWidth, int decodeHeight, int placeHolderResourceId,
+ LocalDataAdapter adapter, boolean inFullScreen) {
+ Glide.with(ctx)
+ .loadFromMediaStore(getContentUri(), mMimeType, mDateModifiedInSeconds, 0)
+ .fitCenter()
+ .placeholder(placeHolderResourceId)
+ .into(v);
return v;
}
@Override
public View getView(Activity activity,
- int decodeWidth, int decodeHeight, Drawable placeHolder,
- LocalDataAdapter adapter) {
- return fillImageView(activity, new ImageView(activity),
- decodeWidth, decodeHeight, placeHolder, adapter);
+ int decodeWidth, int decodeHeight, int placeHolderResourceId,
+ LocalDataAdapter adapter, boolean inFullScreen) {
+
+ mImageView = new ImageView(activity);
+
+ return fillImageView(activity, mImageView,
+ decodeWidth, decodeHeight, placeHolderResourceId, adapter, inFullScreen);
}
@Override
@@ -233,6 +245,10 @@ public abstract class LocalMediaData implements LocalData {
synchronized (mUsing) {
mUsing = false;
}
+
+ if (mImageView != null) {
+ Glide.clear(mImageView);
+ }
}
@Override
@@ -280,10 +296,6 @@ public abstract class LocalMediaData implements LocalData {
@Override
public abstract int getViewType();
- protected abstract BitmapLoadTask getBitmapLoadTask(
- ImageView v, int decodeWidth, int decodeHeight,
- ContentResolver resolver, LocalDataAdapter adapter);
-
public static final class PhotoData extends LocalMediaData {
private static final String TAG = "CAM_PhotoData";
@@ -467,96 +479,63 @@ public abstract class LocalMediaData implements LocalData {
}
@Override
- protected BitmapLoadTask getBitmapLoadTask(
- ImageView v, int decodeWidth, int decodeHeight,
- ContentResolver resolver, LocalDataAdapter adapter) {
- return new PhotoBitmapLoadTask(v, decodeWidth, decodeHeight,
- resolver, adapter);
- }
-
- private final class PhotoBitmapLoadTask extends BitmapLoadTask {
- private final int mDecodeWidth;
- private final int mDecodeHeight;
- private final ContentResolver mResolver;
- private final LocalDataAdapter mAdapter;
-
- private boolean mNeedsRefresh;
-
- public PhotoBitmapLoadTask(ImageView v, int decodeWidth,
- int decodeHeight, ContentResolver resolver,
- LocalDataAdapter adapter) {
- super(v);
- mDecodeWidth = decodeWidth;
- mDecodeHeight = decodeHeight;
- mResolver = resolver;
- mAdapter = adapter;
- }
-
- @Override
- protected Bitmap doInBackground(Void... v) {
- int sampleSize = 1;
- if (mWidth > mDecodeWidth || mHeight > mDecodeHeight) {
- int heightRatio = Math.round((float) mHeight / (float) mDecodeHeight);
- int widthRatio = Math.round((float) mWidth / (float) mDecodeWidth);
- sampleSize = Math.max(heightRatio, widthRatio);
- }
-
- // For correctness, we need to double check the size here. The
- // good news is that decoding bounds take much less time than
- // decoding samples like < 1%.
- // TODO: better organize the decoding and sampling by using a
- // image cache.
- int decodedWidth = 0;
- int decodedHeight = 0;
- BitmapFactory.Options justBoundsOpts = new BitmapFactory.Options();
- justBoundsOpts.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(mPath, justBoundsOpts);
- if (justBoundsOpts.outWidth > 0 && justBoundsOpts.outHeight > 0) {
- decodedWidth = justBoundsOpts.outWidth;
- decodedHeight = justBoundsOpts.outHeight;
- }
-
- // If the width and height is valid and not matching the values
- // from MediaStore, then update the MediaStore. This only
- // happened when the MediaStore had been told a wrong data.
- if (decodedWidth > 0 && decodedHeight > 0 &&
- (decodedWidth != mWidth || decodedHeight != mHeight)) {
- ContentValues values = new ContentValues();
- values.put(Images.Media.WIDTH, decodedWidth);
- values.put(Images.Media.HEIGHT, decodedHeight);
- mResolver.update(getContentUri(), values, null, null);
- mNeedsRefresh = true;
- Log.w(TAG, "Uri " + getContentUri() + " has been updated with" +
- " correct size!");
- return null;
- }
+ protected ImageView fillImageView(Context context, final ImageView v, final int decodeWidth,
+ final int decodeHeight, int placeHolderResourceId, LocalDataAdapter adapter,
+ boolean inFullScreen) {
+ loadImage(context, v, decodeWidth, decodeHeight, placeHolderResourceId, inFullScreen);
+ return v;
+ }
- BitmapFactory.Options opts = new BitmapFactory.Options();
- opts.inSampleSize = sampleSize;
- opts.inTempStorage = DECODE_TEMP_STORAGE;
- if (isCancelled() || !isUsing()) {
- return null;
- }
- Bitmap b = BitmapFactory.decodeFile(mPath, opts);
+ private void loadImage(Context context, ImageView imageView, int decodeWidth,
+ int decodeHeight, int placeHolderResourceId, boolean inFullScreen) {
- if (mOrientation != 0 && b != null) {
- if (isCancelled() || !isUsing()) {
- return null;
- }
- Matrix m = new Matrix();
- m.setRotate(mOrientation);
- b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, false);
- }
- return b;
+ if (decodeWidth <= 0 || decodeHeight <=0) {
+ return;
}
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- super.onPostExecute(bitmap);
- if (mNeedsRefresh && mAdapter != null) {
- mAdapter.refresh(mResolver, getContentUri());
- }
+ final int overrideWidth;
+ final int overrideHeight;
+ final BitmapRequestBuilder<Uri, Bitmap> thumbnailRequest;
+ if (inFullScreen) {
+ // Load up to the maximum size Bitmap we can render.
+ overrideWidth = Math.min(getWidth(), MAXIMUM_TEXTURE_SIZE);
+ overrideHeight = Math.min(getHeight(), MAXIMUM_TEXTURE_SIZE);
+
+ // Load two thumbnails, first the small low quality thumb from the media store,
+ // then a medium quality thumbWidth/thumbHeight image. Using two thumbnails ensures
+ // we don't flicker to grey while we load the maximum size image.
+ thumbnailRequest = loadUri(context)
+ .override(decodeWidth, decodeHeight)
+ .fitCenter()
+ .thumbnail(loadMediaStoreThumb(context));
+ } else {
+ // Load a medium quality thumbWidth/thumbHeight image.
+ overrideWidth = decodeWidth;
+ overrideHeight = decodeHeight;
+
+ // Load a single small low quality thumbnail from the media store.
+ thumbnailRequest = loadMediaStoreThumb(context);
}
+ loadUri(context)
+ .placeholder(placeHolderResourceId)
+ .fitCenter()
+ .override(overrideWidth, overrideHeight)
+ .thumbnail(thumbnailRequest)
+ .into(imageView);
+ }
+
+ /** Loads a thumbnail with a size targeted to use MediaStore.Images.Thumbnails. */
+ private BitmapRequestBuilder<Uri, Bitmap> loadMediaStoreThumb(Context context) {
+ return loadUri(context)
+ .override(MEDIASTORE_THUMB_WIDTH, MEDIASTORE_THUMB_HEIGHT);
+ }
+
+ /** Loads an image using a MediaStore Uri with our default options. */
+ private BitmapRequestBuilder<Uri, Bitmap> loadUri(Context context) {
+ return Glide.with(context)
+ .loadFromMediaStore(getContentUri(), mMimeType, mDateModifiedInSeconds, mOrientation)
+ .asBitmap()
+ .encoder(JPEG_ENCODER);
}
@Override
@@ -750,17 +729,51 @@ public abstract class LocalMediaData implements LocalData {
}
@Override
+ protected ImageView fillImageView(Context context, final ImageView v, final int decodeWidth,
+ final int decodeHeight, int placeHolderResourceId, LocalDataAdapter adapter,
+ boolean inFullScreen) {
+
+ //TODO: Figure out why these can be <= 0.
+ if (decodeWidth <= 0 || decodeHeight <=0) {
+ return v;
+ }
+
+ // band-aid over a race condition where the filmstrip is in the process
+ // of refreshing because of new media just as the camera exits
+ if ((context instanceof Activity) && ((Activity)context).isDestroyed()) {
+ Log.d(TAG, "aborted fillImageView because context was destroyed");
+ return v;
+ }
+
+ Glide.with(context)
+ .loadFromMediaStore(getContentUri(), mMimeType, mDateModifiedInSeconds, 0)
+ .asBitmap()
+ .encoder(JPEG_ENCODER)
+ .thumbnail(Glide.with(context)
+ .loadFromMediaStore(getContentUri(), mMimeType, mDateModifiedInSeconds, 0)
+ .asBitmap()
+ .encoder(JPEG_ENCODER)
+ .override(MEDIASTORE_THUMB_WIDTH, MEDIASTORE_THUMB_HEIGHT))
+ .placeholder(placeHolderResourceId)
+ .fitCenter()
+ .override(decodeWidth, decodeHeight)
+ .into(v);
+
+ return v;
+ }
+
+ @Override
public View getView(final Activity activity,
- int decodeWidth, int decodeHeight, Drawable placeHolder,
- LocalDataAdapter adapter) {
+ int decodeWidth, int decodeHeight, int placeHolderResourceId,
+ LocalDataAdapter adapter, boolean inFullScreen) {
// ImageView for the bitmap.
- ImageView iv = new ImageView(activity);
- iv.setLayoutParams(new FrameLayout.LayoutParams(
+ mImageView = new ImageView(activity);
+ mImageView.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER));
- fillImageView(activity, iv, decodeWidth, decodeHeight, placeHolder,
- adapter);
+ fillImageView(activity, mImageView, decodeWidth, decodeHeight, placeHolderResourceId,
+ adapter, inFullScreen);
// ImageView for the play icon.
ImageView icon = new ImageView(activity);
@@ -777,7 +790,7 @@ public abstract class LocalMediaData implements LocalData {
});
FrameLayout f = new FrameLayout(activity);
- f.addView(iv);
+ f.addView(mImageView);
f.addView(icon);
return f;
}
@@ -788,46 +801,6 @@ public abstract class LocalMediaData implements LocalData {
}
@Override
- protected BitmapLoadTask getBitmapLoadTask(
- ImageView v, int decodeWidth, int decodeHeight,
- ContentResolver resolver, LocalDataAdapter adapter) {
- return new VideoBitmapLoadTask(v);
- }
-
- private final class VideoBitmapLoadTask extends BitmapLoadTask {
-
- public VideoBitmapLoadTask(ImageView v) {
- super(v);
- }
-
- @Override
- protected Bitmap doInBackground(Void... v) {
- if (isCancelled() || !isUsing()) {
- return null;
- }
- MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- Bitmap bitmap = null;
- try {
- retriever.setDataSource(mPath);
- byte[] data = retriever.getEmbeddedPicture();
- if (!isCancelled() && isUsing()) {
- if (data != null) {
- bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
- }
- if (bitmap == null) {
- bitmap = retriever.getFrameAtTime();
- }
- }
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "MediaMetadataRetriever.setDataSource() fail:"
- + e.getMessage());
- }
- retriever.release();
- return bitmap;
- }
- }
-
- @Override
public boolean rotate90Degrees(Context context, LocalDataAdapter adapter,
int currentDataId, boolean clockwise) {
// We don't support rotation for video data.
@@ -836,30 +809,4 @@ public abstract class LocalMediaData implements LocalData {
}
}
- /**
- * An {@link AsyncTask} class that loads the bitmap in the background
- * thread. Sub-classes should implement their own
- * {@code BitmapLoadTask#doInBackground(Void...)}."
- */
- protected abstract class BitmapLoadTask extends AsyncTask<Void, Void, Bitmap> {
- protected ImageView mView;
-
- protected BitmapLoadTask(ImageView v) {
- mView = v;
- }
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- if (!isUsing()) {
- return;
- }
- if (bitmap == null) {
- Log.e(TAG, "Failed decoding bitmap for file:" + mPath);
- return;
- }
- BitmapDrawable d = new BitmapDrawable(bitmap);
- mView.setScaleType(ImageView.ScaleType.FIT_XY);
- mView.setImageDrawable(d);
- }
- }
}
diff --git a/src/com/android/camera/data/SimpleViewData.java b/src/com/android/camera/data/SimpleViewData.java
index ba4459415..18c4af640 100644
--- a/src/com/android/camera/data/SimpleViewData.java
+++ b/src/com/android/camera/data/SimpleViewData.java
@@ -120,8 +120,8 @@ public class SimpleViewData implements LocalData {
}
@Override
- public View getView(Activity activity, int width, int height, Drawable placeHolder,
- LocalDataAdapter adapter) {
+ public View getView(Activity activity, int width, int height, int placeHolderResourceId,
+ LocalDataAdapter adapter, boolean inFullScreen) {
return mView;
}
diff --git a/src/com/android/camera/exif/ExifInterface.java b/src/com/android/camera/exif/ExifInterface.java
index 0f495f227..3049d2680 100644
--- a/src/com/android/camera/exif/ExifInterface.java
+++ b/src/com/android/camera/exif/ExifInterface.java
@@ -36,6 +36,7 @@ import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel.MapMode;
+import java.nio.MappedByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -1039,11 +1040,12 @@ public class ExifInterface {
}
// Map only exif header into memory.
- ByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, exifSize);
+ MappedByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, exifSize);
// Attempt to overwrite tag values without changing lengths (avoids
// file copy).
ret = rewriteExif(buf, tags);
+ buf.force();
} catch (IOException e) {
closeSilently(file);
throw e;
diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java
index 3ac0bf6d9..47f480e57 100644
--- a/src/com/android/camera/ui/FilmStripView.java
+++ b/src/com/android/camera/ui/FilmStripView.java
@@ -281,10 +281,11 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
*
* @param activity The {@link Activity} context to create the view.
* @param dataID The ID of the image data to be presented.
+ * @param inFullScreen if the filmstrip is in fullscreen
* @return The view representing the image data. Null if unavailable or
* the {@code dataID} is out of range.
*/
- public View getView(Activity activity, int dataID);
+ public View getView(Activity activity, int dataID, boolean inFullScreen);
/**
* Returns the {@link ImageData} specified by the ID.
@@ -923,7 +924,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener {
return null;
}
data.prepare();
- View v = mDataAdapter.getView(mActivity, dataID);
+ View v = mDataAdapter.getView(mActivity, dataID, inFullScreen());
if (v == null) {
return null;
}