diff options
author | Mike Lockwood <lockwood@android.com> | 2010-07-02 14:03:31 -0400 |
---|---|---|
committer | Mike Lockwood <lockwood@android.com> | 2010-07-02 14:14:06 -0400 |
commit | 0250361b110267a139cc0865ff7d2f13b4d63bdf (patch) | |
tree | a2a5f01424d963c2b24d2fca8e2c59095ce404f8 | |
parent | fc20aab463f527ab3b0664986f0381a86b375884 (diff) | |
download | frameworks_av-0250361b110267a139cc0865ff7d2f13b4d63bdf.zip frameworks_av-0250361b110267a139cc0865ff7d2f13b4d63bdf.tar.gz frameworks_av-0250361b110267a139cc0865ff7d2f13b4d63bdf.tar.bz2 |
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>
-rw-r--r-- | media/mtp/Android.mk | 12 | ||||
-rw-r--r-- | media/mtp/MtpDatabase.cpp | 504 | ||||
-rw-r--r-- | media/mtp/MtpDatabase.h | 94 | ||||
-rw-r--r-- | media/mtp/MtpServer.cpp | 4 | ||||
-rw-r--r-- | media/mtp/MtpServer.h | 4 | ||||
-rw-r--r-- | media/mtp/MtpSqliteDatabase.cpp | 564 | ||||
-rw-r--r-- | media/mtp/MtpSqliteDatabase.h | 96 | ||||
-rw-r--r-- | media/mtp/SqliteDatabase.h | 4 | ||||
-rw-r--r-- | media/mtp/scantest.cpp | 4 |
9 files changed, 715 insertions, 571 deletions
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk index 3c9909b..13a6430 100644 --- a/media/mtp/Android.mk +++ b/media/mtp/Android.mk @@ -32,6 +32,7 @@ LOCAL_SRC_FILES:= \ MtpRequestPacket.cpp \ MtpResponsePacket.cpp \ MtpServer.cpp \ + MtpSqliteDatabase.cpp \ MtpStorageInfo.cpp \ MtpStringBuffer.cpp \ MtpStorage.cpp \ @@ -70,18 +71,9 @@ include $(CLEAR_VARS) LOCAL_MODULE := scantest LOCAL_SRC_FILES:= \ scantest.cpp \ - MtpMediaScanner.cpp \ - MtpDatabase.cpp \ - MtpDataPacket.cpp \ - MtpPacket.cpp \ - MtpStringBuffer.cpp \ - MtpUtils.cpp \ - SqliteDatabase.cpp \ - SqliteStatement.cpp \ -#LOCAL_STATIC_LIBRARIES := libusbhost -#LOCAL_LDLIBS := -lpthread +LOCAL_STATIC_LIBRARIES := libmtp LOCAL_C_INCLUDES := external/sqlite/dist LOCAL_SHARED_LIBRARIES := libutils libsqlite libstagefright libmedia 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 @@ uint32_t MtpDatabase::getTableForFile(MtpObjectFormat format) { } } -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 diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h index 51d5fb1..0c70d9f 100644 --- a/media/mtp/MtpDatabase.h +++ b/media/mtp/MtpDatabase.h @@ -23,65 +23,57 @@ namespace android { class MtpDataPacket; -class SqliteStatement; - -class MtpDatabase : public SqliteDatabase { -private: - SqliteStatement* mFileIdQuery; - SqliteStatement* mFilePathQuery; - SqliteStatement* mObjectInfoQuery; - SqliteStatement* mFileInserter; - SqliteStatement* mFileDeleter; - SqliteStatement* mAudioInserter; - SqliteStatement* mAudioDeleter; +class MtpDatabase { public: - MtpDatabase(); - virtual ~MtpDatabase(); - - static uint32_t getTableForFile(MtpObjectFormat format); - - bool open(const char* path, bool create); - MtpObjectHandle getObjectHandle(const char* path); - MtpObjectHandle addFile(const char* path, + virtual ~MtpDatabase(); + + static uint32_t getTableForFile(MtpObjectFormat format); + + virtual MtpObjectHandle getObjectHandle(const char* path) = 0; + virtual MtpObjectHandle addFile(const char* path, + MtpObjectFormat format, + MtpObjectHandle parent, + MtpStorageID storage, + uint64_t size, + time_t modified) = 0; + + virtual MtpObjectHandle addAudioFile(MtpObjectHandle id) = 0; + + virtual MtpObjectHandle addAudioFile(MtpObjectHandle id, + 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) = 0; + + virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID, MtpObjectFormat format, - MtpObjectHandle parent, - MtpStorageID storage, - uint64_t size, - time_t modified); - - MtpObjectHandle addAudioFile(MtpObjectHandle id); - - MtpObjectHandle addAudioFile(MtpObjectHandle id, - 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); - - MtpObjectHandleList* getObjectList(MtpStorageID storageID, - MtpObjectFormat format, - MtpObjectHandle parent); + MtpObjectHandle parent) = 0; - MtpResponseCode getObjectProperty(MtpObjectHandle handle, - MtpObjectProperty property, - MtpDataPacket& packet); + virtual MtpResponseCode getObjectProperty(MtpObjectHandle handle, + MtpObjectProperty property, + MtpDataPacket& packet) = 0; - MtpResponseCode getObjectInfo(MtpObjectHandle handle, - MtpDataPacket& packet); + virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle, + MtpDataPacket& packet) = 0; - bool getObjectFilePath(MtpObjectHandle handle, - MtpString& filePath, - int64_t& fileLength); - bool deleteFile(MtpObjectHandle handle); + virtual bool getObjectFilePath(MtpObjectHandle handle, + MtpString& filePath, + int64_t& fileLength) = 0; + virtual bool deleteFile(MtpObjectHandle handle) = 0; // helper for media scanner - MtpObjectHandle* getFileList(int& outCount); + virtual MtpObjectHandle* getFileList(int& outCount) = 0; + + virtual void beginTransaction() = 0; + virtual void commitTransaction() = 0; + virtual void rollbackTransaction() = 0; }; }; // namespace android diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index 0b99cb1..cc6fdad 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -25,9 +25,9 @@ #include <cutils/properties.h> #include "MtpDebug.h" -#include "MtpDatabase.h" #include "MtpProperty.h" #include "MtpServer.h" +#include "MtpSqliteDatabase.h" #include "MtpStorage.h" #include "MtpStringBuffer.h" @@ -122,7 +122,7 @@ MtpServer::MtpServer(int fd, const char* databasePath) mSendObjectHandle(kInvalidObjectHandle), mSendObjectFileSize(0) { - mDatabase = new MtpDatabase(); + mDatabase = new MtpSqliteDatabase(); mDatabase->open(databasePath, true); initObjectProperties(); diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h index 40329c5..42261a9 100644 --- a/media/mtp/MtpServer.h +++ b/media/mtp/MtpServer.h @@ -27,7 +27,7 @@ namespace android { class MtpStorage; -class MtpDatabase; +class MtpSqliteDatabase; class MtpProperty; class MtpServer { @@ -39,7 +39,7 @@ private: // path to our sqlite3 database const char* mDatabasePath; - MtpDatabase* mDatabase; + MtpSqliteDatabase* mDatabase; // current session ID MtpSessionID mSessionID; diff --git a/media/mtp/MtpSqliteDatabase.cpp b/media/mtp/MtpSqliteDatabase.cpp new file mode 100644 index 0000000..fa3bdfe --- /dev/null +++ b/media/mtp/MtpSqliteDatabase.cpp @@ -0,0 +1,564 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "MtpSqliteDatabase" + +#include "MtpDebug.h" +#include "MtpSqliteDatabase.h" +#include "MtpDataPacket.h" +#include "MtpUtils.h" +#include "SqliteDatabase.h" +#include "SqliteStatement.h" + +#include <stdio.h> +#include <stdlib.h> +#include <sqlite3.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; +} + +MtpSqliteDatabase::MtpSqliteDatabase() + : mDatabase(NULL), + mFileIdQuery(NULL), + mFilePathQuery(NULL), + mObjectInfoQuery(NULL), + mFileInserter(NULL), + mFileDeleter(NULL), + mAudioInserter(NULL), + mAudioDeleter(NULL) +{ +} + +MtpSqliteDatabase::~MtpSqliteDatabase() { + delete mDatabase; + delete mFileIdQuery; + delete mFilePathQuery; + delete mObjectInfoQuery; + delete mFileInserter; + delete mFileDeleter; + delete mAudioInserter; + delete mAudioDeleter; +} + +bool MtpSqliteDatabase::open(const char* path, bool create) { + mDatabase = new SqliteDatabase; + + if (!mDatabase->open(path, create)) + goto fail; + + // create tables and indices if necessary + if (!mDatabase->exec(FILE_TABLE_CREATE)) { + LOGE("could not create file table"); + goto fail; + } + if (!mDatabase->exec(PATH_INDEX_CREATE)) { + LOGE("could not path index on file table"); + goto fail; + } + if (!mDatabase->exec(AUDIO_TABLE_CREATE)) { + LOGE("could not create file table"); + goto fail; + } + + if (!mFileIdQuery) { + mFileIdQuery = new SqliteStatement(mDatabase); + if (!mFileIdQuery->prepare(FILE_ID_QUERY)) { + LOGE("could not compile FILE_ID_QUERY"); + goto fail; + } + } + if (!mFilePathQuery) { + mFilePathQuery = new SqliteStatement(mDatabase); + if (!mFilePathQuery->prepare(FILE_PATH_QUERY)) { + LOGE("could not compile FILE_PATH_QUERY"); + goto fail; + } + } + if (!mObjectInfoQuery) { + mObjectInfoQuery = new SqliteStatement(mDatabase); + if (!mObjectInfoQuery->prepare(GET_OBJECT_INFO_QUERY)) { + LOGE("could not compile GET_OBJECT_INFO_QUERY"); + goto fail; + } + } + if (!mFileInserter) { + mFileInserter = new SqliteStatement(mDatabase); + if (!mFileInserter->prepare(FILE_INSERT)) { + LOGE("could not compile FILE_INSERT\n"); + goto fail; + } + } + if (!mFileDeleter) { + mFileDeleter = new SqliteStatement(mDatabase); + if (!mFileDeleter->prepare(FILE_DELETE)) { + LOGE("could not compile FILE_DELETE\n"); + goto fail; + } + } + if (!mAudioInserter) { + mAudioInserter = new SqliteStatement(mDatabase); + if (!mAudioInserter->prepare(AUDIO_INSERT)) { + LOGE("could not compile AUDIO_INSERT\n"); + goto fail; + } + } + if (!mAudioDeleter) { + mAudioDeleter = new SqliteStatement(mDatabase); + if (!mAudioDeleter->prepare(AUDIO_DELETE)) { + LOGE("could not compile AUDIO_DELETE\n"); + goto fail; + } + } + + return true; + +fail: + delete mDatabase; + delete mFileIdQuery; + delete mFilePathQuery; + delete mObjectInfoQuery; + delete mFileInserter; + delete mFileDeleter; + delete mAudioInserter; + delete mAudioDeleter; + mDatabase = NULL; + mFileIdQuery = NULL; + mFilePathQuery = NULL; + mObjectInfoQuery = NULL; + mFileInserter = NULL; + mFileDeleter = NULL; + mAudioInserter = NULL; + mAudioDeleter = NULL; + return false; +} + +void MtpSqliteDatabase::close() { + if (mDatabase) { + mDatabase->close(); + mDatabase = NULL; + } +} + +MtpObjectHandle MtpSqliteDatabase::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 MtpSqliteDatabase::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 = mDatabase->lastInsertedRow(); + return (result <= 0 ? kInvalidObjectHandle : result); +} + +MtpObjectHandle MtpSqliteDatabase::addAudioFile(MtpObjectHandle handle) { + mAudioInserter->bind(AUDIO_ID_COLUMN, handle); + mAudioInserter->step(); + mAudioInserter->reset(); + int result = mDatabase->lastInsertedRow(); + handle |= kObjectHandleTableAudio; + return (result > 0 ? handle : kInvalidObjectHandle); +} + +MtpObjectHandle MtpSqliteDatabase::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 = mDatabase->lastInsertedRow(); + if (result <= 0) + return kInvalidObjectHandle; + result |= kObjectHandleTableAudio; + return result; +} + +MtpObjectHandleList* MtpSqliteDatabase::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(mDatabase); + 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 MtpSqliteDatabase::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(mDatabase); + 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 MtpSqliteDatabase::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 MtpSqliteDatabase::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 MtpSqliteDatabase::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* MtpSqliteDatabase::getFileList(int& outCount) { + MtpObjectHandle* result = NULL; + int count = 0; + SqliteStatement stmt(mDatabase); + 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(mDatabase); + 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; +} + +void MtpSqliteDatabase::beginTransaction() { + mDatabase->beginTransaction(); +} + +void MtpSqliteDatabase::commitTransaction() { + mDatabase->commitTransaction(); +} + +void MtpSqliteDatabase::rollbackTransaction() { + mDatabase->rollbackTransaction(); +} + +} // namespace android diff --git a/media/mtp/MtpSqliteDatabase.h b/media/mtp/MtpSqliteDatabase.h new file mode 100644 index 0000000..74626a8 --- /dev/null +++ b/media/mtp/MtpSqliteDatabase.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MTP_SQLITE_DATABASE_H +#define _MTP_SQLITE_DATABASE_H + +#include "MtpTypes.h" +#include "MtpDatabase.h" + +class SqliteDatabase; + +namespace android { + +class MtpDataPacket; +class SqliteStatement; + +class MtpSqliteDatabase : public MtpDatabase { +private: + SqliteDatabase* mDatabase; + SqliteStatement* mFileIdQuery; + SqliteStatement* mFilePathQuery; + SqliteStatement* mObjectInfoQuery; + SqliteStatement* mFileInserter; + SqliteStatement* mFileDeleter; + SqliteStatement* mAudioInserter; + SqliteStatement* mAudioDeleter; + +public: + MtpSqliteDatabase(); + virtual ~MtpSqliteDatabase(); + + bool open(const char* path, bool create); + void close(); + + virtual MtpObjectHandle getObjectHandle(const char* path); + virtual MtpObjectHandle addFile(const char* path, + MtpObjectFormat format, + MtpObjectHandle parent, + MtpStorageID storage, + uint64_t size, + time_t modified); + + virtual MtpObjectHandle addAudioFile(MtpObjectHandle id); + + virtual MtpObjectHandle addAudioFile(MtpObjectHandle id, + 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); + + virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID, + MtpObjectFormat format, + MtpObjectHandle parent); + + virtual MtpResponseCode getObjectProperty(MtpObjectHandle handle, + MtpObjectProperty property, + MtpDataPacket& packet); + + virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle, + MtpDataPacket& packet); + + virtual bool getObjectFilePath(MtpObjectHandle handle, + MtpString& filePath, + int64_t& fileLength); + virtual bool deleteFile(MtpObjectHandle handle); + + // helper for media scanner + virtual MtpObjectHandle* getFileList(int& outCount); + + virtual void beginTransaction(); + virtual void commitTransaction(); + virtual void rollbackTransaction(); +}; + +}; // namespace android + +#endif // _MTP_SQLITE_DATABASE_H diff --git a/media/mtp/SqliteDatabase.h b/media/mtp/SqliteDatabase.h index 56dd9dd..7d008f9 100644 --- a/media/mtp/SqliteDatabase.h +++ b/media/mtp/SqliteDatabase.h @@ -29,8 +29,8 @@ public: SqliteDatabase(); virtual ~SqliteDatabase(); - virtual bool open(const char* path, bool create); - virtual void close(); + bool open(const char* path, bool create); + void close(); bool exec(const char* sql); int lastInsertedRow(); diff --git a/media/mtp/scantest.cpp b/media/mtp/scantest.cpp index f910bb6..3702a5d 100644 --- a/media/mtp/scantest.cpp +++ b/media/mtp/scantest.cpp @@ -16,7 +16,7 @@ #include <stdio.h> -#include "MtpDatabase.h" +#include "MtpSqliteDatabase.h" #include "MtpMediaScanner.h" using namespace android; @@ -27,7 +27,7 @@ int main(int argc, char* argv[]) { return -1; } - MtpDatabase* database = new MtpDatabase(); + MtpSqliteDatabase* database = new MtpSqliteDatabase(); database->open("scantest.db", true); MtpMediaScanner scanner(1, argv[1], database); |