1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.gallery3d.data;
18
19import android.annotation.TargetApi;
20import android.content.Context;
21import android.graphics.Bitmap;
22import android.graphics.BitmapRegionDecoder;
23import android.hardware.usb.UsbDevice;
24import android.mtp.MtpObjectInfo;
25import android.net.Uri;
26import android.util.Log;
27
28import com.android.gallery3d.app.GalleryApp;
29import com.android.gallery3d.common.ApiHelper;
30import com.android.gallery3d.provider.GalleryProvider;
31import com.android.gallery3d.util.ThreadPool.Job;
32import com.android.gallery3d.util.ThreadPool.JobContext;
33
34import java.text.DateFormat;
35import java.util.Date;
36
37@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB_MR1)
38public class MtpImage extends MediaItem {
39    private static final String TAG = "MtpImage";
40
41    private final int mDeviceId;
42    private int mObjectId;
43    private int mObjectSize;
44    private long mDateTaken;
45    private String mFileName;
46    private final MtpContext mMtpContext;
47    private final MtpObjectInfo mObjInfo;
48    private final int mImageWidth;
49    private final int mImageHeight;
50    private final Context mContext;
51
52    MtpImage(Path path, GalleryApp application, int deviceId,
53            MtpObjectInfo objInfo, MtpContext mtpContext) {
54        super(path, nextVersionNumber());
55        mContext = application.getAndroidContext();
56        mDeviceId = deviceId;
57        mObjInfo = objInfo;
58        mObjectId = objInfo.getObjectHandle();
59        mObjectSize = objInfo.getCompressedSize();
60        mDateTaken = objInfo.getDateCreated();
61        mFileName = objInfo.getName();
62        mImageWidth = objInfo.getImagePixWidth();
63        mImageHeight = objInfo.getImagePixHeight();
64        mMtpContext = mtpContext;
65    }
66
67    MtpImage(Path path, GalleryApp app, int deviceId, int objectId, MtpContext mtpContext) {
68        this(path, app, deviceId, MtpDevice.getObjectInfo(mtpContext, deviceId, objectId),
69                mtpContext);
70    }
71
72    @Override
73    public long getDateInMs() {
74        return mDateTaken;
75    }
76
77    @Override
78    public Job<Bitmap> requestImage(int type) {
79        return new Job<Bitmap>() {
80            @Override
81            public Bitmap run(JobContext jc) {
82                byte[] thumbnail = mMtpContext.getMtpClient().getThumbnail(
83                        UsbDevice.getDeviceName(mDeviceId), mObjectId);
84                if (thumbnail == null) {
85                    Log.w(TAG, "decoding thumbnail failed");
86                    return null;
87                }
88                return DecodeUtils.decode(jc, thumbnail, null);
89            }
90        };
91    }
92
93    @Override
94    public Job<BitmapRegionDecoder> requestLargeImage() {
95        return new Job<BitmapRegionDecoder>() {
96            @Override
97            public BitmapRegionDecoder run(JobContext jc) {
98                byte[] bytes = mMtpContext.getMtpClient().getObject(
99                        UsbDevice.getDeviceName(mDeviceId), mObjectId, mObjectSize);
100                return DecodeUtils.createBitmapRegionDecoder(
101                        jc, bytes, 0, bytes.length, false);
102            }
103        };
104    }
105
106    public byte[] getImageData() {
107        return mMtpContext.getMtpClient().getObject(
108                UsbDevice.getDeviceName(mDeviceId), mObjectId, mObjectSize);
109    }
110
111    @Override
112    public boolean Import() {
113        return mMtpContext.copyFile(UsbDevice.getDeviceName(mDeviceId), mObjInfo);
114    }
115
116    @Override
117    public int getSupportedOperations() {
118        return SUPPORT_FULL_IMAGE | SUPPORT_IMPORT;
119    }
120
121    public void updateContent(MtpObjectInfo info) {
122        if (mObjectId != info.getObjectHandle() || mDateTaken != info.getDateCreated()) {
123            mObjectId = info.getObjectHandle();
124            mDateTaken = info.getDateCreated();
125            mDataVersion = nextVersionNumber();
126        }
127    }
128
129    @Override
130    public String getMimeType() {
131        // Currently only JPEG is supported in MTP.
132        return "image/jpeg";
133    }
134
135    @Override
136    public int getMediaType() {
137        return MEDIA_TYPE_IMAGE;
138    }
139
140    @Override
141    public long getSize() {
142        return mObjectSize;
143    }
144
145    @Override
146    public Uri getContentUri() {
147        return GalleryProvider.getUriFor(mContext, mPath);
148    }
149
150    @Override
151    public MediaDetails getDetails() {
152        MediaDetails details = super.getDetails();
153        DateFormat formater = DateFormat.getDateTimeInstance();
154        details.addDetail(MediaDetails.INDEX_TITLE, mFileName);
155        details.addDetail(MediaDetails.INDEX_DATETIME, formater.format(new Date(mDateTaken)));
156        details.addDetail(MediaDetails.INDEX_WIDTH, mImageWidth);
157        details.addDetail(MediaDetails.INDEX_HEIGHT, mImageHeight);
158        details.addDetail(MediaDetails.INDEX_SIZE, Long.valueOf(mObjectSize));
159        return details;
160    }
161
162    @Override
163    public int getWidth() {
164        return mImageWidth;
165    }
166
167    @Override
168    public int getHeight() {
169        return mImageHeight;
170    }
171}
172