Protect against possible race conditions
Test: make cts -j123 && cts-tradefed run cts-dev -m \
CtsMediaTestCases --compatibility:module-arg \
CtsMediaTestCases:include-annotation:\
android.platform.test.annotations.RequiresDevice
Test: Run the poc in b/38234812
Bug: 38234812
Change-Id: I28322e5a812c02c8e449ab8773715f60b9f5d976
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 77f0cab..11f29cb 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;