DO NOT MERGE: Merge Oreo MR1 into master am: 3b4a1d7e44 -s ours
am: 534ecbd327
Change-Id: Ia222f029fb804cb6d2bdd48f46063d9d0fca96f4
diff --git a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp b/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp
index 01f8d65..f7106b2 100644
--- a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp
+++ b/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.cpp
@@ -36,6 +36,11 @@
uint8_t previousEncryptedCounter[kBlockSize];
memset(previousEncryptedCounter, 0, kBlockSize);
+ if (key.size() != kBlockSize || (sizeof(Iv) / sizeof(uint8_t)) != kBlockSize) {
+ android_errorWriteLog(0x534e4554, "63982768");
+ return android::ERROR_DRM_DECRYPT;
+ }
+
size_t offset = 0;
AES_KEY opensslKey;
AES_set_encrypt_key(key.array(), kBlockBitCount, &opensslKey);
diff --git a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h b/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h
index b416266..edb8445 100644
--- a/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h
+++ b/drm/mediadrm/plugins/clearkey/AesCtrDecryptor.h
@@ -18,6 +18,7 @@
#define CLEARKEY_AES_CTR_DECRYPTOR_H_
#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaErrors.h>
#include <Utils.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
diff --git a/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp b/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp
index 039e402..5db8290 100644
--- a/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp
+++ b/drm/mediadrm/plugins/clearkey/tests/AesCtrDecryptorUnittest.cpp
@@ -34,7 +34,7 @@
uint8_t* destination, const SubSample* subSamples,
size_t numSubSamples, size_t* bytesDecryptedOut) {
Vector<uint8_t> keyVector;
- keyVector.appendArray(key, kBlockSize);
+ keyVector.appendArray(key, sizeof(key) / sizeof(uint8_t));
AesCtrDecryptor decryptor;
return decryptor.decrypt(keyVector, iv, source, destination, subSamples,
@@ -57,6 +57,67 @@
}
};
+TEST_F(AesCtrDecryptorTest, DecryptsWithEmptyKey) {
+ const size_t kTotalSize = 64;
+ const size_t kNumSubsamples = 1;
+
+ // Test vectors from NIST-800-38A
+ Iv iv = {
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+ };
+
+ uint8_t source[kTotalSize] = { 0 };
+ uint8_t destination[kTotalSize] = { 0 };
+ SubSample subSamples[kNumSubsamples] = {
+ {0, 64}
+ };
+
+ size_t bytesDecrypted = 0;
+ Vector<uint8_t> keyVector;
+ keyVector.clear();
+
+ AesCtrDecryptor decryptor;
+ ASSERT_EQ(android::ERROR_DRM_DECRYPT, decryptor.decrypt(keyVector, iv,
+ &source[0], &destination[0],
+ &subSamples[0], kNumSubsamples, &bytesDecrypted));
+ ASSERT_EQ(0u, bytesDecrypted);
+}
+
+TEST_F(AesCtrDecryptorTest, DecryptsWithKeyTooLong) {
+ const size_t kTotalSize = 64;
+ const size_t kNumSubsamples = 1;
+
+ // Test vectors from NIST-800-38A
+ uint8_t key[kBlockSize * 2] = {
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
+ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+ 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+ };
+
+ Iv iv = {
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+ };
+
+ uint8_t source[kTotalSize] = { 0 };
+ uint8_t destination[kTotalSize] = { 0 };
+ SubSample subSamples[kNumSubsamples] = {
+ {0, 64}
+ };
+
+ size_t bytesDecrypted = 0;
+ Vector<uint8_t> keyVector;
+ keyVector.appendArray(key, sizeof(key) / sizeof(uint8_t));
+
+ AesCtrDecryptor decryptor;
+ ASSERT_EQ(android::ERROR_DRM_DECRYPT, decryptor.decrypt(keyVector, iv,
+ &source[0], &destination[0],
+ &subSamples[0], kNumSubsamples, &bytesDecrypted));
+ ASSERT_EQ(0u, bytesDecrypted);
+}
+
TEST_F(AesCtrDecryptorTest, DecryptsContiguousEncryptedBlock) {
const size_t kTotalSize = 64;
const size_t kNumSubsamples = 1;
diff --git a/media/libaaudio/examples/utils/AAudioExampleUtils.h b/media/libaaudio/examples/utils/AAudioExampleUtils.h
index 2671c3a..46b8895 100644
--- a/media/libaaudio/examples/utils/AAudioExampleUtils.h
+++ b/media/libaaudio/examples/utils/AAudioExampleUtils.h
@@ -32,6 +32,7 @@
#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * 1000)
+template <class T = aaudio_sharing_mode_t>
const char *getSharingModeText(aaudio_sharing_mode_t mode) {
const char *text = "unknown";
switch (mode) {
diff --git a/media/libaaudio/src/utility/MonotonicCounter.h b/media/libaaudio/src/utility/MonotonicCounter.h
index 13c92a2..5833eab 100644
--- a/media/libaaudio/src/utility/MonotonicCounter.h
+++ b/media/libaaudio/src/utility/MonotonicCounter.h
@@ -89,6 +89,18 @@
mCounter32 = 0;
}
+ /**
+ * Round 64-bit counter up to a multiple of the period.
+ *
+ * @param period might be, for example, a buffer capacity
+ */
+ void roundUp64(int32_t period) {
+ if (period > 0) {
+ int64_t numPeriods = (mCounter64 + period - 1) / period;
+ mCounter64 = numPeriods * period;
+ }
+ }
+
private:
int64_t mCounter64 = 0;
int32_t mCounter32 = 0;
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index ceba211..d838975 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -960,6 +960,7 @@
bool hasAttributes = data.readInt32() != 0;
if (hasAttributes) {
data.read(&attr, sizeof(audio_attributes_t));
+ sanetizeAudioAttributes(&attr);
}
audio_session_t session = (audio_session_t)data.readInt32();
audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
@@ -1025,6 +1026,7 @@
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_attributes_t attr;
data.read(&attr, sizeof(audio_attributes_t));
+ sanetizeAudioAttributes(&attr);
audio_io_handle_t input = (audio_io_handle_t)data.readInt32();
audio_session_t session = (audio_session_t)data.readInt32();
pid_t pid = (pid_t)data.readInt32();
@@ -1400,6 +1402,7 @@
data.read(&source, sizeof(struct audio_port_config));
audio_attributes_t attributes;
data.read(&attributes, sizeof(audio_attributes_t));
+ sanetizeAudioAttributes(&attributes);
audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
status_t status = startAudioSource(&source, &attributes, &handle);
reply->writeInt32(status);
@@ -1450,6 +1453,15 @@
}
}
+void BnAudioPolicyService::sanetizeAudioAttributes(audio_attributes_t* attr)
+{
+ const size_t tagsMaxSize = AUDIO_ATTRIBUTES_TAGS_MAX_SIZE;
+ if (strnlen(attr->tags, tagsMaxSize) >= tagsMaxSize) {
+ android_errorWriteLog(0x534e4554, "68953950"); // SafetyNet logging
+ }
+ attr->tags[tagsMaxSize - 1] = '\0';
+}
+
// ----------------------------------------------------------------------------
} // namespace android
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 9b3e35e..60ba4ba 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -183,6 +183,8 @@
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
+private:
+ void sanetizeAudioAttributes(audio_attributes_t* attr);
};
// ----------------------------------------------------------------------------
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index ee9406d..3d8e982 100644
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -1889,6 +1889,10 @@
if (param != REVERB_PARAM_PRESET) {
return -EINVAL;
}
+ if (vsize < (int)sizeof(uint16_t)) {
+ android_errorWriteLog(0x534e4554, "67647856");
+ return -EINVAL;
+ }
uint16_t preset = *(uint16_t *)pValue;
ALOGV("set REVERB_PARAM_PRESET, preset %d", preset);
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 496db0d..3f50684 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -600,17 +600,14 @@
MediaPlayerService::Client::~Client()
{
ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
- {
- Mutex::Autolock l(mLock);
- mAudioOutput.clear();
- }
+ mAudioOutput.clear();
wp<Client> client(this);
disconnect();
mService->removeClient(client);
if (mAudioAttributes != NULL) {
free(mAudioAttributes);
}
- clearDeathNotifiers();
+ clearDeathNotifiers_l();
}
void MediaPlayerService::Client::disconnect()
@@ -638,7 +635,10 @@
p->reset();
}
- disconnectNativeWindow();
+ {
+ Mutex::Autolock l(mLock);
+ disconnectNativeWindow_l();
+ }
IPCThreadState::self()->flushCommands();
}
@@ -715,7 +715,7 @@
}
}
-void MediaPlayerService::Client::clearDeathNotifiers() {
+void MediaPlayerService::Client::clearDeathNotifiers_l() {
if (mExtractorDeathListener != nullptr) {
mExtractorDeathListener->unlinkToDeath();
mExtractorDeathListener = nullptr;
@@ -730,7 +730,6 @@
player_type playerType)
{
ALOGV("player type = %d", playerType);
- clearDeathNotifiers();
// create the right type of player
sp<MediaPlayerBase> p = createPlayer(playerType);
@@ -744,9 +743,11 @@
ALOGE("extractor service not available");
return NULL;
}
- mExtractorDeathListener = new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
- binder->linkToDeath(mExtractorDeathListener);
+ sp<ServiceDeathNotifier> extractorDeathListener =
+ new ServiceDeathNotifier(binder, p, MEDIAEXTRACTOR_PROCESS_DEATH);
+ binder->linkToDeath(extractorDeathListener);
+ sp<ServiceDeathNotifier> codecDeathListener;
if (property_get_bool("persist.media.treble_omx", true)) {
// Treble IOmx
sp<IOmx> omx = IOmx::getService();
@@ -754,8 +755,8 @@
ALOGE("Treble IOmx not available");
return NULL;
}
- mCodecDeathListener = new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
- omx->linkToDeath(mCodecDeathListener, 0);
+ codecDeathListener = new ServiceDeathNotifier(omx, p, MEDIACODEC_PROCESS_DEATH);
+ omx->linkToDeath(codecDeathListener, 0);
} else {
// Legacy IOMX
binder = sm->getService(String16("media.codec"));
@@ -763,12 +764,17 @@
ALOGE("codec service not available");
return NULL;
}
- mCodecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
- binder->linkToDeath(mCodecDeathListener);
+ codecDeathListener = new ServiceDeathNotifier(binder, p, MEDIACODEC_PROCESS_DEATH);
+ binder->linkToDeath(codecDeathListener);
}
+ Mutex::Autolock lock(mLock);
+
+ clearDeathNotifiers_l();
+ mExtractorDeathListener = extractorDeathListener;
+ mCodecDeathListener = codecDeathListener;
+
if (!p->hardwareOutput()) {
- Mutex::Autolock l(mLock);
mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(),
mPid, mAudioAttributes);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
@@ -777,29 +783,29 @@
return p;
}
-void MediaPlayerService::Client::setDataSource_post(
+status_t MediaPlayerService::Client::setDataSource_post(
const sp<MediaPlayerBase>& p,
status_t status)
{
ALOGV(" setDataSource");
- mStatus = status;
- if (mStatus != OK) {
- ALOGE(" error: %d", mStatus);
- return;
+ if (status != OK) {
+ ALOGE(" error: %d", status);
+ return status;
}
// Set the re-transmission endpoint if one was chosen.
if (mRetransmitEndpointValid) {
- mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
- if (mStatus != NO_ERROR) {
- ALOGE("setRetransmitEndpoint error: %d", mStatus);
+ status = p->setRetransmitEndpoint(&mRetransmitEndpoint);
+ if (status != NO_ERROR) {
+ ALOGE("setRetransmitEndpoint error: %d", status);
}
}
- if (mStatus == OK) {
- Mutex::Autolock l(mLock);
+ if (status == OK) {
+ Mutex::Autolock lock(mLock);
mPlayer = p;
}
+ return status;
}
status_t MediaPlayerService::Client::setDataSource(
@@ -830,9 +836,9 @@
ALOGE("Couldn't open fd for %s", url);
return UNKNOWN_ERROR;
}
- setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
+ status_t status = setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
close(fd);
- return mStatus;
+ return mStatus = status;
} else {
player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
sp<MediaPlayerBase> p = setDataSource_pre(playerType);
@@ -840,8 +846,9 @@
return NO_INIT;
}
- setDataSource_post(p, p->setDataSource(httpService, url, headers));
- return mStatus;
+ return mStatus =
+ setDataSource_post(
+ p, p->setDataSource(httpService, url, headers));
}
}
@@ -881,8 +888,7 @@
}
// now set data source
- setDataSource_post(p, p->setDataSource(fd, offset, length));
- return mStatus;
+ return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
}
status_t MediaPlayerService::Client::setDataSource(
@@ -895,8 +901,7 @@
}
// now set data source
- setDataSource_post(p, p->setDataSource(source));
- return mStatus;
+ return mStatus = setDataSource_post(p, p->setDataSource(source));
}
status_t MediaPlayerService::Client::setDataSource(
@@ -908,11 +913,10 @@
return NO_INIT;
}
// now set data source
- setDataSource_post(p, p->setDataSource(dataSource));
- return mStatus;
+ return mStatus = setDataSource_post(p, p->setDataSource(dataSource));
}
-void MediaPlayerService::Client::disconnectNativeWindow() {
+void MediaPlayerService::Client::disconnectNativeWindow_l() {
if (mConnectedWindow != NULL) {
status_t err = nativeWindowDisconnect(
mConnectedWindow.get(), "disconnectNativeWindow");
@@ -949,7 +953,8 @@
// ANW, which may result in errors.
reset();
- disconnectNativeWindow();
+ Mutex::Autolock lock(mLock);
+ disconnectNativeWindow_l();
return err;
}
@@ -960,14 +965,22 @@
// on the disconnected ANW, which may result in errors.
status_t err = p->setVideoSurfaceTexture(bufferProducer);
- disconnectNativeWindow();
-
- mConnectedWindow = anw;
+ mLock.lock();
+ disconnectNativeWindow_l();
if (err == OK) {
+ mConnectedWindow = anw;
mConnectedWindowBinder = binder;
+ mLock.unlock();
} else {
- disconnectNativeWindow();
+ mLock.unlock();
+ status_t err = nativeWindowDisconnect(
+ anw.get(), "disconnectNativeWindow");
+
+ if (err != OK) {
+ ALOGW("nativeWindowDisconnect returned an error: %s (%d)",
+ strerror(-err), err);
+ }
}
return err;
@@ -1385,9 +1398,11 @@
if (p != 0) return INVALID_OPERATION;
if (NULL != endpoint) {
+ Mutex::Autolock lock(mLock);
mRetransmitEndpoint = *endpoint;
mRetransmitEndpointValid = true;
} else {
+ Mutex::Autolock lock(mLock);
mRetransmitEndpointValid = false;
}
@@ -1405,6 +1420,7 @@
if (p != NULL)
return p->getRetransmitEndpoint(endpoint);
+ Mutex::Autolock lock(mLock);
if (!mRetransmitEndpointValid)
return NO_INIT;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 06b9cad..e35d098 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -362,7 +362,7 @@
sp<MediaPlayerBase> setDataSource_pre(player_type playerType);
- void setDataSource_post(const sp<MediaPlayerBase>& p,
+ status_t setDataSource_post(const sp<MediaPlayerBase>& p,
status_t status);
static void notify(void* cookie, int msg,
@@ -404,7 +404,7 @@
wp<MediaPlayerBase> mListener;
};
- void clearDeathNotifiers();
+ void clearDeathNotifiers_l();
friend class MediaPlayerService;
Client( const sp<MediaPlayerService>& service,
@@ -433,7 +433,7 @@
void addNewMetadataUpdate(media::Metadata::Type type);
// Disconnect from the currently connected ANativeWindow.
- void disconnectNativeWindow();
+ void disconnectNativeWindow_l();
status_t setAudioAttributes_l(const Parcel &request);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 6400481..9b9b3bb 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -339,7 +339,7 @@
wp<MediaRecorderClient> client(this);
mMediaPlayerService->removeMediaRecorderClient(client);
}
- clearDeathNotifiers();
+ clearDeathNotifiers_l();
return NO_ERROR;
}
@@ -411,7 +411,7 @@
}
}
-void MediaRecorderClient::clearDeathNotifiers() {
+void MediaRecorderClient::clearDeathNotifiers_l() {
if (mCameraDeathListener != nullptr) {
mCameraDeathListener->unlinkToDeath();
mCameraDeathListener = nullptr;
@@ -425,8 +425,8 @@
status_t MediaRecorderClient::setListener(const sp<IMediaRecorderClient>& listener)
{
ALOGV("setListener");
- clearDeathNotifiers();
Mutex::Autolock lock(mLock);
+ clearDeathNotifiers_l();
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
return NO_INIT;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 7868a91..711db2c 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -58,7 +58,7 @@
wp<IMediaRecorderClient> mListener;
};
- void clearDeathNotifiers();
+ void clearDeathNotifiers_l();
public:
virtual status_t setCamera(const sp<hardware::ICamera>& camera,
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index c44e868..a2eb9a8 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5298,8 +5298,9 @@
CHECK(mOutputFormat->findInt32("channel-count", &channelCount));
CHECK(mOutputFormat->findInt32("sample-rate", &sampleRate));
if (mSampleRate != 0 && sampleRate != 0) {
- mEncoderDelay = mEncoderDelay * sampleRate / mSampleRate;
- mEncoderPadding = mEncoderPadding * sampleRate / mSampleRate;
+ // avoiding 32-bit overflows in intermediate values
+ mEncoderDelay = (int32_t)((((int64_t)mEncoderDelay) * sampleRate) / mSampleRate);
+ mEncoderPadding = (int32_t)((((int64_t)mEncoderPadding) * sampleRate) / mSampleRate);
mSampleRate = sampleRate;
}
if (mSkipCutBuffer != NULL) {
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index c342b6c..dae6e79 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -274,10 +274,6 @@
status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op);
- mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
- mCodecCtx->pv_fxns = dec_fxns;
- mCodecCtx->u4_size = sizeof(iv_obj_t);
-
if (status != IV_SUCCESS) {
ALOGE("Error in create: 0x%x",
s_create_op.s_ivd_create_op_t.u4_error_code);
@@ -285,6 +281,10 @@
mCodecCtx = NULL;
return UNKNOWN_ERROR;
}
+
+ mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
+ mCodecCtx->pv_fxns = dec_fxns;
+ mCodecCtx->u4_size = sizeof(iv_obj_t);
}
/* Reset the plugin state */
@@ -530,7 +530,7 @@
notifyEmptyBufferDone(inHeader);
if (!(inHeader->nFlags & OMX_BUFFERFLAG_EOS)) {
- continue;
+ return;
}
mReceivedEOS = true;
diff --git a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
index 358c743..32fdbd3 100644
--- a/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/SoftAVCEnc.cpp
@@ -1170,6 +1170,12 @@
ps_inp_raw_buf->e_color_fmt = mIvVideoColorFormat;
source = NULL;
if ((inputBufferHeader != NULL) && inputBufferHeader->nFilledLen) {
+ OMX_ERRORTYPE error = validateInputBuffer(inputBufferHeader);
+ if (error != OMX_ErrorNone) {
+ ALOGE("b/69065651");
+ android_errorWriteLog(0x534e4554, "69065651");
+ return error;
+ }
source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
if (mInputDataIsMeta) {
diff --git a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
index 2745087..103fc22 100644
--- a/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
+++ b/media/libstagefright/codecs/hevcdec/SoftHEVC.cpp
@@ -312,10 +312,6 @@
status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op);
- mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
- mCodecCtx->pv_fxns = dec_fxns;
- mCodecCtx->u4_size = sizeof(iv_obj_t);
-
if (status != IV_SUCCESS) {
ALOGE("Error in create: 0x%x",
s_create_op.s_ivd_create_op_t.u4_error_code);
@@ -323,6 +319,10 @@
mCodecCtx = NULL;
return UNKNOWN_ERROR;
}
+
+ mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
+ mCodecCtx->pv_fxns = dec_fxns;
+ mCodecCtx->u4_size = sizeof(iv_obj_t);
}
/* Reset the plugin state */
diff --git a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
index 7b90a01..f6a7b0e 100644
--- a/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
+++ b/media/libstagefright/codecs/m4v_h263/enc/SoftMPEG4Encoder.cpp
@@ -434,6 +434,14 @@
}
if (inHeader->nFilledLen > 0) {
+ OMX_ERRORTYPE error = validateInputBuffer(inHeader);
+ if (error != OMX_ErrorNone) {
+ ALOGE("b/69065651");
+ android_errorWriteLog(0x534e4554, "69065651");
+ mSignalledError = true;
+ notify(OMX_EventError, error, 0, 0);
+ return;
+ }
const uint8_t *inputData = NULL;
if (mInputDataIsMeta) {
inputData =
diff --git a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
index a5666da..f6257b1 100644
--- a/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
+++ b/media/libstagefright/codecs/on2/enc/SoftVPXEncoder.cpp
@@ -653,6 +653,13 @@
return;
}
+ OMX_ERRORTYPE error = validateInputBuffer(inputBufferHeader);
+ if (error != OMX_ErrorNone) {
+ ALOGE("b/27569635");
+ android_errorWriteLog(0x534e4554, "27569635");
+ notify(OMX_EventError, error, 0, 0);
+ return;
+ }
const uint8_t *source =
inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
@@ -668,14 +675,6 @@
return;
}
} else {
- if (inputBufferHeader->nFilledLen < frameSize) {
- android_errorWriteLog(0x534e4554, "27569635");
- notify(OMX_EventError, OMX_ErrorUndefined, 0, 0);
- return;
- } else if (inputBufferHeader->nFilledLen > frameSize) {
- ALOGW("Input buffer contains too many pixels");
- }
-
if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
ConvertYUV420SemiPlanarToYUV420Planar(
source, mConversionBuffer, mWidth, mHeight);
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 71feb9a..8a6482b 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -897,6 +897,9 @@
}
}
+ if (meta->get() == NULL) {
+ return ERROR_MALFORMED;
+ }
return OK;
}
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index 8d1ad66..58d8b13 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -392,7 +392,12 @@
--mSize;
--dataSize;
}
- mData[writeOffset++] = mData[readOffset++];
+ if (i + 1 < dataSize) {
+ // Only move data if there's actually something to move.
+ // This handles the special case of the data being only [0xff, 0x00]
+ // which should be converted to just 0xff if unsynchronization is on.
+ mData[writeOffset++] = mData[readOffset++];
+ }
}
// move the remaining data following this frame
if (readOffset <= oldSize) {
diff --git a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
index f33bdc0..6e563b7 100644
--- a/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoEncoderOMXComponent.cpp
@@ -664,4 +664,17 @@
return SimpleSoftOMXComponent::getExtensionIndex(name, index);
}
+OMX_ERRORTYPE SoftVideoEncoderOMXComponent::validateInputBuffer(
+ const OMX_BUFFERHEADERTYPE *inputBufferHeader) {
+ size_t frameSize = mInputDataIsMeta ?
+ max(sizeof(VideoNativeMetadata), sizeof(VideoGrallocMetadata))
+ : mWidth * mHeight * 3 / 2;
+ if (inputBufferHeader->nFilledLen < frameSize) {
+ return OMX_ErrorUndefined;
+ } else if (inputBufferHeader->nFilledLen > frameSize) {
+ ALOGW("Input buffer contains more data than expected.");
+ }
+ return OMX_ErrorNone;
+}
+
} // namespace android
diff --git a/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h b/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h
index db5496a..2d6f31b 100644
--- a/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h
+++ b/media/libstagefright/omx/include/media/stagefright/omx/SoftVideoEncoderOMXComponent.h
@@ -67,6 +67,8 @@
virtual OMX_ERRORTYPE getExtensionIndex(const char *name, OMX_INDEXTYPE *index);
+ OMX_ERRORTYPE validateInputBuffer(const OMX_BUFFERHEADERTYPE *inputBufferHeader);
+
enum {
kInputPortIndex = 0,
kOutputPortIndex = 1,
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index 87b649a..c4ff537 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -53,7 +53,6 @@
void
AImage::close(int releaseFenceFd) {
- lockReader();
Mutex::Autolock _l(mLock);
if (mIsClosed) {
return;
@@ -71,7 +70,6 @@
mBuffer = nullptr;
mLockedBuffer = nullptr;
mIsClosed = true;
- unlockReader();
}
void
@@ -622,7 +620,9 @@
void AImage_deleteAsync(AImage* image, int releaseFenceFd) {
ALOGV("%s", __FUNCTION__);
if (image != nullptr) {
+ image->lockReader();
image->close(releaseFenceFd);
+ image->unlockReader();
if (!image->isClosed()) {
LOG_ALWAYS_FATAL("Image close failed!");
}
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index e90783d..fd6ecb5 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -349,8 +349,8 @@
for (auto it = mAcquiredImages.begin();
it != mAcquiredImages.end(); it++) {
AImage* image = *it;
+ Mutex::Autolock _l(image->mLock);
releaseImageLocked(image, /*releaseFenceFd*/-1);
- image->close();
}
// Delete Buffer Items
@@ -502,6 +502,8 @@
mBufferItemConsumer->releaseBuffer(*buffer, bufferFence);
returnBufferItemLocked(buffer);
image->mBuffer = nullptr;
+ image->mLockedBuffer = nullptr;
+ image->mIsClosed = true;
bool found = false;
// cleanup acquired image list
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index 989b937..bed8a21 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -85,7 +85,7 @@
// Called by AImageReader_acquireXXX to acquire a Buffer and setup AImage.
media_status_t acquireImageLocked(/*out*/AImage** image, /*out*/int* fenceFd);
- // Called by AImage to close image
+ // Called by AImage/~AImageReader to close image. Caller is responsible to grab AImage::mLock
void releaseImageLocked(AImage* image, int releaseFenceFd);
static int getBufferWidth(BufferItem* buffer);
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 2cf648f..585d2eb 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -859,6 +859,12 @@
outputStreams.push(getPreviewStreamId());
+ if (params.isDeviceZslSupported) {
+ // If device ZSL is supported, resume preview buffers that may be paused
+ // during last takePicture().
+ mDevice->dropStreamBuffers(false, getPreviewStreamId());
+ }
+
if (!params.recordingHint) {
if (!restart) {
res = mStreamingProcessor->updatePreviewRequest(params);
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
index b65f1c7..1ee216f 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
@@ -553,6 +553,12 @@
return DONE;
}
+ if (l.mParameters.isDeviceZslSupported) {
+ // If device ZSL is supported, drop all pending preview buffers to reduce the chance of
+ // rendering preview frames newer than the still frame.
+ client->getCameraDevice()->dropStreamBuffers(true, client->getPreviewStreamId());
+ }
+
/**
* Clear the streaming request for still-capture pictures
* (as opposed to i.e. video snapshots)
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 3919bfa..a90050e 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -349,6 +349,11 @@
virtual status_t setConsumerSurfaces(int streamId,
const std::vector<sp<Surface>>& consumers) = 0;
+ /**
+ * Drop buffers for stream of streamId if dropping is true. If dropping is false, do not
+ * drop buffers for stream of streamId.
+ */
+ virtual status_t dropStreamBuffers(bool /*dropping*/, int /*streamId*/) = 0;
};
}; // namespace android
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index ced1d3a..a980cde 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1977,6 +1977,20 @@
return OK;
}
+status_t Camera3Device::dropStreamBuffers(bool dropping, int streamId) {
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
+
+ int idx = mOutputStreams.indexOfKey(streamId);
+ if (idx == NAME_NOT_FOUND) {
+ ALOGE("%s: Stream %d is not found.", __FUNCTION__, streamId);
+ return BAD_VALUE;
+ }
+
+ sp<Camera3OutputStreamInterface> stream = mOutputStreams.editValueAt(idx);
+ return stream->dropBuffers(dropping);
+}
+
/**
* Camera3Device private methods
*/
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index fbbbd08..081af19 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -178,6 +178,12 @@
*/
status_t setConsumerSurfaces(int streamId, const std::vector<sp<Surface>>& consumers) override;
+ /**
+ * Drop buffers for stream of streamId if dropping is true. If dropping is false, do not
+ * drop buffers for stream of streamId.
+ */
+ status_t dropStreamBuffers(bool dropping, int streamId) override;
+
private:
// internal typedefs
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
index 6e2978f..84fb890 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.cpp
@@ -108,6 +108,10 @@
return false;
}
+status_t Camera3DummyStream::dropBuffers(bool /*dropping*/) {
+ return OK;
+}
+
status_t Camera3DummyStream::setConsumers(const std::vector<sp<Surface>>& /*consumers*/) {
ALOGE("%s: Stream %d: Dummy stream doesn't support set consumer surface!",
__FUNCTION__, mId);
diff --git a/services/camera/libcameraservice/device3/Camera3DummyStream.h b/services/camera/libcameraservice/device3/Camera3DummyStream.h
index 492fb49..9710765 100644
--- a/services/camera/libcameraservice/device3/Camera3DummyStream.h
+++ b/services/camera/libcameraservice/device3/Camera3DummyStream.h
@@ -57,6 +57,12 @@
virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd);
/**
+ * Drop buffers for stream of streamId if dropping is true. If dropping is false, do not
+ * drop buffers for stream of streamId.
+ */
+ virtual status_t dropBuffers(bool /*dropping*/) override;
+
+ /**
* Return if this output stream is for video encoding.
*/
bool isVideoStream() const;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index dcaefe3..8460c34 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -44,6 +44,7 @@
mUseBufferManager(false),
mTimestampOffset(timestampOffset),
mConsumerUsage(0),
+ mDropBuffers(false),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
if (mConsumer == NULL) {
@@ -70,6 +71,7 @@
mUseBufferManager(false),
mTimestampOffset(timestampOffset),
mConsumerUsage(0),
+ mDropBuffers(false),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
if (format != HAL_PIXEL_FORMAT_BLOB && format != HAL_PIXEL_FORMAT_RAW_OPAQUE) {
@@ -100,6 +102,7 @@
mUseBufferManager(false),
mTimestampOffset(timestampOffset),
mConsumerUsage(consumerUsage),
+ mDropBuffers(false),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
// Deferred consumer only support preview surface format now.
if (format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
@@ -139,6 +142,7 @@
mUseBufferManager(false),
mTimestampOffset(timestampOffset),
mConsumerUsage(consumerUsage),
+ mDropBuffers(false),
mDequeueBufferLatency(kDequeueLatencyBinSize) {
if (setId > CAMERA3_STREAM_SET_ID_INVALID) {
@@ -227,9 +231,14 @@
/**
* Return buffer back to ANativeWindow
*/
- if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR) {
+ if (buffer.status == CAMERA3_BUFFER_STATUS_ERROR || mDropBuffers) {
// Cancel buffer
- ALOGW("A frame is dropped for stream %d", mId);
+ if (mDropBuffers) {
+ ALOGV("%s: Dropping a frame for stream %d.", __FUNCTION__, mId);
+ } else {
+ ALOGW("%s: A frame is dropped for stream %d due to buffer error.", __FUNCTION__, mId);
+ }
+
res = currentConsumer->cancelBuffer(currentConsumer.get(),
anwBuffer,
anwReleaseFence);
@@ -777,6 +786,12 @@
return res;
}
+status_t Camera3OutputStream::dropBuffers(bool dropping) {
+ Mutex::Autolock l(mLock);
+ mDropBuffers = dropping;
+ return OK;
+}
+
status_t Camera3OutputStream::notifyBufferReleased(ANativeWindowBuffer* /*anwBuffer*/) {
return OK;
}
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index 7023d5d..4865be7 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -166,6 +166,11 @@
virtual status_t notifyBufferReleased(ANativeWindowBuffer *anwBuffer);
/**
+ * Drop buffers if dropping is true. If dropping is false, do not drop buffers.
+ */
+ virtual status_t dropBuffers(bool dropping) override;
+
+ /**
* Set the graphic buffer manager to get/return the stream buffers.
*
* It is only legal to call this method when stream is in STATE_CONSTRUCTED state.
@@ -247,6 +252,9 @@
*/
uint64_t mConsumerUsage;
+ // Whether to drop valid buffers.
+ bool mDropBuffers;
+
/**
* Internal Camera3Stream interface
*/
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index 8107dd0..1719d74 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -59,6 +59,11 @@
*
*/
virtual status_t detachBuffer(sp<GraphicBuffer>* buffer, int* fenceFd) = 0;
+
+ /**
+ * Drop buffers if dropping is true. If dropping is false, do not drop buffers.
+ */
+ virtual status_t dropBuffers(bool /*dropping*/) = 0;
};
} // namespace camera3
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 4be25c8..7e6e247 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -258,6 +258,13 @@
aaudio_result_t AAudioServiceEndpointMMAP::stopStream(sp<AAudioServiceStreamBase> stream,
audio_port_handle_t clientHandle) {
mFramesTransferred.reset32();
+
+ // Round 64-bit counter up to a multiple of the buffer capacity.
+ // This is required because the 64-bit counter is used as an index
+ // into a circular buffer and the actual HW position is reset to zero
+ // when the stream is stopped.
+ mFramesTransferred.roundUp64(getBufferCapacity());
+
return stopClient(mPortHandle);
}
diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp
index e670129..ff0b037 100644
--- a/services/oboeservice/AAudioServiceStreamBase.cpp
+++ b/services/oboeservice/AAudioServiceStreamBase.cpp
@@ -202,19 +202,23 @@
ALOGE("AAudioServiceStreamShared::pause() missing endpoint");
return AAUDIO_ERROR_INVALID_STATE;
}
+
+ // Send it now because the timestamp gets rounded up when stopStream() is called below.
+ // Also we don't need the timestamps while we are shutting down.
+ sendCurrentTimestamp();
+
+ result = stopTimestampThread();
+ if (result != AAUDIO_OK) {
+ disconnect();
+ return result;
+ }
+
result = mServiceEndpoint->stopStream(this, mClientHandle);
if (result != AAUDIO_OK) {
ALOGE("AAudioServiceStreamShared::pause() mServiceEndpoint returned %d", result);
disconnect(); // TODO should we return or pause Base first?
}
- sendCurrentTimestamp();
- mThreadEnabled.store(false);
- result = mTimestampThread.stop();
- if (result != AAUDIO_OK) {
- disconnect();
- return result;
- }
sendServiceEvent(AAUDIO_SERVICE_EVENT_PAUSED);
setState(AAUDIO_STREAM_STATE_PAUSED);
return result;
@@ -231,6 +235,8 @@
return AAUDIO_ERROR_INVALID_STATE;
}
+ // Send it now because the timestamp gets rounded up when stopStream() is called below.
+ // Also we don't need the timestamps while we are shutting down.
sendCurrentTimestamp(); // warning - this calls a virtual function
result = stopTimestampThread();
if (result != AAUDIO_OK) {