gecko-dev/dom/system/gonk/MozMtpDatabase.h

276 lines
9.0 KiB
C++

/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_system_mozmtpdatabase_h__
#define mozilla_system_mozmtpdatabase_h__
#include "MozMtpCommon.h"
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsIThread.h"
#include "nsTArray.h"
class DeviceStorageFile;
BEGIN_MTP_NAMESPACE // mozilla::system::mtp
class RefCountedMtpServer;
using namespace android;
class MozMtpDatabase MOZ_FINAL : public MtpDatabase
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MozMtpDatabase)
MozMtpDatabase();
virtual ~MozMtpDatabase();
// called from SendObjectInfo to reserve a database entry for the incoming file
virtual MtpObjectHandle beginSendObject(const char* aPath,
MtpObjectFormat aFormat,
MtpObjectHandle aParent,
MtpStorageID aStorageID,
uint64_t aSize,
time_t aModified);
// called to report success or failure of the SendObject file transfer
// success should signal a notification of the new object's creation,
// failure should remove the database entry created in beginSendObject
virtual void endSendObject(const char* aPath,
MtpObjectHandle aHandle,
MtpObjectFormat aFormat,
bool aSucceeded);
virtual MtpObjectHandleList* getObjectList(MtpStorageID aStorageID,
MtpObjectFormat aFormat,
MtpObjectHandle aParent);
virtual int getNumObjects(MtpStorageID aStorageID,
MtpObjectFormat aFormat,
MtpObjectHandle aParent);
virtual MtpObjectFormatList* getSupportedPlaybackFormats();
virtual MtpObjectFormatList* getSupportedCaptureFormats();
virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat aFormat);
virtual MtpDevicePropertyList* getSupportedDeviceProperties();
virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle aHandle,
MtpObjectProperty aProperty,
MtpDataPacket& aPacket);
virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle aHandle,
MtpObjectProperty aProperty,
MtpDataPacket& aPacket);
virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty aProperty,
MtpDataPacket& aPacket);
virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty aProperty,
MtpDataPacket& aPacket);
virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty aProperty);
virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle aHandle,
uint32_t aFormat,
uint32_t aProperty,
int aGroupCode,
int aDepth,
MtpDataPacket& aPacket);
virtual MtpResponseCode getObjectInfo(MtpObjectHandle aHandle,
MtpObjectInfo& aInfo);
virtual void* getThumbnail(MtpObjectHandle aHandle, size_t& aOutThumbSize);
virtual MtpResponseCode getObjectFilePath(MtpObjectHandle aHandle,
MtpString& aOutFilePath,
int64_t& aOutFileLength,
MtpObjectFormat& aOutFormat);
virtual MtpResponseCode deleteFile(MtpObjectHandle aHandle);
virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle aHandle);
virtual MtpResponseCode setObjectReferences(MtpObjectHandle aHandle,
MtpObjectHandleList* aReferences);
virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty aProperty,
MtpObjectFormat aFormat);
virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty aProperty);
virtual void sessionStarted();
virtual void sessionEnded();
void AddStorage(MtpStorageID aStorageID, const char* aPath, const char *aName);
void RemoveStorage(MtpStorageID aStorageID);
void FileWatcherUpdate(RefCountedMtpServer* aMtpServer,
DeviceStorageFile* aFile,
const nsACString& aEventType);
private:
struct DbEntry
{
DbEntry()
: mHandle(0),
mStorageID(0),
mObjectFormat(MTP_FORMAT_DEFINED),
mParent(0),
mObjectSize(0),
mDateCreated(0),
mDateModified(0) {}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DbEntry)
MtpObjectHandle mHandle; // uint32_t
MtpStorageID mStorageID; // uint32_t
nsCString mObjectName;
MtpObjectFormat mObjectFormat; // uint16_t
MtpObjectHandle mParent; // uint32_t
uint64_t mObjectSize;
nsCString mDisplayName;
nsCString mPath;
PRTime mDateCreated;
PRTime mDateModified;
};
template<class T>
class ProtectedTArray : private nsTArray<T>
{
public:
typedef T elem_type;
typedef typename nsTArray<T>::size_type size_type;
typedef typename nsTArray<T>::index_type index_type;
typedef nsTArray<T> base_type;
static const index_type NoIndex = base_type::NoIndex;
ProtectedTArray(mozilla::Mutex& aMutex)
: mMutex(aMutex)
{}
size_type Length() const
{
// GRR - This assert prints to stderr and won't show up in logcat.
mMutex.AssertCurrentThreadOwns();
return base_type::Length();
}
template <class Item>
elem_type* AppendElement(const Item& aItem)
{
mMutex.AssertCurrentThreadOwns();
return base_type::AppendElement(aItem);
}
void Clear()
{
mMutex.AssertCurrentThreadOwns();
base_type::Clear();
}
void RemoveElementAt(index_type aIndex)
{
mMutex.AssertCurrentThreadOwns();
base_type::RemoveElementAt(aIndex);
}
elem_type& operator[](index_type aIndex)
{
mMutex.AssertCurrentThreadOwns();
return base_type::ElementAt(aIndex);
}
const elem_type& operator[](index_type aIndex) const
{
mMutex.AssertCurrentThreadOwns();
return base_type::ElementAt(aIndex);
}
private:
mozilla::Mutex& mMutex;
};
typedef nsTArray<mozilla::RefPtr<DbEntry> > UnprotectedDbArray;
typedef ProtectedTArray<mozilla::RefPtr<DbEntry> > ProtectedDbArray;
struct StorageEntry
{
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StorageEntry)
MtpStorageID mStorageID;
nsCString mStoragePath;
nsCString mStorageName;
};
typedef ProtectedTArray<mozilla::RefPtr<StorageEntry> > StorageArray;
enum MatchType
{
MatchAll,
MatchHandle,
MatchParent,
MatchFormat,
MatchHandleFormat,
MatchParentFormat,
};
bool IsValidHandle(MtpObjectHandle aHandle)
{
return aHandle > 0 && aHandle < mDb.Length();
}
void AddEntry(DbEntry* aEntry);
void AddEntryAndNotify(DbEntry* aEntr, RefCountedMtpServer* aMtpServer);
void DumpEntries(const char* aLabel);
MtpObjectHandle FindEntryByPath(const nsACString& aPath);
mozilla::TemporaryRef<DbEntry> GetEntry(MtpObjectHandle aHandle);
void RemoveEntry(MtpObjectHandle aHandle);
void RemoveEntryAndNotify(MtpObjectHandle aHandle, RefCountedMtpServer* aMtpServer);
void QueryEntries(MatchType aMatchType, uint32_t aMatchField1,
uint32_t aMatchField2, UnprotectedDbArray& aResult);
nsCString BaseName(const nsCString& aPath);
MtpObjectHandle GetNextHandle()
{
return mDb.Length();
}
void AddDirectory(MtpStorageID aStorageID, const char *aPath, MtpObjectHandle aParent);
void CreateEntryForFileAndNotify(const nsACString& aPath,
DeviceStorageFile* aFile,
RefCountedMtpServer* aMtpServer);
StorageArray::index_type FindStorage(MtpStorageID aStorageID);
MtpStorageID FindStorageIDFor(const nsACString& aPath, nsCSubstring& aRemainder);
void FileWatcherNotify(DbEntry* aEntry, const char* aEventType);
// We need a mutex to protext mDb and mStorage. The MTP server runs on a
// dedicated thread, and it updates/accesses mDb. When files are updated
// through DeviceStorage, we need to update/access mDb and mStorage as well
// (from a non-MTP server thread).
mozilla::Mutex mMutex;
ProtectedDbArray mDb;
StorageArray mStorage;
bool mBeginSendObjectCalled;
};
END_MTP_NAMESPACE
#endif // mozilla_system_mozmtpdatabase_h__