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:
Mike Lockwood
2011-01-06 09:39:28 -05:00
parent 65d2a4cb5f
commit 27480cd494
10 changed files with 0 additions and 1538 deletions

View File

@@ -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";
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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 \

View File

@@ -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;

View File

@@ -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));
}

View File

@@ -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));
}

View File

@@ -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

View File

@@ -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

View File

@@ -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