Merge changes Id88d546a,I14c23eea,I08286bff into rvc-qpr-dev
* changes:
MediaCodec: fix possible crash at stop & error
stagefright: add test for MediaCodec::reclaim/release race
MediaCodec: ensure reply does not get lost
diff --git a/apex/Android.bp b/apex/Android.bp
index c1ef3d8..be6185e 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -31,6 +31,8 @@
"libmpeg2extractor",
"liboggextractor",
"libwavextractor",
+ // JNI
+ "libmediaparser-jni"
],
},
},
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 0626c8d..1654b11 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -618,25 +618,26 @@
}
void CCodecBufferChannel::feedInputBufferIfAvailableInternal() {
- if (mInputMetEos || mPipelineWatcher.lock()->pipelineFull()) {
+ if (mInputMetEos) {
return;
}
{
Mutexed<Output>::Locked output(mOutput);
if (!output->buffers ||
output->buffers->hasPending() ||
- output->buffers->numClientBuffers() >= output->numSlots) {
+ output->buffers->numActiveSlots() >= output->numSlots) {
return;
}
}
- size_t numInputSlots = mInput.lock()->numSlots;
- for (size_t i = 0; i < numInputSlots; ++i) {
+ size_t numActiveSlots = 0;
+ while (!mPipelineWatcher.lock()->pipelineFull()) {
sp<MediaCodecBuffer> inBuffer;
size_t index;
{
Mutexed<Input>::Locked input(mInput);
- if (input->buffers->numClientBuffers() >= input->numSlots) {
- return;
+ numActiveSlots = input->buffers->numActiveSlots();
+ if (numActiveSlots >= input->numSlots) {
+ break;
}
if (!input->buffers->requestNewBuffer(&index, &inBuffer)) {
ALOGV("[%s] no new buffer available", mName);
@@ -646,6 +647,7 @@
ALOGV("[%s] new input index = %zu [%p]", mName, index, inBuffer.get());
mCallback->onInputBufferAvailable(index, inBuffer);
}
+ ALOGV("[%s] # active slots after feedInputBufferIfAvailable = %zu", mName, numActiveSlots);
}
status_t CCodecBufferChannel::renderOutputBuffer(
diff --git a/media/codec2/sfplugin/CCodecBuffers.cpp b/media/codec2/sfplugin/CCodecBuffers.cpp
index c49a16c..bddaa9f 100644
--- a/media/codec2/sfplugin/CCodecBuffers.cpp
+++ b/media/codec2/sfplugin/CCodecBuffers.cpp
@@ -493,11 +493,12 @@
mBuffers.clear();
}
-size_t FlexBuffersImpl::numClientBuffers() const {
+size_t FlexBuffersImpl::numActiveSlots() const {
return std::count_if(
mBuffers.begin(), mBuffers.end(),
[](const Entry &entry) {
- return (entry.clientBuffer != nullptr);
+ return (entry.clientBuffer != nullptr
+ || !entry.compBuffer.expired());
});
}
@@ -643,11 +644,11 @@
}
}
-size_t BuffersArrayImpl::numClientBuffers() const {
+size_t BuffersArrayImpl::numActiveSlots() const {
return std::count_if(
mBuffers.begin(), mBuffers.end(),
[](const Entry &entry) {
- return entry.ownedByClient;
+ return entry.ownedByClient || !entry.compBuffer.expired();
});
}
@@ -697,8 +698,8 @@
mImpl.flush();
}
-size_t InputBuffersArray::numClientBuffers() const {
- return mImpl.numClientBuffers();
+size_t InputBuffersArray::numActiveSlots() const {
+ return mImpl.numActiveSlots();
}
sp<Codec2Buffer> InputBuffersArray::createNewBuffer() {
@@ -735,8 +736,8 @@
return nullptr;
}
-size_t SlotInputBuffers::numClientBuffers() const {
- return mImpl.numClientBuffers();
+size_t SlotInputBuffers::numActiveSlots() const {
+ return mImpl.numActiveSlots();
}
sp<Codec2Buffer> SlotInputBuffers::createNewBuffer() {
@@ -787,8 +788,8 @@
return std::move(array);
}
-size_t LinearInputBuffers::numClientBuffers() const {
- return mImpl.numClientBuffers();
+size_t LinearInputBuffers::numActiveSlots() const {
+ return mImpl.numActiveSlots();
}
// static
@@ -964,8 +965,8 @@
return std::move(array);
}
-size_t GraphicMetadataInputBuffers::numClientBuffers() const {
- return mImpl.numClientBuffers();
+size_t GraphicMetadataInputBuffers::numActiveSlots() const {
+ return mImpl.numActiveSlots();
}
sp<Codec2Buffer> GraphicMetadataInputBuffers::createNewBuffer() {
@@ -1029,8 +1030,8 @@
return std::move(array);
}
-size_t GraphicInputBuffers::numClientBuffers() const {
- return mImpl.numClientBuffers();
+size_t GraphicInputBuffers::numActiveSlots() const {
+ return mImpl.numActiveSlots();
}
sp<Codec2Buffer> GraphicInputBuffers::createNewBuffer() {
@@ -1119,8 +1120,8 @@
mImpl.getArray(array);
}
-size_t OutputBuffersArray::numClientBuffers() const {
- return mImpl.numClientBuffers();
+size_t OutputBuffersArray::numActiveSlots() const {
+ return mImpl.numActiveSlots();
}
void OutputBuffersArray::realloc(const std::shared_ptr<C2Buffer> &c2buffer) {
@@ -1230,8 +1231,8 @@
return array;
}
-size_t FlexOutputBuffers::numClientBuffers() const {
- return mImpl.numClientBuffers();
+size_t FlexOutputBuffers::numActiveSlots() const {
+ return mImpl.numActiveSlots();
}
// LinearOutputBuffers
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index 0d4fa81..4772ab5 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -72,7 +72,7 @@
/**
* Return number of buffers the client owns.
*/
- virtual size_t numClientBuffers() const = 0;
+ virtual size_t numActiveSlots() const = 0;
/**
* Examine image data from the buffer and update the format if necessary.
@@ -584,7 +584,7 @@
* Return the number of buffers that are sent to the client but not released
* yet.
*/
- size_t numClientBuffers() const;
+ size_t numActiveSlots() const;
/**
* Return the number of buffers that are sent to the component but not
@@ -705,7 +705,7 @@
* Return the number of buffers that are sent to the client but not released
* yet.
*/
- size_t numClientBuffers() const;
+ size_t numActiveSlots() const;
/**
* Return the size of the array.
@@ -765,7 +765,7 @@
void flush() override;
- size_t numClientBuffers() const final;
+ size_t numActiveSlots() const final;
protected:
sp<Codec2Buffer> createNewBuffer() override;
@@ -796,7 +796,7 @@
std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
- size_t numClientBuffers() const final;
+ size_t numActiveSlots() const final;
protected:
sp<Codec2Buffer> createNewBuffer() final;
@@ -826,7 +826,7 @@
std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
- size_t numClientBuffers() const final;
+ size_t numActiveSlots() const final;
protected:
sp<Codec2Buffer> createNewBuffer() override;
@@ -894,7 +894,7 @@
std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
- size_t numClientBuffers() const final;
+ size_t numActiveSlots() const final;
protected:
sp<Codec2Buffer> createNewBuffer() override;
@@ -924,7 +924,7 @@
std::unique_ptr<InputBuffers> toArrayMode(
size_t size) final;
- size_t numClientBuffers() const final;
+ size_t numActiveSlots() const final;
protected:
sp<Codec2Buffer> createNewBuffer() override;
@@ -965,7 +965,7 @@
array->clear();
}
- size_t numClientBuffers() const final {
+ size_t numActiveSlots() const final {
return 0u;
}
@@ -1019,7 +1019,7 @@
void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
- size_t numClientBuffers() const final;
+ size_t numActiveSlots() const final;
/**
* Reallocate the array, filled with buffers with the same size as given
@@ -1073,7 +1073,7 @@
std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) override;
- size_t numClientBuffers() const final;
+ size_t numActiveSlots() const final;
/**
* Return an appropriate Codec2Buffer object for the type of buffers.
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index d19447a..901b29d 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -95,9 +95,9 @@
AMediaFormat *mMeta;
uint16_t mWaveFormat;
const bool mOutputFloat;
- int32_t mSampleRate;
- int32_t mNumChannels;
- int32_t mBitsPerSample;
+ uint32_t mSampleRate;
+ uint32_t mNumChannels;
+ uint32_t mBitsPerSample;
off64_t mOffset;
size_t mSize;
bool mStarted;
@@ -379,9 +379,9 @@
mOffset(offset),
mSize(size),
mStarted(false) {
- CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &mSampleRate));
- CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &mNumChannels));
- CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, &mBitsPerSample));
+ CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, (int32_t*) &mSampleRate));
+ CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, (int32_t*) &mNumChannels));
+ CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, (int32_t*) &mBitsPerSample));
}
WAVSource::~WAVSource() {
@@ -472,7 +472,7 @@
}
const size_t maxBytesAvailable =
- (mCurrentPos - mOffset >= (off64_t)mSize)
+ (mCurrentPos < mOffset || mCurrentPos - mOffset >= (off64_t)mSize)
? 0 : mSize - (mCurrentPos - mOffset);
if (maxBytesToRead > maxBytesAvailable) {
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 050ad65..ee78a2d 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -853,6 +853,11 @@
{ .duration = 0 , .waveFreq = { 0 }, 0, 0}},
.repeatCnt = ToneGenerator::TONEGEN_INF,
.repeatSegment = 0 }, // TONE_INDIA_RINGTONE
+ { .segments = { { .duration = 1000, .waveFreq = { 440, 480, 0 }, 0, 0 },
+ { .duration = 2000, .waveFreq = { 0 }, 0, 0 },
+ { .duration = 0 , .waveFreq = { 0 }, 0, 0}},
+ .repeatCnt = ToneGenerator::TONEGEN_INF,
+ .repeatSegment = 0 }, // TONE_TW_RINGTONE
};
// Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
@@ -937,6 +942,16 @@
TONE_SUP_ERROR, // TONE_SUP_ERROR
TONE_INDIA_CALL_WAITING, // TONE_SUP_CALL_WAITING
TONE_INDIA_RINGTONE // TONE_SUP_RINGTONE
+ },
+ { // TAIWAN
+ TONE_SUP_DIAL, // TONE_SUP_DIAL
+ TONE_SUP_BUSY, // TONE_SUP_BUSY
+ TONE_SUP_CONGESTION, // TONE_SUP_CONGESTION
+ TONE_SUP_RADIO_ACK, // TONE_SUP_RADIO_ACK
+ TONE_SUP_RADIO_NOTAVAIL, // TONE_SUP_RADIO_NOTAVAIL
+ TONE_SUP_ERROR, // TONE_SUP_ERROR
+ TONE_SUP_CALL_WAITING, // TONE_SUP_CALL_WAITING
+ TONE_TW_RINGTONE // TONE_SUP_RINGTONE
}
};
@@ -1010,6 +1025,8 @@
mRegion = IRELAND;
} else if (strstr(value, "in") != NULL) {
mRegion = INDIA;
+ } else if (strstr(value, "tw") != NULL) {
+ mRegion = TAIWAN;
} else {
mRegion = CEPT;
}
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 5b0689a..04357a8 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -218,6 +218,7 @@
TONE_INDIA_CONGESTION, // Congestion tone: 400 Hz, 250ms ON, 250ms OFF...
TONE_INDIA_CALL_WAITING, // Call waiting tone: 400 Hz, tone repeated in a 0.2s on, 0.1s off, 0.2s on, 7.5s off pattern.
TONE_INDIA_RINGTONE, // Ring tone: 400 Hz tone modulated with 25Hz, 0.4 on 0.2 off 0.4 on 2..0 off
+ TONE_TW_RINGTONE, // Ring Tone: 440 Hz + 480 Hz repeated with pattern 1s on, 3s off.
NUM_ALTERNATE_TONES
};
@@ -230,6 +231,7 @@
HONGKONG,
IRELAND,
INDIA,
+ TAIWAN,
CEPT,
NUM_REGIONS
};
diff --git a/media/libmedia/aidl/android/media/IResourceManagerService.aidl b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
index 1b2d522..621bd84 100644
--- a/media/libmedia/aidl/android/media/IResourceManagerService.aidl
+++ b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
@@ -102,4 +102,11 @@
* @param clientId clientId within the pid that will be removed.
*/
void markClientForPendingRemoval(int pid, long clientId);
+
+ /**
+ * Reclaim resources from clients pending removal, if any.
+ *
+ * @param pid pid from which resources will be reclaimed.
+ */
+ void reclaimResourcesFromClientsPendingRemoval(int pid);
}
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index 03068c7..a63b8b4 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -53,6 +53,7 @@
visibility: [
"//cts/tests/tests/nativemedia/mediametrics",
"//frameworks/av:__subpackages__",
+ "//frameworks/base/apex/media/framework",
"//frameworks/base/core/jni",
"//frameworks/base/media/jni",
],
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 98b01916..3e191fe 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -241,6 +241,9 @@
}
AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+
+ // Kill clients pending removal.
+ mService->reclaimResourcesFromClientsPendingRemoval(mPid);
}
//static
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 4bb21fa..ea5d2de 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1433,7 +1433,13 @@
if (mSampleDecryptor != NULL && (nalType == 1 || nalType == 5)) {
uint8_t *nalData = mBuffer->data() + pos.nalOffset;
size_t newSize = mSampleDecryptor->processNal(nalData, pos.nalSize);
- // Note: the data can shrink due to unescaping
+ // Note: the data can shrink due to unescaping, but it can never grow
+ if (newSize > pos.nalSize) {
+ // don't log unless verbose, since this can get called a lot if
+ // the caller is trying to resynchronize
+ ALOGV("expected sample size < %u, got %zu", pos.nalSize, newSize);
+ return NULL;
+ }
memcpy(accessUnit->data() + dstOffset + 4,
nalData,
newSize);
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index f033d5c..91590e1 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -131,6 +131,7 @@
"statsd_codec.cpp",
"statsd_drm.cpp",
"statsd_extractor.cpp",
+ "statsd_mediaparser.cpp",
"statsd_nuplayer.cpp",
"statsd_recorder.cpp",
"StringUtils.cpp"
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index 48e766e..bf6e428 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -468,6 +468,7 @@
"codec",
"extractor",
"mediadrm",
+ "mediaparser",
"nuplayer",
}) {
if (key == allowedKey) {
diff --git a/services/mediametrics/iface_statsd.cpp b/services/mediametrics/iface_statsd.cpp
index 6e51f72..16204de 100644
--- a/services/mediametrics/iface_statsd.cpp
+++ b/services/mediametrics/iface_statsd.cpp
@@ -64,6 +64,7 @@
{ "drmmanager", statsd_drmmanager },
{ "extractor", statsd_extractor },
{ "mediadrm", statsd_mediadrm },
+ { "mediaparser", statsd_mediaparser },
{ "nuplayer", statsd_nuplayer },
{ "nuplayer2", statsd_nuplayer },
{ "recorder", statsd_recorder },
diff --git a/services/mediametrics/iface_statsd.h b/services/mediametrics/iface_statsd.h
index 19505a4..9b49556 100644
--- a/services/mediametrics/iface_statsd.h
+++ b/services/mediametrics/iface_statsd.h
@@ -25,6 +25,7 @@
extern bool statsd_audiotrack(const mediametrics::Item *);
extern bool statsd_codec(const mediametrics::Item *);
extern bool statsd_extractor(const mediametrics::Item *);
+extern bool statsd_mediaparser(const mediametrics::Item *);
extern bool statsd_nuplayer(const mediametrics::Item *);
extern bool statsd_recorder(const mediametrics::Item *);
diff --git a/services/mediametrics/statsd_mediaparser.cpp b/services/mediametrics/statsd_mediaparser.cpp
new file mode 100644
index 0000000..3258ebf
--- /dev/null
+++ b/services/mediametrics/statsd_mediaparser.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2020 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_TAG "statsd_mediaparser"
+#include <utils/Log.h>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <statslog.h>
+
+#include "MediaMetricsService.h"
+#include "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.pb.h"
+#include "iface_statsd.h"
+
+namespace android {
+
+bool statsd_mediaparser(const mediametrics::Item *item)
+{
+ if (item == nullptr) {
+ return false;
+ }
+
+ // statsd wrapper data.
+ const nsecs_t timestamp = MediaMetricsService::roundTime(item->getTimestamp());
+ std::string pkgName = item->getPkgName();
+ int64_t pkgVersionCode = item->getPkgVersionCode();
+
+ std::string parserName;
+ item->getString("android.media.mediaparser.parserName", &parserName);
+
+ int32_t createdByName = -1;
+ item->getInt32("android.media.mediaparser.createdByName", &createdByName);
+
+ std::string parserPool;
+ item->getString("android.media.mediaparser.parserPool", &parserPool);
+
+ std::string lastException;
+ item->getString("android.media.mediaparser.lastException", &lastException);
+
+ int64_t resourceByteCount = -1;
+ item->getInt64("android.media.mediaparser.resourceByteCount", &resourceByteCount);
+
+ int64_t durationMillis = -1;
+ item->getInt64("android.media.mediaparser.durationMillis", &durationMillis);
+
+ std::string trackMimeTypes;
+ item->getString("android.media.mediaparser.trackMimeTypes", &trackMimeTypes);
+
+ std::string trackCodecs;
+ item->getString("android.media.mediaparser.trackCodecs", &trackCodecs);
+
+ std::string alteredParameters;
+ item->getString("android.media.mediaparser.alteredParameters", &alteredParameters);
+
+ int32_t videoWidth = -1;
+ item->getInt32("android.media.mediaparser.videoWidth", &videoWidth);
+
+ int32_t videoHeight = -1;
+ item->getInt32("android.media.mediaparser.videoHeight", &videoHeight);
+
+ if (enabled_statsd) {
+ (void) android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
+ timestamp,
+ pkgName.c_str(),
+ pkgVersionCode,
+ parserName.c_str(),
+ createdByName,
+ parserPool.c_str(),
+ lastException.c_str(),
+ resourceByteCount,
+ durationMillis,
+ trackMimeTypes.c_str(),
+ trackCodecs.c_str(),
+ alteredParameters.c_str(),
+ videoWidth,
+ videoHeight);
+ } else {
+ ALOGV("NOT sending MediaParser media metrics.");
+ }
+
+ return true;
+}
+
+} // namespace android
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 3d36f8e..db06a36 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -575,13 +575,19 @@
}
}
+ *_aidl_return = reclaimInternal(clients);
+ return Status::ok();
+}
+
+bool ResourceManagerService::reclaimInternal(
+ const Vector<std::shared_ptr<IResourceManagerClient>> &clients) {
if (clients.size() == 0) {
- return Status::ok();
+ return false;
}
std::shared_ptr<IResourceManagerClient> failedClient;
for (size_t i = 0; i < clients.size(); ++i) {
- log = String8::format("reclaimResource from client %p", clients[i].get());
+ String8 log = String8::format("reclaimResource from client %p", clients[i].get());
mServiceLog->add(log);
bool success;
Status status = clients[i]->reclaimResource(&success);
@@ -592,8 +598,7 @@
}
if (failedClient == NULL) {
- *_aidl_return = true;
- return Status::ok();
+ return true;
}
{
@@ -618,7 +623,7 @@
}
}
- return Status::ok();
+ return false;
}
Status ResourceManagerService::overridePid(
@@ -681,6 +686,36 @@
return Status::ok();
}
+Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t pid) {
+ String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid);
+ mServiceLog->add(log);
+
+ Vector<std::shared_ptr<IResourceManagerClient>> clients;
+ {
+ Mutex::Autolock lock(mLock);
+ if (!mProcessInfo->isValidPid(pid)) {
+ ALOGE("Rejected reclaimResourcesFromClientsPendingRemoval call with invalid pid.");
+ return Status::fromServiceSpecificError(BAD_VALUE);
+ }
+
+ for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
+ MediaResource::Type::kNonSecureCodec,
+ MediaResource::Type::kGraphicMemory,
+ MediaResource::Type::kDrmSession}) {
+ std::shared_ptr<IResourceManagerClient> client;
+ if (getBiggestClient_l(pid, type, &client, true /* pendingRemovalOnly */)) {
+ clients.add(client);
+ break;
+ }
+ }
+ }
+
+ if (!clients.empty()) {
+ reclaimInternal(clients);
+ }
+ return Status::ok();
+}
+
bool ResourceManagerService::getPriority_l(int pid, int* priority) {
int newPid = pid;
@@ -804,7 +839,8 @@
bool pendingRemovalOnly) {
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
- ALOGE("getBiggestClient_l: can't find resource info for pid %d", pid);
+ ALOGE_IF(!pendingRemovalOnly,
+ "getBiggestClient_l: can't find resource info for pid %d", pid);
return false;
}
@@ -828,7 +864,9 @@
}
if (clientTemp == NULL) {
- ALOGE("getBiggestClient_l: can't find resource type %s for pid %d", asString(type), pid);
+ ALOGE_IF(!pendingRemovalOnly,
+ "getBiggestClient_l: can't find resource type %s for pid %d",
+ asString(type), pid);
return false;
}
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index ee982b7..3972d23 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -127,11 +127,18 @@
Status markClientForPendingRemoval(int32_t pid, int64_t clientId) override;
+ Status reclaimResourcesFromClientsPendingRemoval(int32_t pid) override;
+
Status removeResource(int pid, int64_t clientId, bool checkValid);
private:
friend class ResourceManagerServiceTest;
+ // Reclaims resources from |clients|. Returns true if reclaim succeeded
+ // for all clients.
+ bool reclaimInternal(
+ const Vector<std::shared_ptr<IResourceManagerClient>> &clients);
+
// Gets the list of all the clients who own the specified resource type.
// Returns false if any client belongs to a process with higher priority than the
// calling process. The clients will remain unchanged if returns false.
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 702935d..a6ecc09 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -520,6 +520,30 @@
// clean up client 3 which still left
mService->removeClient(kTestPid2, getId(mTestClient3));
}
+
+ {
+ addResource();
+ mService->mSupportsSecureWithNonSecureCodec = true;
+
+ mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+
+ // client marked for pending removal got reclaimed
+ EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
+ verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
+
+ // No more clients marked for removal
+ EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
+ verifyClients(false /* c1 */, false /* c2 */, false /* c3 */);
+
+ mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient3));
+
+ // client marked for pending removal got reclaimed
+ EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
+ verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
+
+ // clean up client 1 which still left
+ mService->removeClient(kTestPid1, getId(mTestClient1));
+ }
}
void testRemoveClient() {