blob: 8b3fc1cc10ca9ae612393c60db3313ca9f588a34 [file] [log] [blame]
/*
* Copyright (C) 2022 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.
*/
#pragma once
#include <binder/IBinder.h>
#ifndef __BIONIC__
#ifndef __assert
// defined differently by liblog
#pragma push_macro("LOG_PRI")
#ifdef LOG_PRI
#undef LOG_PRI
#endif
#include <syslog.h>
#pragma pop_macro("LOG_PRI")
#define __assert(a, b, c) \
do { \
syslog(LOG_ERR, a ": " c); \
abort(); \
} while (false)
#endif // __assert
#endif // __BIONIC__
namespace android {
/*
* Used to manage AIDL's *Delegator types.
* This is used to:
* - create a new *Delegator object that delegates to the binder argument.
* - or return an existing *Delegator object that already delegates to the
* binder argument.
* - or return the underlying delegate binder if the binder argument is a
* *Delegator itself.
*
* @param binder - the binder to delegate to or unwrap
*
* @return pointer to the *Delegator object or the unwrapped binder object
*/
template <typename T>
sp<T> delegate(const sp<T>& binder) {
const void* isDelegatorId = &T::descriptor;
const void* hasDelegatorId = &T::descriptor + 1;
// is binder itself a delegator?
if (T::asBinder(binder)->findObject(isDelegatorId)) {
if (T::asBinder(binder)->findObject(hasDelegatorId)) {
__assert(__FILE__, __LINE__,
"This binder has a delegator and is also delegator itself! This is "
"likely an unintended mixing of binders.");
return nullptr;
}
// unwrap the delegator
return static_cast<typename T::DefaultDelegator*>(binder.get())->getImpl();
}
struct MakeArgs {
const sp<T>* binder;
const void* id;
} makeArgs;
makeArgs.binder = &binder;
makeArgs.id = isDelegatorId;
// the binder is not a delegator, so construct one
sp<IBinder> newDelegator = T::asBinder(binder)->lookupOrCreateWeak(
hasDelegatorId,
[](const void* args) -> sp<IBinder> {
auto delegator = sp<typename T::DefaultDelegator>::make(
*static_cast<const MakeArgs*>(args)->binder);
// make sure we know this binder is a delegator by attaching a unique ID
(void)delegator->attachObject(static_cast<const MakeArgs*>(args)->id,
reinterpret_cast<void*>(0x1), nullptr, nullptr);
return delegator;
},
static_cast<const void*>(&makeArgs));
return sp<typename T::DefaultDelegator>::cast(newDelegator);
}
} // namespace android