blob: 0f9b898448ec6a4ae66e87a24bfa8899d0840c37 [file] [log] [blame]
Mike Lockwood16864ba2010-05-11 17:16:59 -04001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mike Lockwoodb14e5882010-06-29 18:11:52 -040017#define LOG_TAG "MtpDatabase"
18
19#include "MtpDebug.h"
Mike Lockwood16864ba2010-05-11 17:16:59 -040020#include "MtpDatabase.h"
21#include "MtpDataPacket.h"
Mike Lockwood335dd2b2010-05-19 10:33:39 -040022#include "MtpUtils.h"
Mike Lockwood16864ba2010-05-11 17:16:59 -040023#include "SqliteDatabase.h"
24#include "SqliteStatement.h"
25
26#include <stdio.h>
Mike Lockwoodfceef462010-05-14 15:35:17 -040027#include <stdlib.h>
Mike Lockwood16864ba2010-05-11 17:16:59 -040028#include <sqlite3.h>
29
Mike Lockwood7850ef92010-05-14 10:10:36 -040030namespace android {
31
Mike Lockwoodfceef462010-05-14 15:35:17 -040032#define FILE_ID_COLUMN 1
33#define FILE_PATH_COLUMN 2
34#define FILE_FORMAT_COLUMN 3
35#define FILE_PARENT_COLUMN 4
36#define FILE_STORAGE_COLUMN 5
37#define FILE_SIZE_COLUMN 6
38#define FILE_MODIFIED_COLUMN 7
Mike Lockwood16864ba2010-05-11 17:16:59 -040039
Mike Lockwoodfceef462010-05-14 15:35:17 -040040#define AUDIO_ID_COLUMN 1
41#define AUDIO_TITLE_COLUMN 2
42#define AUDIO_ARTIST_COLUMN 3
43#define AUDIO_ALBUM_COLUMN 4
44#define AUDIO_ALBUM_ARTIST_COLUMN 5
45#define AUDIO_GENRE_COLUMN 6
46#define AUDIO_COMPOSER_COLUMN 7
47#define AUDIO_TRACK_NUMBER_COLUMN 8
48#define AUDIO_YEAR_COLUMN 9
49#define AUDIO_DURATION_COLUMN 10
50#define AUDIO_USE_COUNT_COLUMN 11
51#define AUDIO_SAMPLE_RATE_COLUMN 12
52#define AUDIO_NUM_CHANNELS_COLUMN 13
53#define AUDIO_AUDIO_WAVE_CODEC_COLUMN 14
54#define AUDIO_AUDIO_BIT_RATE_COLUMN 15
55
56#define FILE_TABLE_CREATE "CREATE TABLE IF NOT EXISTS files (" \
Mike Lockwood16864ba2010-05-11 17:16:59 -040057 "_id INTEGER PRIMARY KEY," \
58 "path TEXT," \
59 "format INTEGER," \
60 "parent INTEGER," \
61 "storage INTEGER," \
62 "size INTEGER," \
Mike Lockwoodfceef462010-05-14 15:35:17 -040063 "date_modified INTEGER" \
64 ");"
65
66#define AUDIO_TABLE_CREATE "CREATE TABLE IF NOT EXISTS audio (" \
67 "id INTEGER PRIMARY KEY," \
68 "title TEXT," \
69 "artist TEXT," \
70 "album TEXT," \
71 "album_artist TEXT," \
72 "genre TEXT," \
73 "composer TEXT," \
74 "track_number INTEGER," \
75 "year INTEGER," \
76 "duration INTEGER," \
77 "use_count INTEGER," \
78 "sample_rate INTEGER," \
79 "num_channels INTEGER," \
80 "audio_wave_codec TEXT," \
81 "audio_bit_rate INTEGER" \
Mike Lockwood16864ba2010-05-11 17:16:59 -040082 ");"
83
84#define PATH_INDEX_CREATE "CREATE INDEX IF NOT EXISTS path_index on files(path);"
85
Mike Lockwoodfceef462010-05-14 15:35:17 -040086#define FILE_ID_QUERY "SELECT _id,format FROM files WHERE path = ?;"
Mike Lockwood16864ba2010-05-11 17:16:59 -040087#define FILE_PATH_QUERY "SELECT path,size FROM files WHERE _id = ?"
88
Mike Lockwoodfceef462010-05-14 15:35:17 -040089#define GET_OBJECT_INFO_QUERY "SELECT storage,format,parent,path,size,date_modified FROM files WHERE _id = ?;"
90#define FILE_INSERT "INSERT INTO files VALUES(?,?,?,?,?,?,?);"
91#define FILE_DELETE "DELETE FROM files WHERE _id = ?;"
92
93#define AUDIO_INSERT "INSERT INTO audio VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"
94#define AUDIO_DELETE "DELETE FROM audio WHERE id = ?;"
Mike Lockwood16864ba2010-05-11 17:16:59 -040095
Mike Lockwood16864ba2010-05-11 17:16:59 -040096struct PropertyTableEntry {
97 MtpObjectProperty property;
98 int type;
99 const char* columnName;
100};
101
102static const PropertyTableEntry kPropertyTable[] = {
103 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32, "parent" },
104 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, "storage" },
105 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT32, "format" },
106 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR, "path" },
107 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64, "size" },
Mike Lockwood16864ba2010-05-11 17:16:59 -0400108 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR, "date_modified" },
109};
110
111static bool getPropertyInfo(MtpObjectProperty property, int& type, const char*& columnName) {
112 int count = sizeof(kPropertyTable) / sizeof(kPropertyTable[0]);
113 const PropertyTableEntry* entry = kPropertyTable;
114 for (int i = 0; i < count; i++, entry++) {
115 if (entry->property == property) {
116 type = entry->type;
117 columnName = entry->columnName;
118 return true;
119 }
120 }
121 return false;
122}
123
124
Mike Lockwoodfceef462010-05-14 15:35:17 -0400125
Mike Lockwood16864ba2010-05-11 17:16:59 -0400126MtpDatabase::MtpDatabase()
127 : mFileIdQuery(NULL),
Mike Lockwooda177ae12010-06-14 09:11:19 -0700128 mFilePathQuery(NULL),
Mike Lockwood16864ba2010-05-11 17:16:59 -0400129 mObjectInfoQuery(NULL),
130 mFileInserter(NULL),
Mike Lockwoodfceef462010-05-14 15:35:17 -0400131 mFileDeleter(NULL),
132 mAudioInserter(NULL),
133 mAudioDeleter(NULL)
Mike Lockwood16864ba2010-05-11 17:16:59 -0400134{
135}
136
137MtpDatabase::~MtpDatabase() {
138}
139
140bool MtpDatabase::open(const char* path, bool create) {
141 if (!SqliteDatabase::open(path, create))
142 return false;
143
Mike Lockwoodfceef462010-05-14 15:35:17 -0400144 // create tables and indices if necessary
145 if (!exec(FILE_TABLE_CREATE)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400146 LOGE("could not create file table");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400147 return false;
148 }
149 if (!exec(PATH_INDEX_CREATE)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400150 LOGE("could not path index on file table");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400151 return false;
152 }
Mike Lockwoodfceef462010-05-14 15:35:17 -0400153 if (!exec(AUDIO_TABLE_CREATE)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400154 LOGE("could not create file table");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400155 return false;
156 }
157
158 if (!mFileIdQuery) {
159 mFileIdQuery = new SqliteStatement(this);
160 if (!mFileIdQuery->prepare(FILE_ID_QUERY)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400161 LOGE("could not compile FILE_ID_QUERY");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400162 exit(-1);
163 }
164 }
165 if (!mFilePathQuery) {
166 mFilePathQuery = new SqliteStatement(this);
167 if (!mFilePathQuery->prepare(FILE_PATH_QUERY)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400168 LOGE("could not compile FILE_PATH_QUERY");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400169 exit(-1);
170 }
171 }
172 if (!mObjectInfoQuery) {
173 mObjectInfoQuery = new SqliteStatement(this);
174 if (!mObjectInfoQuery->prepare(GET_OBJECT_INFO_QUERY)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400175 LOGE("could not compile GET_OBJECT_INFO_QUERY");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400176 exit(-1);
177 }
178 }
179 if (!mFileInserter) {
180 mFileInserter = new SqliteStatement(this);
181 if (!mFileInserter->prepare(FILE_INSERT)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400182 LOGE("could not compile FILE_INSERT\n");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400183 exit(-1);
184 }
185 }
186 if (!mFileDeleter) {
187 mFileDeleter = new SqliteStatement(this);
188 if (!mFileDeleter->prepare(FILE_DELETE)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400189 LOGE("could not compile FILE_DELETE\n");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400190 exit(-1);
191 }
192 }
193 if (!mAudioInserter) {
194 mAudioInserter = new SqliteStatement(this);
195 if (!mAudioInserter->prepare(AUDIO_INSERT)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400196 LOGE("could not compile AUDIO_INSERT\n");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400197 exit(-1);
198 }
199 }
200 if (!mAudioDeleter) {
201 mAudioDeleter = new SqliteStatement(this);
202 if (!mAudioDeleter->prepare(AUDIO_DELETE)) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400203 LOGE("could not compile AUDIO_DELETE\n");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400204 exit(-1);
205 }
206 }
207
Mike Lockwood16864ba2010-05-11 17:16:59 -0400208 return true;
209}
210
Mike Lockwoodfceef462010-05-14 15:35:17 -0400211uint32_t MtpDatabase::getTableForFile(MtpObjectFormat format) {
212 switch (format) {
213 case MTP_FORMAT_AIFF:
214 case MTP_FORMAT_WAV:
215 case MTP_FORMAT_MP3:
216 case MTP_FORMAT_FLAC:
217 case MTP_FORMAT_UNDEFINED_AUDIO:
218 case MTP_FORMAT_WMA:
219 case MTP_FORMAT_OGG:
220 case MTP_FORMAT_AAC:
221 case MTP_FORMAT_AUDIBLE:
222 return kObjectHandleTableAudio;
223 case MTP_FORMAT_AVI:
224 case MTP_FORMAT_MPEG:
225 case MTP_FORMAT_ASF:
226 case MTP_FORMAT_UNDEFINED_VIDEO:
227 case MTP_FORMAT_WMV:
228 case MTP_FORMAT_MP4_CONTAINER:
229 case MTP_FORMAT_MP2:
230 case MTP_FORMAT_3GP_CONTAINER:
231 return kObjectHandleTableVideo;
232 case MTP_FORMAT_DEFINED:
233 case MTP_FORMAT_EXIF_JPEG:
234 case MTP_FORMAT_TIFF_EP:
235 case MTP_FORMAT_FLASHPIX:
236 case MTP_FORMAT_BMP:
237 case MTP_FORMAT_CIFF:
238 case MTP_FORMAT_GIF:
239 case MTP_FORMAT_JFIF:
240 case MTP_FORMAT_CD:
241 case MTP_FORMAT_PICT:
242 case MTP_FORMAT_PNG:
243 case MTP_FORMAT_TIFF:
244 case MTP_FORMAT_TIFF_IT:
245 case MTP_FORMAT_JP2:
246 case MTP_FORMAT_JPX:
247 case MTP_FORMAT_WINDOWS_IMAGE_FORMAT:
248 return kObjectHandleTableImage;
249 case MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST:
250 case MTP_FORMAT_ABSTRACT_AV_PLAYLIST:
251 case MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST:
252 case MTP_FORMAT_WPL_PLAYLIST:
253 case MTP_FORMAT_M3U_PLAYLIST:
254 case MTP_FORMAT_MPL_PLAYLIST:
255 case MTP_FORMAT_ASX_PLAYLIST:
256 case MTP_FORMAT_PLS_PLAYLIST:
257 return kObjectHandleTablePlaylist;
258 default:
259 return kObjectHandleTableFile;
260 }
261}
262
263MtpObjectHandle MtpDatabase::getObjectHandle(const char* path) {
264 mFileIdQuery->reset();
265 mFileIdQuery->bind(1, path);
266 if (mFileIdQuery->step()) {
267 int row = mFileIdQuery->getColumnInt(0);
268 if (row > 0) {
269 MtpObjectFormat format = mFileIdQuery->getColumnInt(1);
270 row |= getTableForFile(format);
271 return row;
272 }
273 }
274
275 return 0;
276}
277
Mike Lockwood16864ba2010-05-11 17:16:59 -0400278MtpObjectHandle MtpDatabase::addFile(const char* path,
279 MtpObjectFormat format,
280 MtpObjectHandle parent,
281 MtpStorageID storage,
282 uint64_t size,
Mike Lockwood16864ba2010-05-11 17:16:59 -0400283 time_t modified) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400284 mFileInserter->bind(FILE_PATH_COLUMN, path);
285 mFileInserter->bind(FILE_FORMAT_COLUMN, format);
286 mFileInserter->bind(FILE_PARENT_COLUMN, parent);
287 mFileInserter->bind(FILE_STORAGE_COLUMN, storage);
288 mFileInserter->bind(FILE_SIZE_COLUMN, size);
289 mFileInserter->bind(FILE_MODIFIED_COLUMN, modified);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400290 mFileInserter->step();
291 mFileInserter->reset();
Mike Lockwoodfceef462010-05-14 15:35:17 -0400292 int result = lastInsertedRow();
293 return (result <= 0 ? kInvalidObjectHandle : result);
294}
295
296MtpObjectHandle MtpDatabase::addAudioFile(MtpObjectHandle handle) {
297 mAudioInserter->bind(AUDIO_ID_COLUMN, handle);
298 mAudioInserter->step();
299 mAudioInserter->reset();
300 int result = lastInsertedRow();
301 handle |= kObjectHandleTableAudio;
302 return (result > 0 ? handle : kInvalidObjectHandle);
303}
304
305MtpObjectHandle MtpDatabase::addAudioFile(MtpObjectHandle handle,
306 const char* title,
307 const char* artist,
308 const char* album,
309 const char* albumArtist,
310 const char* genre,
311 const char* composer,
312 const char* mimeType,
313 int track,
314 int year,
315 int duration) {
316 mAudioInserter->bind(AUDIO_ID_COLUMN, handle);
317 if (title) mAudioInserter->bind(AUDIO_TITLE_COLUMN, title);
318 if (artist) mAudioInserter->bind(AUDIO_ARTIST_COLUMN, artist);
319 if (album) mAudioInserter->bind(AUDIO_ALBUM_COLUMN, album);
320 if (albumArtist) mAudioInserter->bind(AUDIO_ALBUM_ARTIST_COLUMN, albumArtist);
321 if (genre) mAudioInserter->bind(AUDIO_GENRE_COLUMN, genre);
322 if (composer) mAudioInserter->bind(AUDIO_COMPOSER_COLUMN, composer);
323 if (track) mAudioInserter->bind(AUDIO_TRACK_NUMBER_COLUMN, track);
324 if (year) mAudioInserter->bind(AUDIO_YEAR_COLUMN, year);
325 if (duration) mAudioInserter->bind(AUDIO_DURATION_COLUMN, duration);
326 mAudioInserter->step();
327 mAudioInserter->reset();
328 int result = lastInsertedRow();
329 if (result <= 0)
330 return kInvalidObjectHandle;
331 result |= kObjectHandleTableAudio;
332 return result;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400333}
334
335MtpObjectHandleList* MtpDatabase::getObjectList(MtpStorageID storageID,
336 MtpObjectFormat format,
337 MtpObjectHandle parent) {
338 bool whereStorage = (storageID != 0xFFFFFFFF);
339 bool whereFormat = (format != 0);
340 bool whereParent = (parent != 0);
341 char intBuffer[20];
342
Mike Lockwoodfceef462010-05-14 15:35:17 -0400343 MtpString query("SELECT _id,format FROM files");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400344 if (whereStorage || whereFormat || whereParent)
345 query += " WHERE";
346 if (whereStorage) {
347 snprintf(intBuffer, sizeof(intBuffer), "%d", storageID);
348 query += " storage = ";
349 query += intBuffer;
350 }
351 if (whereFormat) {
352 snprintf(intBuffer, sizeof(intBuffer), "%d", format);
353 if (whereStorage)
354 query += " AND";
355 query += " format = ";
356 query += intBuffer;
357 }
358 if (whereParent) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400359 if (parent != MTP_PARENT_ROOT)
360 parent &= kObjectHandleIndexMask;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400361 snprintf(intBuffer, sizeof(intBuffer), "%d", parent);
362 if (whereStorage || whereFormat)
363 query += " AND";
364 query += " parent = ";
365 query += intBuffer;
366 }
367 query += ";";
368
369 SqliteStatement stmt(this);
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400370 LOGV("%s", (const char *)query);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400371 stmt.prepare(query);
372
373 MtpObjectHandleList* list = new MtpObjectHandleList();
374 while (!stmt.isDone()) {
375 if (stmt.step()) {
376 int index = stmt.getColumnInt(0);
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400377 LOGV("stmt.getColumnInt returned %d", index);
Mike Lockwoodfceef462010-05-14 15:35:17 -0400378 if (index > 0) {
379 MtpObjectFormat format = stmt.getColumnInt(1);
380 index |= getTableForFile(format);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400381 list->push(index);
Mike Lockwoodfceef462010-05-14 15:35:17 -0400382 }
Mike Lockwood16864ba2010-05-11 17:16:59 -0400383 }
384 }
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400385 LOGV("list size: %d", list->size());
Mike Lockwood16864ba2010-05-11 17:16:59 -0400386 return list;
387}
388
Mike Lockwoodfceef462010-05-14 15:35:17 -0400389
Mike Lockwood16864ba2010-05-11 17:16:59 -0400390MtpResponseCode MtpDatabase::getObjectProperty(MtpObjectHandle handle,
391 MtpObjectProperty property,
392 MtpDataPacket& packet) {
393 int type;
394 const char* columnName;
395 char intBuffer[20];
396
Mike Lockwoodfceef462010-05-14 15:35:17 -0400397 if (handle != MTP_PARENT_ROOT)
398 handle &= kObjectHandleIndexMask;
399
Mike Lockwood16864ba2010-05-11 17:16:59 -0400400 if (!getPropertyInfo(property, type, columnName))
401 return MTP_RESPONSE_INVALID_OBJECT_PROP_CODE;
402 snprintf(intBuffer, sizeof(intBuffer), "%d", handle);
403
404 MtpString query("SELECT ");
405 query += columnName;
406 query += " FROM files WHERE _id = ";
407 query += intBuffer;
408 query += ";";
409
410 SqliteStatement stmt(this);
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400411 LOGV("%s", (const char *)query);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400412 stmt.prepare(query);
413
414 if (!stmt.step())
415 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
416
417 switch (type) {
418 case MTP_TYPE_INT8:
419 packet.putInt8(stmt.getColumnInt(0));
420 break;
421 case MTP_TYPE_UINT8:
422 packet.putUInt8(stmt.getColumnInt(0));
423 break;
424 case MTP_TYPE_INT16:
425 packet.putInt16(stmt.getColumnInt(0));
426 break;
427 case MTP_TYPE_UINT16:
428 packet.putUInt16(stmt.getColumnInt(0));
429 break;
430 case MTP_TYPE_INT32:
431 packet.putInt32(stmt.getColumnInt(0));
432 break;
433 case MTP_TYPE_UINT32:
434 packet.putUInt32(stmt.getColumnInt(0));
435 break;
436 case MTP_TYPE_INT64:
437 packet.putInt64(stmt.getColumnInt64(0));
438 break;
439 case MTP_TYPE_UINT64:
440 packet.putUInt64(stmt.getColumnInt64(0));
441 break;
442 case MTP_TYPE_STR:
443 packet.putString(stmt.getColumnString(0));
444 break;
445 default:
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400446 LOGE("unsupported object type\n");
Mike Lockwood16864ba2010-05-11 17:16:59 -0400447 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
448 }
449 return MTP_RESPONSE_OK;
450}
451
452MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
453 MtpDataPacket& packet) {
454 char date[20];
455
Mike Lockwoodfceef462010-05-14 15:35:17 -0400456 if (handle != MTP_PARENT_ROOT)
457 handle &= kObjectHandleIndexMask;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400458
Mike Lockwoodfceef462010-05-14 15:35:17 -0400459 mObjectInfoQuery->reset();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400460 mObjectInfoQuery->bind(1, handle);
461 if (!mObjectInfoQuery->step())
462 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
463
464 MtpStorageID storageID = mObjectInfoQuery->getColumnInt(0);
465 MtpObjectFormat format = mObjectInfoQuery->getColumnInt(1);
466 MtpObjectHandle parent = mObjectInfoQuery->getColumnInt(2);
467 // extract name from path. do we want a separate database entry for this?
468 const char* name = mObjectInfoQuery->getColumnString(3);
469 const char* lastSlash = strrchr(name, '/');
470 if (lastSlash)
471 name = lastSlash + 1;
472 int64_t size = mObjectInfoQuery->getColumnInt64(4);
Mike Lockwoodfceef462010-05-14 15:35:17 -0400473 time_t modified = mObjectInfoQuery->getColumnInt(5);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400474 int associationType = (format == MTP_FORMAT_ASSOCIATION ?
475 MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
476 MTP_ASSOCIATION_TYPE_UNDEFINED);
477
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400478 LOGV("storageID: %d, format: %d, parent: %d", storageID, format, parent);
Mike Lockwood16864ba2010-05-11 17:16:59 -0400479
480 packet.putUInt32(storageID);
481 packet.putUInt16(format);
482 packet.putUInt16(0); // protection status
483 packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
484 packet.putUInt16(0); // thumb format
485 packet.putUInt32(0); // thumb compressed size
486 packet.putUInt32(0); // thumb pix width
487 packet.putUInt32(0); // thumb pix height
488 packet.putUInt32(0); // image pix width
489 packet.putUInt32(0); // image pix height
490 packet.putUInt32(0); // image bit depth
491 packet.putUInt32(parent);
492 packet.putUInt16(associationType);
493 packet.putUInt32(0); // association desc
494 packet.putUInt32(0); // sequence number
495 packet.putString(name); // file name
Mike Lockwoodfceef462010-05-14 15:35:17 -0400496 packet.putEmptyString();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400497 formatDateTime(modified, date, sizeof(date));
498 packet.putString(date); // date modified
499 packet.putEmptyString(); // keywords
500
501 return MTP_RESPONSE_OK;
502}
503
504bool MtpDatabase::getObjectFilePath(MtpObjectHandle handle,
505 MtpString& filePath,
506 int64_t& fileLength) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400507 if (handle != MTP_PARENT_ROOT)
508 handle &= kObjectHandleIndexMask;
509 mFilePathQuery->reset();
Mike Lockwood16864ba2010-05-11 17:16:59 -0400510 mFilePathQuery->bind(1, handle);
511 if (!mFilePathQuery->step())
512 return false;
513
514 const char* path = mFilePathQuery->getColumnString(0);
515 if (!path)
516 return false;
517 filePath = path;
518 fileLength = mFilePathQuery->getColumnInt64(1);
519 return true;
520}
521
522bool MtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodfceef462010-05-14 15:35:17 -0400523 uint32_t table = handle & kObjectHandleTableMask;
524 handle &= kObjectHandleIndexMask;
Mike Lockwood16864ba2010-05-11 17:16:59 -0400525 mFileDeleter->bind(1, handle);
526 mFileDeleter->step();
527 mFileDeleter->reset();
Mike Lockwoodfceef462010-05-14 15:35:17 -0400528 if (table == kObjectHandleTableAudio) {
529 mAudioDeleter->bind(1, handle);
530 mAudioDeleter->step();
531 mAudioDeleter->reset();
532 }
533
Mike Lockwood16864ba2010-05-11 17:16:59 -0400534 return true;
535}
536
Mike Lockwoodfceef462010-05-14 15:35:17 -0400537MtpObjectHandle* MtpDatabase::getFileList(int& outCount) {
538 MtpObjectHandle* result = NULL;
539 int count = 0;
540 SqliteStatement stmt(this);
541 stmt.prepare("SELECT count(*) FROM files;");
542
543 MtpObjectHandleList* list = new MtpObjectHandleList();
544 if (stmt.step())
545 count = stmt.getColumnInt(0);
546
547 if (count > 0) {
548 result = new MtpObjectHandle[count];
549 memset(result, 0, count * sizeof(*result));
550 SqliteStatement stmt2(this);
551 stmt2.prepare("SELECT _id,format FROM files;");
552
553 for (int i = 0; i < count; i++) {
554 if (!stmt2.step()) {
Mike Lockwoodb14e5882010-06-29 18:11:52 -0400555 LOGW("getFileList ended early");
Mike Lockwoodfceef462010-05-14 15:35:17 -0400556 count = i;
557 break;
558 }
559 MtpObjectHandle handle = stmt2.getColumnInt(0);
560 MtpObjectFormat format = stmt2.getColumnInt(1);
561 handle |= getTableForFile(format);
562 result[i] = handle;
563 }
564 }
565 outCount = count;
566 return result;
567}
568
Mike Lockwood16864ba2010-05-11 17:16:59 -0400569/*
570 for getObjectPropDesc
571
572 packet.putUInt16(property);
573 packet.putUInt16(dataType);
574 packet.putUInt8(getSet);
575 // default value DTS
576 packet.putUInt32(groupCode);
577 packet.putUInt8(formFlag);
578 // form, variable
579*/
Mike Lockwood7850ef92010-05-14 10:10:36 -0400580
581} // namespace android