Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4fe7ff5 authored by Mike Lockwood's avatar Mike Lockwood Committed by The Android Automerger
Browse files

DO NOT MERGE: MTP: Add support for dynamically adding and removing storage units



BUG: 3402847

Change-Id: I46e90f546a8d72c273cd7f2de2d086bb6dbdc1b8
Signed-off-by: default avatarMike Lockwood <lockwood@android.com>
parent 8af74a53
Loading
Loading
Loading
Loading
+74 −17
Original line number Diff line number Diff line
@@ -84,6 +84,8 @@ static const MtpOperationCode kSupportedOperationCodes[] = {
static const MtpEventCode kSupportedEventCodes[] = {
    MTP_EVENT_OBJECT_ADDED,
    MTP_EVENT_OBJECT_REMOVED,
    MTP_EVENT_STORE_ADDED,
    MTP_EVENT_STORE_REMOVED,
};

MtpServer::MtpServer(int fd, MtpDatabase* database,
@@ -104,11 +106,23 @@ MtpServer::MtpServer(int fd, MtpDatabase* database,
MtpServer::~MtpServer() {
}

void MtpServer::addStorage(const char* filePath, uint64_t reserveSpace) {
    int index = mStorages.size() + 1;
    index |= index << 16;   // set high and low part to our index
    MtpStorage* storage = new MtpStorage(index, filePath, reserveSpace);
    addStorage(storage);
void MtpServer::addStorage(MtpStorage* storage) {
    Mutex::Autolock autoLock(mMutex);

    mStorages.push(storage);
    sendStoreAdded(storage->getStorageID());
}

void MtpServer::removeStorage(MtpStorage* storage) {
    Mutex::Autolock autoLock(mMutex);

    for (int i = 0; i < mStorages.size(); i++) {
        if (mStorages[i] == storage) {
            mStorages.removeAt(i);
            sendStoreRemoved(storage->getStorageID());
            break;
        }
    }
}

MtpStorage* MtpServer::getStorage(MtpStorageID id) {
@@ -122,6 +136,12 @@ MtpStorage* MtpServer::getStorage(MtpStorageID id) {
    return NULL;
}

bool MtpServer::hasStorage(MtpStorageID id) {
    if (id == 0 || id == 0xFFFFFFFF)
        return mStorages.size() > 0;
    return (getStorage(id) != NULL);
}

void MtpServer::run() {
    int fd = mFD;

@@ -203,28 +223,38 @@ void MtpServer::run() {
}

void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
    if (mSessionOpen) {
    LOGV("sendObjectAdded %d\n", handle);
        mEvent.setEventCode(MTP_EVENT_OBJECT_ADDED);
        mEvent.setTransactionID(mRequest.getTransactionID());
        mEvent.setParameter(1, handle);
        int ret = mEvent.write(mFD);
        LOGV("mEvent.write returned %d\n", ret);
    }
    sendEvent(MTP_EVENT_OBJECT_ADDED, handle);
}

void MtpServer::sendObjectRemoved(MtpObjectHandle handle) {
    if (mSessionOpen) {
    LOGV("sendObjectRemoved %d\n", handle);
        mEvent.setEventCode(MTP_EVENT_OBJECT_REMOVED);
    sendEvent(MTP_EVENT_OBJECT_REMOVED, handle);
}

void MtpServer::sendStoreAdded(MtpStorageID id) {
    LOGV("sendStoreAdded %08X\n", id);
    sendEvent(MTP_EVENT_STORE_ADDED, id);
}

void MtpServer::sendStoreRemoved(MtpStorageID id) {
    LOGV("sendStoreRemoved %08X\n", id);
    sendEvent(MTP_EVENT_STORE_REMOVED, id);
}

void MtpServer::sendEvent(MtpEventCode code, uint32_t param1) {
    if (mSessionOpen) {
        mEvent.setEventCode(code);
        mEvent.setTransactionID(mRequest.getTransactionID());
        mEvent.setParameter(1, handle);
        mEvent.setParameter(1, param1);
        int ret = mEvent.write(mFD);
        LOGV("mEvent.write returned %d\n", ret);
    }
}

bool MtpServer::handleRequest() {
    Mutex::Autolock autoLock(mMutex);

    MtpOperationCode operation = mRequest.getOperationCode();
    MtpResponseCode response;

@@ -438,6 +468,9 @@ MtpResponseCode MtpServer::doGetObjectHandles() {
    MtpObjectFormat format = mRequest.getParameter(2);      // 0 for all formats
    MtpObjectHandle parent = mRequest.getParameter(3);      // 0xFFFFFFFF for objects with no parent
                                                            // 0x00000000 for all objects?

    if (!hasStorage(storageID))
        return MTP_RESPONSE_INVALID_STORAGE_ID;
    if (parent == 0xFFFFFFFF)
        parent = 0;

@@ -454,6 +487,8 @@ MtpResponseCode MtpServer::doGetNumObjects() {
    MtpObjectFormat format = mRequest.getParameter(2);      // 0 for all formats
    MtpObjectHandle parent = mRequest.getParameter(3);      // 0xFFFFFFFF for objects with no parent
                                                            // 0x00000000 for all objects?
    if (!hasStorage(storageID))
        return MTP_RESPONSE_INVALID_STORAGE_ID;
    if (parent == 0xFFFFFFFF)
        parent = 0;

@@ -470,7 +505,9 @@ MtpResponseCode MtpServer::doGetNumObjects() {
MtpResponseCode MtpServer::doGetObjectReferences() {
    if (!mSessionOpen)
        return MTP_RESPONSE_SESSION_NOT_OPEN;
    MtpStorageID handle = mRequest.getParameter(1);
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
    MtpObjectHandle handle = mRequest.getParameter(1);

    // FIXME - check for invalid object handle
    MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle);
@@ -486,7 +523,10 @@ MtpResponseCode MtpServer::doGetObjectReferences() {
MtpResponseCode MtpServer::doSetObjectReferences() {
    if (!mSessionOpen)
        return MTP_RESPONSE_SESSION_NOT_OPEN;
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
    MtpStorageID handle = mRequest.getParameter(1);

    MtpObjectHandleList* references = mData.getAUInt32();
    MtpResponseCode result = mDatabase->setObjectReferences(handle, references);
    delete references;
@@ -494,6 +534,8 @@ MtpResponseCode MtpServer::doSetObjectReferences() {
}

MtpResponseCode MtpServer::doGetObjectPropValue() {
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
    MtpObjectHandle handle = mRequest.getParameter(1);
    MtpObjectProperty property = mRequest.getParameter(2);
    LOGV("GetObjectPropValue %d %s\n", handle,
@@ -503,6 +545,8 @@ MtpResponseCode MtpServer::doGetObjectPropValue() {
}

MtpResponseCode MtpServer::doSetObjectPropValue() {
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
    MtpObjectHandle handle = mRequest.getParameter(1);
    MtpObjectProperty property = mRequest.getParameter(2);
    LOGV("SetObjectPropValue %d %s\n", handle,
@@ -536,6 +580,8 @@ MtpResponseCode MtpServer::doResetDevicePropValue() {
}

MtpResponseCode MtpServer::doGetObjectPropList() {
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;

    MtpObjectHandle handle = mRequest.getParameter(1);
    // use uint32_t so we can support 0xFFFFFFFF
@@ -551,11 +597,15 @@ MtpResponseCode MtpServer::doGetObjectPropList() {
}

MtpResponseCode MtpServer::doGetObjectInfo() {
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
    MtpObjectHandle handle = mRequest.getParameter(1);
    return mDatabase->getObjectInfo(handle, mData);
}

MtpResponseCode MtpServer::doGetObject() {
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
    MtpObjectHandle handle = mRequest.getParameter(1);
    MtpString pathBuf;
    int64_t fileLength;
@@ -591,6 +641,8 @@ MtpResponseCode MtpServer::doGetObject() {
}

MtpResponseCode MtpServer::doGetPartialObject() {
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
    MtpObjectHandle handle = mRequest.getParameter(1);
    uint32_t offset = mRequest.getParameter(2);
    uint32_t length = mRequest.getParameter(3);
@@ -687,6 +739,7 @@ MtpResponseCode MtpServer::doSendObjectInfo() {
    if (mSendObjectFileSize > storage->getFreeSpace())
        return MTP_RESPONSE_STORAGE_FULL;

LOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID);
    MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
            format, parent, storageID, mSendObjectFileSize, modifiedTime);
    if (handle == kInvalidObjectHandle) {
@@ -718,6 +771,8 @@ MtpResponseCode MtpServer::doSendObjectInfo() {
}

MtpResponseCode MtpServer::doSendObject() {
    if (!hasStorage())
        return MTP_RESPONSE_GENERAL_ERROR;
    MtpResponseCode result = MTP_RESPONSE_OK;
    mode_t mask;
    int ret;
@@ -834,6 +889,8 @@ static void deletePath(const char* path) {
}

MtpResponseCode MtpServer::doDeleteObject() {
    if (!hasStorage())
        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
    MtpObjectHandle handle = mRequest.getParameter(1);
    MtpObjectFormat format = mRequest.getParameter(2);
    // FIXME - support deleting all objects if handle is 0xFFFFFFFF
+14 −4
Original line number Diff line number Diff line
@@ -22,9 +22,10 @@
#include "MtpResponsePacket.h"
#include "MtpEventPacket.h"
#include "mtp.h"

#include "MtpUtils.h"

#include <utils/threads.h>

namespace android {

class MtpDatabase;
@@ -62,20 +63,29 @@ private:
    MtpString           mSendObjectFilePath;
    size_t              mSendObjectFileSize;

    Mutex               mMutex;

public:
                        MtpServer(int fd, MtpDatabase* database,
                                    int fileGroup, int filePerm, int directoryPerm);
    virtual             ~MtpServer();

    void                addStorage(const char* filePath, uint64_t reserveSpace);
    inline void         addStorage(MtpStorage* storage) { mStorages.push(storage); }
    MtpStorage*         getStorage(MtpStorageID id);
    void                addStorage(MtpStorage* storage);
    void                removeStorage(MtpStorage* storage);

    void                run();

    void                sendObjectAdded(MtpObjectHandle handle);
    void                sendObjectRemoved(MtpObjectHandle handle);

private:
    MtpStorage*         getStorage(MtpStorageID id);
    inline bool         hasStorage() { return mStorages.size() > 0; }
    bool                hasStorage(MtpStorageID id);
    void                sendStoreAdded(MtpStorageID id);
    void                sendStoreRemoved(MtpStorageID id);
    void                sendEvent(MtpEventCode code, uint32_t param1);

    bool                handleRequest();

    MtpResponseCode     doGetDeviceInfo();
+2 −2
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ int MtpStorage::getAccessCapability() const {
uint64_t MtpStorage::getMaxCapacity() {
    if (mMaxCapacity == 0) {
        struct statfs   stat;
        if (statfs(mFilePath, &stat))
        if (statfs(getPath(), &stat))
            return -1;
        mMaxCapacity = (uint64_t)stat.f_blocks * (uint64_t)stat.f_bsize;
    }
@@ -68,7 +68,7 @@ uint64_t MtpStorage::getMaxCapacity() {

uint64_t MtpStorage::getFreeSpace() {
    struct statfs   stat;
    if (statfs(mFilePath, &stat))
    if (statfs(getPath(), &stat))
        return -1;
    uint64_t freeSpace = (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize;
    return (freeSpace > mReserveSpace ? freeSpace - mReserveSpace : 0);
+3 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef _MTP_STORAGE_H
#define _MTP_STORAGE_H

#include "MtpTypes.h"
#include "mtp.h"

namespace android {
@@ -27,7 +28,7 @@ class MtpStorage {

private:
    MtpStorageID            mStorageID;
    const char*             mFilePath;
    MtpString               mFilePath;
    uint64_t                mMaxCapacity;
    // amount of free space to leave unallocated
    uint64_t                mReserveSpace;
@@ -44,7 +45,7 @@ public:
    uint64_t                getMaxCapacity();
    uint64_t                getFreeSpace();
    const char*             getDescription() const;
    inline const char*      getPath() const { return mFilePath; }
    inline const char*      getPath() const { return (const char *)mFilePath; }
};

}; // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@

#define MTP_STANDARD_VERSION            100

#define MTP_FIRST_STORAGE_ID            0x00010001

// Container Types
#define MTP_CONTAINER_TYPE_UNDEFINED    0
#define MTP_CONTAINER_TYPE_COMMAND      1