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