summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/mediarecorder.cpp11
-rw-r--r--media/libstagefright/foundation/ABitReader.cpp4
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.cpp83
-rw-r--r--media/libstagefright/rtsp/AMPEG4AudioAssembler.h1
-rw-r--r--media/libstagefright/rtsp/APacketSource.cpp3
-rw-r--r--media/libstagefright/rtsp/ARTPSource.cpp3
-rw-r--r--media/libstagefright/rtsp/ARawAudioAssembler.cpp143
-rw-r--r--media/libstagefright/rtsp/ARawAudioAssembler.h60
-rw-r--r--media/libstagefright/rtsp/Android.mk1
-rw-r--r--media/mtp/MtpServer.cpp91
-rw-r--r--media/mtp/MtpServer.h18
-rw-r--r--media/mtp/MtpStorage.cpp4
-rw-r--r--media/mtp/MtpStorage.h5
-rw-r--r--media/mtp/mtp.h2
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> &notify, const char *desc, const AString &params)
+ : 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> &notify,
+ const char *desc, const AString &params);
+
+ 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