1c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu/* 2c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * Copyright (C) 2013 The Android Open Source Project 3c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * 4c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * Licensed under the Apache License, Version 2.0 (the "License"); 5c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * you may not use this file except in compliance with the License. 6c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * You may obtain a copy of the License at 7c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * 8c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * http://www.apache.org/licenses/LICENSE-2.0 9c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * 10c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * Unless required by applicable law or agreed to in writing, software 11c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * distributed under the License is distributed on an "AS IS" BASIS, 12c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * See the License for the specific language governing permissions and 14c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu * limitations under the License. 15c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu */ 16c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 17c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescupackage com.android.gallery3d.ingest.ui; 18c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 19f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport com.android.gallery3d.R; 20f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport com.android.gallery3d.ingest.data.BitmapWithMetadata; 21f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport com.android.gallery3d.ingest.data.IngestObjectInfo; 22f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport com.android.gallery3d.ingest.data.MtpBitmapFetch; 23f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescuimport com.android.gallery3d.ingest.data.MtpDeviceIndex; 24f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 25c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescuimport android.content.Context; 26f349b1b2b2d3a1c024a979328e89c112d3e2cf25Bobby Georgescuimport android.graphics.Canvas; 27573dfae59a96663b6ff6e47b4c7db326c651a3cfBobby Georgescuimport android.graphics.Matrix; 28f349b1b2b2d3a1c024a979328e89c112d3e2cf25Bobby Georgescuimport android.graphics.drawable.Drawable; 29c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescuimport android.mtp.MtpDevice; 3037faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescuimport android.os.Handler; 3137faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescuimport android.os.HandlerThread; 3237faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescuimport android.os.Looper; 3337faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescuimport android.os.Message; 34c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescuimport android.util.AttributeSet; 35c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescuimport android.widget.ImageView; 36c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 3737faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescuimport java.lang.ref.WeakReference; 38c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 39f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu/** 40f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu * View for images from an MTP devices 41f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu */ 4237faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescupublic class MtpImageView extends ImageView { 43f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu // We will use the thumbnail for images larger than this threshold 44f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private static final int MAX_FULLSIZE_PREVIEW_SIZE = 8388608; // 8 megabytes 45baa68886db66f4beb6a07e4441b122975b778f1cBobby Georgescu 46f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private int mObjectHandle; 47f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private int mGeneration; 48c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 49f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private WeakReference<MtpImageView> mWeakReference = new WeakReference<MtpImageView>(this); 50f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private Object mFetchLock = new Object(); 51f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private boolean mFetchPending = false; 52f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private IngestObjectInfo mFetchObjectInfo; 53f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private MtpDevice mFetchDevice; 54f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private Object mFetchResult; 55f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private Drawable mOverlayIcon; 56f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private boolean mShowOverlayIcon; 5737faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescu 58f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private static final FetchImageHandler sFetchHandler = FetchImageHandler.createOnNewThread(); 59f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private static final ShowImageHandler sFetchCompleteHandler = new ShowImageHandler(); 6037faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescu 61f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private void init() { 62f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu showPlaceholder(); 63f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 64c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 65f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public MtpImageView(Context context) { 66f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu super(context); 67f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu init(); 68f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 69c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 70f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public MtpImageView(Context context, AttributeSet attrs) { 71f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu super(context, attrs); 72f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu init(); 73f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 74c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 75f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public MtpImageView(Context context, AttributeSet attrs, int defStyle) { 76f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu super(context, attrs, defStyle); 77f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu init(); 78f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 79c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 80f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private void showPlaceholder() { 81f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu setImageResource(android.R.color.transparent); 82f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 83c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 84f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public void setMtpDeviceAndObjectInfo(MtpDevice device, IngestObjectInfo object, int gen) { 85f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int handle = object.getObjectHandle(); 86f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (handle == mObjectHandle && gen == mGeneration) { 87f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 88f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 89f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu cancelLoadingAndClear(); 90f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu showPlaceholder(); 91f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mGeneration = gen; 92f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mObjectHandle = handle; 93f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mShowOverlayIcon = MtpDeviceIndex.SUPPORTED_VIDEO_FORMATS.contains(object.getFormat()); 94f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (mShowOverlayIcon && mOverlayIcon == null) { 95f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mOverlayIcon = getResources().getDrawable(R.drawable.ic_control_play); 96f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu updateOverlayIconBounds(); 97c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu } 98f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu synchronized (mFetchLock) { 99f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mFetchObjectInfo = object; 100f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mFetchDevice = device; 101f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (mFetchPending) { 102f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 103f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 104f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mFetchPending = true; 105f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu sFetchHandler.sendMessage( 106f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu sFetchHandler.obtainMessage(0, mWeakReference)); 107f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 108f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 109c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 110f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected Object fetchMtpImageDataFromDevice(MtpDevice device, IngestObjectInfo info) { 111f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (info.getCompressedSize() <= MAX_FULLSIZE_PREVIEW_SIZE 112f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu && MtpDeviceIndex.SUPPORTED_IMAGE_FORMATS.contains(info.getFormat())) { 113f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return MtpBitmapFetch.getFullsize(device, info); 114f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 115f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return new BitmapWithMetadata(MtpBitmapFetch.getThumbnail(device, info), 0); 116c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu } 117f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 118c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 119f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private float mLastBitmapWidth; 120f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private float mLastBitmapHeight; 121f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private int mLastRotationDegrees; 122f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private Matrix mDrawMatrix = new Matrix(); 123573dfae59a96663b6ff6e47b4c7db326c651a3cfBobby Georgescu 124f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private void updateDrawMatrix() { 125f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mDrawMatrix.reset(); 126f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu float dwidth; 127f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu float dheight; 128f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu float vheight = getHeight(); 129f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu float vwidth = getWidth(); 130f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu float scale; 131f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu boolean rotated90 = (mLastRotationDegrees % 180 != 0); 132f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (rotated90) { 133f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu dwidth = mLastBitmapHeight; 134f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu dheight = mLastBitmapWidth; 135f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 136f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu dwidth = mLastBitmapWidth; 137f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu dheight = mLastBitmapHeight; 138f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 139f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (dwidth <= vwidth && dheight <= vheight) { 140f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu scale = 1.0f; 141f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 142f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu scale = Math.min(vwidth / dwidth, vheight / dheight); 143f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 144f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mDrawMatrix.setScale(scale, scale); 145f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (rotated90) { 146f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mDrawMatrix.postTranslate(-dheight * scale * 0.5f, 147f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu -dwidth * scale * 0.5f); 148f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mDrawMatrix.postRotate(mLastRotationDegrees); 149f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mDrawMatrix.postTranslate(dwidth * scale * 0.5f, 150f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu dheight * scale * 0.5f); 151573dfae59a96663b6ff6e47b4c7db326c651a3cfBobby Georgescu } 152f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mDrawMatrix.postTranslate((vwidth - dwidth * scale) * 0.5f, 153f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu (vheight - dheight * scale) * 0.5f); 154f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (!rotated90 && mLastRotationDegrees > 0) { 155f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu // rotated by a multiple of 180 156f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mDrawMatrix.postRotate(mLastRotationDegrees, vwidth / 2, vheight / 2); 157f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 158f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu setImageMatrix(mDrawMatrix); 159f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 160573dfae59a96663b6ff6e47b4c7db326c651a3cfBobby Georgescu 161f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private static final int OVERLAY_ICON_SIZE_DENOMINATOR = 4; 162f349b1b2b2d3a1c024a979328e89c112d3e2cf25Bobby Georgescu 163f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private void updateOverlayIconBounds() { 164f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int iheight = mOverlayIcon.getIntrinsicHeight(); 165f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int iwidth = mOverlayIcon.getIntrinsicWidth(); 166f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int vheight = getHeight(); 167f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu int vwidth = getWidth(); 168f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu float scaleHeight = ((float) vheight) / (iheight * OVERLAY_ICON_SIZE_DENOMINATOR); 169f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu float scaleWidth = ((float) vwidth) / (iwidth * OVERLAY_ICON_SIZE_DENOMINATOR); 170f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (scaleHeight >= 1f && scaleWidth >= 1f) { 171f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mOverlayIcon.setBounds((vwidth - iwidth) / 2, 172f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu (vheight - iheight) / 2, 173f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu (vwidth + iwidth) / 2, 174f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu (vheight + iheight) / 2); 175f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 176f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu float scale = Math.min(scaleHeight, scaleWidth); 177f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mOverlayIcon.setBounds((int) (vwidth - scale * iwidth) / 2, 178f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu (int) (vheight - scale * iheight) / 2, 179f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu (int) (vwidth + scale * iwidth) / 2, 180f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu (int) (vheight + scale * iheight) / 2); 181f349b1b2b2d3a1c024a979328e89c112d3e2cf25Bobby Georgescu } 182f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 183f349b1b2b2d3a1c024a979328e89c112d3e2cf25Bobby Georgescu 184f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu @Override 185f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 186f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu super.onLayout(changed, left, top, right, bottom); 187f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (changed && getScaleType() == ScaleType.MATRIX) { 188f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu updateDrawMatrix(); 189f349b1b2b2d3a1c024a979328e89c112d3e2cf25Bobby Georgescu } 190f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (mShowOverlayIcon && changed && mOverlayIcon != null) { 191f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu updateOverlayIconBounds(); 192573dfae59a96663b6ff6e47b4c7db326c651a3cfBobby Georgescu } 193f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 194573dfae59a96663b6ff6e47b4c7db326c651a3cfBobby Georgescu 195f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu @Override 196f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected void onDraw(Canvas canvas) { 197f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu super.onDraw(canvas); 198f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (mShowOverlayIcon && mOverlayIcon != null) { 199f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mOverlayIcon.draw(canvas); 200c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu } 201f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 202c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 203f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected void onMtpImageDataFetchedFromDevice(Object result) { 204f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu BitmapWithMetadata bitmapWithMetadata = (BitmapWithMetadata) result; 205f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (getScaleType() == ScaleType.MATRIX) { 206f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mLastBitmapHeight = bitmapWithMetadata.bitmap.getHeight(); 207f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mLastBitmapWidth = bitmapWithMetadata.bitmap.getWidth(); 208f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mLastRotationDegrees = bitmapWithMetadata.rotationDegrees; 209f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu updateDrawMatrix(); 210f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } else { 211f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu setRotation(bitmapWithMetadata.rotationDegrees); 21237faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescu } 213f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu setAlpha(0f); 214f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu setImageBitmap(bitmapWithMetadata.bitmap); 215f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu animate().alpha(1f); 216f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 217c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 218f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu protected void cancelLoadingAndClear() { 219f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu synchronized (mFetchLock) { 220f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mFetchDevice = null; 221f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mFetchObjectInfo = null; 222f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu mFetchResult = null; 22337faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescu } 224f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu animate().cancel(); 225f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu setImageResource(android.R.color.transparent); 226f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 22737faa3150feebccecd8872658af32bd88a0d2073Bobby Georgescu 228f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu @Override 229f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public void onDetachedFromWindow() { 230f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu cancelLoadingAndClear(); 231f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu super.onDetachedFromWindow(); 232f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 233c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 234f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private static class FetchImageHandler extends Handler { 235f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public FetchImageHandler(Looper l) { 236f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu super(l); 237f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 238c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 239f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public static FetchImageHandler createOnNewThread() { 240f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu HandlerThread t = new HandlerThread("MtpImageView Fetch"); 241f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu t.start(); 242f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return new FetchImageHandler(t.getLooper()); 243c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu } 244c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu 245f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu @Override 246f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public void handleMessage(Message msg) { 247f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu @SuppressWarnings("unchecked") 248f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get(); 249f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (parent == null) { 250f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 251f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 252f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu IngestObjectInfo objectInfo; 253f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpDevice device; 254f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu synchronized (parent.mFetchLock) { 255f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu parent.mFetchPending = false; 256f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu device = parent.mFetchDevice; 257f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu objectInfo = parent.mFetchObjectInfo; 258f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 259f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (device == null) { 260f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 261f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 262f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu Object result = parent.fetchMtpImageDataFromDevice(device, objectInfo); 263f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (result == null) { 264f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 265f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 266f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu synchronized (parent.mFetchLock) { 267f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (parent.mFetchObjectInfo != objectInfo) { 268f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 269c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu } 270f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu parent.mFetchResult = result; 271f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu parent.mFetchDevice = null; 272f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu parent.mFetchObjectInfo = null; 273f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu sFetchCompleteHandler.sendMessage( 274f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu sFetchCompleteHandler.obtainMessage(0, parent.mWeakReference)); 275f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 276f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 277f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 278f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu 279f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu private static class ShowImageHandler extends Handler { 280f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu @Override 281f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu public void handleMessage(Message msg) { 282f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu @SuppressWarnings("unchecked") 283f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get(); 284f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (parent == null) { 285f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 286f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 287f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu Object result; 288f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu synchronized (parent.mFetchLock) { 289f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu result = parent.mFetchResult; 290f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 291f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu if (result == null) { 292f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu return; 293f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 294f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu parent.onMtpImageDataFetchedFromDevice(result); 295c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu } 296f640d379259bb114a50e3200f49961b89d60f2c2Bobby Georgescu } 297c8a9e86919dca8938948f97efc3dcbe143e806bfBobby Georgescu} 298