diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/libmedia/mediarecorder.cpp | 11 | ||||
-rw-r--r-- | media/libstagefright/foundation/ABitReader.cpp | 4 | ||||
-rw-r--r-- | media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp | 83 | ||||
-rw-r--r-- | media/libstagefright/rtsp/AMPEG4AudioAssembler.h | 1 | ||||
-rw-r--r-- | media/libstagefright/rtsp/APacketSource.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/rtsp/ARTPSource.cpp | 3 | ||||
-rw-r--r-- | media/libstagefright/rtsp/ARawAudioAssembler.cpp | 143 | ||||
-rw-r--r-- | media/libstagefright/rtsp/ARawAudioAssembler.h | 60 | ||||
-rw-r--r-- | media/libstagefright/rtsp/Android.mk | 1 | ||||
-rw-r--r-- | media/mtp/MtpServer.cpp | 91 | ||||
-rw-r--r-- | media/mtp/MtpServer.h | 18 | ||||
-rw-r--r-- | media/mtp/MtpStorage.cpp | 4 | ||||
-rw-r--r-- | media/mtp/MtpStorage.h | 5 | ||||
-rw-r--r-- | media/mtp/mtp.h | 2 |
14 files changed, 392 insertions, 37 deletions
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index fd575fe..0100a17 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -298,6 +298,17 @@ status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) return INVALID_OPERATION; } + // It appears that if an invalid file descriptor is passed through + // binder calls, the server-side of the inter-process function call + // is skipped. As a result, the check at the server-side to catch + // the invalid file descritpor never gets invoked. This is to workaround + // this issue by checking the file descriptor first before passing + // it through binder call. + if (fd < 0) { + LOGE("Invalid file descriptor: %d", fd); + return BAD_VALUE; + } + status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); if (OK != ret) { LOGV("setOutputFile failed: %d", ret); diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/libstagefright/foundation/ABitReader.cpp index 24c8df8..f07dd4f 100644 --- a/media/libstagefright/foundation/ABitReader.cpp +++ b/media/libstagefright/foundation/ABitReader.cpp @@ -90,9 +90,7 @@ size_t ABitReader::numBitsLeft() const { } const uint8_t *ABitReader::data() const { - CHECK_EQ(mNumBitsLeft % 8, 0u); - - return mData - mNumBitsLeft / 8; + return mData - (mNumBitsLeft + 7) / 8; } } // namespace android diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp index 8bfe285..11d9c22 100644 --- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp +++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp @@ -14,6 +14,9 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "AMPEG4AudioAssembler" + #include "AMPEG4AudioAssembler.h" #include "ARTPSource.h" @@ -139,7 +142,10 @@ static status_t parseGASpecificConfig( return OK; } -static status_t parseAudioSpecificConfig(ABitReader *bits) { +static status_t parseAudioSpecificConfig(ABitReader *bits, sp<ABuffer> *asc) { + const uint8_t *dataStart = bits->data(); + size_t totalNumBits = bits->numBitsLeft(); + unsigned audioObjectType; CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK); @@ -185,13 +191,13 @@ static status_t parseAudioSpecificConfig(ABitReader *bits) { } } -#if 0 - // This is not supported here as the upper layers did not explicitly - // signal the length of AudioSpecificConfig. - if (extensionAudioObjectType != 5 && bits->numBitsLeft() >= 16) { + size_t numBitsLeftAtStart = bits->numBitsLeft(); + unsigned syncExtensionType = bits->getBits(11); if (syncExtensionType == 0x2b7) { + LOGI("found syncExtension"); + CHECK_EQ(parseAudioObjectType(bits, &extensionAudioObjectType), (status_t)OK); @@ -203,9 +209,45 @@ static status_t parseAudioSpecificConfig(ABitReader *bits) { /* unsigned extensionSamplingFrequency = */bits->getBits(24); } } + + size_t numBitsInExtension = + numBitsLeftAtStart - bits->numBitsLeft(); + + if (numBitsInExtension & 7) { + // Apparently an extension is always considered an even + // multiple of 8 bits long. + + LOGI("Skipping %d bits after sync extension", + 8 - (numBitsInExtension & 7)); + + bits->skipBits(8 - (numBitsInExtension & 7)); + } + } else { + bits->putBits(syncExtensionType, 11); + } + } + + if (asc != NULL) { + size_t bitpos = totalNumBits & 7; + + ABitReader bs(dataStart, (totalNumBits + 7) / 8); + + totalNumBits -= bits->numBitsLeft(); + + size_t numBytes = (totalNumBits + 7) / 8; + + *asc = new ABuffer(numBytes); + + if (bitpos & 7) { + bs.skipBits(8 - (bitpos & 7)); + } + + uint8_t *dstPtr = (*asc)->data(); + while (numBytes > 0) { + *dstPtr++ = bs.getBits(8); + --numBytes; } } -#endif return OK; } @@ -214,6 +256,7 @@ static status_t parseStreamMuxConfig( ABitReader *bits, unsigned *numSubFrames, unsigned *frameLengthType, + ssize_t *fixedFrameLength, bool *otherDataPresent, unsigned *otherDataLenBits) { unsigned audioMuxVersion = bits->getBits(1); @@ -242,12 +285,14 @@ static status_t parseStreamMuxConfig( if (audioMuxVersion == 0) { // AudioSpecificConfig - CHECK_EQ(parseAudioSpecificConfig(bits), (status_t)OK); + CHECK_EQ(parseAudioSpecificConfig(bits, NULL /* asc */), (status_t)OK); } else { TRESPASS(); // XXX to be implemented } *frameLengthType = bits->getBits(3); + *fixedFrameLength = -1; + switch (*frameLengthType) { case 0: { @@ -260,7 +305,14 @@ static status_t parseStreamMuxConfig( case 1: { - /* unsigned frameLength = */bits->getBits(9); + *fixedFrameLength = bits->getBits(9); + break; + } + + case 2: + { + // reserved + TRESPASS(); break; } @@ -338,9 +390,21 @@ sp<ABuffer> AMPEG4AudioAssembler::removeLATMFraming(const sp<ABuffer> &buffer) { break; } + case 2: + { + // reserved + + TRESPASS(); + break; + } + default: - TRESPASS(); // XXX to be implemented + { + CHECK_GE(mFixedFrameLength, 0); + + payloadLength = mFixedFrameLength; break; + } } CHECK_LE(offset + payloadLength, buffer->size()); @@ -393,6 +457,7 @@ AMPEG4AudioAssembler::AMPEG4AudioAssembler( ABitReader bits(config->data(), config->size()); status_t err = parseStreamMuxConfig( &bits, &mNumSubFrames, &mFrameLengthType, + &mFixedFrameLength, &mOtherDataPresent, &mOtherDataLenBits); CHECK_EQ(err, (status_t)NO_ERROR); diff --git a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h index 9cef94c..1361cd2 100644 --- a/media/libstagefright/rtsp/AMPEG4AudioAssembler.h +++ b/media/libstagefright/rtsp/AMPEG4AudioAssembler.h @@ -46,6 +46,7 @@ private: bool mMuxConfigPresent; unsigned mNumSubFrames; unsigned mFrameLengthType; + ssize_t mFixedFrameLength; bool mOtherDataPresent; unsigned mOtherDataLenBits; diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp index 679dcab..6819fef 100644 --- a/media/libstagefright/rtsp/APacketSource.cpp +++ b/media/libstagefright/rtsp/APacketSource.cpp @@ -20,6 +20,7 @@ #include "APacketSource.h" +#include "ARawAudioAssembler.h" #include "ASessionDescription.h" #include "avc_utils.h" @@ -661,6 +662,8 @@ APacketSource::APacketSource( mFormat->setData( kKeyESDS, 0, codecSpecificData->data(), codecSpecificData->size()); + } else if (ARawAudioAssembler::Supports(desc.c_str())) { + ARawAudioAssembler::MakeFormat(desc.c_str(), mFormat); } else { mInitCheck = ERROR_UNSUPPORTED; } diff --git a/media/libstagefright/rtsp/ARTPSource.cpp b/media/libstagefright/rtsp/ARTPSource.cpp index 84c666f..3aa07ce 100644 --- a/media/libstagefright/rtsp/ARTPSource.cpp +++ b/media/libstagefright/rtsp/ARTPSource.cpp @@ -25,6 +25,7 @@ #include "AH263Assembler.h" #include "AMPEG4AudioAssembler.h" #include "AMPEG4ElementaryAssembler.h" +#include "ARawAudioAssembler.h" #include "ASessionDescription.h" #include <media/stagefright/foundation/ABuffer.h> @@ -70,6 +71,8 @@ ARTPSource::ARTPSource( || !strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) { mAssembler = new AMPEG4ElementaryAssembler(notify, desc, params); mIssueFIRRequests = true; + } else if (ARawAudioAssembler::Supports(desc.c_str())) { + mAssembler = new ARawAudioAssembler(notify, desc.c_str(), params); } else { TRESPASS(); } diff --git a/media/libstagefright/rtsp/ARawAudioAssembler.cpp b/media/libstagefright/rtsp/ARawAudioAssembler.cpp new file mode 100644 index 0000000..dd47ea3 --- /dev/null +++ b/media/libstagefright/rtsp/ARawAudioAssembler.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2011 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_NDEBUG 0 +#define LOG_TAG "ARawAudioAssembler" +#include <utils/Log.h> + +#include "ARawAudioAssembler.h" + +#include "ARTPSource.h" +#include "ASessionDescription.h" + +#include <media/stagefright/foundation/ABuffer.h> +#include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/foundation/hexdump.h> +#include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MetaData.h> +#include <media/stagefright/Utils.h> + +namespace android { + +ARawAudioAssembler::ARawAudioAssembler( + const sp<AMessage> ¬ify, const char *desc, const AString ¶ms) + : mNotifyMsg(notify), + mNextExpectedSeqNoValid(false), + mNextExpectedSeqNo(0) { +} + +ARawAudioAssembler::~ARawAudioAssembler() { +} + +ARTPAssembler::AssemblyStatus ARawAudioAssembler::assembleMore( + const sp<ARTPSource> &source) { + return addPacket(source); +} + +ARTPAssembler::AssemblyStatus ARawAudioAssembler::addPacket( + const sp<ARTPSource> &source) { + List<sp<ABuffer> > *queue = source->queue(); + + if (queue->empty()) { + return NOT_ENOUGH_DATA; + } + + if (mNextExpectedSeqNoValid) { + List<sp<ABuffer> >::iterator it = queue->begin(); + while (it != queue->end()) { + if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) { + break; + } + + it = queue->erase(it); + } + + if (queue->empty()) { + return NOT_ENOUGH_DATA; + } + } + + sp<ABuffer> buffer = *queue->begin(); + + if (!mNextExpectedSeqNoValid) { + mNextExpectedSeqNoValid = true; + mNextExpectedSeqNo = (uint32_t)buffer->int32Data(); + } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) { + LOGV("Not the sequence number I expected"); + + return WRONG_SEQUENCE_NUMBER; + } + + // hexdump(buffer->data(), buffer->size()); + + if (buffer->size() < 1) { + queue->erase(queue->begin()); + ++mNextExpectedSeqNo; + + LOGV("raw audio packet too short."); + + return MALFORMED_PACKET; + } + + sp<AMessage> msg = mNotifyMsg->dup(); + msg->setObject("access-unit", buffer); + msg->post(); + + queue->erase(queue->begin()); + ++mNextExpectedSeqNo; + + return OK; +} + +void ARawAudioAssembler::packetLost() { + CHECK(mNextExpectedSeqNoValid); + ++mNextExpectedSeqNo; +} + +void ARawAudioAssembler::onByeReceived() { + sp<AMessage> msg = mNotifyMsg->dup(); + msg->setInt32("eos", true); + msg->post(); +} + +// static +bool ARawAudioAssembler::Supports(const char *desc) { + return !strncmp(desc, "PCMU/", 5) + || !strncmp(desc, "PCMA/", 5); +} + +// static +void ARawAudioAssembler::MakeFormat( + const char *desc, const sp<MetaData> &format) { + if (!strncmp(desc, "PCMU/", 5)) { + format->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW); + } else if (!strncmp(desc, "PCMA/", 5)) { + format->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW); + } else { + TRESPASS(); + } + + int32_t sampleRate, numChannels; + ASessionDescription::ParseFormatDesc( + desc, &sampleRate, &numChannels); + + format->setInt32(kKeySampleRate, sampleRate); + format->setInt32(kKeyChannelCount, numChannels); +} + +} // namespace android + diff --git a/media/libstagefright/rtsp/ARawAudioAssembler.h b/media/libstagefright/rtsp/ARawAudioAssembler.h new file mode 100644 index 0000000..ed7af08 --- /dev/null +++ b/media/libstagefright/rtsp/ARawAudioAssembler.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2011 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 A_RAW_AUDIO_ASSEMBLER_H_ + +#define A_RAW_AUDIO_ASSEMBLER_H_ + +#include "ARTPAssembler.h" + +namespace android { + +struct AMessage; +struct AString; +struct MetaData; + +struct ARawAudioAssembler : public ARTPAssembler { + ARawAudioAssembler( + const sp<AMessage> ¬ify, + const char *desc, const AString ¶ms); + + static bool Supports(const char *desc); + + static void MakeFormat( + const char *desc, const sp<MetaData> &format); + +protected: + virtual ~ARawAudioAssembler(); + + virtual AssemblyStatus assembleMore(const sp<ARTPSource> &source); + virtual void onByeReceived(); + virtual void packetLost(); + +private: + bool mIsWide; + + sp<AMessage> mNotifyMsg; + bool mNextExpectedSeqNoValid; + uint32_t mNextExpectedSeqNo; + + AssemblyStatus addPacket(const sp<ARTPSource> &source); + + DISALLOW_EVIL_CONSTRUCTORS(ARawAudioAssembler); +}; + +} // namespace android + +#endif // A_RAW_AUDIO_ASSEMBLER_H_ diff --git a/media/libstagefright/rtsp/Android.mk b/media/libstagefright/rtsp/Android.mk index fb42de8..8530ff3 100644 --- a/media/libstagefright/rtsp/Android.mk +++ b/media/libstagefright/rtsp/Android.mk @@ -9,6 +9,7 @@ LOCAL_SRC_FILES:= \ AMPEG4AudioAssembler.cpp \ AMPEG4ElementaryAssembler.cpp \ APacketSource.cpp \ + ARawAudioAssembler.cpp \ ARTPAssembler.cpp \ ARTPConnection.cpp \ ARTPSource.cpp \ diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp index 853a5af..37e02a3 100644 --- a/media/mtp/MtpServer.cpp +++ b/media/mtp/MtpServer.cpp @@ -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); - } + LOGV("sendObjectAdded %d\n", handle); + sendEvent(MTP_EVENT_OBJECT_ADDED, handle); } void MtpServer::sendObjectRemoved(MtpObjectHandle handle) { + LOGV("sendObjectRemoved %d\n", handle); + 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) { - LOGV("sendObjectRemoved %d\n", handle); - mEvent.setEventCode(MTP_EVENT_OBJECT_REMOVED); + 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; @@ -439,6 +469,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; @@ -455,6 +488,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; @@ -471,7 +506,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); @@ -487,7 +524,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; @@ -495,6 +535,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, @@ -504,6 +546,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, @@ -537,6 +581,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 @@ -552,11 +598,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; @@ -592,6 +642,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); @@ -688,6 +740,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) { @@ -719,6 +772,8 @@ MtpResponseCode MtpServer::doSendObjectInfo() { } MtpResponseCode MtpServer::doSendObject() { + if (!hasStorage()) + return MTP_RESPONSE_GENERAL_ERROR; MtpResponseCode result = MTP_RESPONSE_OK; mode_t mask; int ret; @@ -835,6 +890,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 diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h index 605d5a2..1efa715 100644 --- a/media/mtp/MtpServer.h +++ b/media/mtp/MtpServer.h @@ -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(); diff --git a/media/mtp/MtpStorage.cpp b/media/mtp/MtpStorage.cpp index 2fbbc51..6cb88b3 100644 --- a/media/mtp/MtpStorage.cpp +++ b/media/mtp/MtpStorage.cpp @@ -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); diff --git a/media/mtp/MtpStorage.h b/media/mtp/MtpStorage.h index ace720b..858c9d3 100644 --- a/media/mtp/MtpStorage.h +++ b/media/mtp/MtpStorage.h @@ -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 diff --git a/media/mtp/mtp.h b/media/mtp/mtp.h index 8bc2e22..6fedc16 100644 --- a/media/mtp/mtp.h +++ b/media/mtp/mtp.h @@ -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 |