Remove support for obsolete PTP content provider
This will be replaced by a new PTP host API in an upcoming commit. Change-Id: Ib914194e332b5c090cb8e34ed35bd691bc9f85d1 Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package android.provider;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* The PTP provider supports accessing content on PTP devices.
|
||||
* Currently the provider supports:
|
||||
* - enumerating the storage units, files and directories on PTP devices
|
||||
* - deleting files and directories on PTP devices
|
||||
* - importing a file from PTP device into the host device's storage
|
||||
* and adding it to the media provider
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class Ptp
|
||||
{
|
||||
private final static String TAG = "Ptp";
|
||||
|
||||
public static final String AUTHORITY = "ptp";
|
||||
|
||||
private static final String CONTENT_AUTHORITY_SLASH = "content://" + AUTHORITY + "/";
|
||||
private static final String CONTENT_AUTHORITY_DEVICE_SLASH = "content://" + AUTHORITY + "/device/";
|
||||
|
||||
/**
|
||||
* Contains list of all PTP devices
|
||||
* The BaseColumns._ID column contains a hardware specific identifier for the attached
|
||||
* USB device, and is not guaranteed to be persistent across USB disconnects.
|
||||
*/
|
||||
public static final class Device implements BaseColumns {
|
||||
|
||||
public static final Uri CONTENT_URI = Uri.parse(CONTENT_AUTHORITY_SLASH + "device");
|
||||
|
||||
public static Uri getContentUri(int deviceID) {
|
||||
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID);
|
||||
}
|
||||
|
||||
/**
|
||||
* The manufacturer of the device
|
||||
* <P>Type: TEXT</P>
|
||||
*/
|
||||
public static final String MANUFACTURER = "manufacturer";
|
||||
|
||||
/**
|
||||
* The model name of the device
|
||||
* <P>Type: TEXT</P>
|
||||
*/
|
||||
public static final String MODEL = "model";
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains list of storage units for an PTP device.
|
||||
* The BaseColumns._ID column contains the PTP StorageID for the storage unit.
|
||||
*/
|
||||
public static final class Storage implements BaseColumns {
|
||||
|
||||
public static Uri getContentUri(int deviceID) {
|
||||
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + "/storage");
|
||||
}
|
||||
|
||||
public static Uri getContentUri(int deviceID, long storageID) {
|
||||
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID + "/storage/" + storageID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage unit identifier
|
||||
* <P>Type: TEXT</P>
|
||||
*/
|
||||
public static final String IDENTIFIER = "identifier";
|
||||
|
||||
/**
|
||||
* Storage unit description
|
||||
* <P>Type: TEXT</P>
|
||||
*/
|
||||
public static final String DESCRIPTION = "description";
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains list of objects on a PTP device.
|
||||
* The columns in this table correspond directly to the ObjectInfo dataset
|
||||
* described in the PTP specification (PIMA 15740:2000).
|
||||
* The BaseColumns._ID column contains the object's PTP ObjectHandle.
|
||||
*/
|
||||
public static final class Object implements BaseColumns {
|
||||
|
||||
public static Uri getContentUri(int deviceID, long objectID) {
|
||||
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
|
||||
+ "/object/" + objectID);
|
||||
}
|
||||
|
||||
public static Uri getContentUriForObjectChildren(int deviceID, long objectID) {
|
||||
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
|
||||
+ "/object/" + objectID + "/child");
|
||||
}
|
||||
|
||||
public static Uri getContentUriForStorageChildren(int deviceID, long storageID) {
|
||||
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
|
||||
+ "/storage/" + storageID + "/child");
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for copying files from device to host.
|
||||
* Constructs a Uri based on the ID of the device and object for the source file,
|
||||
* and the path for the destination file.
|
||||
* When passed to the ContentProvider.insert() method, the file will be transferred
|
||||
* to the specified destination directory and insert() will return a content Uri
|
||||
* for the new file in the MediaProvider.
|
||||
* ContentProvider.insert() will throw IllegalArgumentException if the destination
|
||||
* path is not in the external storage or internal media directory.
|
||||
*/
|
||||
public static Uri getContentUriForImport(int deviceID, long objectID, String destPath) {
|
||||
if (destPath.length() == 0 || destPath.charAt(0) != '/') {
|
||||
throw new IllegalArgumentException(
|
||||
"destPath must be a full path in getContentUriForImport");
|
||||
}
|
||||
return Uri.parse(CONTENT_AUTHORITY_DEVICE_SLASH + deviceID
|
||||
+ "/import/" + objectID + "?" + destPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* The following columns correspond to the fields in the ObjectInfo dataset
|
||||
* as described in the PTP specification.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The ID of the storage unit containing the object.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String STORAGE_ID = "storage_id";
|
||||
|
||||
/**
|
||||
* The object's format. Can be any of the valid PTP object formats
|
||||
* as defined in the PTP specification.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String FORMAT = "format";
|
||||
|
||||
/**
|
||||
* The protection status of the object.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String PROTECTION_STATUS = "protection_status";
|
||||
|
||||
/**
|
||||
* The size of the object in bytes.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String SIZE = "size";
|
||||
|
||||
/**
|
||||
* The object's thumbnail format. Can be any of the valid PTP object formats
|
||||
* as defined in the PTP specification.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String THUMB_FORMAT = "thumb_format";
|
||||
|
||||
/**
|
||||
* The size of the object's thumbnail in bytes.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String THUMB_SIZE = "thumb_size";
|
||||
|
||||
/**
|
||||
* The width of the object's thumbnail in pixels.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String THUMB_WIDTH = "thumb_width";
|
||||
|
||||
/**
|
||||
* The height of the object's thumbnail in pixels.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
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>
|
||||
*/
|
||||
public static final String IMAGE_WIDTH = "image_width";
|
||||
|
||||
/**
|
||||
* The height of the object in pixels.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String IMAGE_HEIGHT = "image_height";
|
||||
|
||||
/**
|
||||
* The depth of the object in bits per pixel.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String IMAGE_DEPTH = "image_depth";
|
||||
|
||||
/**
|
||||
* The ID of the object's parent, or zero if the object
|
||||
* is in the root of its storage unit.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String PARENT = "parent";
|
||||
|
||||
/**
|
||||
* The association type for a container object.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String ASSOCIATION_TYPE = "association_type";
|
||||
|
||||
/**
|
||||
* Contains additional information about container objects.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String ASSOCIATION_DESC = "association_desc";
|
||||
|
||||
/**
|
||||
* The sequence number of the object, typically used for an association
|
||||
* containing images taken in sequence.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String SEQUENCE_NUMBER = "sequence_number";
|
||||
|
||||
/**
|
||||
* The name of the object.
|
||||
* <P>Type: TEXT</P>
|
||||
*/
|
||||
public static final String NAME = "name";
|
||||
|
||||
/**
|
||||
* The date the object was created, in seconds since January 1, 1970.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String DATE_CREATED = "date_created";
|
||||
|
||||
/**
|
||||
* The date the object was last modified, in seconds since January 1, 1970.
|
||||
* <P>Type: INTEGER</P>
|
||||
*/
|
||||
public static final String DATE_MODIFIED = "date_modified";
|
||||
|
||||
/**
|
||||
* A list of keywords associated with an object, separated by spaces.
|
||||
* <P>Type: TEXT</P>
|
||||
*/
|
||||
public static final String KEYWORDS = "keywords";
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package android.mtp;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public class PtpClient {
|
||||
|
||||
private static final String TAG = "PtpClient";
|
||||
|
||||
private final Listener mListener;
|
||||
|
||||
static {
|
||||
System.loadLibrary("media_jni");
|
||||
}
|
||||
|
||||
public PtpClient(Listener listener) {
|
||||
native_setup();
|
||||
if (listener == null) {
|
||||
throw new NullPointerException("PtpClient: listener is null");
|
||||
}
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
native_finalize();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean start() {
|
||||
return native_start();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
native_stop();
|
||||
}
|
||||
|
||||
public boolean deleteObject(int deviceID, long objectID) {
|
||||
return native_delete_object(deviceID, objectID);
|
||||
}
|
||||
|
||||
public long getParent(int deviceID, long objectID) {
|
||||
return native_get_parent(deviceID, objectID);
|
||||
}
|
||||
|
||||
public long getStorageID(int deviceID, long objectID) {
|
||||
return native_get_storage_id(deviceID, objectID);
|
||||
}
|
||||
|
||||
// Reads a file from device to host to the specified destination.
|
||||
// Returns true if the transfer succeeds.
|
||||
public boolean importFile(int deviceID, long objectID, String destPath) {
|
||||
return native_import_file(deviceID, objectID, destPath);
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
// called when a new PTP device has been discovered
|
||||
void deviceAdded(int id);
|
||||
|
||||
// called when an PTP device has been removed
|
||||
void deviceRemoved(int id);
|
||||
}
|
||||
|
||||
// called from native code
|
||||
private void deviceAdded(int id) {
|
||||
Log.d(TAG, "deviceAdded " + id);
|
||||
mListener.deviceAdded(id);
|
||||
}
|
||||
|
||||
// called from native code
|
||||
private void deviceRemoved(int id) {
|
||||
Log.d(TAG, "deviceRemoved " + id);
|
||||
mListener.deviceRemoved(id);
|
||||
}
|
||||
|
||||
// used by the JNI code
|
||||
private int mNativeContext;
|
||||
|
||||
private native final void native_setup();
|
||||
private native final void native_finalize();
|
||||
private native boolean native_start();
|
||||
private native void native_stop();
|
||||
private native boolean native_delete_object(int deviceID, long objectID);
|
||||
private native long native_get_parent(int deviceID, long objectID);
|
||||
private native long native_get_storage_id(int deviceID, long objectID);
|
||||
private native boolean native_import_file(int deviceID, long objectID, String destPath);
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package android.mtp;
|
||||
|
||||
import android.database.AbstractWindowedCursor;
|
||||
import android.database.CursorWindow;
|
||||
import android.provider.Ptp;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Cursor class for PTP content provider
|
||||
* @hide
|
||||
*/
|
||||
public final class PtpCursor extends AbstractWindowedCursor {
|
||||
static final String TAG = "PtpCursor";
|
||||
static final int NO_COUNT = -1;
|
||||
|
||||
/* constants for queryType */
|
||||
public static final int DEVICE = 1;
|
||||
public static final int DEVICE_ID = 2;
|
||||
public static final int STORAGE = 3;
|
||||
public static final int STORAGE_ID = 4;
|
||||
public static final int OBJECT = 5;
|
||||
public static final int OBJECT_ID = 6;
|
||||
public static final int STORAGE_CHILDREN = 7;
|
||||
public static final int OBJECT_CHILDREN = 8;
|
||||
public static final int OBJECT_IMPORT = 9;
|
||||
|
||||
/** The names of the columns in the projection */
|
||||
private String[] mColumns;
|
||||
|
||||
/** The number of rows in the cursor */
|
||||
private int mCount = NO_COUNT;
|
||||
|
||||
|
||||
public PtpCursor(PtpClient client, int queryType, int deviceID, long storageID, long objectID,
|
||||
String[] projection) {
|
||||
if (client == null) {
|
||||
throw new NullPointerException("client null in PtpCursor constructor");
|
||||
}
|
||||
mColumns = projection;
|
||||
|
||||
HashMap<String, Integer> map;
|
||||
switch (queryType) {
|
||||
case DEVICE:
|
||||
case DEVICE_ID:
|
||||
map = sDeviceProjectionMap;
|
||||
break;
|
||||
case STORAGE:
|
||||
case STORAGE_ID:
|
||||
map = sStorageProjectionMap;
|
||||
break;
|
||||
case OBJECT:
|
||||
case OBJECT_ID:
|
||||
case STORAGE_CHILDREN:
|
||||
case OBJECT_CHILDREN:
|
||||
map = sObjectProjectionMap;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("unknown query type " + queryType);
|
||||
}
|
||||
|
||||
int[] columns = new int[projection.length];
|
||||
for (int i = 0; i < projection.length; i++) {
|
||||
Integer id = map.get(projection[i]);
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("unknown column " + projection[i]);
|
||||
}
|
||||
columns[i] = id.intValue();
|
||||
}
|
||||
native_setup(client, queryType, deviceID, storageID, objectID, columns);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() {
|
||||
try {
|
||||
native_finalize();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (mCount == NO_COUNT) {
|
||||
fillWindow(0);
|
||||
}
|
||||
return mCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requery() {
|
||||
Log.d(TAG, "requery");
|
||||
mCount = NO_COUNT;
|
||||
if (mWindow != null) {
|
||||
mWindow.clear();
|
||||
}
|
||||
return super.requery();
|
||||
}
|
||||
|
||||
private void fillWindow(int startPos) {
|
||||
if (mWindow == null) {
|
||||
// If there isn't a window set already it will only be accessed locally
|
||||
mWindow = new CursorWindow(true /* the window is local only */);
|
||||
} else {
|
||||
mWindow.clear();
|
||||
}
|
||||
mWindow.setStartPosition(startPos);
|
||||
mCount = native_fill_window(mWindow, startPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getColumnNames() {
|
||||
Log.d(TAG, "getColumnNames returning " + mColumns);
|
||||
return mColumns;
|
||||
}
|
||||
|
||||
/* Device Column IDs */
|
||||
/* These must match the values in PtpCursor.cpp */
|
||||
private static final int DEVICE_ROW_ID = 1;
|
||||
private static final int DEVICE_MANUFACTURER = 2;
|
||||
private static final int DEVICE_MODEL = 3;
|
||||
|
||||
/* Storage Column IDs */
|
||||
/* These must match the values in PtpCursor.cpp */
|
||||
private static final int STORAGE_ROW_ID = 101;
|
||||
private static final int STORAGE_IDENTIFIER = 102;
|
||||
private static final int STORAGE_DESCRIPTION = 103;
|
||||
|
||||
/* Object Column IDs */
|
||||
/* These must match the values in PtpCursor.cpp */
|
||||
private static final int OBJECT_ROW_ID = 201;
|
||||
private static final int OBJECT_STORAGE_ID = 202;
|
||||
private static final int OBJECT_FORMAT = 203;
|
||||
private static final int OBJECT_PROTECTION_STATUS = 204;
|
||||
private static final int OBJECT_SIZE = 205;
|
||||
private static final int OBJECT_THUMB_FORMAT = 206;
|
||||
private static final int OBJECT_THUMB_SIZE = 207;
|
||||
private static final int OBJECT_THUMB_WIDTH = 208;
|
||||
private static final int OBJECT_THUMB_HEIGHT = 209;
|
||||
private static final int OBJECT_IMAGE_WIDTH = 210;
|
||||
private static final int OBJECT_IMAGE_HEIGHT = 211;
|
||||
private static final int OBJECT_IMAGE_DEPTH = 212;
|
||||
private static final int OBJECT_PARENT = 213;
|
||||
private static final int OBJECT_ASSOCIATION_TYPE = 214;
|
||||
private static final int OBJECT_ASSOCIATION_DESC = 215;
|
||||
private static final int OBJECT_SEQUENCE_NUMBER = 216;
|
||||
private static final int OBJECT_NAME = 217;
|
||||
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;
|
||||
private static HashMap<String, Integer> sObjectProjectionMap;
|
||||
|
||||
static {
|
||||
sDeviceProjectionMap = new HashMap<String, Integer>();
|
||||
sDeviceProjectionMap.put(Ptp.Device._ID, new Integer(DEVICE_ROW_ID));
|
||||
sDeviceProjectionMap.put(Ptp.Device.MANUFACTURER, new Integer(DEVICE_MANUFACTURER));
|
||||
sDeviceProjectionMap.put(Ptp.Device.MODEL, new Integer(DEVICE_MODEL));
|
||||
|
||||
sStorageProjectionMap = new HashMap<String, Integer>();
|
||||
sStorageProjectionMap.put(Ptp.Storage._ID, new Integer(STORAGE_ROW_ID));
|
||||
sStorageProjectionMap.put(Ptp.Storage.IDENTIFIER, new Integer(STORAGE_IDENTIFIER));
|
||||
sStorageProjectionMap.put(Ptp.Storage.DESCRIPTION, new Integer(STORAGE_DESCRIPTION));
|
||||
|
||||
sObjectProjectionMap = new HashMap<String, Integer>();
|
||||
sObjectProjectionMap.put(Ptp.Object._ID, new Integer(OBJECT_ROW_ID));
|
||||
sObjectProjectionMap.put(Ptp.Object.STORAGE_ID, new Integer(OBJECT_STORAGE_ID));
|
||||
sObjectProjectionMap.put(Ptp.Object.FORMAT, new Integer(OBJECT_FORMAT));
|
||||
sObjectProjectionMap.put(Ptp.Object.PROTECTION_STATUS, new Integer(OBJECT_PROTECTION_STATUS));
|
||||
sObjectProjectionMap.put(Ptp.Object.SIZE, new Integer(OBJECT_SIZE));
|
||||
sObjectProjectionMap.put(Ptp.Object.THUMB_FORMAT, new Integer(OBJECT_THUMB_FORMAT));
|
||||
sObjectProjectionMap.put(Ptp.Object.THUMB_SIZE, new Integer(OBJECT_THUMB_SIZE));
|
||||
sObjectProjectionMap.put(Ptp.Object.THUMB_WIDTH, new Integer(OBJECT_THUMB_WIDTH));
|
||||
sObjectProjectionMap.put(Ptp.Object.THUMB_HEIGHT, new Integer(OBJECT_THUMB_HEIGHT));
|
||||
sObjectProjectionMap.put(Ptp.Object.IMAGE_WIDTH, new Integer(OBJECT_IMAGE_WIDTH));
|
||||
sObjectProjectionMap.put(Ptp.Object.IMAGE_HEIGHT, new Integer(OBJECT_IMAGE_HEIGHT));
|
||||
sObjectProjectionMap.put(Ptp.Object.IMAGE_DEPTH, new Integer(OBJECT_IMAGE_DEPTH));
|
||||
sObjectProjectionMap.put(Ptp.Object.PARENT, new Integer(OBJECT_PARENT));
|
||||
sObjectProjectionMap.put(Ptp.Object.ASSOCIATION_TYPE, new Integer(OBJECT_ASSOCIATION_TYPE));
|
||||
sObjectProjectionMap.put(Ptp.Object.ASSOCIATION_DESC, new Integer(OBJECT_ASSOCIATION_DESC));
|
||||
sObjectProjectionMap.put(Ptp.Object.SEQUENCE_NUMBER, new Integer(OBJECT_SEQUENCE_NUMBER));
|
||||
sObjectProjectionMap.put(Ptp.Object.NAME, new Integer(OBJECT_NAME));
|
||||
sObjectProjectionMap.put(Ptp.Object.DATE_CREATED, new Integer(OBJECT_DATE_CREATED));
|
||||
sObjectProjectionMap.put(Ptp.Object.DATE_MODIFIED, new Integer(OBJECT_DATE_MODIFIED));
|
||||
sObjectProjectionMap.put(Ptp.Object.KEYWORDS, new Integer(OBJECT_KEYWORDS));
|
||||
sObjectProjectionMap.put(Ptp.Object.THUMB, new Integer(OBJECT_THUMB));
|
||||
|
||||
sObjectProjectionMap.put(Ptp.Object.NAME, new Integer(OBJECT_NAME));
|
||||
}
|
||||
|
||||
// used by the JNI code
|
||||
private int mNativeContext;
|
||||
|
||||
private native final void native_setup(PtpClient client, int queryType,
|
||||
int deviceID, long storageID, long objectID, int[] columns);
|
||||
private native final void native_finalize();
|
||||
private native void native_wait_for_event();
|
||||
private native int native_fill_window(CursorWindow window, int startPos);
|
||||
}
|
||||
@@ -11,8 +11,6 @@ LOCAL_SRC_FILES:= \
|
||||
android_media_AmrInputStream.cpp \
|
||||
android_mtp_MtpDatabase.cpp \
|
||||
android_mtp_MtpServer.cpp \
|
||||
android_mtp_PtpClient.cpp \
|
||||
android_mtp_PtpCursor.cpp \
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libandroid_runtime \
|
||||
|
||||
@@ -777,8 +777,6 @@ extern int register_android_media_MediaProfiles(JNIEnv *env);
|
||||
extern int register_android_media_AmrInputStream(JNIEnv *env);
|
||||
extern int register_android_mtp_MtpDatabase(JNIEnv *env);
|
||||
extern int register_android_mtp_MtpServer(JNIEnv *env);
|
||||
extern int register_android_mtp_PtpClient(JNIEnv *env);
|
||||
extern int register_android_mtp_PtpCursor(JNIEnv *env);
|
||||
|
||||
jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
{
|
||||
@@ -826,16 +824,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (register_android_mtp_PtpClient(env) < 0) {
|
||||
LOGE("ERROR: PtpClient native registration failed");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (register_android_mtp_PtpCursor(env) < 0) {
|
||||
LOGE("ERROR: PtpCursor native registration failed");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (register_android_mtp_MtpDatabase(env) < 0) {
|
||||
LOGE("ERROR: MtpDatabase native registration failed");
|
||||
goto bail;
|
||||
|
||||
@@ -1,254 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "PtpClientJNI"
|
||||
#include "utils/Log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "private/android_filesystem_config.h"
|
||||
|
||||
#include "MtpClient.h"
|
||||
#include "MtpDevice.h"
|
||||
#include "MtpObjectInfo.h"
|
||||
|
||||
using namespace android;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static jmethodID method_deviceAdded;
|
||||
static jmethodID method_deviceRemoved;
|
||||
static jfieldID field_context;
|
||||
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
|
||||
static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("An exception was thrown by callback '%s'.", methodName);
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
}
|
||||
}
|
||||
|
||||
class MyClient : public MtpClient {
|
||||
private:
|
||||
virtual void deviceAdded(MtpDevice *device);
|
||||
virtual void deviceRemoved(MtpDevice *device);
|
||||
|
||||
jobject mClient;
|
||||
MtpDevice* mEventDevice;
|
||||
|
||||
public:
|
||||
MyClient(JNIEnv *env, jobject client);
|
||||
void cleanup(JNIEnv *env);
|
||||
};
|
||||
|
||||
MtpClient* get_client_from_object(JNIEnv* env, jobject javaClient)
|
||||
{
|
||||
return (MtpClient*)env->GetIntField(javaClient, field_context);
|
||||
}
|
||||
|
||||
|
||||
MyClient::MyClient(JNIEnv *env, jobject client)
|
||||
: mClient(env->NewGlobalRef(client))
|
||||
{
|
||||
}
|
||||
|
||||
void MyClient::cleanup(JNIEnv *env) {
|
||||
env->DeleteGlobalRef(mClient);
|
||||
}
|
||||
|
||||
void MyClient::deviceAdded(MtpDevice *device) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
const char* name = device->getDeviceName();
|
||||
LOGD("MyClient::deviceAdded %s\n", name);
|
||||
|
||||
env->CallVoidMethod(mClient, method_deviceAdded, device->getID());
|
||||
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
}
|
||||
|
||||
void MyClient::deviceRemoved(MtpDevice *device) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
const char* name = device->getDeviceName();
|
||||
LOGD("MyClient::deviceRemoved %s\n", name);
|
||||
|
||||
env->CallVoidMethod(mClient, method_deviceRemoved, device->getID());
|
||||
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
}
|
||||
|
||||
#endif // HAVE_ANDROID_OS
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
android_mtp_PtpClient_setup(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
LOGD("setup\n");
|
||||
MyClient* client = new MyClient(env, thiz);
|
||||
client->start();
|
||||
env->SetIntField(thiz, field_context, (int)client);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
android_mtp_PtpClient_finalize(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
LOGD("finalize\n");
|
||||
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
|
||||
client->cleanup(env);
|
||||
delete client;
|
||||
env->SetIntField(thiz, field_context, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_mtp_PtpClient_start(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
LOGD("start\n");
|
||||
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
|
||||
return client->start();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
android_mtp_PtpClient_stop(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
LOGD("stop\n");
|
||||
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
|
||||
client->stop();
|
||||
#endif
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_mtp_PtpClient_delete_object(JNIEnv *env, jobject thiz,
|
||||
jint device_id, jlong object_id)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
|
||||
MtpDevice* device = client->getDevice(device_id);
|
||||
if (device)
|
||||
return device->deleteObject(object_id);
|
||||
else
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static jlong
|
||||
android_mtp_PtpClient_get_parent(JNIEnv *env, jobject thiz,
|
||||
jint device_id, jlong object_id)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
|
||||
MtpDevice* device = client->getDevice(device_id);
|
||||
if (device)
|
||||
return device->getParent(object_id);
|
||||
else
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
static jlong
|
||||
android_mtp_PtpClient_get_storage_id(JNIEnv *env, jobject thiz,
|
||||
jint device_id, jlong object_id)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
|
||||
MtpDevice* device = client->getDevice(device_id);
|
||||
if (device)
|
||||
return device->getStorageID(object_id);
|
||||
else
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_mtp_PtpClient_import_file(JNIEnv *env, jobject thiz,
|
||||
jint device_id, jlong object_id, jstring dest_path)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
MyClient *client = (MyClient *)env->GetIntField(thiz, field_context);
|
||||
MtpDevice* device = client->getDevice(device_id);
|
||||
if (device) {
|
||||
const char *destPathStr = env->GetStringUTFChars(dest_path, NULL);
|
||||
bool result = device->readObject(object_id, destPathStr, AID_SDCARD_RW, 0664);
|
||||
env->ReleaseStringUTFChars(dest_path, destPathStr);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{"native_setup", "()V", (void *)android_mtp_PtpClient_setup},
|
||||
{"native_finalize", "()V", (void *)android_mtp_PtpClient_finalize},
|
||||
{"native_start", "()Z", (void *)android_mtp_PtpClient_start},
|
||||
{"native_stop", "()V", (void *)android_mtp_PtpClient_stop},
|
||||
{"native_delete_object", "(IJ)Z", (void *)android_mtp_PtpClient_delete_object},
|
||||
{"native_get_parent", "(IJ)J", (void *)android_mtp_PtpClient_get_parent},
|
||||
{"native_get_storage_id", "(IJ)J", (void *)android_mtp_PtpClient_get_storage_id},
|
||||
{"native_import_file", "(IJLjava/lang/String;)Z",
|
||||
(void *)android_mtp_PtpClient_import_file},
|
||||
};
|
||||
|
||||
static const char* const kClassPathName = "android/mtp/PtpClient";
|
||||
|
||||
int register_android_mtp_PtpClient(JNIEnv *env)
|
||||
{
|
||||
jclass clazz;
|
||||
|
||||
LOGD("register_android_mtp_PtpClient\n");
|
||||
|
||||
clazz = env->FindClass("android/mtp/PtpClient");
|
||||
if (clazz == NULL) {
|
||||
LOGE("Can't find android/mtp/PtpClient");
|
||||
return -1;
|
||||
}
|
||||
method_deviceAdded = env->GetMethodID(clazz, "deviceAdded", "(I)V");
|
||||
if (method_deviceAdded == NULL) {
|
||||
LOGE("Can't find deviceAdded");
|
||||
return -1;
|
||||
}
|
||||
method_deviceRemoved = env->GetMethodID(clazz, "deviceRemoved", "(I)V");
|
||||
if (method_deviceRemoved == NULL) {
|
||||
LOGE("Can't find deviceRemoved");
|
||||
return -1;
|
||||
}
|
||||
field_context = env->GetFieldID(clazz, "mNativeContext", "I");
|
||||
if (field_context == NULL) {
|
||||
LOGE("Can't find PtpClient.mNativeContext");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(env,
|
||||
"android/mtp/PtpClient", gMethods, NELEM(gMethods));
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "PtpCursorJNI"
|
||||
#include "utils/Log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "binder/CursorWindow.h"
|
||||
|
||||
#include "MtpClient.h"
|
||||
#include "PtpCursor.h"
|
||||
|
||||
using namespace android;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static jfieldID field_context;
|
||||
|
||||
// From android_mtp_PtpClient.cpp
|
||||
MtpClient * get_client_from_object(JNIEnv * env, jobject javaClient);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static bool ExceptionCheck(void* env)
|
||||
{
|
||||
return ((JNIEnv *)env)->ExceptionCheck();
|
||||
}
|
||||
|
||||
static void
|
||||
android_mtp_PtpCursor_setup(JNIEnv *env, jobject thiz, jobject javaClient,
|
||||
jint queryType, jint deviceID, jlong storageID, jlong objectID, jintArray javaColumns)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
LOGD("android_mtp_PtpCursor_setup queryType: %d deviceID: %d storageID: %lld objectID: %lld\n",
|
||||
queryType, deviceID, storageID, objectID);
|
||||
|
||||
int* columns = NULL;
|
||||
int columnCount = 0;
|
||||
if (javaColumns) {
|
||||
columns = env->GetIntArrayElements(javaColumns, 0);
|
||||
columnCount = env->GetArrayLength(javaColumns);
|
||||
}
|
||||
|
||||
MtpClient* client = get_client_from_object(env, javaClient);
|
||||
PtpCursor* cursor = new PtpCursor(client, queryType,
|
||||
deviceID, storageID, objectID, columnCount, columns);
|
||||
|
||||
if (columns)
|
||||
env->ReleaseIntArrayElements(javaColumns, columns, 0);
|
||||
env->SetIntField(thiz, field_context, (int)cursor);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
android_mtp_PtpCursor_finalize(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
LOGD("finalize\n");
|
||||
PtpCursor *cursor = (PtpCursor *)env->GetIntField(thiz, field_context);
|
||||
delete cursor;
|
||||
#endif
|
||||
}
|
||||
|
||||
static jint
|
||||
android_mtp_PtpCursor_fill_window(JNIEnv *env, jobject thiz, jobject javaWindow, jint startPos)
|
||||
{
|
||||
#ifdef HAVE_ANDROID_OS
|
||||
CursorWindow* window = get_window_from_object(env, javaWindow);
|
||||
if (!window) {
|
||||
LOGE("Invalid CursorWindow");
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException",
|
||||
"Bad CursorWindow");
|
||||
return 0;
|
||||
}
|
||||
PtpCursor *cursor = (PtpCursor *)env->GetIntField(thiz, field_context);
|
||||
|
||||
return cursor->fillWindow(window, startPos);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{"native_setup", "(Landroid/mtp/PtpClient;IIJJ[I)V",
|
||||
(void *)android_mtp_PtpCursor_setup},
|
||||
{"native_finalize", "()V", (void *)android_mtp_PtpCursor_finalize},
|
||||
{"native_fill_window", "(Landroid/database/CursorWindow;I)I",
|
||||
(void *)android_mtp_PtpCursor_fill_window},
|
||||
|
||||
};
|
||||
|
||||
static const char* const kClassPathName = "android/mtp/PtpCursor";
|
||||
|
||||
int register_android_mtp_PtpCursor(JNIEnv *env)
|
||||
{
|
||||
jclass clazz;
|
||||
|
||||
LOGD("register_android_mtp_PtpCursor\n");
|
||||
|
||||
clazz = env->FindClass("android/mtp/PtpCursor");
|
||||
if (clazz == NULL) {
|
||||
LOGE("Can't find android/mtp/PtpCursor");
|
||||
return -1;
|
||||
}
|
||||
field_context = env->GetFieldID(clazz, "mNativeContext", "I");
|
||||
if (field_context == NULL) {
|
||||
LOGE("Can't find PtpCursor.mNativeContext");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(env,
|
||||
"android/mtp/PtpCursor", gMethods, NELEM(gMethods));
|
||||
}
|
||||
@@ -37,7 +37,6 @@ LOCAL_SRC_FILES:= \
|
||||
MtpStringBuffer.cpp \
|
||||
MtpStorage.cpp \
|
||||
MtpUtils.cpp \
|
||||
PtpCursor.cpp \
|
||||
|
||||
LOCAL_MODULE:= libmtp
|
||||
|
||||
@@ -69,7 +68,6 @@ LOCAL_SRC_FILES:= \
|
||||
MtpStringBuffer.cpp \
|
||||
MtpStorage.cpp \
|
||||
MtpUtils.cpp \
|
||||
PtpCursor.cpp \
|
||||
|
||||
LOCAL_MODULE:= libmtp
|
||||
|
||||
|
||||
@@ -1,461 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "PtpCursor"
|
||||
|
||||
#include "MtpDebug.h"
|
||||
#include "MtpClient.h"
|
||||
#include "PtpCursor.h"
|
||||
#include "MtpDevice.h"
|
||||
#include "MtpDeviceInfo.h"
|
||||
#include "MtpObjectInfo.h"
|
||||
#include "MtpStorageInfo.h"
|
||||
|
||||
|
||||
#include "binder/CursorWindow.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
/* Device Column IDs */
|
||||
/* These must match the values in PtpCursor.java */
|
||||
#define DEVICE_ROW_ID 1
|
||||
#define DEVICE_MANUFACTURER 2
|
||||
#define DEVICE_MODEL 3
|
||||
|
||||
/* Storage Column IDs */
|
||||
/* These must match the values in PtpCursor.java */
|
||||
#define STORAGE_ROW_ID 101
|
||||
#define STORAGE_IDENTIFIER 102
|
||||
#define STORAGE_DESCRIPTION 103
|
||||
|
||||
/* Object Column IDs */
|
||||
/* These must match the values in PtpCursor.java */
|
||||
#define OBJECT_ROW_ID 201
|
||||
#define OBJECT_STORAGE_ID 202
|
||||
#define OBJECT_FORMAT 203
|
||||
#define OBJECT_PROTECTION_STATUS 204
|
||||
#define OBJECT_SIZE 205
|
||||
#define OBJECT_THUMB_FORMAT 206
|
||||
#define OBJECT_THUMB_SIZE 207
|
||||
#define OBJECT_THUMB_WIDTH 208
|
||||
#define OBJECT_THUMB_HEIGHT 209
|
||||
#define OBJECT_IMAGE_WIDTH 210
|
||||
#define OBJECT_IMAGE_HEIGHT 211
|
||||
#define OBJECT_IMAGE_DEPTH 212
|
||||
#define OBJECT_PARENT 213
|
||||
#define OBJECT_ASSOCIATION_TYPE 214
|
||||
#define OBJECT_ASSOCIATION_DESC 215
|
||||
#define OBJECT_SEQUENCE_NUMBER 216
|
||||
#define OBJECT_NAME 217
|
||||
#define OBJECT_DATE_CREATED 218
|
||||
#define OBJECT_DATE_MODIFIED 219
|
||||
#define OBJECT_KEYWORDS 220
|
||||
#define OBJECT_THUMB 221
|
||||
|
||||
PtpCursor::PtpCursor(MtpClient* client, int queryType, int deviceID,
|
||||
MtpStorageID storageID, MtpObjectHandle objectID,
|
||||
int columnCount, int* columns)
|
||||
: mClient(client),
|
||||
mQueryType(queryType),
|
||||
mDeviceID(deviceID),
|
||||
mStorageID(storageID),
|
||||
mQbjectID(objectID),
|
||||
mColumnCount(columnCount),
|
||||
mColumns(NULL)
|
||||
{
|
||||
if (columns) {
|
||||
mColumns = new int[columnCount];
|
||||
memcpy(mColumns, columns, columnCount * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
PtpCursor::~PtpCursor() {
|
||||
delete[] mColumns;
|
||||
}
|
||||
|
||||
int PtpCursor::fillWindow(CursorWindow* window, int startPos) {
|
||||
LOGD("PtpCursor::fillWindow mQueryType: %d\n", mQueryType);
|
||||
|
||||
switch (mQueryType) {
|
||||
case DEVICE:
|
||||
return fillDevices(window, startPos);
|
||||
case DEVICE_ID:
|
||||
return fillDevice(window, startPos);
|
||||
case STORAGE:
|
||||
return fillStorages(window, startPos);
|
||||
case STORAGE_ID:
|
||||
return fillStorage(window, startPos);
|
||||
case OBJECT:
|
||||
return fillObjects(window, 0, startPos);
|
||||
case OBJECT_ID:
|
||||
return fillObject(window, startPos);
|
||||
case STORAGE_CHILDREN:
|
||||
return fillObjects(window, -1, startPos);
|
||||
case OBJECT_CHILDREN:
|
||||
return fillObjects(window, mQbjectID, startPos);
|
||||
default:
|
||||
LOGE("PtpCursor::fillWindow: unknown query type %d\n", mQueryType);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int PtpCursor::fillDevices(CursorWindow* window, int startPos) {
|
||||
int count = 0;
|
||||
MtpDeviceList& deviceList = mClient->getDeviceList();
|
||||
for (int i = 0; i < deviceList.size(); i++) {
|
||||
MtpDevice* device = deviceList[i];
|
||||
if (fillDevice(window, device, startPos)) {
|
||||
count++;
|
||||
startPos++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int PtpCursor::fillDevice(CursorWindow* window, int startPos) {
|
||||
MtpDevice* device = mClient->getDevice(mDeviceID);
|
||||
if (device && fillDevice(window, device, startPos))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PtpCursor::fillStorages(CursorWindow* window, int startPos) {
|
||||
int count = 0;
|
||||
MtpDevice* device = mClient->getDevice(mDeviceID);
|
||||
if (!device)
|
||||
return 0;
|
||||
MtpStorageIDList* storageIDs = device->getStorageIDs();
|
||||
if (!storageIDs)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < storageIDs->size(); i++) {
|
||||
MtpStorageID storageID = (*storageIDs)[i];
|
||||
if (fillStorage(window, device, storageID, startPos)) {
|
||||
count++;
|
||||
startPos++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete storageIDs;
|
||||
return count;
|
||||
}
|
||||
|
||||
int PtpCursor::fillStorage(CursorWindow* window, int startPos) {
|
||||
MtpDevice* device = mClient->getDevice(mDeviceID);
|
||||
if (device && fillStorage(window, device, mStorageID, startPos))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PtpCursor::fillObjects(CursorWindow* window, int parent, int startPos) {
|
||||
int count = 0;
|
||||
MtpDevice* device = mClient->getDevice(mDeviceID);
|
||||
if (!device)
|
||||
return 0;
|
||||
MtpObjectHandleList* handles = device->getObjectHandles(mStorageID, 0, parent);
|
||||
if (!handles)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < handles->size(); i++) {
|
||||
MtpObjectHandle handle = (*handles)[i];
|
||||
if (fillObject(window, device, handle, startPos)) {
|
||||
count++;
|
||||
startPos++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete handles;
|
||||
return count;
|
||||
}
|
||||
|
||||
int PtpCursor::fillObject(CursorWindow* window, int startPos) {
|
||||
MtpDevice* device = mClient->getDevice(mDeviceID);
|
||||
if (device && fillObject(window, device, mQbjectID, startPos))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PtpCursor::fillDevice(CursorWindow* window, MtpDevice* device, int row) {
|
||||
MtpDeviceInfo* deviceInfo = device->getDeviceInfo();
|
||||
if (!deviceInfo)
|
||||
return false;
|
||||
if (!prepareRow(window))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < mColumnCount; i++) {
|
||||
switch (mColumns[i]) {
|
||||
case DEVICE_ROW_ID:
|
||||
if (!putLong(window, device->getID(), row, i))
|
||||
return false;
|
||||
break;
|
||||
case DEVICE_MANUFACTURER:
|
||||
if (!putString(window, deviceInfo->mManufacturer, row, i))
|
||||
return false;
|
||||
break;
|
||||
case DEVICE_MODEL:
|
||||
if (!putString(window, deviceInfo->mModel, row, i))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
LOGE("fillDevice: unknown column %d\n", mColumns[i]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PtpCursor::fillStorage(CursorWindow* window, MtpDevice* device,
|
||||
MtpStorageID storageID, int row) {
|
||||
|
||||
LOGD("fillStorage %d\n", storageID);
|
||||
|
||||
MtpStorageInfo* storageInfo = device->getStorageInfo(storageID);
|
||||
if (!storageInfo)
|
||||
return false;
|
||||
if (!prepareRow(window)) {
|
||||
delete storageInfo;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* text;
|
||||
for (int i = 0; i < mColumnCount; i++) {
|
||||
switch (mColumns[i]) {
|
||||
case STORAGE_ROW_ID:
|
||||
if (!putLong(window, storageID, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case STORAGE_IDENTIFIER:
|
||||
text = storageInfo->mVolumeIdentifier;
|
||||
if (!text || !text[0])
|
||||
text = "Camera Storage";
|
||||
if (!putString(window, text, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case STORAGE_DESCRIPTION:
|
||||
text = storageInfo->mStorageDescription;
|
||||
if (!text || !text[0])
|
||||
text = "Storage Description";
|
||||
if (!putString(window, text, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
default:
|
||||
LOGE("fillStorage: unknown column %d\n", mColumns[i]);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
delete storageInfo;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
delete storageInfo;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PtpCursor::fillObject(CursorWindow* window, MtpDevice* device,
|
||||
MtpObjectHandle objectID, int row) {
|
||||
|
||||
MtpObjectInfo* objectInfo = device->getObjectInfo(objectID);
|
||||
if (!objectInfo)
|
||||
return false;
|
||||
// objectInfo->print();
|
||||
if (!prepareRow(window)) {
|
||||
delete objectInfo;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mColumnCount; i++) {
|
||||
switch (mColumns[i]) {
|
||||
case OBJECT_ROW_ID:
|
||||
if (!putLong(window, objectID, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_STORAGE_ID:
|
||||
if (!putLong(window, objectInfo->mStorageID, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_FORMAT:
|
||||
if (!putLong(window, objectInfo->mFormat, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_PROTECTION_STATUS:
|
||||
if (!putLong(window, objectInfo->mProtectionStatus, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_SIZE:
|
||||
if (!putLong(window, objectInfo->mCompressedSize, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_THUMB_FORMAT:
|
||||
if (!putLong(window, objectInfo->mThumbFormat, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_THUMB_SIZE:
|
||||
if (!putLong(window, objectInfo->mThumbCompressedSize, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_THUMB_WIDTH:
|
||||
if (!putLong(window, objectInfo->mThumbPixWidth, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_THUMB_HEIGHT:
|
||||
if (!putLong(window, objectInfo->mThumbPixHeight, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_IMAGE_WIDTH:
|
||||
if (!putLong(window, objectInfo->mImagePixWidth, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_IMAGE_HEIGHT:
|
||||
if (!putLong(window, objectInfo->mImagePixHeight, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_IMAGE_DEPTH:
|
||||
if (!putLong(window, objectInfo->mImagePixDepth, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_PARENT:
|
||||
if (!putLong(window, objectInfo->mParent, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_ASSOCIATION_TYPE:
|
||||
if (!putLong(window, objectInfo->mAssociationType, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_ASSOCIATION_DESC:
|
||||
if (!putLong(window, objectInfo->mAssociationDesc, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_SEQUENCE_NUMBER:
|
||||
if (!putLong(window, objectInfo->mSequenceNumber, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_NAME:
|
||||
if (!putString(window, objectInfo->mName, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_DATE_CREATED:
|
||||
if (!putLong(window, objectInfo->mDateCreated, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_DATE_MODIFIED:
|
||||
if (!putLong(window, objectInfo->mDateModified, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_KEYWORDS:
|
||||
if (!putString(window, objectInfo->mKeywords, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
case OBJECT_THUMB:
|
||||
if (!putThumbnail(window, objectID, objectInfo->mFormat, row, i))
|
||||
goto fail;
|
||||
break;
|
||||
default:
|
||||
LOGE("fillObject: unknown column %d\n", mColumns[i]);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
delete objectInfo;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
delete objectInfo;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PtpCursor::prepareRow(CursorWindow* window) {
|
||||
if (!window->setNumColumns(mColumnCount)) {
|
||||
LOGE("Failed to change column count from %d to %d", window->getNumColumns(), mColumnCount);
|
||||
return false;
|
||||
}
|
||||
field_slot_t * fieldDir = window->allocRow();
|
||||
if (!fieldDir) {
|
||||
LOGE("Failed allocating fieldDir");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PtpCursor::putLong(CursorWindow* window, int64_t value, int row, int column) {
|
||||
if (!window->putLong(row, column, value)) {
|
||||
window->freeLastRow();
|
||||
LOGE("Failed allocating space for a long in column %d", column);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PtpCursor::putString(CursorWindow* window, const char* text, int row, int column) {
|
||||
int size = strlen(text) + 1;
|
||||
int offset = window->alloc(size);
|
||||
if (!offset) {
|
||||
window->freeLastRow();
|
||||
LOGE("Failed allocating %u bytes for text/blob %s", size, text);
|
||||
return false;
|
||||
}
|
||||
window->copyIn(offset, (const uint8_t*)text, 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_STRING;
|
||||
fieldSlot->data.buffer.offset = offset;
|
||||
fieldSlot->data.buffer.size = size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PtpCursor::putThumbnail(CursorWindow* window, MtpObjectHandle objectID,
|
||||
MtpObjectFormat format, int row, int column) {
|
||||
MtpDevice* device = mClient->getDevice(mDeviceID);
|
||||
void* thumbnail;
|
||||
int size, offset;
|
||||
if (format == MTP_FORMAT_ASSOCIATION) {
|
||||
thumbnail = NULL;
|
||||
size = offset = 0;
|
||||
} else {
|
||||
thumbnail = device->getThumbnail(objectID, size);
|
||||
|
||||
LOGV("putThumbnail: %p, size: %d\n", thumbnail, size);
|
||||
offset = window->alloc(size);
|
||||
if (!offset) {
|
||||
window->freeLastRow();
|
||||
LOGE("Failed allocating %u bytes for thumbnail", size);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (thumbnail)
|
||||
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
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _PTP_CURSOR_H
|
||||
#define _PTP_CURSOR_H
|
||||
|
||||
#include "MtpTypes.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
class CursorWindow;
|
||||
|
||||
class PtpCursor {
|
||||
private:
|
||||
enum {
|
||||
DEVICE = 1,
|
||||
DEVICE_ID = 2,
|
||||
STORAGE = 3,
|
||||
STORAGE_ID = 4,
|
||||
OBJECT = 5,
|
||||
OBJECT_ID = 6,
|
||||
STORAGE_CHILDREN = 7,
|
||||
OBJECT_CHILDREN = 8,
|
||||
};
|
||||
|
||||
MtpClient* mClient;
|
||||
int mQueryType;
|
||||
int mDeviceID;
|
||||
MtpStorageID mStorageID;
|
||||
MtpObjectHandle mQbjectID;
|
||||
int mColumnCount;
|
||||
int* mColumns;
|
||||
|
||||
public:
|
||||
PtpCursor(MtpClient* client, int queryType, int deviceID,
|
||||
MtpStorageID storageID, MtpObjectHandle objectID,
|
||||
int columnCount, int* columns);
|
||||
virtual ~PtpCursor();
|
||||
|
||||
int fillWindow(CursorWindow* window, int startPos);
|
||||
|
||||
private:
|
||||
int fillDevices(CursorWindow* window, int startPos);
|
||||
int fillDevice(CursorWindow* window, int startPos);
|
||||
int fillStorages(CursorWindow* window, int startPos);
|
||||
int fillStorage(CursorWindow* window, int startPos);
|
||||
int fillObjects(CursorWindow* window, int parent, int startPos);
|
||||
int fillObject(CursorWindow* window, int startPos);
|
||||
|
||||
bool fillDevice(CursorWindow* window, MtpDevice* device, int startPos);
|
||||
bool fillStorage(CursorWindow* window, MtpDevice* device,
|
||||
MtpStorageID storageID, int row);
|
||||
bool fillObject(CursorWindow* window, MtpDevice* device,
|
||||
MtpObjectHandle objectID, int row);
|
||||
|
||||
bool prepareRow(CursorWindow* window);
|
||||
bool putLong(CursorWindow* window, int64_t value, int row, int column);
|
||||
bool putString(CursorWindow* window, const char* text, int row, int column);
|
||||
bool putThumbnail(CursorWindow* window, MtpObjectHandle objectID,
|
||||
MtpObjectFormat format, int row, int column);
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // _PTP_CURSOR_H
|
||||
Reference in New Issue
Block a user