1 /*
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 
25 namespace android {
26 
27 // client singleton for binder interface to services
28 Mutex IMediaDeathNotifier::sServiceLock;
29 sp<IMediaPlayerService> IMediaDeathNotifier::sMediaPlayerService;
30 sp<IMediaDeathNotifier::DeathNotifier> IMediaDeathNotifier::sDeathNotifier;
31 SortedVector< wp<IMediaDeathNotifier> > IMediaDeathNotifier::sObitRecipients;
32 
33 // establish binder interface to MediaPlayerService
34 /*static*/const sp<IMediaPlayerService>
getMediaPlayerService()35 IMediaDeathNotifier::getMediaPlayerService()
36 {
37     ALOGV("getMediaPlayerService");
38     Mutex::Autolock _l(sServiceLock);
39     if (sMediaPlayerService == 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             }
47             ALOGW("Media player service not published, waiting...");
48             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     }
57     ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
58     return sMediaPlayerService;
59 }
60 
61 /*static*/ void
addObitRecipient(const wp<IMediaDeathNotifier> & recipient)62 IMediaDeathNotifier::addObitRecipient(const wp<IMediaDeathNotifier>& recipient)
63 {
64     ALOGV("addObitRecipient");
65     Mutex::Autolock _l(sServiceLock);
66     sObitRecipients.add(recipient);
67 }
68 
69 /*static*/ void
removeObitRecipient(const wp<IMediaDeathNotifier> & recipient)70 IMediaDeathNotifier::removeObitRecipient(const wp<IMediaDeathNotifier>& recipient)
71 {
72     ALOGV("removeObitRecipient");
73     Mutex::Autolock _l(sServiceLock);
74     sObitRecipients.remove(recipient);
75 }
76 
77 void
binderDied(const wp<IBinder> & who __unused)78 IMediaDeathNotifier::DeathNotifier::binderDied(const wp<IBinder>& who __unused) {
79     ALOGW("media server died");
80 
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 
~DeathNotifier()101 IMediaDeathNotifier::DeathNotifier::~DeathNotifier()
102 {
103     ALOGV("DeathNotifier::~DeathNotifier");
104     Mutex::Autolock _l(sServiceLock);
105     sObitRecipients.clear();
106     if (sMediaPlayerService != 0) {
107         IInterface::asBinder(sMediaPlayerService)->unlinkToDeath(this);
108     }
109 }
110 
111 } // namespace android
112