blob: ab22f670edabad44ccbde04c2a7b4d9c03c4590d [file] [log] [blame]
/*
* Copyright 2019 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 "MediaPlayerService-DeathNotifier"
#include <android-base/logging.h>
#include "DeathNotifier.h"
namespace android {
class DeathNotifier::DeathRecipient :
public IBinder::DeathRecipient,
public hardware::hidl_death_recipient {
public:
using Notify = DeathNotifier::Notify;
DeathRecipient(Notify const& notify): mNotify{notify} {
}
void initNdk() {
mNdkRecipient.set(AIBinder_DeathRecipient_new(OnBinderDied));
}
virtual void binderDied(wp<IBinder> const&) override {
mNotify();
}
virtual void serviceDied(uint64_t, wp<HBase> const&) override {
mNotify();
}
static void OnBinderDied(void *cookie) {
DeathRecipient *thiz = (DeathRecipient *)cookie;
thiz->mNotify();
}
AIBinder_DeathRecipient *getNdkRecipient() {
return mNdkRecipient.get();;
}
private:
Notify mNotify;
::ndk::ScopedAIBinder_DeathRecipient mNdkRecipient;
};
DeathNotifier::DeathNotifier(sp<IBinder> const& service, Notify const& notify)
: mService{std::in_place_index<1>, service},
mDeathRecipient{new DeathRecipient(notify)} {
service->linkToDeath(mDeathRecipient);
}
DeathNotifier::DeathNotifier(sp<HBase> const& service, Notify const& notify)
: mService{std::in_place_index<2>, service},
mDeathRecipient{new DeathRecipient(notify)} {
service->linkToDeath(mDeathRecipient, 0);
}
DeathNotifier::DeathNotifier(::ndk::SpAIBinder const& service, Notify const& notify)
: mService{std::in_place_index<3>, service},
mDeathRecipient{new DeathRecipient(notify)} {
mDeathRecipient->initNdk();
AIBinder_linkToDeath(
service.get(), mDeathRecipient->getNdkRecipient(), mDeathRecipient.get());
}
DeathNotifier::DeathNotifier(DeathNotifier&& other)
: mService{other.mService}, mDeathRecipient{other.mDeathRecipient} {
other.mService.emplace<0>();
other.mDeathRecipient = nullptr;
}
DeathNotifier::~DeathNotifier() {
switch (mService.index()) {
case 0:
break;
case 1:
std::get<1>(mService)->unlinkToDeath(mDeathRecipient);
break;
case 2:
std::get<2>(mService)->unlinkToDeath(mDeathRecipient);
break;
case 3:
AIBinder_unlinkToDeath(
std::get<3>(mService).get(),
mDeathRecipient->getNdkRecipient(),
mDeathRecipient.get());
break;
default:
CHECK(false) << "Corrupted service type during destruction.";
}
}
} // namespace android