Media server death nodification
This commit is contained in:
61
include/media/IMediaDeathNotifier.h
Normal file
61
include/media/IMediaDeathNotifier.h
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
111
media/libmedia/IMediaDeathNotifier.cpp
Normal file
111
media/libmedia/IMediaDeathNotifier.cpp
Normal 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
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user