michael@0: /* michael@0: ** Copyright 2010, The Android Open Source Project michael@0: ** Copyright 2013, Mozilla Foundation michael@0: ** michael@0: ** Licensed under the Apache License, Version 2.0 (the "License"); michael@0: ** you may not use this file except in compliance with the License. michael@0: ** You may obtain a copy of the License at michael@0: ** michael@0: ** http://www.apache.org/licenses/LICENSE-2.0 michael@0: ** michael@0: ** Unless required by applicable law or agreed to in writing, software michael@0: ** distributed under the License is distributed on an "AS IS" BASIS, michael@0: ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: ** See the License for the specific language governing permissions and michael@0: ** limitations under the License. michael@0: */ michael@0: michael@0: //#define LOG_NDEBUG 0 michael@0: #define LOG_TAG "IMediaResourceManagerDeathNotifier" michael@0: #include michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "IMediaResourceManagerDeathNotifier.h" michael@0: michael@0: #define DN_LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) michael@0: #define DN_LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) michael@0: #define DN_LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) michael@0: #define DN_LOGE_IF(cond, ...) \ michael@0: ( (CONDITION(cond)) \ michael@0: ? ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) \ michael@0: : (void)0 ) michael@0: michael@0: namespace android { michael@0: michael@0: // client singleton for binder interface to services michael@0: Mutex IMediaResourceManagerDeathNotifier::sServiceLock; michael@0: sp IMediaResourceManagerDeathNotifier::sMediaResourceManagerService; michael@0: sp IMediaResourceManagerDeathNotifier::sDeathNotifier; michael@0: SortedVector< wp > IMediaResourceManagerDeathNotifier::sObitRecipients; michael@0: michael@0: // establish binder interface to MediaResourceManagerService michael@0: /*static*/const sp& michael@0: IMediaResourceManagerDeathNotifier::getMediaResourceManagerService() michael@0: { michael@0: DN_LOGV("getMediaResourceManagerService"); michael@0: Mutex::Autolock _l(sServiceLock); michael@0: if (sMediaResourceManagerService.get() == 0) { michael@0: sp sm = defaultServiceManager(); michael@0: sp binder; michael@0: do { michael@0: binder = sm->getService(String16("media.resource_manager")); michael@0: if (binder != 0) { michael@0: break; michael@0: } michael@0: DN_LOGW("Media resource manager service not published, waiting..."); michael@0: usleep(500000); // 0.5 s michael@0: } while(true); michael@0: michael@0: if (sDeathNotifier == NULL) { michael@0: sDeathNotifier = new DeathNotifier(); michael@0: } michael@0: binder->linkToDeath(sDeathNotifier); michael@0: sMediaResourceManagerService = interface_cast(binder); michael@0: } michael@0: DN_LOGE_IF(sMediaResourceManagerService == 0, "no media player service!?"); michael@0: return sMediaResourceManagerService; michael@0: } michael@0: michael@0: /*static*/ void michael@0: IMediaResourceManagerDeathNotifier::addObitRecipient(const wp& recipient) michael@0: { michael@0: Mutex::Autolock _l(sServiceLock); michael@0: sObitRecipients.add(recipient); michael@0: } michael@0: michael@0: /*static*/ void michael@0: IMediaResourceManagerDeathNotifier::removeObitRecipient(const wp& recipient) michael@0: { michael@0: Mutex::Autolock _l(sServiceLock); michael@0: sObitRecipients.remove(recipient); michael@0: } michael@0: michael@0: void michael@0: IMediaResourceManagerDeathNotifier::DeathNotifier::binderDied(const wp& who) michael@0: { michael@0: DN_LOGW("media resource manager service died"); michael@0: // Need to do this with the lock held michael@0: SortedVector< wp > list; michael@0: { michael@0: Mutex::Autolock _l(sServiceLock); michael@0: sMediaResourceManagerService.clear(); michael@0: list = sObitRecipients; michael@0: } michael@0: michael@0: // Notify application when media server dies. michael@0: // Don't hold the static lock during callback in case app michael@0: // makes a call that needs the lock. michael@0: size_t count = list.size(); michael@0: for (size_t iter = 0; iter < count; ++iter) { michael@0: sp notifier = list[iter].promote(); michael@0: if (notifier != 0) { michael@0: notifier->died(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: IMediaResourceManagerDeathNotifier::DeathNotifier::~DeathNotifier() michael@0: { michael@0: Mutex::Autolock _l(sServiceLock); michael@0: sObitRecipients.clear(); michael@0: if (sMediaResourceManagerService != 0) { michael@0: sMediaResourceManagerService->asBinder()->unlinkToDeath(this); michael@0: } michael@0: } michael@0: michael@0: }; // namespace android