17d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood/* 27d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 37d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * 47d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 57d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * you may not use this file except in compliance with the License. 67d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * You may obtain a copy of the License at 77d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * 87d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 97d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * 107d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * Unless required by applicable law or agreed to in writing, software 117d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * See the License for the specific language governing permissions and 147d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood * limitations under the License. 157d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood */ 167d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 170cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodpackage android.mtp; 187d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 197d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.content.IContentProvider; 207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.database.Cursor; 217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.net.Uri; 227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.os.RemoteException; 237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.provider.MediaStore; 247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.provider.MediaStore.Audio; 257d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.provider.MediaStore.Files; 267d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.provider.MediaStore.Images; 277d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.provider.MediaStore.MediaColumns; 287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport android.util.Log; 297d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 307d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport java.util.ArrayList; 317d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 327d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodclass MtpPropertyGroup { 337d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 347d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private static final String TAG = "MtpPropertyGroup"; 357d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private class Property { 377d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // MTP property code 387d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int code; 397d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // MTP data type 407d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int type; 417d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // column index for our query 427d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int column; 437d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 447d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Property(int code, int type, int column) { 457d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood this.code = code; 467d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood this.type = type; 477d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood this.column = column; 487d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 497d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 507d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 517d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final MtpDatabase mDatabase; 527d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final IContentProvider mProvider; 537d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final String mVolumeName; 547d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final Uri mUri; 557d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 567d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // list of all properties in this group 577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final Property[] mProperties; 587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 597d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // list of columns for database query 607d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private String[] mColumns; 617d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 627d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private static final String ID_WHERE = Files.FileColumns._ID + "=?"; 634356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood private static final String FORMAT_WHERE = Files.FileColumns.FORMAT + "=?"; 644356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood private static final String ID_FORMAT_WHERE = ID_WHERE + " AND " + FORMAT_WHERE; 657d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?"; 664356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " + FORMAT_WHERE; 677d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // constructs a property group for a list of properties 687d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood public MtpPropertyGroup(MtpDatabase database, IContentProvider provider, String volume, 697d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int[] properties) { 707d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mDatabase = database; 717d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mProvider = provider; 727d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mVolumeName = volume; 737d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mUri = Files.getMtpObjectsUri(volume); 747d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 757d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int count = properties.length; 767d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood ArrayList<String> columns = new ArrayList<String>(count); 777d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood columns.add(Files.FileColumns._ID); 787d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 797d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mProperties = new Property[count]; 807d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood for (int i = 0; i < count; i++) { 817d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mProperties[i] = createProperty(properties[i], columns); 827d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 837d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood count = columns.size(); 847d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mColumns = new String[count]; 857d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood for (int i = 0; i < count; i++) { 867d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mColumns[i] = columns.get(i); 877d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 887d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 897d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 907d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private Property createProperty(int code, ArrayList<String> columns) { 917d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood String column = null; 927d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int type; 937d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 947d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood switch (code) { 957d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_STORAGE_ID: 96b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood column = Files.FileColumns.STORAGE_ID; 977d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UINT32; 987d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 997d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_OBJECT_FORMAT: 1007d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Files.FileColumns.FORMAT; 1017d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UINT16; 1027d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1037d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_PROTECTION_STATUS: 1047d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // protection status is always 0 1057d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UINT16; 1067d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1077d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_OBJECT_SIZE: 1087d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Files.FileColumns.SIZE; 1097d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UINT64; 1107d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1117d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_OBJECT_FILE_NAME: 1127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Files.FileColumns.DATA; 1137d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1147d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1157d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_NAME: 1167d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = MediaColumns.TITLE; 1177d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1187d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1197d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_DATE_MODIFIED: 1207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Files.FileColumns.DATE_MODIFIED; 1217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_DATE_ADDED: 1247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Files.FileColumns.DATE_ADDED; 1257d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1267d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1277d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE: 1287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Audio.AudioColumns.YEAR; 1297d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1307d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1317d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_PARENT_OBJECT: 1327d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Files.FileColumns.PARENT; 1337d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UINT32; 1347d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1357d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_PERSISTENT_UID: 1367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // PUID is concatenation of storageID and object handle 137b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood column = Files.FileColumns.STORAGE_ID; 1387d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UINT128; 1397d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1407d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_DURATION: 1417d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Audio.AudioColumns.DURATION; 1427d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UINT32; 1437d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1447d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_TRACK: 1457d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Audio.AudioColumns.TRACK; 1467d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UINT16; 1477d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1487d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_DISPLAY_NAME: 1497d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = MediaColumns.DISPLAY_NAME; 1507d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1517d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1527d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_ARTIST: 1537d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1547d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1557d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_ALBUM_NAME: 1567d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_ALBUM_ARTIST: 1597d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Audio.AudioColumns.ALBUM_ARTIST; 1607d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1617d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1627d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_GENRE: 1637d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // genre requires a special query 1647d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1657d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1667d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_COMPOSER: 1677d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Audio.AudioColumns.COMPOSER; 1687d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1697d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1707d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_DESCRIPTION: 1717d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood column = Images.ImageColumns.DESCRIPTION; 1727d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_STR; 1737d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1747d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood default: 1757d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood type = MtpConstants.TYPE_UNDEFINED; 1767d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Log.e(TAG, "unsupported property " + code); 1777d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 1787d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 1797d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 1807d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (column != null) { 1817d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood columns.add(column); 1827d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return new Property(code, type, columns.size() - 1); 1837d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 1847d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return new Property(code, type, -1); 1857d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 1867d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 1877d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 1887d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private String queryString(int id, String column) { 1897d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Cursor c = null; 1907d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood try { 1917d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // for now we are only reading properties from the "objects" table 1927d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c = mProvider.query(mUri, 1937d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood new String [] { Files.FileColumns._ID, column }, 19475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown ID_WHERE, new String[] { Integer.toString(id) }, null, null); 1957d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null && c.moveToNext()) { 1967d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return c.getString(1); 1977d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 1987d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return ""; 1997d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2007d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } catch (Exception e) { 2017d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return null; 2027d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } finally { 2037d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null) { 2047d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c.close(); 2057d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2067d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2077d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2087d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 2097d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private String queryAudio(int id, String column) { 2107d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Cursor c = null; 2117d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood try { 2127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c = mProvider.query(Audio.Media.getContentUri(mVolumeName), 2137d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood new String [] { Files.FileColumns._ID, column }, 21475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown ID_WHERE, new String[] { Integer.toString(id) }, null, null); 2157d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null && c.moveToNext()) { 2167d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return c.getString(1); 2177d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 2187d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return ""; 2197d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } catch (Exception e) { 2217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return null; 2227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } finally { 2237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null) { 2247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c.close(); 2257d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2267d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2277d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 2297d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private String queryGenre(int id) { 2307d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Cursor c = null; 2317d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood try { 2327d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Uri uri = Audio.Genres.getContentUriForAudioId(mVolumeName, id); 2337d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c = mProvider.query(uri, 2347d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood new String [] { Files.FileColumns._ID, Audio.GenresColumns.NAME }, 23575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown null, null, null, null); 2367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null && c.moveToNext()) { 2377d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return c.getString(1); 2387d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 2397d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return ""; 2407d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2417d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } catch (Exception e) { 2427d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Log.e(TAG, "queryGenre exception", e); 2437d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return null; 2447d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } finally { 2457d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null) { 2467d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c.close(); 2477d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2487d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2497d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2507d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 2517d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private Long queryLong(int id, String column) { 2527d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Cursor c = null; 2537d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood try { 2547d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // for now we are only reading properties from the "objects" table 2557d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c = mProvider.query(mUri, 2567d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood new String [] { Files.FileColumns._ID, column }, 25775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown ID_WHERE, new String[] { Integer.toString(id) }, null, null); 2587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null && c.moveToNext()) { 2597d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return new Long(c.getLong(1)); 2607d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2617d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } catch (Exception e) { 2627d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } finally { 2637d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null) { 2647d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c.close(); 2657d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2667d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2677d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return null; 2687d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2697d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 2707d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private static String nameFromPath(String path) { 2717d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // extract name from full path 2727d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int start = 0; 2737d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int lastSlash = path.lastIndexOf('/'); 2747d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (lastSlash >= 0) { 2757d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood start = lastSlash + 1; 2767d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2777d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int end = path.length(); 2787d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (end - start > 255) { 2797d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood end = start + 255; 2807d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2817d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return path.substring(start, end); 2827d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2837d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 284b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood MtpPropertyList getPropertyList(int handle, int format, int depth) { 285071b2b6739c83d3de806cda5d7be2aba33fde1afMike Lockwood //Log.d(TAG, "getPropertyList handle: " + handle + " format: " + format + " depth: " + depth); 2867d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (depth > 1) { 2877d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // we only support depth 0 and 1 2887d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // depth 0: single object, depth 1: immediate children 2897d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED); 2907d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 2917d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 2927d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood String where; 2937d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood String[] whereArgs; 2947d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (format == 0) { 2954356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood if (handle == 0xFFFFFFFF) { 2964356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood // select all objects 2974356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood where = null; 2984356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood whereArgs = null; 2997d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 3004356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood whereArgs = new String[] { Integer.toString(handle) }; 3014356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood if (depth == 1) { 3024356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood where = PARENT_WHERE; 3034356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood } else { 3044356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood where = ID_WHERE; 3054356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood } 3067d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3077d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 3084356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood if (handle == 0xFFFFFFFF) { 3094356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood // select all objects with given format 3104356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood where = FORMAT_WHERE; 3114356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood whereArgs = new String[] { Integer.toString(format) }; 3127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 3134356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood whereArgs = new String[] { Integer.toString(handle), Integer.toString(format) }; 3144356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood if (depth == 1) { 3154356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood where = PARENT_FORMAT_WHERE; 3164356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood } else { 3174356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood where = ID_FORMAT_WHERE; 3184356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood } 3197d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 3227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Cursor c = null; 3237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood try { 3247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // don't query if not necessary 3254356d81b34a57a4046d9fa2287c2d85b51c7ca24Mike Lockwood if (depth > 0 || handle == 0xFFFFFFFF || mColumns.length > 1) { 32675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown c = mProvider.query(mUri, mColumns, where, whereArgs, null, null); 3277d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c == null) { 3287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return new MtpPropertyList(0, MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE); 3297d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3307d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3317d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 3327d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int count = (c == null ? 1 : c.getCount()); 3337d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpPropertyList result = new MtpPropertyList(count * mProperties.length, 3347d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.RESPONSE_OK); 3357d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 3367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // iterate over all objects in the query 3377d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood for (int objectIndex = 0; objectIndex < count; objectIndex++) { 3387d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null) { 3397d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c.moveToNext(); 340fd22edc66818e0336597e23dafc9db4dcfb6878eMike Lockwood handle = (int)c.getLong(0); 3417d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3427d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 3437d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // iterate over all properties in the query for the given object 3447d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood for (int propertyIndex = 0; propertyIndex < mProperties.length; propertyIndex++) { 3457d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood Property property = mProperties[propertyIndex]; 3467d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int propertyCode = property.code; 3477d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int column = property.column; 3487d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 3497d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // handle some special cases 3507d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood switch (propertyCode) { 3517d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_PROTECTION_STATUS: 3527d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // protection status is always 0 3537d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 0); 3547d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 3557d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_OBJECT_FILE_NAME: 3567d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // special case - need to extract file name from full path 3577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood String value = c.getString(column); 3587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (value != null) { 3597d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, nameFromPath(value)); 3607d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 3617d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE); 3627d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3637d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 3647d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_NAME: 3657d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // first try title 3667d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood String name = c.getString(column); 3677d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // then try name 3687d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (name == null) { 3697d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood name = queryString(handle, Audio.PlaylistsColumns.NAME); 3707d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3717d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // if title and name fail, extract name from full path 3727d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (name == null) { 3737d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood name = queryString(handle, Files.FileColumns.DATA); 3747d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (name != null) { 3757d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood name = nameFromPath(name); 3767d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3777d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3787d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (name != null) { 3797d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, name); 3807d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 3817d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE); 3827d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 3837d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 3847d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_DATE_MODIFIED: 3857d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_DATE_ADDED: 3867d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // convert from seconds to DateTime 3877d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, format_date_time(c.getInt(column))); 3887d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 3897d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE: 3907d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // release date is stored internally as just the year 3917d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int year = c.getInt(column); 3927d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood String dateTime = Integer.toString(year) + "0101T000000"; 3937d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, dateTime); 3947d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 3957d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_PERSISTENT_UID: 3967d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // PUID is concatenation of storageID and object handle 397b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood long puid = c.getLong(column); 3987d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood puid <<= 32; 3997d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood puid += handle; 4007d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, MtpConstants.TYPE_UINT128, puid); 4017d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 4027d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_TRACK: 4037d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 4047d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c.getInt(column) % 1000); 4057d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 4067d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_ARTIST: 4077d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, 4087d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood queryAudio(handle, Audio.AudioColumns.ARTIST)); 4097d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 4107d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_ALBUM_NAME: 4117d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, 4127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood queryAudio(handle, Audio.AudioColumns.ALBUM)); 4137d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 4147d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case MtpConstants.PROPERTY_GENRE: 4157d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood String genre = queryGenre(handle); 4167d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (genre != null) { 4177d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, genre); 4187d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 4197d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE); 4207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 4217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 4227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood default: 4237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (property.type == MtpConstants.TYPE_STR) { 4247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, c.getString(column)); 4257d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else if (property.type == MtpConstants.TYPE_UNDEFINED) { 4267d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, property.type, 0); 4277d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 4287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood result.append(handle, propertyCode, property.type, 4297d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c.getLong(column)); 4307d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 4317d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood break; 4327d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 4337d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 4347d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 4357d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 4367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return result; 4377d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } catch (RemoteException e) { 4387d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return new MtpPropertyList(0, MtpConstants.RESPONSE_GENERAL_ERROR); 4397d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } finally { 4407d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (c != null) { 4417d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood c.close(); 4427d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 4437d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 4447d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // impossible to get here, so no return statement 4457d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } 4467d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 4477d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private native String format_date_time(long seconds); 4487d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood} 449