summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mike Lockwood <lockwood@android.com> 2010-06-10 14:21:53 -0700
committer Android (Google) Code Review <android-gerrit@google.com> 2010-06-10 14:21:53 -0700
commitaefed3626efeccf87692aba5b7a1aafe07a25308 (patch)
tree5f695b9e9539ac369b9c07efd05563f228dd1e6b
parenta876b851fa5d6f63c6356f67122ff53dff799b22 (diff)
parent99b3452f404e1574508665ebb71362766d362603 (diff)
Merge changes I99b3452f,Idda56860
* changes: CameraBrowser: Display thumbnails for camera images. MTP: Add support for retrieving thumbnails to MTP content provider.
-rw-r--r--core/java/android/provider/Mtp.java6
-rw-r--r--media/java/android/media/MtpCursor.java2
-rw-r--r--media/mtp/MtpCursor.cpp29
-rw-r--r--media/mtp/MtpCursor.h1
-rw-r--r--media/mtp/MtpDataPacket.cpp37
-rw-r--r--media/mtp/MtpDataPacket.h1
-rw-r--r--media/mtp/MtpDevice.cpp14
-rw-r--r--media/mtp/MtpDevice.h1
-rw-r--r--media/tests/CameraBrowser/res/layout/object_info.xml3
-rw-r--r--media/tests/CameraBrowser/res/layout/object_list.xml33
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java54
-rw-r--r--media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java18
12 files changed, 185 insertions, 14 deletions
diff --git a/core/java/android/provider/Mtp.java b/core/java/android/provider/Mtp.java
index ec2698f8975f..3906d230e8cf 100644
--- a/core/java/android/provider/Mtp.java
+++ b/core/java/android/provider/Mtp.java
@@ -152,6 +152,12 @@ public final class Mtp
public static final String THUMB_HEIGHT = "thumb_height";
/**
+ * The object's thumbnail.
+ * <P>Type: BLOB</P>
+ */
+ public static final String THUMB = "thumb";
+
+ /**
* The width of the object in pixels.
* <P>Type: INTEGER</P>
*/
diff --git a/media/java/android/media/MtpCursor.java b/media/java/android/media/MtpCursor.java
index baf3c12bedb5..cf3bc09db25f 100644
--- a/media/java/android/media/MtpCursor.java
+++ b/media/java/android/media/MtpCursor.java
@@ -159,6 +159,7 @@ public final class MtpCursor extends AbstractWindowedCursor {
private static final int OBJECT_DATE_CREATED = 218;
private static final int OBJECT_DATE_MODIFIED = 219;
private static final int OBJECT_KEYWORDS = 220;
+ private static final int OBJECT_THUMB = 221;
private static HashMap<String, Integer> sDeviceProjectionMap;
private static HashMap<String, Integer> sStorageProjectionMap;
@@ -196,6 +197,7 @@ public final class MtpCursor extends AbstractWindowedCursor {
sObjectProjectionMap.put(Mtp.Object.DATE_CREATED, new Integer(OBJECT_DATE_CREATED));
sObjectProjectionMap.put(Mtp.Object.DATE_MODIFIED, new Integer(OBJECT_DATE_MODIFIED));
sObjectProjectionMap.put(Mtp.Object.KEYWORDS, new Integer(OBJECT_KEYWORDS));
+ sObjectProjectionMap.put(Mtp.Object.THUMB, new Integer(OBJECT_THUMB));
sObjectProjectionMap.put(Mtp.Object.NAME, new Integer(OBJECT_NAME));
}
diff --git a/media/mtp/MtpCursor.cpp b/media/mtp/MtpCursor.cpp
index 42d9e38092d9..d63a5bf4d388 100644
--- a/media/mtp/MtpCursor.cpp
+++ b/media/mtp/MtpCursor.cpp
@@ -62,6 +62,7 @@ namespace android {
#define OBJECT_DATE_CREATED 218
#define OBJECT_DATE_MODIFIED 219
#define OBJECT_KEYWORDS 220
+#define OBJECT_THUMB 221
MtpCursor::MtpCursor(MtpClient* client, int queryType, int deviceID,
int storageID, int objectID, int columnCount, int* columns)
@@ -364,6 +365,10 @@ bool MtpCursor::fillObject(CursorWindow* window, MtpDevice* device,
if (!putString(window, objectInfo->mKeywords, row, i))
goto fail;
break;
+ case OBJECT_THUMB:
+ if (!putThumbnail(window, objectID, row, i))
+ goto fail;
+ break;
default:
LOGE("fillStorage: unknown column %d\n", mColumns[i]);
goto fail;
@@ -421,4 +426,28 @@ bool MtpCursor::putString(CursorWindow* window, const char* text, int row, int c
return true;
}
+bool MtpCursor::putThumbnail(CursorWindow* window, int objectID, int row, int column) {
+ MtpDevice* device = mClient->getDevice(mDeviceID);
+ int size;
+ void* thumbnail = device->getThumbnail(objectID, size);
+
+ LOGD("putThumbnail: %p, size: %d\n", thumbnail, size);
+ int offset = window->alloc(size);
+ if (!offset) {
+ window->freeLastRow();
+ LOGE("Failed allocating %u bytes for thumbnail", size);
+ return false;
+ }
+ if (size > 0)
+ window->copyIn(offset, (const uint8_t*)thumbnail, size);
+
+ // This must be updated after the call to alloc(), since that
+ // may move the field around in the window
+ field_slot_t * fieldSlot = window->getFieldSlot(row, column);
+ fieldSlot->type = FIELD_TYPE_BLOB;
+ fieldSlot->data.buffer.offset = offset;
+ fieldSlot->data.buffer.size = size;
+ return true;
+}
+
} // namespace android
diff --git a/media/mtp/MtpCursor.h b/media/mtp/MtpCursor.h
index 422f0c92e736..d51c0524c61e 100644
--- a/media/mtp/MtpCursor.h
+++ b/media/mtp/MtpCursor.h
@@ -68,6 +68,7 @@ private:
bool prepareRow(CursorWindow* window);
bool putLong(CursorWindow* window, int value, int row, int column);
bool putString(CursorWindow* window, const char* text, int row, int column);
+ bool putThumbnail(CursorWindow* window, int objectID, int row, int column);
};
}; // namespace android
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index f96284c3182a..d12425aa24a7 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -361,11 +361,24 @@ int MtpDataPacket::writeDataHeader(int fd, uint32_t length) {
#ifdef MTP_HOST
int MtpDataPacket::read(struct usb_endpoint *ep) {
// first read the header
- int ret = transfer(ep, mBuffer, mBufferSize);
-printf("MtpDataPacket::transfer returned %d\n", ret);
- if (ret >= 0)
- mPacketSize = ret;
- return ret;
+ int length = transfer(ep, mBuffer, mBufferSize);
+ if (length > MTP_CONTAINER_HEADER_SIZE) {
+ // look at the length field to see if the data spans multiple packets
+ uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
+ while (totalLength > length) {
+ allocate(length + mAllocationIncrement);
+ int ret = transfer(ep, mBuffer + length, mAllocationIncrement);
+ if (ret >= 0)
+ length += ret;
+ else {
+ length = ret;
+ break;
+ }
+ }
+ }
+ if (length >= 0)
+ mPacketSize = length;
+ return length;
}
int MtpDataPacket::write(struct usb_endpoint *ep) {
@@ -382,4 +395,18 @@ int MtpDataPacket::write(struct usb_endpoint *ep) {
#endif // MTP_HOST
+void* MtpDataPacket::getData(int& outLength) const {
+ int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
+ if (length > 0) {
+ void* result = malloc(length);
+ if (result) {
+ memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
+ outLength = length;
+ return result;
+ }
+ }
+ outLength = 0;
+ return NULL;
+}
+
} // namespace android
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 4e743b2d64d6..146ef642695e 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -99,6 +99,7 @@ public:
#endif
inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
+ void* getData(int& outLength) const;
};
}; // namespace android
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 5c39628eedff..ee352174e414 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -194,6 +194,20 @@ MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
return NULL;
}
+void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
+ mRequest.reset();
+ mRequest.setParameter(1, handle);
+ if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
+ MtpResponseCode ret = readResponse();
+ if (ret == MTP_RESPONSE_OK) {
+ return mData.getData(outLength);
+ }
+ }
+ outLength = 0;
+ return NULL;
+
+}
+
MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
mRequest.reset();
mRequest.setParameter(1, code);
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 226b247113b6..0ee930f7dd5b 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -70,6 +70,7 @@ public:
MtpStorageInfo* getStorageInfo(MtpStorageID storageID);
MtpObjectHandleList* getObjectHandles(MtpStorageID storageID, MtpObjectFormat format, MtpObjectHandle parent);
MtpObjectInfo* getObjectInfo(MtpObjectHandle handle);
+ void* getThumbnail(MtpObjectHandle handle, int& outLength);
MtpProperty* getDevicePropDesc(MtpDeviceProperty code);
diff --git a/media/tests/CameraBrowser/res/layout/object_info.xml b/media/tests/CameraBrowser/res/layout/object_info.xml
index f67397fa93f9..c7fd8301c14d 100644
--- a/media/tests/CameraBrowser/res/layout/object_info.xml
+++ b/media/tests/CameraBrowser/res/layout/object_info.xml
@@ -140,5 +140,8 @@
<TextView android:id="@+id/keywords"
style="@style/info_value" />
</TableRow>
+ <TableRow>
+ <ImageView android:id="@+id/thumbnail" />
+ </TableRow>
</TableLayout>
diff --git a/media/tests/CameraBrowser/res/layout/object_list.xml b/media/tests/CameraBrowser/res/layout/object_list.xml
new file mode 100644
index 000000000000..30c18bb8a077
--- /dev/null
+++ b/media/tests/CameraBrowser/res/layout/object_list.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ImageView android:id="@+id/thumbnail"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView android:id="@+id/name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:paddingLeft="6dip"
+ android:minHeight="?android:attr/listPreferredItemHeight" />
+</LinearLayout>
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
index da29be830634..019d58457a7c 100644
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectBrowser.java
@@ -17,16 +17,21 @@
package com.android.camerabrowser;
import android.app.ListActivity;
+import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Mtp;
import android.util.Log;
import android.view.View;
import android.widget.ListAdapter;
+import android.widget.ImageView;
import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
+import android.widget.ResourceCursorAdapter;
+import android.widget.TextView;
/**
* A list view displaying all objects within a container (folder or storage unit).
@@ -41,7 +46,12 @@ public class ObjectBrowser extends ListActivity {
private int mObjectID;
private static final String[] OBJECT_COLUMNS =
- new String[] { Mtp.Object._ID, Mtp.Object.NAME, Mtp.Object.FORMAT };
+ new String[] { Mtp.Object._ID, Mtp.Object.NAME, Mtp.Object.FORMAT, Mtp.Object.THUMB };
+
+ static final int ID_COLUMN = 0;
+ static final int NAME_COLUMN = 1;
+ static final int FORMAT_COLUMN = 2;
+ static final int THUMB_COLUMN = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -70,10 +80,7 @@ public class ObjectBrowser extends ListActivity {
startManagingCursor(c);
// Map Cursor columns to views defined in simple_list_item_1.xml
- mAdapter = new SimpleCursorAdapter(this,
- android.R.layout.simple_list_item_1, c,
- new String[] { Mtp.Object.NAME },
- new int[] { android.R.id.text1, android.R.id.text2 });
+ mAdapter = new ObjectCursorAdapter(this, c);
setListAdapter(mAdapter);
}
}
@@ -88,9 +95,9 @@ public class ObjectBrowser extends ListActivity {
long format = 0;
if (c != null && c.getCount() == 1) {
c.moveToFirst();
- long rowId = c.getLong(0);
- String name = c.getString(1);
- format = c.getLong(2);
+ long rowId = c.getLong(ID_COLUMN);
+ String name = c.getString(NAME_COLUMN);
+ format = c.getLong(FORMAT_COLUMN);
Log.d(TAG, "rowId: " + rowId + " name: " + name + " format: " + format);
}
if (format == Mtp.Object.FORMAT_JFIF) {
@@ -107,4 +114,33 @@ public class ObjectBrowser extends ListActivity {
startActivity(intent);
}
}
+
+ private class ObjectCursorAdapter extends ResourceCursorAdapter {
+
+ public ObjectCursorAdapter(Context context, Cursor c) {
+ super(context, R.layout.object_list, c);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ ImageView thumbView = (ImageView)view.findViewById(R.id.thumbnail);
+ TextView nameView = (TextView)view.findViewById(R.id.name);
+
+ // get the thumbnail
+ byte[] thumbnail = cursor.getBlob(THUMB_COLUMN);
+ if (thumbnail != null) {
+ Bitmap bitmap = BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length);
+ if (bitmap != null) {
+ thumbView.setImageBitmap(bitmap);
+ }
+ }
+
+ // get the name
+ String name = cursor.getString(NAME_COLUMN);
+ if (name == null) {
+ name = "";
+ }
+ nameView.setText(name);
+ }
+ }
}
diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
index 7055fc566fee..3033c543dc03 100644
--- a/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
+++ b/media/tests/CameraBrowser/src/com/android/camerabrowser/ObjectViewer.java
@@ -18,11 +18,14 @@ package com.android.camerabrowser;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Mtp;
import android.util.Log;
import android.view.View;
+import android.widget.ImageView;
import android.widget.TextView;
import java.util.Date;
@@ -52,6 +55,7 @@ public class ObjectViewer extends Activity {
Mtp.Object.DATE_CREATED,
Mtp.Object.DATE_MODIFIED,
Mtp.Object.KEYWORDS,
+ Mtp.Object.THUMB,
};
@Override
@@ -100,6 +104,20 @@ public class ObjectViewer extends Activity {
view.setText(date.toString());
view = (TextView)findViewById(R.id.keywords);
view.setText(c.getString(12));
+ byte[] thumbnail = c.getBlob(13);
+ if (thumbnail != null) {
+ Log.d(TAG, "got thumbnail, length: " + thumbnail.length);
+ for (int i = 0; i < 50; i++) {
+ Log.d(TAG, " " + Integer.toHexString(thumbnail[i]));
+ }
+
+ ImageView thumbView = (ImageView)findViewById(R.id.thumbnail);
+ Bitmap bitmap = BitmapFactory.decodeByteArray(thumbnail, 0, thumbnail.length);
+ Log.d(TAG, "bitmap: " + bitmap);
+ if (bitmap != null) {
+ thumbView.setImageBitmap(bitmap);
+ }
+ }
}
}
}