FileDocCategorySizeDatePackage
MtpPropertyGroup.javaAPI DocAndroid 5.1 API19521Thu Mar 12 22:22:30 GMT 2015android.mtp

MtpPropertyGroup

public class MtpPropertyGroup extends Object

Fields Summary
private static final String
TAG
private final MtpDatabase
mDatabase
private final android.content.IContentProvider
mProvider
private final String
mPackageName
private final String
mVolumeName
private final android.net.Uri
mUri
private final Property[]
mProperties
private String[]
mColumns
private static final String
ID_WHERE
private static final String
FORMAT_WHERE
private static final String
ID_FORMAT_WHERE
private static final String
PARENT_WHERE
private static final String
PARENT_FORMAT_WHERE
Constructors Summary
public MtpPropertyGroup(MtpDatabase database, android.content.IContentProvider provider, String packageName, String volume, int[] properties)

    // constructs a property group for a list of properties
          
                
        mDatabase = database;
        mProvider = provider;
        mPackageName = packageName;
        mVolumeName = volume;
        mUri = Files.getMtpObjectsUri(volume);

        int count = properties.length;
        ArrayList<String> columns = new ArrayList<String>(count);
        columns.add(Files.FileColumns._ID);

        mProperties = new Property[count];
        for (int i = 0; i < count; i++) {
            mProperties[i] = createProperty(properties[i], columns);
        }
        count = columns.size();
        mColumns = new String[count];
        for (int i = 0; i < count; i++) {
            mColumns[i] = columns.get(i);
        }
    
Methods Summary
private android.mtp.MtpPropertyGroup$PropertycreateProperty(int code, java.util.ArrayList columns)

        String column = null;
        int type;

         switch (code) {
            case MtpConstants.PROPERTY_STORAGE_ID:
                column = Files.FileColumns.STORAGE_ID;
                type = MtpConstants.TYPE_UINT32;
                break;
             case MtpConstants.PROPERTY_OBJECT_FORMAT:
                column = Files.FileColumns.FORMAT;
                type = MtpConstants.TYPE_UINT16;
                break;
            case MtpConstants.PROPERTY_PROTECTION_STATUS:
                // protection status is always 0
                type = MtpConstants.TYPE_UINT16;
                break;
            case MtpConstants.PROPERTY_OBJECT_SIZE:
                column = Files.FileColumns.SIZE;
                type = MtpConstants.TYPE_UINT64;
                break;
            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
                column = Files.FileColumns.DATA;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_NAME:
                column = MediaColumns.TITLE;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_DATE_MODIFIED:
                column = Files.FileColumns.DATE_MODIFIED;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_DATE_ADDED:
                column = Files.FileColumns.DATE_ADDED;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE:
                column = Audio.AudioColumns.YEAR;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_PARENT_OBJECT:
                column = Files.FileColumns.PARENT;
                type = MtpConstants.TYPE_UINT32;
                break;
            case MtpConstants.PROPERTY_PERSISTENT_UID:
                // PUID is concatenation of storageID and object handle
                column = Files.FileColumns.STORAGE_ID;
                type = MtpConstants.TYPE_UINT128;
                break;
            case MtpConstants.PROPERTY_DURATION:
                column = Audio.AudioColumns.DURATION;
                type = MtpConstants.TYPE_UINT32;
                break;
            case MtpConstants.PROPERTY_TRACK:
                column = Audio.AudioColumns.TRACK;
                type = MtpConstants.TYPE_UINT16;
                break;
            case MtpConstants.PROPERTY_DISPLAY_NAME:
                column = MediaColumns.DISPLAY_NAME;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_ARTIST:
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_ALBUM_NAME:
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_ALBUM_ARTIST:
                column = Audio.AudioColumns.ALBUM_ARTIST;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_GENRE:
                // genre requires a special query
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_COMPOSER:
                column = Audio.AudioColumns.COMPOSER;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_DESCRIPTION:
                column = Images.ImageColumns.DESCRIPTION;
                type = MtpConstants.TYPE_STR;
                break;
            case MtpConstants.PROPERTY_AUDIO_WAVE_CODEC:
            case MtpConstants.PROPERTY_AUDIO_BITRATE:
            case MtpConstants.PROPERTY_SAMPLE_RATE:
                // these are special cased
                type = MtpConstants.TYPE_UINT32;
                break;
            case MtpConstants.PROPERTY_BITRATE_TYPE:
            case MtpConstants.PROPERTY_NUMBER_OF_CHANNELS:
                // these are special cased
                type = MtpConstants.TYPE_UINT16;
                break;
            default:
                type = MtpConstants.TYPE_UNDEFINED;
                Log.e(TAG, "unsupported property " + code);
                break;
        }

        if (column != null) {
            columns.add(column);
            return new Property(code, type, columns.size() - 1);
        } else {
            return new Property(code, type, -1);
        }
    
private native java.lang.Stringformat_date_time(long seconds)

MtpPropertyListgetPropertyList(int handle, int format, int depth)

        //Log.d(TAG, "getPropertyList handle: " + handle + " format: " + format + " depth: " + depth);
        if (depth > 1) {
            // we only support depth 0 and 1
            // depth 0: single object, depth 1: immediate children
            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED);
        }

        String where;
        String[] whereArgs;
        if (format == 0) {
            if (handle == 0xFFFFFFFF) {
                // select all objects
                where = null;
                whereArgs = null;
            } else {
                whereArgs = new String[] { Integer.toString(handle) };
                if (depth == 1) {
                    where = PARENT_WHERE;
                } else {
                    where = ID_WHERE;
                }
            }
        } else {
            if (handle == 0xFFFFFFFF) {
                // select all objects with given format
                where = FORMAT_WHERE;
                whereArgs = new String[] { Integer.toString(format) };
            } else {
                whereArgs = new String[] { Integer.toString(handle), Integer.toString(format) };
                if (depth == 1) {
                    where = PARENT_FORMAT_WHERE;
                } else {
                    where = ID_FORMAT_WHERE;
                }
            }
        }

        Cursor c = null;
        try {
            // don't query if not necessary
            if (depth > 0 || handle == 0xFFFFFFFF || mColumns.length > 1) {
                c = mProvider.query(mPackageName, mUri, mColumns, where, whereArgs, null, null);
                if (c == null) {
                    return new MtpPropertyList(0, MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
                }
            }

            int count = (c == null ? 1 : c.getCount());
            MtpPropertyList result = new MtpPropertyList(count * mProperties.length,
                    MtpConstants.RESPONSE_OK);

            // iterate over all objects in the query
            for (int objectIndex = 0; objectIndex < count; objectIndex++) {
                if (c != null) {
                    c.moveToNext();
                    handle = (int)c.getLong(0);
                }

                // iterate over all properties in the query for the given object
                for (int propertyIndex = 0; propertyIndex < mProperties.length; propertyIndex++) {
                    Property property = mProperties[propertyIndex];
                    int propertyCode = property.code;
                    int column = property.column;

                    // handle some special cases
                    switch (propertyCode) {
                        case MtpConstants.PROPERTY_PROTECTION_STATUS:
                            // protection status is always 0
                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 0);
                            break;
                        case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
                            // special case - need to extract file name from full path
                            String value = c.getString(column);
                            if (value != null) {
                                result.append(handle, propertyCode, nameFromPath(value));
                            } else {
                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
                            }
                            break;
                        case MtpConstants.PROPERTY_NAME:
                            // first try title
                            String name = c.getString(column);
                            // then try name
                            if (name == null) {
                                name = queryString(handle, Audio.PlaylistsColumns.NAME);
                            }
                            // if title and name fail, extract name from full path
                            if (name == null) {
                                name = queryString(handle, Files.FileColumns.DATA);
                                if (name != null) {
                                    name = nameFromPath(name);
                                }
                            }
                            if (name != null) {
                                result.append(handle, propertyCode, name);
                            } else {
                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
                            }
                            break;
                        case MtpConstants.PROPERTY_DATE_MODIFIED:
                        case MtpConstants.PROPERTY_DATE_ADDED:
                            // convert from seconds to DateTime
                            result.append(handle, propertyCode, format_date_time(c.getInt(column)));
                            break;
                        case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE:
                            // release date is stored internally as just the year
                            int year = c.getInt(column);
                            String dateTime = Integer.toString(year) + "0101T000000";
                            result.append(handle, propertyCode, dateTime);
                            break;
                        case MtpConstants.PROPERTY_PERSISTENT_UID:
                            // PUID is concatenation of storageID and object handle
                            long puid = c.getLong(column);
                            puid <<= 32;
                            puid += handle;
                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT128, puid);
                            break;
                        case MtpConstants.PROPERTY_TRACK:
                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT16,
                                        c.getInt(column) % 1000);
                            break;
                        case MtpConstants.PROPERTY_ARTIST:
                            result.append(handle, propertyCode,
                                    queryAudio(handle, Audio.AudioColumns.ARTIST));
                            break;
                        case MtpConstants.PROPERTY_ALBUM_NAME:
                            result.append(handle, propertyCode,
                                    queryAudio(handle, Audio.AudioColumns.ALBUM));
                            break;
                        case MtpConstants.PROPERTY_GENRE:
                            String genre = queryGenre(handle);
                            if (genre != null) {
                                result.append(handle, propertyCode, genre);
                            } else {
                                result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
                            }
                            break;
                        case MtpConstants.PROPERTY_AUDIO_WAVE_CODEC:
                        case MtpConstants.PROPERTY_AUDIO_BITRATE:
                        case MtpConstants.PROPERTY_SAMPLE_RATE:
                            // we don't have these in our database, so return 0
                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT32, 0);
                            break;
                        case MtpConstants.PROPERTY_BITRATE_TYPE:
                        case MtpConstants.PROPERTY_NUMBER_OF_CHANNELS:
                            // we don't have these in our database, so return 0
                            result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 0);
                            break;
                        default:
                            if (property.type == MtpConstants.TYPE_STR) {
                                result.append(handle, propertyCode, c.getString(column));
                            } else if (property.type == MtpConstants.TYPE_UNDEFINED) {
                                result.append(handle, propertyCode, property.type, 0);
                            } else {
                                result.append(handle, propertyCode, property.type,
                                        c.getLong(column));
                            }
                            break;
                    }
                }
            }

            return result;
        } catch (RemoteException e) {
            return new MtpPropertyList(0, MtpConstants.RESPONSE_GENERAL_ERROR);
        } finally {
            if (c != null) {
                c.close();
            }
        }
        // impossible to get here, so no return statement
    
private static java.lang.StringnameFromPath(java.lang.String path)

        // extract name from full path
        int start = 0;
        int lastSlash = path.lastIndexOf('/");
        if (lastSlash >= 0) {
            start = lastSlash + 1;
        }
        int end = path.length();
        if (end - start > 255) {
            end = start + 255;
        }
        return path.substring(start, end);
    
private java.lang.StringqueryAudio(int id, java.lang.String column)

        Cursor c = null;
        try {
            c = mProvider.query(mPackageName, Audio.Media.getContentUri(mVolumeName),
                            new String [] { Files.FileColumns._ID, column },
                            ID_WHERE, new String[] { Integer.toString(id) }, null, null);
            if (c != null && c.moveToNext()) {
                return c.getString(1);
            } else {
                return "";
            }
        } catch (Exception e) {
            return null;
        } finally {
            if (c != null) {
                c.close();
            }
        }
    
private java.lang.StringqueryGenre(int id)

        Cursor c = null;
        try {
            Uri uri = Audio.Genres.getContentUriForAudioId(mVolumeName, id);
            c = mProvider.query(mPackageName, uri,
                            new String [] { Files.FileColumns._ID, Audio.GenresColumns.NAME },
                            null, null, null, null);
            if (c != null && c.moveToNext()) {
                return c.getString(1);
            } else {
                return "";
            }
        } catch (Exception e) {
            Log.e(TAG, "queryGenre exception", e);
            return null;
        } finally {
            if (c != null) {
                c.close();
            }
        }
    
private java.lang.LongqueryLong(int id, java.lang.String column)

        Cursor c = null;
        try {
            // for now we are only reading properties from the "objects" table
            c = mProvider.query(mPackageName, mUri,
                            new String [] { Files.FileColumns._ID, column },
                            ID_WHERE, new String[] { Integer.toString(id) }, null, null);
            if (c != null && c.moveToNext()) {
                return new Long(c.getLong(1));
            }
        } catch (Exception e) {
        } finally {
            if (c != null) {
                c.close();
            }
        }
        return null;
    
private java.lang.StringqueryString(int id, java.lang.String column)

        Cursor c = null;
        try {
            // for now we are only reading properties from the "objects" table
            c = mProvider.query(mPackageName, mUri,
                            new String [] { Files.FileColumns._ID, column },
                            ID_WHERE, new String[] { Integer.toString(id) }, null, null);
            if (c != null && c.moveToNext()) {
                return c.getString(1);
            } else {
                return "";
            }
        } catch (Exception e) {
            return null;
        } finally {
            if (c != null) {
                c.close();
            }
        }