blob: 85254822657bae13bd7093f75ff4e5443e804bd1 [file] [log] [blame]
James Dong34bbc222010-01-15 18:13:58 -08001/*
2** Copyright 2010, The Android Open Source Project
3**
4** Licensed under the Apache License, Version 2.0 (the "License");
5** you may not use this file except in compliance with the License.
6** You may obtain a copy of the License at
7**
8** http://www.apache.org/licenses/LICENSE-2.0
9**
10** Unless required by applicable law or agreed to in writing, software
11** distributed under the License is distributed on an "AS IS" BASIS,
12** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13** See the License for the specific language governing permissions and
14** limitations under the License.
15*/
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "IMediaDeathNotifier"
19#include <utils/Log.h>
20
21#include <binder/IServiceManager.h>
22#include <binder/IPCThreadState.h>
23#include <media/IMediaDeathNotifier.h>
24
25namespace android {
26
27// client singleton for binder interface to services
28Mutex IMediaDeathNotifier::sServiceLock;
29sp<IMediaPlayerService> IMediaDeathNotifier::sMediaPlayerService;
30sp<IMediaDeathNotifier::DeathNotifier> IMediaDeathNotifier::sDeathNotifier;
31SortedVector< wp<IMediaDeathNotifier> > IMediaDeathNotifier::sObitRecipients;
32
33// establish binder interface to MediaPlayerService
34/*static*/const sp<IMediaPlayerService>&
35IMediaDeathNotifier::getMediaPlayerService()
36{
Steve Block71f2cf12011-10-20 11:56:00 +010037 ALOGV("getMediaPlayerService");
James Dong34bbc222010-01-15 18:13:58 -080038 Mutex::Autolock _l(sServiceLock);
39 if (sMediaPlayerService.get() == 0) {
40 sp<IServiceManager> sm = defaultServiceManager();
41 sp<IBinder> binder;
42 do {
43 binder = sm->getService(String16("media.player"));
44 if (binder != 0) {
45 break;
46 }
Steve Block8564c8d2012-01-05 23:22:43 +000047 ALOGW("Media player service not published, waiting...");
James Dong34bbc222010-01-15 18:13:58 -080048 usleep(500000); // 0.5 s
49 } while(true);
50
51 if (sDeathNotifier == NULL) {
52 sDeathNotifier = new DeathNotifier();
53 }
54 binder->linkToDeath(sDeathNotifier);
55 sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
56 }
Steve Block3762c312012-01-06 19:20:56 +000057 ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
James Dong34bbc222010-01-15 18:13:58 -080058 return sMediaPlayerService;
59}
60
61/*static*/ void
62IMediaDeathNotifier::addObitRecipient(const wp<IMediaDeathNotifier>& recipient)
63{
Steve Block71f2cf12011-10-20 11:56:00 +010064 ALOGV("addObitRecipient");
James Dong34bbc222010-01-15 18:13:58 -080065 Mutex::Autolock _l(sServiceLock);
66 sObitRecipients.add(recipient);
67}
68
69/*static*/ void
70IMediaDeathNotifier::removeObitRecipient(const wp<IMediaDeathNotifier>& recipient)
71{
Steve Block71f2cf12011-10-20 11:56:00 +010072 ALOGV("removeObitRecipient");
James Dong34bbc222010-01-15 18:13:58 -080073 Mutex::Autolock _l(sServiceLock);
74 sObitRecipients.remove(recipient);
75}
76
77void
78IMediaDeathNotifier::DeathNotifier::binderDied(const wp<IBinder>& who) {
Steve Block8564c8d2012-01-05 23:22:43 +000079 ALOGW("media server died");
James Dong34bbc222010-01-15 18:13:58 -080080
81 // Need to do this with the lock held
82 SortedVector< wp<IMediaDeathNotifier> > list;
83 {
84 Mutex::Autolock _l(sServiceLock);
85 sMediaPlayerService.clear();
86 list = sObitRecipients;
87 }
88
89 // Notify application when media server dies.
90 // Don't hold the static lock during callback in case app
91 // makes a call that needs the lock.
92 size_t count = list.size();
93 for (size_t iter = 0; iter < count; ++iter) {
94 sp<IMediaDeathNotifier> notifier = list[iter].promote();
95 if (notifier != 0) {
96 notifier->died();
97 }
98 }
99}
100
101IMediaDeathNotifier::DeathNotifier::~DeathNotifier()
102{
Steve Block71f2cf12011-10-20 11:56:00 +0100103 ALOGV("DeathNotifier::~DeathNotifier");
James Dong34bbc222010-01-15 18:13:58 -0800104 Mutex::Autolock _l(sServiceLock);
105 sObitRecipients.clear();
106 if (sMediaPlayerService != 0) {
107 sMediaPlayerService->asBinder()->unlinkToDeath(this);
108 }
109}
110
111}; // namespace android