Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 27480cd4 authored by Mike Lockwood's avatar Mike Lockwood
Browse files

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: default avatarMike Lockwood <lockwood@android.com>
parent 65d2a4cb
Loading
Loading
Loading
Loading
+0 −266
Original line number Diff line number Diff line
/*
 * 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";
    }
}
+0 −108
Original line number Diff line number Diff line
/*
 * 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);
}
+0 −219
Original line number Diff line number Diff line
/*
 * 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);
}
+0 −2
Original line number Diff line number Diff line
@@ -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 \
+0 −12
Original line number Diff line number Diff line
@@ -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;
Loading