Merge "Access AVCDEC context after create fail check" into mnc-dr-dev am: eba5ad1a07 am: ba9840c1ce am: 6fd437edf7 am: b334ac03d9 am: a61eab4354 am: 193030ccf0
am: 407b19779b
Change-Id: I6015a513f379a5d7a71ae6fbddc719f0de40ebc0
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
index 86bf047..8356bcc 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
@@ -75,6 +75,8 @@
}
status_t res = session->provideKeyResponse(response);
if (res == android::OK) {
+ // This is for testing AMediaDrm_setOnEventListener only.
+ sendEvent(kDrmPluginEventVendorDefined, 0, &scope, NULL);
keySetId.clear();
}
return res;
@@ -90,6 +92,8 @@
value = "ClearKey CDM";
} else if (name == "algorithms") {
value = "";
+ } else if (name == "listenerTestSupport") {
+ value = "true";
} else {
ALOGE("App requested unknown string property %s", name.string());
return android::ERROR_DRM_CANNOT_HANDLE;
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 8fc410d..2ec89a4 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -87,7 +87,6 @@
int64_t mStartTimeUs;
int16_t mMaxAmplitude;
int64_t mPrevSampleTimeUs;
- int64_t mFirstSampleTimeUs;
int64_t mInitialReadTimeUs;
int64_t mNumFramesReceived;
int64_t mNumClientOwnedBuffers;
diff --git a/include/media/stagefright/SimpleDecodingSource.h b/include/media/stagefright/SimpleDecodingSource.h
index 534097b..e6aee6a 100644
--- a/include/media/stagefright/SimpleDecodingSource.h
+++ b/include/media/stagefright/SimpleDecodingSource.h
@@ -71,12 +71,13 @@
// Construct this using a codec, source and looper.
SimpleDecodingSource(
const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
- bool usingSurface, const sp<AMessage> &format);
+ bool usingSurface, bool isVorbis, const sp<AMessage> &format);
sp<MediaCodec> mCodec;
sp<IMediaSource> mSource;
sp<ALooper> mLooper;
bool mUsingSurface;
+ bool mIsVorbis;
enum State {
INIT,
STARTED,
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index ff5903d..a80c891 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -1274,6 +1274,9 @@
return true;
}
}
+ if (exitPending()) {
+ return false;
+ }
nsecs_t ns = mReceiver.processAudioBuffer();
switch (ns) {
case 0:
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index f0f44e6..af2d0f3 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -876,6 +876,10 @@
status_t NuPlayer::GenericSource::dequeueAccessUnit(
bool audio, sp<ABuffer> *accessUnit) {
+ if (audio && !mStarted) {
+ return -EWOULDBLOCK;
+ }
+
Track *track = audio ? &mAudioTrack : &mVideoTrack;
if (track->mSource == NULL) {
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 790c6da..efdee77 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -60,7 +60,6 @@
mStartTimeUs(0),
mMaxAmplitude(0),
mPrevSampleTimeUs(0),
- mFirstSampleTimeUs(-1ll),
mInitialReadTimeUs(0),
mNumFramesReceived(0),
mNumClientOwnedBuffers(0) {
@@ -277,12 +276,8 @@
}
if (mSampleRate != mOutSampleRate) {
- if (mFirstSampleTimeUs < 0) {
- mFirstSampleTimeUs = timeUs;
- }
- timeUs = mFirstSampleTimeUs + (timeUs - mFirstSampleTimeUs)
- * (int64_t)mSampleRate / (int64_t)mOutSampleRate;
- buffer->meta_data()->setInt64(kKeyTime, timeUs);
+ timeUs *= (int64_t)mSampleRate / (int64_t)mOutSampleRate;
+ buffer->meta_data()->setInt64(kKeyTime, timeUs);
}
*out = buffer;
diff --git a/media/libstagefright/SimpleDecodingSource.cpp b/media/libstagefright/SimpleDecodingSource.cpp
index de21c5e..2503a32 100644
--- a/media/libstagefright/SimpleDecodingSource.cpp
+++ b/media/libstagefright/SimpleDecodingSource.cpp
@@ -18,6 +18,7 @@
#include <media/ICrypto.h>
#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
@@ -74,7 +75,10 @@
err = codec->getOutputFormat(&format);
}
if (err == OK) {
- return new SimpleDecodingSource(codec, source, looper, surface != NULL, format);
+ return new SimpleDecodingSource(codec, source, looper,
+ surface != NULL,
+ strcmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS) == 0,
+ format);
}
ALOGD("Failed to configure codec '%s'", componentName.c_str());
@@ -90,11 +94,12 @@
SimpleDecodingSource::SimpleDecodingSource(
const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
- bool usingSurface, const sp<AMessage> &format)
+ bool usingSurface, bool isVorbis, const sp<AMessage> &format)
: mCodec(codec),
mSource(source),
mLooper(looper),
mUsingSurface(usingSurface),
+ mIsVorbis(isVorbis),
mProtectedState(format) {
mCodec->getName(&mComponentName);
}
@@ -280,16 +285,25 @@
if (in_buf != NULL) {
int64_t timestampUs = 0;
CHECK(in_buf->meta_data()->findInt64(kKeyTime, ×tampUs));
- if (in_buf->range_length() > in_buffer->capacity()) {
+ if (in_buf->range_length() + (mIsVorbis ? 4 : 0) > in_buffer->capacity()) {
ALOGW("'%s' received %zu input bytes for buffer of size %zu",
mComponentName.c_str(),
- in_buf->range_length(), in_buffer->capacity());
+ in_buf->range_length() + (mIsVorbis ? 4 : 0), in_buffer->capacity());
}
+ size_t cpLen = min(in_buf->range_length(), in_buffer->capacity());
memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(),
- min(in_buf->range_length(), in_buffer->capacity()));
+ cpLen );
+
+ if (mIsVorbis) {
+ int32_t numPageSamples;
+ if (!in_buf->meta_data()->findInt32(kKeyValidSamples, &numPageSamples)) {
+ numPageSamples = -1;
+ }
+ memcpy(in_buffer->base() + cpLen, &numPageSamples, sizeof(numPageSamples));
+ }
res = mCodec->queueInputBuffer(
- in_ix, 0 /* offset */, in_buf->range_length(),
+ in_ix, 0 /* offset */, in_buf->range_length() + (mIsVorbis ? 4 : 0),
timestampUs, 0 /* flags */);
if (res != OK) {
ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix);
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index d1b2f54..1c170b8 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -42,13 +42,9 @@
namespace android {
-static Mutex gWVMutex;
-
WVMExtractor::WVMExtractor(const sp<DataSource> &source)
: mDataSource(source)
{
- Mutex::Autolock autoLock(gWVMutex);
-
if (!getVendorLibHandle()) {
return;
}
@@ -169,8 +165,6 @@
const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
- Mutex::Autolock autoLock(gWVMutex);
-
if (!WVMExtractor::getVendorLibHandle()) {
return false;
}
diff --git a/media/libstagefright/foundation/MediaBufferGroup.cpp b/media/libstagefright/foundation/MediaBufferGroup.cpp
index 54f768a..8e4d064 100644
--- a/media/libstagefright/foundation/MediaBufferGroup.cpp
+++ b/media/libstagefright/foundation/MediaBufferGroup.cpp
@@ -39,6 +39,12 @@
MediaBufferGroup::MediaBufferGroup(size_t buffers, size_t buffer_size, size_t growthLimit)
: mGrowthLimit(growthLimit) {
+ if (mGrowthLimit > 0 && buffers > mGrowthLimit) {
+ ALOGW("Preallocated buffers %zu > growthLimit %zu, increasing growthLimit",
+ buffers, mGrowthLimit);
+ mGrowthLimit = buffers;
+ }
+
if (buffer_size >= kSharedMemoryThreshold) {
ALOGD("creating MemoryDealer");
// Using a single MemoryDealer is efficient for a group of shared memory objects.
@@ -102,9 +108,22 @@
void MediaBufferGroup::add_buffer(MediaBuffer *buffer) {
Mutex::Autolock autoLock(mLock);
+ // if we're above our growth limit, release buffers if we can
+ for (auto it = mBuffers.begin();
+ mGrowthLimit > 0
+ && mBuffers.size() >= mGrowthLimit
+ && it != mBuffers.end();) {
+ if ((*it)->refcount() == 0) {
+ (*it)->setObserver(nullptr);
+ (*it)->release();
+ it = mBuffers.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
buffer->setObserver(this);
mBuffers.emplace_back(buffer);
- // optionally: mGrowthLimit = max(mGrowthLimit, mBuffers.size());
}
bool MediaBufferGroup::has_buffers() {
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 8b6c591..e1bcd28 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -804,7 +804,8 @@
if (mPrevCaptureUs < 0ll) {
// first capture
mPrevCaptureUs = timeUs;
- mPrevFrameUs = timeUs;
+ // adjust the first sample timestamp.
+ mPrevFrameUs = (timeUs * mTimePerFrameUs) / mTimePerCaptureUs;
} else {
// snap to nearest capture point
int64_t nFrames = (timeUs + mTimePerCaptureUs / 2 - mPrevCaptureUs)
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 0381edf..0e9bc34 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -16,17 +16,38 @@
#define LOG_TAG "MtpDataPacket"
+#include "MtpDataPacket.h"
+
+#include <algorithm>
+#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
-#include <fcntl.h>
-
#include <usbhost/usbhost.h>
-
-#include "MtpDataPacket.h"
#include "MtpStringBuffer.h"
namespace android {
+namespace {
+// Reads the exact |count| bytes from |fd| to |buf|.
+// Returns |count| if it succeed to read the bytes. Otherwise returns -1. If it reaches EOF, the
+// function regards it as an error.
+ssize_t readExactBytes(int fd, void* buf, size_t count) {
+ if (count > SSIZE_MAX) {
+ return -1;
+ }
+ size_t read_count = 0;
+ while (read_count < count) {
+ int result = read(fd, static_cast<int8_t*>(buf) + read_count, count - read_count);
+ // Assume that EOF is error.
+ if (result <= 0) {
+ return -1;
+ }
+ read_count += result;
+ }
+ return read_count == count ? count : -1;
+}
+} // namespace
+
MtpDataPacket::MtpDataPacket()
: MtpPacket(MTP_BUFFER_SIZE), // MAX_USBFS_BUFFER_SIZE
mOffset(MTP_CONTAINER_HEADER_SIZE)
@@ -511,29 +532,104 @@
return length;
}
-int MtpDataPacket::writeDataHeader(struct usb_request *request, uint32_t length) {
- MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
- MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
- request->buffer = mBuffer;
- request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
- int ret = transfer(request);
- return (ret < 0 ? ret : 0);
-}
+int MtpDataPacket::write(struct usb_request *request, UrbPacketDivisionMode divisionMode) {
+ if (mPacketSize < MTP_CONTAINER_HEADER_SIZE || mPacketSize > MTP_BUFFER_SIZE) {
+ ALOGE("Illegal packet size.");
+ return -1;
+ }
-int MtpDataPacket::write(struct usb_request *request) {
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
- request->buffer = mBuffer;
- request->buffer_length = mPacketSize;
- int ret = transfer(request);
- return (ret < 0 ? ret : 0);
+
+ size_t processedBytes = 0;
+ while (processedBytes < mPacketSize) {
+ const size_t write_size =
+ processedBytes == 0 && divisionMode == FIRST_PACKET_ONLY_HEADER ?
+ MTP_CONTAINER_HEADER_SIZE : mPacketSize - processedBytes;
+ request->buffer = mBuffer + processedBytes;
+ request->buffer_length = write_size;
+ const int result = transfer(request);
+ if (result < 0) {
+ ALOGE("Failed to write bytes to the device.");
+ return -1;
+ }
+ processedBytes += result;
+ }
+
+ return processedBytes == mPacketSize ? processedBytes : -1;
}
-int MtpDataPacket::write(struct usb_request *request, void* buffer, uint32_t length) {
- request->buffer = buffer;
- request->buffer_length = length;
- int ret = transfer(request);
- return (ret < 0 ? ret : 0);
+int MtpDataPacket::write(struct usb_request *request,
+ UrbPacketDivisionMode divisionMode,
+ int fd,
+ size_t payloadSize) {
+ // Obtain the greatest multiple of minimum packet size that is not greater than
+ // MTP_BUFFER_SIZE.
+ if (request->max_packet_size <= 0) {
+ ALOGE("Cannot determine bulk transfer size due to illegal max packet size %d.",
+ request->max_packet_size);
+ return -1;
+ }
+ const size_t maxBulkTransferSize =
+ MTP_BUFFER_SIZE - (MTP_BUFFER_SIZE % request->max_packet_size);
+ const size_t containerLength = payloadSize + MTP_CONTAINER_HEADER_SIZE;
+ size_t processedBytes = 0;
+ bool readError = false;
+
+ // Bind the packet with given request.
+ request->buffer = mBuffer;
+ allocate(maxBulkTransferSize);
+
+ while (processedBytes < containerLength) {
+ size_t bulkTransferSize = 0;
+
+ // prepare header.
+ const bool headerSent = processedBytes != 0;
+ if (!headerSent) {
+ MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, containerLength);
+ MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
+ bulkTransferSize += MTP_CONTAINER_HEADER_SIZE;
+ }
+
+ // Prepare payload.
+ if (headerSent || divisionMode == FIRST_PACKET_HAS_PAYLOAD) {
+ const size_t processedPayloadBytes =
+ headerSent ? processedBytes - MTP_CONTAINER_HEADER_SIZE : 0;
+ const size_t maxRead = payloadSize - processedPayloadBytes;
+ const size_t maxWrite = maxBulkTransferSize - bulkTransferSize;
+ const size_t bulkTransferPayloadSize = std::min(maxRead, maxWrite);
+ // prepare payload.
+ if (!readError) {
+ const ssize_t result = readExactBytes(
+ fd,
+ mBuffer + bulkTransferSize,
+ bulkTransferPayloadSize);
+ if (result < 0) {
+ ALOGE("Found an error while reading data from FD. Send 0 data instead.");
+ readError = true;
+ }
+ }
+ if (readError) {
+ memset(mBuffer + bulkTransferSize, 0, bulkTransferPayloadSize);
+ }
+ bulkTransferSize += bulkTransferPayloadSize;
+ }
+
+ // Bulk transfer.
+ mPacketSize = bulkTransferSize;
+ request->buffer_length = bulkTransferSize;
+ const int result = transfer(request);
+ if (result != static_cast<ssize_t>(bulkTransferSize)) {
+ // Cannot recover writing error.
+ ALOGE("Found an error while write data to MtpDevice.");
+ return -1;
+ }
+
+ // Update variables.
+ processedBytes += bulkTransferSize;
+ }
+
+ return readError ? -1 : processedBytes;
}
#endif // MTP_HOST
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index 6240f28..82e0ee4 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -93,7 +93,6 @@
inline void putEmptyString() { putUInt8(0); }
inline void putEmptyArray() { putUInt32(0); }
-
#ifdef MTP_DEVICE
// fill our buffer with data from the given file descriptor
int read(int fd);
@@ -110,9 +109,15 @@
int readDataWait(struct usb_device *device);
int readDataHeader(struct usb_request *ep);
- int writeDataHeader(struct usb_request *ep, uint32_t length);
- int write(struct usb_request *ep);
- int write(struct usb_request *ep, void* buffer, uint32_t length);
+ // Write a whole data packet with payload to the end point given by a request. |divisionMode|
+ // specifies whether to divide header and payload. See |UrbPacketDivisionMode| for meanings of
+ // each value. Return the number of bytes (including header size) sent to the device on success.
+ // Otherwise -1.
+ int write(struct usb_request *request, UrbPacketDivisionMode divisionMode);
+ // Similar to previous write method but it reads the payload from |fd|. If |size| is larger than
+ // MTP_BUFFER_SIZE, the data will be sent by multiple bulk transfer requests.
+ int write(struct usb_request *request, UrbPacketDivisionMode divisionMode,
+ int fd, size_t size);
#endif
inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index bd89a51..e3d2ec6 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -220,7 +220,10 @@
mTransactionID(0),
mReceivedResponse(false),
mProcessingEvent(false),
- mCurrentEventHandle(0)
+ mCurrentEventHandle(0),
+ mLastSendObjectInfoTransactionID(0),
+ mLastSendObjectInfoObjectHandle(0),
+ mPacketDivisionMode(FIRST_PACKET_HAS_PAYLOAD)
{
mRequestIn1 = usb_request_new(device, ep_in);
mRequestIn2 = usb_request_new(device, ep_in);
@@ -490,6 +493,8 @@
if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
+ mLastSendObjectInfoTransactionID = mRequest.getTransactionID();
+ mLastSendObjectInfoObjectHandle = mResponse.getParameter(3);
info->mStorageID = mResponse.getParameter(1);
info->mParent = mResponse.getParameter(2);
info->mHandle = mResponse.getParameter(3);
@@ -502,31 +507,21 @@
bool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) {
Mutex::Autolock autoLock(mMutex);
- int remaining = size;
- mRequest.reset();
- mRequest.setParameter(1, handle);
- bool error = false;
- if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
- // send data header
- writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
-
- // USB writes greater than 16K don't work
- char buffer[MTP_BUFFER_SIZE];
- while (remaining > 0) {
- int count = read(srcFD, buffer, sizeof(buffer));
- if (count > 0) {
- if (mData.write(mRequestOut, buffer, count) < 0) {
- error = true;
- }
- // FIXME check error
- remaining -= count;
- } else {
- break;
- }
- }
+ if (mLastSendObjectInfoTransactionID + 1 != mTransactionID ||
+ mLastSendObjectInfoObjectHandle != handle) {
+ ALOGE("A sendObject request must follow the sendObjectInfo request.");
+ return false;
}
- MtpResponseCode ret = readResponse();
- return (remaining == 0 && ret == MTP_RESPONSE_OK && !error);
+
+ mRequest.reset();
+ if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
+ mData.setOperationCode(mRequest.getOperationCode());
+ mData.setTransactionID(mRequest.getTransactionID());
+ const int writeResult = mData.write(mRequestOut, mPacketDivisionMode, srcFD, size);
+ const MtpResponseCode ret = readResponse();
+ return ret == MTP_RESPONSE_OK && writeResult > 0;
+ }
+ return false;
}
bool MtpDevice::deleteObject(MtpObjectHandle handle) {
@@ -698,8 +693,8 @@
return false;
}
- // If object size 0 byte, the remote device can reply response packet
- // without sending any data packets.
+ // If object size 0 byte, the remote device may reply a response packet without sending any data
+ // packets.
if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
mResponse.copyFrom(mData);
return mResponse.getResponseCode() == MTP_RESPONSE_OK;
@@ -722,6 +717,14 @@
{
int initialDataLength = 0;
void* const initialData = mData.getData(&initialDataLength);
+ if (fullLength > MTP_CONTAINER_HEADER_SIZE && initialDataLength == 0) {
+ // According to the MTP spec, the responder (MTP device) can choose two ways of sending
+ // data. a) The first packet contains the head and as much of the payload as possible
+ // b) The first packet contains only the header. The initiator (MTP host) needs
+ // to remember which way the responder used, and send upcoming data in the same way.
+ ALOGD("Found short packet that contains only a header.");
+ mPacketDivisionMode = FIRST_PACKET_ONLY_HEADER;
+ }
if (initialData) {
if (initialDataLength > 0) {
if (!callback(initialData, offset, initialDataLength, clientData)) {
@@ -845,7 +848,7 @@
ALOGV("sendData\n");
mData.setOperationCode(mRequest.getOperationCode());
mData.setTransactionID(mRequest.getTransactionID());
- int ret = mData.write(mRequestOut);
+ int ret = mData.write(mRequestOut, mPacketDivisionMode);
mData.dump();
return (ret >= 0);
}
@@ -872,12 +875,6 @@
}
}
-bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
- mData.setOperationCode(operation);
- mData.setTransactionID(mRequest.getTransactionID());
- return (!mData.writeDataHeader(mRequestOut, dataLength));
-}
-
MtpResponseCode MtpDevice::readResponse() {
ALOGV("readResponse\n");
if (mReceivedResponse) {
diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h
index 4be44cf..c84c842 100644
--- a/media/mtp/MtpDevice.h
+++ b/media/mtp/MtpDevice.h
@@ -62,11 +62,18 @@
bool mProcessingEvent;
int mCurrentEventHandle;
+ // to check if a sendObject request follows the last sendObjectInfo request.
+ MtpTransactionID mLastSendObjectInfoTransactionID;
+ MtpObjectHandle mLastSendObjectInfoObjectHandle;
+
// to ensure only one MTP transaction at a time
Mutex mMutex;
Mutex mEventMutex;
Mutex mEventMutexForInterrupt;
+ // Remember the device's packet division mode.
+ UrbPacketDivisionMode mPacketDivisionMode;
+
public:
typedef bool (*ReadObjectCallback)
(void* data, uint32_t offset, uint32_t length, void* clientData);
diff --git a/media/mtp/MtpTypes.h b/media/mtp/MtpTypes.h
index 720c854..c749c66 100644
--- a/media/mtp/MtpTypes.h
+++ b/media/mtp/MtpTypes.h
@@ -73,6 +73,13 @@
typedef String8 MtpString;
+enum UrbPacketDivisionMode {
+ // First packet only contains a header.
+ FIRST_PACKET_ONLY_HEADER,
+ // First packet contains payload much as possible.
+ FIRST_PACKET_HAS_PAYLOAD
+};
+
}; // namespace android
#endif // _MTP_TYPES_H
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index be71f43..166e6f1 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -221,8 +221,7 @@
static bool findId(AMediaDrm *mObj, const AMediaDrmByteArray &id, List<idvec_t>::iterator &iter) {
- iter = mObj->mIds.begin();
- while (iter != mObj->mIds.end()) {
+ for (iter = mObj->mIds.begin(); iter != mObj->mIds.end(); ++iter) {
if (iter->array() == id.ptr && iter->size() == id.length) {
return true;
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index d0df6d1..6124fed 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -467,8 +467,8 @@
// CameraInfo is for android.hardware.Camera which does not
// support external camera facing. The closest approximation would be
// front camera.
- if (cameraInfo->orientation == CAMERA_FACING_EXTERNAL) {
- cameraInfo->orientation = CAMERA_FACING_FRONT;
+ if (cameraInfo->facing == CAMERA_FACING_EXTERNAL) {
+ cameraInfo->facing = CAMERA_FACING_FRONT;
}
}
return rc;
@@ -2532,7 +2532,8 @@
write(fd, result.string(), result.size());
} else {
result.appendFormat(" Facing: %s\n",
- info.facing == CAMERA_FACING_BACK ? "BACK" : "FRONT");
+ info.facing == CAMERA_FACING_BACK ? "BACK" :
+ info.facing == CAMERA_FACING_FRONT ? "FRONT" : "EXTERNAL");
result.appendFormat(" Orientation: %d\n", info.orientation);
int deviceVersion;
if (mModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_0) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 48a2a99..eece01b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2222,6 +2222,14 @@
}
}
+void Camera3Device::removeInFlightMapEntryLocked(int idx) {
+ mInFlightMap.removeItemsAt(idx, 1);
+
+ // Indicate idle inFlightMap to the status tracker
+ if (mInFlightMap.size() == 0) {
+ mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
+ }
+}
void Camera3Device::removeInFlightRequestIfReadyLocked(int idx) {
@@ -2257,13 +2265,7 @@
returnOutputBuffers(request.pendingOutputBuffers.array(),
request.pendingOutputBuffers.size(), 0);
- mInFlightMap.removeItemsAt(idx, 1);
-
- // Indicate idle inFlightMap to the status tracker
- if (mInFlightMap.size() == 0) {
- mStatusTracker->markComponentIdle(mInFlightStatusId, Fence::NO_FENCE);
- }
-
+ removeInFlightMapEntryLocked(idx);
ALOGVV("%s: removed frame %d from InFlightMap", __FUNCTION__, frameNumber);
}
@@ -3438,6 +3440,20 @@
captureRequest->mResultExtras);
}
}
+
+ // Remove yet-to-be submitted inflight request from inflightMap
+ {
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent != NULL) {
+ Mutex::Autolock l(parent->mInFlightLock);
+ ssize_t idx = parent->mInFlightMap.indexOfKey(captureRequest->mResultExtras.frameNumber);
+ if (idx >= 0) {
+ ALOGV("%s: Remove inflight request from queue: frameNumber %" PRId64,
+ __FUNCTION__, captureRequest->mResultExtras.frameNumber);
+ parent->removeInFlightMapEntryLocked(idx);
+ }
+ }
+ }
}
Mutex::Autolock l(mRequestLock);
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index 17893a9..f422813 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -849,6 +849,9 @@
/**** Scope for mInFlightLock ****/
+ // Remove the in-flight map entry of the given index from mInFlightMap.
+ // It must only be called with mInFlightLock held.
+ void removeInFlightMapEntryLocked(int idx);
// Remove the in-flight request of the given index from mInFlightMap
// if it's no longer needed. It must only be called with mInFlightLock held.
void removeInFlightRequestIfReadyLocked(int idx);