Merge "Fix security vulnerability: Equalizer command might allow negative indexes"
diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h
index 2ec89a4..f20c2cd 100644
--- a/include/media/stagefright/AudioSource.h
+++ b/include/media/stagefright/AudioSource.h
@@ -89,6 +89,8 @@
int64_t mPrevSampleTimeUs;
int64_t mInitialReadTimeUs;
int64_t mNumFramesReceived;
+ int64_t mNumFramesSkipped;
+ int64_t mNumFramesLost;
int64_t mNumClientOwnedBuffers;
List<MediaBuffer * > mBuffersReceived;
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 2c31a0d..89def5d 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -64,14 +64,15 @@
};
static const pid_t kNoPid = -1;
+ static const uid_t kNoUid = -1;
static sp<MediaCodec> CreateByType(
const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err = NULL,
- pid_t pid = kNoPid);
+ pid_t pid = kNoPid, uid_t uid = kNoUid);
static sp<MediaCodec> CreateByComponentName(
const sp<ALooper> &looper, const AString &name, status_t *err = NULL,
- pid_t pid = kNoPid);
+ pid_t pid = kNoPid, uid_t uid = kNoUid);
static sp<PersistentSurface> CreatePersistentInputSurface();
@@ -286,6 +287,7 @@
};
State mState;
+ uid_t mUid;
bool mReleasedByResourceManager;
sp<ALooper> mLooper;
sp<ALooper> mCodecLooper;
@@ -345,7 +347,7 @@
bool mHaveInputSurface;
bool mHavePendingInputBuffers;
- MediaCodec(const sp<ALooper> &looper, pid_t pid);
+ MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid);
static sp<CodecBase> GetCodecBase(const AString &name, bool nameIsType = false);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 0490fd5..c3b2609 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1641,7 +1641,7 @@
} else {
mSource->setOffloadAudio(false /* offload */);
- *decoder = new Decoder(notify, mSource, mPID, mRenderer);
+ *decoder = new Decoder(notify, mSource, mPID, mUID, mRenderer);
}
} else {
sp<AMessage> notify = new AMessage(kWhatVideoNotify, this);
@@ -1649,7 +1649,7 @@
notify->setInt32("generation", mVideoDecoderGeneration);
*decoder = new Decoder(
- notify, mSource, mPID, mRenderer, mSurface, mCCDecoder);
+ notify, mSource, mPID, mUID, mRenderer, mSurface, mCCDecoder);
// enable FRC if high-quality AV sync is requested, even if not
// directly queuing to display, as this will even improve textureview
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index c3274f0..6974207 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -58,6 +58,7 @@
const sp<AMessage> ¬ify,
const sp<Source> &source,
pid_t pid,
+ uid_t uid,
const sp<Renderer> &renderer,
const sp<Surface> &surface,
const sp<CCDecoder> &ccDecoder)
@@ -67,6 +68,7 @@
mRenderer(renderer),
mCCDecoder(ccDecoder),
mPid(pid),
+ mUid(uid),
mSkipRenderingUntilMediaTimeUs(-1ll),
mNumFramesTotal(0ll),
mNumInputFramesDropped(0ll),
@@ -266,7 +268,7 @@
ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), mSurface.get());
mCodec = MediaCodec::CreateByType(
- mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid);
+ mCodecLooper, mime.c_str(), false /* encoder */, NULL /* err */, mPid, mUid);
int32_t secure = 0;
if (format->findInt32("secure", &secure) && secure != 0) {
if (mCodec != NULL) {
@@ -275,7 +277,7 @@
mCodec->release();
ALOGI("[%s] creating", mComponentName.c_str());
mCodec = MediaCodec::CreateByComponentName(
- mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid);
+ mCodecLooper, mComponentName.c_str(), NULL /* err */, mPid, mUid);
}
}
if (mCodec == NULL) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 8186862..a576ae5 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -29,6 +29,7 @@
Decoder(const sp<AMessage> ¬ify,
const sp<Source> &source,
pid_t pid,
+ uid_t uid,
const sp<Renderer> &renderer = NULL,
const sp<Surface> &surface = NULL,
const sp<CCDecoder> &ccDecoder = NULL);
@@ -85,6 +86,7 @@
Vector<size_t> mDequeuedInputBuffers;
const pid_t mPid;
+ const uid_t mUid;
int64_t mSkipRenderingUntilMediaTimeUs;
int64_t mNumFramesTotal;
int64_t mNumInputFramesDropped;
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index efdee77..4ccd2d0 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -62,6 +62,8 @@
mPrevSampleTimeUs(0),
mInitialReadTimeUs(0),
mNumFramesReceived(0),
+ mNumFramesSkipped(0),
+ mNumFramesLost(0),
mNumClientOwnedBuffers(0) {
ALOGV("sampleRate: %u, outSampleRate: %u, channelCount: %u",
sampleRate, outSampleRate, channelCount);
@@ -295,11 +297,27 @@
}
status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) {
- int64_t timeUs = systemTime() / 1000ll;
- // Estimate the real sampling time of the 1st sample in this buffer
- // from AudioRecord's latency. (Apply this adjustment first so that
- // the start time logic is not affected.)
- timeUs -= mRecord->latency() * 1000LL;
+ int64_t timeUs, position, timeNs;
+ ExtendedTimestamp ts;
+ ExtendedTimestamp::Location location;
+ const int32_t usPerSec = 1000000;
+
+ if (mRecord->getTimestamp(&ts) == OK &&
+ ts.getBestTimestamp(&position, &timeNs, ExtendedTimestamp::TIMEBASE_MONOTONIC,
+ &location) == OK) {
+ // Use audio timestamp.
+ timeUs = timeNs / 1000 -
+ (position - mNumFramesSkipped -
+ mNumFramesReceived + mNumFramesLost) * usPerSec / mSampleRate;
+ } else {
+ // This should not happen in normal case.
+ ALOGW("Failed to get audio timestamp, fallback to use systemclock");
+ timeUs = systemTime() / 1000ll;
+ // Estimate the real sampling time of the 1st sample in this buffer
+ // from AudioRecord's latency. (Apply this adjustment first so that
+ // the start time logic is not affected.)
+ timeUs -= mRecord->latency() * 1000LL;
+ }
ALOGV("dataCallbackTimestamp: %" PRId64 " us", timeUs);
Mutex::Autolock autoLock(mLock);
@@ -308,10 +326,15 @@
return OK;
}
+ const size_t bufferSize = audioBuffer.size;
+
// Drop retrieved and previously lost audio data.
if (mNumFramesReceived == 0 && timeUs < mStartTimeUs) {
(void) mRecord->getInputFramesLost();
- ALOGV("Drop audio data at %" PRId64 "/%" PRId64 " us", timeUs, mStartTimeUs);
+ int64_t receievedFrames = bufferSize / mRecord->frameSize();
+ ALOGV("Drop audio data(%" PRId64 " frames) at %" PRId64 "/%" PRId64 " us",
+ receievedFrames, timeUs, mStartTimeUs);
+ mNumFramesSkipped += receievedFrames;
return OK;
}
@@ -320,11 +343,7 @@
// Initial delay
if (mStartTimeUs > 0) {
mStartTimeUs = timeUs - mStartTimeUs;
- } else {
- // Assume latency is constant.
- mStartTimeUs += mRecord->latency() * 1000;
}
-
mPrevSampleTimeUs = mStartTimeUs;
}
@@ -354,6 +373,7 @@
MediaBuffer *lostAudioBuffer = new MediaBuffer(bufferSize);
memset(lostAudioBuffer->data(), 0, bufferSize);
lostAudioBuffer->set_range(0, bufferSize);
+ mNumFramesLost += bufferSize / mRecord->frameSize();
queueInputBuffer_l(lostAudioBuffer, timeUs);
}
@@ -362,7 +382,6 @@
return OK;
}
- const size_t bufferSize = audioBuffer.size;
MediaBuffer *buffer = new MediaBuffer(bufferSize);
memcpy((uint8_t *) buffer->data(),
audioBuffer.i16, audioBuffer.size);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 12eca10..e617b24 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -173,8 +173,9 @@
// static
sp<MediaCodec> MediaCodec::CreateByType(
- const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid) {
- sp<MediaCodec> codec = new MediaCodec(looper, pid);
+ const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid,
+ uid_t uid) {
+ sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
if (err != NULL) {
@@ -185,8 +186,8 @@
// static
sp<MediaCodec> MediaCodec::CreateByComponentName(
- const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid) {
- sp<MediaCodec> codec = new MediaCodec(looper, pid);
+ const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) {
+ sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
if (err != NULL) {
@@ -234,7 +235,7 @@
return new PersistentSurface(bufferProducer, bufferSource);
}
-MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid)
+MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid)
: mState(UNINITIALIZED),
mReleasedByResourceManager(false),
mLooper(looper),
@@ -256,6 +257,11 @@
mDequeueOutputReplyID(0),
mHaveInputSurface(false),
mHavePendingInputBuffers(false) {
+ if (uid == kNoUid) {
+ mUid = IPCThreadState::self()->getCallingUid();
+ } else {
+ mUid = uid;
+ }
}
MediaCodec::~MediaCodec() {
@@ -1333,12 +1339,30 @@
static_cast<CodecBase::PortDescription *>(obj.get());
size_t numBuffers = portDesc->countBuffers();
+
+ size_t totalSize = 0;
+ for (size_t i = 0; i < numBuffers; ++i) {
+ if (portIndex == kPortIndexInput && mCrypto != NULL) {
+ totalSize += portDesc->bufferAt(i)->capacity();
+ }
+ }
+
+ if (totalSize) {
+ mDealer = new MemoryDealer(totalSize, "MediaCodec");
+ }
+
for (size_t i = 0; i < numBuffers; ++i) {
BufferInfo info;
info.mBufferID = portDesc->bufferIDAt(i);
info.mOwnedByClient = false;
+ sp<MediaCodecBuffer> buffer = portDesc->bufferAt(i);
+ if (portIndex == kPortIndexInput && mCrypto != NULL) {
+ info.mSharedEncryptedBuffer = mDealer->allocate(buffer->capacity());
+ buffer = new SharedMemoryBuffer(
+ mInputFormat, info.mSharedEncryptedBuffer);
+ }
buffers->push_back(info);
- mPortBufferArrays[portIndex].push_back(portDesc->bufferAt(i));
+ mPortBufferArrays[portIndex].push_back(buffer);
}
if (portIndex == kPortIndexOutput) {
@@ -2380,17 +2404,6 @@
sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
- if (portIndex == kPortIndexInput && mCrypto != NULL && mDealer == NULL) {
- // Lazy initialization for encrypted buffers.
- size_t capacity = buffer->capacity();
- size_t totalSize = capacity * buffers->size();
-
- mDealer = new MemoryDealer(totalSize, "MediaCodec");
- for (size_t i = 0; i < buffers->size(); ++i) {
- BufferInfo *info = &buffers->editItemAt(i);
- info->mSharedEncryptedBuffer = mDealer->allocate(capacity);
- }
- }
for (size_t i = 0; i < buffers->size(); ++i) {
BufferInfo *info = &buffers->editItemAt(i);
@@ -2904,10 +2917,10 @@
}
if (mState == CONFIGURED && !mBatteryStatNotified) {
- BatteryNotifier::getInstance().noteStartVideo();
+ BatteryNotifier::getInstance().noteStartVideo(mUid);
mBatteryStatNotified = true;
} else if (mState == UNINITIALIZED && mBatteryStatNotified) {
- BatteryNotifier::getInstance().noteStopVideo();
+ BatteryNotifier::getInstance().noteStopVideo(mUid);
mBatteryStatNotified = false;
}
}
diff --git a/media/utils/BatteryNotifier.cpp b/media/utils/BatteryNotifier.cpp
index 341d391..7a7321f 100644
--- a/media/utils/BatteryNotifier.cpp
+++ b/media/utils/BatteryNotifier.cpp
@@ -29,7 +29,7 @@
BatteryNotifier::getInstance().onBatteryStatServiceDied();
}
-BatteryNotifier::BatteryNotifier() : mVideoRefCount(0), mAudioRefCount(0) {}
+BatteryNotifier::BatteryNotifier() {}
BatteryNotifier::~BatteryNotifier() {
Mutex::Autolock _l(mLock);
@@ -38,67 +38,73 @@
}
}
-void BatteryNotifier::noteStartVideo() {
+void BatteryNotifier::noteStartVideo(int uid) {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
- if (mVideoRefCount == 0 && batteryService != nullptr) {
- batteryService->noteStartVideo(AID_MEDIA);
+ if (mVideoRefCounts[uid] == 0 && batteryService != nullptr) {
+ batteryService->noteStartVideo(uid);
}
- mVideoRefCount++;
+ mVideoRefCounts[uid]++;
}
-void BatteryNotifier::noteStopVideo() {
+void BatteryNotifier::noteStopVideo(int uid) {
Mutex::Autolock _l(mLock);
- if (mVideoRefCount == 0) {
- ALOGW("%s: video refcount is broken.", __FUNCTION__);
+ if (mVideoRefCounts.find(uid) == mVideoRefCounts.end()) {
+ ALOGW("%s: video refcount is broken for uid(%d).", __FUNCTION__, (int)uid);
return;
}
sp<IBatteryStats> batteryService = getBatteryService_l();
- mVideoRefCount--;
- if (mVideoRefCount == 0 && batteryService != nullptr) {
- batteryService->noteStopVideo(AID_MEDIA);
+ mVideoRefCounts[uid]--;
+ if (mVideoRefCounts[uid] == 0) {
+ if (batteryService != nullptr) {
+ batteryService->noteStopVideo(uid);
+ }
+ mVideoRefCounts.erase(uid);
}
}
void BatteryNotifier::noteResetVideo() {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
- mVideoRefCount = 0;
+ mVideoRefCounts.clear();
if (batteryService != nullptr) {
batteryService->noteResetVideo();
}
}
-void BatteryNotifier::noteStartAudio() {
+void BatteryNotifier::noteStartAudio(int uid) {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
- if (mAudioRefCount == 0 && batteryService != nullptr) {
- batteryService->noteStartAudio(AID_AUDIOSERVER);
+ if (mAudioRefCounts[uid] == 0 && batteryService != nullptr) {
+ batteryService->noteStartAudio(uid);
}
- mAudioRefCount++;
+ mAudioRefCounts[uid]++;
}
-void BatteryNotifier::noteStopAudio() {
+void BatteryNotifier::noteStopAudio(int uid) {
Mutex::Autolock _l(mLock);
- if (mAudioRefCount == 0) {
- ALOGW("%s: audio refcount is broken.", __FUNCTION__);
+ if (mAudioRefCounts.find(uid) == mAudioRefCounts.end()) {
+ ALOGW("%s: audio refcount is broken for uid(%d).", __FUNCTION__, (int)uid);
return;
}
sp<IBatteryStats> batteryService = getBatteryService_l();
- mAudioRefCount--;
- if (mAudioRefCount == 0 && batteryService != nullptr) {
- batteryService->noteStopAudio(AID_AUDIOSERVER);
+ mAudioRefCounts[uid]--;
+ if (mAudioRefCounts[uid] == 0) {
+ if (batteryService != nullptr) {
+ batteryService->noteStopAudio(uid);
+ }
+ mAudioRefCounts.erase(uid);
}
}
void BatteryNotifier::noteResetAudio() {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
- mAudioRefCount = 0;
+ mAudioRefCounts.clear();
if (batteryService != nullptr) {
batteryService->noteResetAudio();
}
@@ -176,7 +182,7 @@
Mutex::Autolock _l(mLock);
mBatteryStatService.clear();
mDeathNotifier.clear();
- // Do not reset mVideoRefCount and mAudioRefCount here. The ref
+ // Do not reset mVideoRefCounts and mAudioRefCounts here. The ref
// counting is independent of the battery service availability.
// We need this if battery service becomes available after media
// started.
@@ -205,11 +211,13 @@
// Notify start now if mediaserver or audioserver is already started.
// 1) mediaserver and audioserver is started before batterystats service
// 2) batterystats server may have crashed.
- if (mVideoRefCount > 0) {
- mBatteryStatService->noteStartVideo(AID_MEDIA);
+ std::map<int, int>::iterator it = mVideoRefCounts.begin();
+ for (; it != mVideoRefCounts.end(); ++it) {
+ mBatteryStatService->noteStartVideo(it->first);
}
- if (mAudioRefCount > 0) {
- mBatteryStatService->noteStartAudio(AID_AUDIOSERVER);
+ it = mAudioRefCounts.begin();
+ for (; it != mAudioRefCounts.end(); ++it) {
+ mBatteryStatService->noteStartAudio(it->first);
}
// TODO: Notify for camera and flashlight state as well?
}
diff --git a/media/utils/include/mediautils/BatteryNotifier.h b/media/utils/include/mediautils/BatteryNotifier.h
index 49048042..2ba4c76 100644
--- a/media/utils/include/mediautils/BatteryNotifier.h
+++ b/media/utils/include/mediautils/BatteryNotifier.h
@@ -37,11 +37,11 @@
public:
~BatteryNotifier();
- void noteStartVideo();
- void noteStopVideo();
+ void noteStartVideo(int uid);
+ void noteStopVideo(int uid);
void noteResetVideo();
- void noteStartAudio();
- void noteStopAudio();
+ void noteStartAudio(int uid);
+ void noteStopAudio(int uid);
void noteResetAudio();
void noteFlashlightOn(const String8& id, int uid);
void noteFlashlightOff(const String8& id, int uid);
@@ -58,8 +58,8 @@
};
Mutex mLock;
- int mVideoRefCount;
- int mAudioRefCount;
+ std::map<int, int> mVideoRefCounts;
+ std::map<int, int> mAudioRefCounts;
std::map<std::pair<String8, int>, bool> mFlashlightState;
std::map<std::pair<String8, int>, bool> mCameraState;
sp<IBatteryStats> mBatteryStatService;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6b23e56..4ae5a02 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -33,6 +33,7 @@
#include <utils/Trace.h>
#include <private/media/AudioTrackShared.h>
+#include <private/android_filesystem_config.h>
#include <audio_utils/conversion.h>
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
@@ -1040,7 +1041,8 @@
}
if (!mNotifiedBatteryStart) {
- BatteryNotifier::getInstance().noteStartAudio();
+ // TODO: call this function for each track when it becomes active.
+ BatteryNotifier::getInstance().noteStartAudio(AID_AUDIOSERVER);
mNotifiedBatteryStart = true;
}
gBoottime.acquire(mWakeLockToken);
@@ -1067,7 +1069,8 @@
}
if (mNotifiedBatteryStart) {
- BatteryNotifier::getInstance().noteStopAudio();
+ // TODO: call this function for each track when it becomes inactive.
+ BatteryNotifier::getInstance().noteStopAudio(AID_AUDIOSERVER);
mNotifiedBatteryStart = false;
}
}
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 8ce84ae..a19fe1d 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -2900,6 +2900,7 @@
}
// Get min frame duration for each size and check if the given fps range can be supported.
+ const int32_t FPS_MARGIN = 1;
for (size_t i = 0 ; i < sizes.size(); i++) {
int64_t minFrameDuration = getMinFrameDurationNs(sizes[i], format);
if (minFrameDuration <= 0) {
@@ -2908,6 +2909,8 @@
return false;
}
int32_t maxSupportedFps = 1e9 / minFrameDuration;
+ // Add some margin here for the case where the hal supports 29.xxxfps.
+ maxSupportedFps += FPS_MARGIN;
if (fps > maxSupportedFps) {
return false;
}