Media server death nodification

This commit is contained in:
James Dong
2010-01-15 18:13:58 -08:00
parent dded6447b5
commit 34bbc22cbc
7 changed files with 198 additions and 120 deletions

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2010 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.
*/
#ifndef ANDROID_IMEDIADEATHNOTIFIER_H
#define ANDROID_IMEDIADEATHNOTIFIER_H
#include <utils/threads.h>
#include <media/IMediaPlayerService.h>
#include <utils/SortedVector.h>
namespace android {
class IMediaDeathNotifier: virtual public RefBase
{
public:
IMediaDeathNotifier() { addObitRecipient(this); }
virtual ~IMediaDeathNotifier() { removeObitRecipient(this); }
virtual void died() = 0;
static const sp<IMediaPlayerService>& getMediaPlayerService();
private:
IMediaDeathNotifier &operator=(const IMediaDeathNotifier &);
IMediaDeathNotifier(const IMediaDeathNotifier &);
static void addObitRecipient(const wp<IMediaDeathNotifier>& recipient);
static void removeObitRecipient(const wp<IMediaDeathNotifier>& recipient);
class DeathNotifier: public IBinder::DeathRecipient
{
public:
DeathNotifier() {}
virtual ~DeathNotifier();
virtual void binderDied(const wp<IBinder>& who);
};
friend class DeathNotifier;
static Mutex sServiceLock;
static sp<IMediaPlayerService> sMediaPlayerService;
static sp<DeathNotifier> sDeathNotifier;
static SortedVector< wp<IMediaDeathNotifier> > sObitRecipients;
};
}; // namespace android
#endif // ANDROID_IMEDIADEATHNOTIFIER_H

View File

@@ -21,8 +21,7 @@
#include <ui/Surface.h>
#include <media/IMediaPlayerClient.h>
#include <media/IMediaPlayer.h>
#include <media/IMediaPlayerService.h>
#include <utils/SortedVector.h>
#include <media/IMediaDeathNotifier.h>
namespace android {
@@ -123,12 +122,13 @@ public:
virtual void notify(int msg, int ext1, int ext2) = 0;
};
class MediaPlayer : public BnMediaPlayerClient
class MediaPlayer : public BnMediaPlayerClient,
public virtual IMediaDeathNotifier
{
public:
MediaPlayer();
~MediaPlayer();
void onFirstRef();
void died();
void disconnect();
status_t setDataSource(const char *url);
status_t setDataSource(int fd, int64_t offset, int64_t length);
@@ -164,19 +164,6 @@ private:
status_t getDuration_l(int *msec);
status_t setDataSource(const sp<IMediaPlayer>& player);
static const sp<IMediaPlayerService>& getMediaPlayerService();
static void addObitRecipient(const wp<MediaPlayer>& recipient);
static void removeObitRecipient(const wp<MediaPlayer>& recipient);
class DeathNotifier: public IBinder::DeathRecipient
{
public:
DeathNotifier() {}
virtual ~DeathNotifier();
virtual void binderDied(const wp<IBinder>& who);
};
sp<IMediaPlayer> mPlayer;
thread_id_t mLockThreadId;
Mutex mLock;
@@ -196,13 +183,6 @@ private:
float mRightVolume;
int mVideoWidth;
int mVideoHeight;
friend class DeathNotifier;
static Mutex sServiceLock;
static sp<IMediaPlayerService> sMediaPlayerService;
static sp<DeathNotifier> sDeathNotifier;
static SortedVector< wp<MediaPlayer> > sObitRecipients;
};
}; // namespace android

View File

@@ -23,6 +23,7 @@
#include <utils/List.h>
#include <utils/Errors.h>
#include <media/IMediaPlayerClient.h>
#include <media/IMediaDeathNotifier.h>
namespace android {
@@ -145,12 +146,14 @@ public:
virtual void notify(int msg, int ext1, int ext2) = 0;
};
class MediaRecorder : public BnMediaPlayerClient
class MediaRecorder : public BnMediaPlayerClient,
public virtual IMediaDeathNotifier
{
public:
MediaRecorder();
~MediaRecorder();
void died();
status_t initCheck();
status_t setCamera(const sp<ICamera>& camera);
status_t setPreviewSurface(const sp<Surface>& surface);

View File

@@ -24,7 +24,8 @@ LOCAL_SRC_FILES:= \
IAudioPolicyService.cpp \
MediaScanner.cpp \
MediaScannerClient.cpp \
autodetect.cpp
autodetect.cpp \
IMediaDeathNotifier.cpp
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox libicuuc

View File

@@ -0,0 +1,111 @@
/*
** Copyright 2010, 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_NDEBUG 0
#define LOG_TAG "IMediaDeathNotifier"
#include <utils/Log.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <media/IMediaDeathNotifier.h>
namespace android {
// client singleton for binder interface to services
Mutex IMediaDeathNotifier::sServiceLock;
sp<IMediaPlayerService> IMediaDeathNotifier::sMediaPlayerService;
sp<IMediaDeathNotifier::DeathNotifier> IMediaDeathNotifier::sDeathNotifier;
SortedVector< wp<IMediaDeathNotifier> > IMediaDeathNotifier::sObitRecipients;
// establish binder interface to MediaPlayerService
/*static*/const sp<IMediaPlayerService>&
IMediaDeathNotifier::getMediaPlayerService()
{
LOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService.get() == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
LOGW("Media player service not published, waiting...");
usleep(500000); // 0.5 s
} while(true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
LOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
/*static*/ void
IMediaDeathNotifier::addObitRecipient(const wp<IMediaDeathNotifier>& recipient)
{
LOGV("addObitRecipient");
Mutex::Autolock _l(sServiceLock);
sObitRecipients.add(recipient);
}
/*static*/ void
IMediaDeathNotifier::removeObitRecipient(const wp<IMediaDeathNotifier>& recipient)
{
LOGV("removeObitRecipient");
Mutex::Autolock _l(sServiceLock);
sObitRecipients.remove(recipient);
}
void
IMediaDeathNotifier::DeathNotifier::binderDied(const wp<IBinder>& who) {
LOGW("media server died");
// Need to do this with the lock held
SortedVector< wp<IMediaDeathNotifier> > list;
{
Mutex::Autolock _l(sServiceLock);
sMediaPlayerService.clear();
list = sObitRecipients;
}
// Notify application when media server dies.
// Don't hold the static lock during callback in case app
// makes a call that needs the lock.
size_t count = list.size();
for (size_t iter = 0; iter < count; ++iter) {
sp<IMediaDeathNotifier> notifier = list[iter].promote();
if (notifier != 0) {
notifier->died();
}
}
}
IMediaDeathNotifier::DeathNotifier::~DeathNotifier()
{
LOGV("DeathNotifier::~DeathNotifier");
Mutex::Autolock _l(sServiceLock);
sObitRecipients.clear();
if (sMediaPlayerService != 0) {
sMediaPlayerService->asBinder()->unlinkToDeath(this);
}
}
}; // namespace android

View File

@@ -34,48 +34,6 @@
namespace android {
// client singleton for binder interface to service
Mutex MediaPlayer::sServiceLock;
sp<IMediaPlayerService> MediaPlayer::sMediaPlayerService;
sp<MediaPlayer::DeathNotifier> MediaPlayer::sDeathNotifier;
SortedVector< wp<MediaPlayer> > MediaPlayer::sObitRecipients;
// establish binder interface to service
const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService()
{
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService.get() == 0) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != 0)
break;
LOGW("MediaPlayerService not published, waiting...");
usleep(500000); // 0.5 s
} while(true);
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?");
return sMediaPlayerService;
}
void MediaPlayer::addObitRecipient(const wp<MediaPlayer>& recipient)
{
Mutex::Autolock _l(sServiceLock);
sObitRecipients.add(recipient);
}
void MediaPlayer::removeObitRecipient(const wp<MediaPlayer>& recipient)
{
Mutex::Autolock _l(sServiceLock);
sObitRecipients.remove(recipient);
}
MediaPlayer::MediaPlayer()
{
LOGV("constructor");
@@ -94,15 +52,9 @@ MediaPlayer::MediaPlayer()
mLockThreadId = 0;
}
void MediaPlayer::onFirstRef()
{
addObitRecipient(this);
}
MediaPlayer::~MediaPlayer()
{
LOGV("destructor");
removeObitRecipient(this);
disconnect();
IPCThreadState::self()->flushCommands();
}
@@ -630,45 +582,13 @@ void MediaPlayer::notify(int msg, int ext1, int ext2)
}
}
void MediaPlayer::DeathNotifier::binderDied(const wp<IBinder>& who) {
LOGW("MediaPlayer server died!");
// Need to do this with the lock held
SortedVector< wp<MediaPlayer> > list;
{
Mutex::Autolock _l(MediaPlayer::sServiceLock);
MediaPlayer::sMediaPlayerService.clear();
list = sObitRecipients;
}
// Notify application when media server dies.
// Don't hold the static lock during callback in case app
// makes a call that needs the lock.
size_t count = list.size();
for (size_t iter = 0; iter < count; ++iter) {
sp<MediaPlayer> player = list[iter].promote();
if ((player != 0) && (player->mPlayer != 0)) {
player->notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
}
}
}
MediaPlayer::DeathNotifier::~DeathNotifier()
{
Mutex::Autolock _l(sServiceLock);
sObitRecipients.clear();
if (sMediaPlayerService != 0) {
sMediaPlayerService->asBinder()->unlinkToDeath(this);
}
}
/*static*/ sp<IMemory> MediaPlayer::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
{
LOGV("decode(%s)", url);
sp<IMemory> p;
const sp<IMediaPlayerService>& service = getMediaPlayerService();
if (service != 0) {
p = sMediaPlayerService->decode(url, pSampleRate, pNumChannels, pFormat);
p = service->decode(url, pSampleRate, pNumChannels, pFormat);
} else {
LOGE("Unable to locate media service");
}
@@ -676,13 +596,19 @@ MediaPlayer::DeathNotifier::~DeathNotifier()
}
void MediaPlayer::died()
{
LOGV("died");
notify(MEDIA_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
}
/*static*/ sp<IMemory> MediaPlayer::decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat)
{
LOGV("decode(%d, %lld, %lld)", fd, offset, length);
sp<IMemory> p;
const sp<IMediaPlayerService>& service = getMediaPlayerService();
if (service != 0) {
p = sMediaPlayerService->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
p = service->decode(fd, offset, length, pSampleRate, pNumChannels, pFormat);
} else {
LOGE("Unable to locate media service");
}

View File

@@ -24,6 +24,7 @@
#include <utils/String8.h>
#include <media/IMediaPlayerService.h>
#include <media/IMediaRecorder.h>
#include <media/mediaplayer.h> // for MEDIA_ERROR_SERVER_DIED
namespace android {
@@ -576,19 +577,8 @@ status_t MediaRecorder::release()
MediaRecorder::MediaRecorder()
{
LOGV("constructor");
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != NULL) {
break;
}
LOGW("MediaPlayerService not published, waiting...");
usleep(500000); // 0.5 s
} while(true);
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != NULL) {
mMediaRecorder = service->createMediaRecorder(getpid());
}
@@ -637,5 +627,11 @@ void MediaRecorder::notify(int msg, int ext1, int ext2)
}
}
void MediaRecorder::died()
{
LOGV("died");
notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0);
}
}; // namespace android