MTP: Make MtpDatabase class abstract so we can have multiple implementations
Rename existing test database to MtpSqliteDatabase
This is the first step in transitioning to using the media provider database
Change-Id: I5f36c854c6e76a79137c267b000a52ced803776c
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/media/mtp/MtpDatabase.cpp b/media/mtp/MtpDatabase.cpp
index 0f9b898..eabd993 100644
--- a/media/mtp/MtpDatabase.cpp
+++ b/media/mtp/MtpDatabase.cpp
@@ -18,196 +18,14 @@
#include "MtpDebug.h"
#include "MtpDatabase.h"
-#include "MtpDataPacket.h"
-#include "MtpUtils.h"
-#include "SqliteDatabase.h"
-#include "SqliteStatement.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sqlite3.h>
+#include "MtpTypes.h"
+#include "mtp.h"
namespace android {
-#define FILE_ID_COLUMN 1
-#define FILE_PATH_COLUMN 2
-#define FILE_FORMAT_COLUMN 3
-#define FILE_PARENT_COLUMN 4
-#define FILE_STORAGE_COLUMN 5
-#define FILE_SIZE_COLUMN 6
-#define FILE_MODIFIED_COLUMN 7
-
-#define AUDIO_ID_COLUMN 1
-#define AUDIO_TITLE_COLUMN 2
-#define AUDIO_ARTIST_COLUMN 3
-#define AUDIO_ALBUM_COLUMN 4
-#define AUDIO_ALBUM_ARTIST_COLUMN 5
-#define AUDIO_GENRE_COLUMN 6
-#define AUDIO_COMPOSER_COLUMN 7
-#define AUDIO_TRACK_NUMBER_COLUMN 8
-#define AUDIO_YEAR_COLUMN 9
-#define AUDIO_DURATION_COLUMN 10
-#define AUDIO_USE_COUNT_COLUMN 11
-#define AUDIO_SAMPLE_RATE_COLUMN 12
-#define AUDIO_NUM_CHANNELS_COLUMN 13
-#define AUDIO_AUDIO_WAVE_CODEC_COLUMN 14
-#define AUDIO_AUDIO_BIT_RATE_COLUMN 15
-
-#define FILE_TABLE_CREATE "CREATE TABLE IF NOT EXISTS files (" \
- "_id INTEGER PRIMARY KEY," \
- "path TEXT," \
- "format INTEGER," \
- "parent INTEGER," \
- "storage INTEGER," \
- "size INTEGER," \
- "date_modified INTEGER" \
- ");"
-
-#define AUDIO_TABLE_CREATE "CREATE TABLE IF NOT EXISTS audio (" \
- "id INTEGER PRIMARY KEY," \
- "title TEXT," \
- "artist TEXT," \
- "album TEXT," \
- "album_artist TEXT," \
- "genre TEXT," \
- "composer TEXT," \
- "track_number INTEGER," \
- "year INTEGER," \
- "duration INTEGER," \
- "use_count INTEGER," \
- "sample_rate INTEGER," \
- "num_channels INTEGER," \
- "audio_wave_codec TEXT," \
- "audio_bit_rate INTEGER" \
- ");"
-
-#define PATH_INDEX_CREATE "CREATE INDEX IF NOT EXISTS path_index on files(path);"
-
-#define FILE_ID_QUERY "SELECT _id,format FROM files WHERE path = ?;"
-#define FILE_PATH_QUERY "SELECT path,size FROM files WHERE _id = ?"
-
-#define GET_OBJECT_INFO_QUERY "SELECT storage,format,parent,path,size,date_modified FROM files WHERE _id = ?;"
-#define FILE_INSERT "INSERT INTO files VALUES(?,?,?,?,?,?,?);"
-#define FILE_DELETE "DELETE FROM files WHERE _id = ?;"
-
-#define AUDIO_INSERT "INSERT INTO audio VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);"
-#define AUDIO_DELETE "DELETE FROM audio WHERE id = ?;"
-
-struct PropertyTableEntry {
- MtpObjectProperty property;
- int type;
- const char* columnName;
-};
-
-static const PropertyTableEntry kPropertyTable[] = {
- { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32, "parent" },
- { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32, "storage" },
- { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT32, "format" },
- { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR, "path" },
- { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64, "size" },
- { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR, "date_modified" },
-};
-
-static bool getPropertyInfo(MtpObjectProperty property, int& type, const char*& columnName) {
- int count = sizeof(kPropertyTable) / sizeof(kPropertyTable[0]);
- const PropertyTableEntry* entry = kPropertyTable;
- for (int i = 0; i < count; i++, entry++) {
- if (entry->property == property) {
- type = entry->type;
- columnName = entry->columnName;
- return true;
- }
- }
- return false;
-}
-
-
-
-MtpDatabase::MtpDatabase()
- : mFileIdQuery(NULL),
- mFilePathQuery(NULL),
- mObjectInfoQuery(NULL),
- mFileInserter(NULL),
- mFileDeleter(NULL),
- mAudioInserter(NULL),
- mAudioDeleter(NULL)
-{
-}
-
MtpDatabase::~MtpDatabase() {
}
-bool MtpDatabase::open(const char* path, bool create) {
- if (!SqliteDatabase::open(path, create))
- return false;
-
- // create tables and indices if necessary
- if (!exec(FILE_TABLE_CREATE)) {
- LOGE("could not create file table");
- return false;
- }
- if (!exec(PATH_INDEX_CREATE)) {
- LOGE("could not path index on file table");
- return false;
- }
- if (!exec(AUDIO_TABLE_CREATE)) {
- LOGE("could not create file table");
- return false;
- }
-
- if (!mFileIdQuery) {
- mFileIdQuery = new SqliteStatement(this);
- if (!mFileIdQuery->prepare(FILE_ID_QUERY)) {
- LOGE("could not compile FILE_ID_QUERY");
- exit(-1);
- }
- }
- if (!mFilePathQuery) {
- mFilePathQuery = new SqliteStatement(this);
- if (!mFilePathQuery->prepare(FILE_PATH_QUERY)) {
- LOGE("could not compile FILE_PATH_QUERY");
- exit(-1);
- }
- }
- if (!mObjectInfoQuery) {
- mObjectInfoQuery = new SqliteStatement(this);
- if (!mObjectInfoQuery->prepare(GET_OBJECT_INFO_QUERY)) {
- LOGE("could not compile GET_OBJECT_INFO_QUERY");
- exit(-1);
- }
- }
- if (!mFileInserter) {
- mFileInserter = new SqliteStatement(this);
- if (!mFileInserter->prepare(FILE_INSERT)) {
- LOGE("could not compile FILE_INSERT\n");
- exit(-1);
- }
- }
- if (!mFileDeleter) {
- mFileDeleter = new SqliteStatement(this);
- if (!mFileDeleter->prepare(FILE_DELETE)) {
- LOGE("could not compile FILE_DELETE\n");
- exit(-1);
- }
- }
- if (!mAudioInserter) {
- mAudioInserter = new SqliteStatement(this);
- if (!mAudioInserter->prepare(AUDIO_INSERT)) {
- LOGE("could not compile AUDIO_INSERT\n");
- exit(-1);
- }
- }
- if (!mAudioDeleter) {
- mAudioDeleter = new SqliteStatement(this);
- if (!mAudioDeleter->prepare(AUDIO_DELETE)) {
- LOGE("could not compile AUDIO_DELETE\n");
- exit(-1);
- }
- }
-
- return true;
-}
-
uint32_t MtpDatabase::getTableForFile(MtpObjectFormat format) {
switch (format) {
case MTP_FORMAT_AIFF:
@@ -260,322 +78,4 @@
}
}
-MtpObjectHandle MtpDatabase::getObjectHandle(const char* path) {
- mFileIdQuery->reset();
- mFileIdQuery->bind(1, path);
- if (mFileIdQuery->step()) {
- int row = mFileIdQuery->getColumnInt(0);
- if (row > 0) {
- MtpObjectFormat format = mFileIdQuery->getColumnInt(1);
- row |= getTableForFile(format);
- return row;
- }
- }
-
- return 0;
-}
-
-MtpObjectHandle MtpDatabase::addFile(const char* path,
- MtpObjectFormat format,
- MtpObjectHandle parent,
- MtpStorageID storage,
- uint64_t size,
- time_t modified) {
- mFileInserter->bind(FILE_PATH_COLUMN, path);
- mFileInserter->bind(FILE_FORMAT_COLUMN, format);
- mFileInserter->bind(FILE_PARENT_COLUMN, parent);
- mFileInserter->bind(FILE_STORAGE_COLUMN, storage);
- mFileInserter->bind(FILE_SIZE_COLUMN, size);
- mFileInserter->bind(FILE_MODIFIED_COLUMN, modified);
- mFileInserter->step();
- mFileInserter->reset();
- int result = lastInsertedRow();
- return (result <= 0 ? kInvalidObjectHandle : result);
-}
-
-MtpObjectHandle MtpDatabase::addAudioFile(MtpObjectHandle handle) {
- mAudioInserter->bind(AUDIO_ID_COLUMN, handle);
- mAudioInserter->step();
- mAudioInserter->reset();
- int result = lastInsertedRow();
- handle |= kObjectHandleTableAudio;
- return (result > 0 ? handle : kInvalidObjectHandle);
-}
-
-MtpObjectHandle MtpDatabase::addAudioFile(MtpObjectHandle handle,
- const char* title,
- const char* artist,
- const char* album,
- const char* albumArtist,
- const char* genre,
- const char* composer,
- const char* mimeType,
- int track,
- int year,
- int duration) {
- mAudioInserter->bind(AUDIO_ID_COLUMN, handle);
- if (title) mAudioInserter->bind(AUDIO_TITLE_COLUMN, title);
- if (artist) mAudioInserter->bind(AUDIO_ARTIST_COLUMN, artist);
- if (album) mAudioInserter->bind(AUDIO_ALBUM_COLUMN, album);
- if (albumArtist) mAudioInserter->bind(AUDIO_ALBUM_ARTIST_COLUMN, albumArtist);
- if (genre) mAudioInserter->bind(AUDIO_GENRE_COLUMN, genre);
- if (composer) mAudioInserter->bind(AUDIO_COMPOSER_COLUMN, composer);
- if (track) mAudioInserter->bind(AUDIO_TRACK_NUMBER_COLUMN, track);
- if (year) mAudioInserter->bind(AUDIO_YEAR_COLUMN, year);
- if (duration) mAudioInserter->bind(AUDIO_DURATION_COLUMN, duration);
- mAudioInserter->step();
- mAudioInserter->reset();
- int result = lastInsertedRow();
- if (result <= 0)
- return kInvalidObjectHandle;
- result |= kObjectHandleTableAudio;
- return result;
-}
-
-MtpObjectHandleList* MtpDatabase::getObjectList(MtpStorageID storageID,
- MtpObjectFormat format,
- MtpObjectHandle parent) {
- bool whereStorage = (storageID != 0xFFFFFFFF);
- bool whereFormat = (format != 0);
- bool whereParent = (parent != 0);
- char intBuffer[20];
-
- MtpString query("SELECT _id,format FROM files");
- if (whereStorage || whereFormat || whereParent)
- query += " WHERE";
- if (whereStorage) {
- snprintf(intBuffer, sizeof(intBuffer), "%d", storageID);
- query += " storage = ";
- query += intBuffer;
- }
- if (whereFormat) {
- snprintf(intBuffer, sizeof(intBuffer), "%d", format);
- if (whereStorage)
- query += " AND";
- query += " format = ";
- query += intBuffer;
- }
- if (whereParent) {
- if (parent != MTP_PARENT_ROOT)
- parent &= kObjectHandleIndexMask;
- snprintf(intBuffer, sizeof(intBuffer), "%d", parent);
- if (whereStorage || whereFormat)
- query += " AND";
- query += " parent = ";
- query += intBuffer;
- }
- query += ";";
-
- SqliteStatement stmt(this);
- LOGV("%s", (const char *)query);
- stmt.prepare(query);
-
- MtpObjectHandleList* list = new MtpObjectHandleList();
- while (!stmt.isDone()) {
- if (stmt.step()) {
- int index = stmt.getColumnInt(0);
- LOGV("stmt.getColumnInt returned %d", index);
- if (index > 0) {
- MtpObjectFormat format = stmt.getColumnInt(1);
- index |= getTableForFile(format);
- list->push(index);
- }
- }
- }
- LOGV("list size: %d", list->size());
- return list;
-}
-
-
-MtpResponseCode MtpDatabase::getObjectProperty(MtpObjectHandle handle,
- MtpObjectProperty property,
- MtpDataPacket& packet) {
- int type;
- const char* columnName;
- char intBuffer[20];
-
- if (handle != MTP_PARENT_ROOT)
- handle &= kObjectHandleIndexMask;
-
- if (!getPropertyInfo(property, type, columnName))
- return MTP_RESPONSE_INVALID_OBJECT_PROP_CODE;
- snprintf(intBuffer, sizeof(intBuffer), "%d", handle);
-
- MtpString query("SELECT ");
- query += columnName;
- query += " FROM files WHERE _id = ";
- query += intBuffer;
- query += ";";
-
- SqliteStatement stmt(this);
- LOGV("%s", (const char *)query);
- stmt.prepare(query);
-
- if (!stmt.step())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
-
- switch (type) {
- case MTP_TYPE_INT8:
- packet.putInt8(stmt.getColumnInt(0));
- break;
- case MTP_TYPE_UINT8:
- packet.putUInt8(stmt.getColumnInt(0));
- break;
- case MTP_TYPE_INT16:
- packet.putInt16(stmt.getColumnInt(0));
- break;
- case MTP_TYPE_UINT16:
- packet.putUInt16(stmt.getColumnInt(0));
- break;
- case MTP_TYPE_INT32:
- packet.putInt32(stmt.getColumnInt(0));
- break;
- case MTP_TYPE_UINT32:
- packet.putUInt32(stmt.getColumnInt(0));
- break;
- case MTP_TYPE_INT64:
- packet.putInt64(stmt.getColumnInt64(0));
- break;
- case MTP_TYPE_UINT64:
- packet.putUInt64(stmt.getColumnInt64(0));
- break;
- case MTP_TYPE_STR:
- packet.putString(stmt.getColumnString(0));
- break;
- default:
- LOGE("unsupported object type\n");
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
- MtpDataPacket& packet) {
- char date[20];
-
- if (handle != MTP_PARENT_ROOT)
- handle &= kObjectHandleIndexMask;
-
- mObjectInfoQuery->reset();
- mObjectInfoQuery->bind(1, handle);
- if (!mObjectInfoQuery->step())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
-
- MtpStorageID storageID = mObjectInfoQuery->getColumnInt(0);
- MtpObjectFormat format = mObjectInfoQuery->getColumnInt(1);
- MtpObjectHandle parent = mObjectInfoQuery->getColumnInt(2);
- // extract name from path. do we want a separate database entry for this?
- const char* name = mObjectInfoQuery->getColumnString(3);
- const char* lastSlash = strrchr(name, '/');
- if (lastSlash)
- name = lastSlash + 1;
- int64_t size = mObjectInfoQuery->getColumnInt64(4);
- time_t modified = mObjectInfoQuery->getColumnInt(5);
- int associationType = (format == MTP_FORMAT_ASSOCIATION ?
- MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
- MTP_ASSOCIATION_TYPE_UNDEFINED);
-
- LOGV("storageID: %d, format: %d, parent: %d", storageID, format, parent);
-
- packet.putUInt32(storageID);
- packet.putUInt16(format);
- packet.putUInt16(0); // protection status
- packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
- packet.putUInt16(0); // thumb format
- packet.putUInt32(0); // thumb compressed size
- packet.putUInt32(0); // thumb pix width
- packet.putUInt32(0); // thumb pix height
- packet.putUInt32(0); // image pix width
- packet.putUInt32(0); // image pix height
- packet.putUInt32(0); // image bit depth
- packet.putUInt32(parent);
- packet.putUInt16(associationType);
- packet.putUInt32(0); // association desc
- packet.putUInt32(0); // sequence number
- packet.putString(name); // file name
- packet.putEmptyString();
- formatDateTime(modified, date, sizeof(date));
- packet.putString(date); // date modified
- packet.putEmptyString(); // keywords
-
- return MTP_RESPONSE_OK;
-}
-
-bool MtpDatabase::getObjectFilePath(MtpObjectHandle handle,
- MtpString& filePath,
- int64_t& fileLength) {
- if (handle != MTP_PARENT_ROOT)
- handle &= kObjectHandleIndexMask;
- mFilePathQuery->reset();
- mFilePathQuery->bind(1, handle);
- if (!mFilePathQuery->step())
- return false;
-
- const char* path = mFilePathQuery->getColumnString(0);
- if (!path)
- return false;
- filePath = path;
- fileLength = mFilePathQuery->getColumnInt64(1);
- return true;
-}
-
-bool MtpDatabase::deleteFile(MtpObjectHandle handle) {
- uint32_t table = handle & kObjectHandleTableMask;
- handle &= kObjectHandleIndexMask;
- mFileDeleter->bind(1, handle);
- mFileDeleter->step();
- mFileDeleter->reset();
- if (table == kObjectHandleTableAudio) {
- mAudioDeleter->bind(1, handle);
- mAudioDeleter->step();
- mAudioDeleter->reset();
- }
-
- return true;
-}
-
-MtpObjectHandle* MtpDatabase::getFileList(int& outCount) {
- MtpObjectHandle* result = NULL;
- int count = 0;
- SqliteStatement stmt(this);
- stmt.prepare("SELECT count(*) FROM files;");
-
- MtpObjectHandleList* list = new MtpObjectHandleList();
- if (stmt.step())
- count = stmt.getColumnInt(0);
-
- if (count > 0) {
- result = new MtpObjectHandle[count];
- memset(result, 0, count * sizeof(*result));
- SqliteStatement stmt2(this);
- stmt2.prepare("SELECT _id,format FROM files;");
-
- for (int i = 0; i < count; i++) {
- if (!stmt2.step()) {
- LOGW("getFileList ended early");
- count = i;
- break;
- }
- MtpObjectHandle handle = stmt2.getColumnInt(0);
- MtpObjectFormat format = stmt2.getColumnInt(1);
- handle |= getTableForFile(format);
- result[i] = handle;
- }
- }
- outCount = count;
- return result;
-}
-
-/*
- for getObjectPropDesc
-
- packet.putUInt16(property);
- packet.putUInt16(dataType);
- packet.putUInt8(getSet);
- // default value DTS
- packet.putUInt32(groupCode);
- packet.putUInt8(formFlag);
- // form, variable
-*/
-
} // namespace android