1*8222fbe1SAndroid Build Coastguard Worker /*
2*8222fbe1SAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*8222fbe1SAndroid Build Coastguard Worker *
4*8222fbe1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*8222fbe1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*8222fbe1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*8222fbe1SAndroid Build Coastguard Worker *
8*8222fbe1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*8222fbe1SAndroid Build Coastguard Worker *
10*8222fbe1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*8222fbe1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*8222fbe1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*8222fbe1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*8222fbe1SAndroid Build Coastguard Worker * limitations under the License.
15*8222fbe1SAndroid Build Coastguard Worker */
16*8222fbe1SAndroid Build Coastguard Worker
17*8222fbe1SAndroid Build Coastguard Worker #include <hidl/HidlPassthroughSupport.h>
18*8222fbe1SAndroid Build Coastguard Worker
19*8222fbe1SAndroid Build Coastguard Worker #include "InternalStatic.h" // TODO(b/69122224): remove this include, for tryWrap
20*8222fbe1SAndroid Build Coastguard Worker
21*8222fbe1SAndroid Build Coastguard Worker #include <hidl/HidlTransportUtils.h>
22*8222fbe1SAndroid Build Coastguard Worker #include <hidl/Static.h>
23*8222fbe1SAndroid Build Coastguard Worker
24*8222fbe1SAndroid Build Coastguard Worker using ::android::hidl::base::V1_0::IBase;
25*8222fbe1SAndroid Build Coastguard Worker
26*8222fbe1SAndroid Build Coastguard Worker namespace android {
27*8222fbe1SAndroid Build Coastguard Worker namespace hardware {
28*8222fbe1SAndroid Build Coastguard Worker namespace details {
29*8222fbe1SAndroid Build Coastguard Worker
tryWrap(const std::string & descriptor,sp<IBase> iface)30*8222fbe1SAndroid Build Coastguard Worker static sp<IBase> tryWrap(const std::string& descriptor, sp<IBase> iface) {
31*8222fbe1SAndroid Build Coastguard Worker auto func = getBsConstructorMap().get(descriptor, nullptr);
32*8222fbe1SAndroid Build Coastguard Worker if (func) {
33*8222fbe1SAndroid Build Coastguard Worker return func(static_cast<void*>(iface.get()));
34*8222fbe1SAndroid Build Coastguard Worker }
35*8222fbe1SAndroid Build Coastguard Worker return nullptr;
36*8222fbe1SAndroid Build Coastguard Worker }
37*8222fbe1SAndroid Build Coastguard Worker
wrapPassthroughInternal(sp<IBase> iface)38*8222fbe1SAndroid Build Coastguard Worker sp<IBase> wrapPassthroughInternal(sp<IBase> iface) {
39*8222fbe1SAndroid Build Coastguard Worker if (iface == nullptr || iface->isRemote()) {
40*8222fbe1SAndroid Build Coastguard Worker // doesn't know how to handle it.
41*8222fbe1SAndroid Build Coastguard Worker return iface;
42*8222fbe1SAndroid Build Coastguard Worker }
43*8222fbe1SAndroid Build Coastguard Worker
44*8222fbe1SAndroid Build Coastguard Worker // Consider the case when an AOSP interface is extended by partners.
45*8222fbe1SAndroid Build Coastguard Worker // Then the partner's HAL interface library is loaded only in the vndk
46*8222fbe1SAndroid Build Coastguard Worker // linker namespace, but not in the default linker namespace, where
47*8222fbe1SAndroid Build Coastguard Worker // this code runs. As a result, BsConstructorMap in the latter does not
48*8222fbe1SAndroid Build Coastguard Worker // have the entry for the descriptor name.
49*8222fbe1SAndroid Build Coastguard Worker //
50*8222fbe1SAndroid Build Coastguard Worker // Therefore, we try to wrap using the descript names of the parent
51*8222fbe1SAndroid Build Coastguard Worker // types along the interface chain, instead of always using the descriptor
52*8222fbe1SAndroid Build Coastguard Worker // name of the current interface.
53*8222fbe1SAndroid Build Coastguard Worker sp<IBase> base;
54*8222fbe1SAndroid Build Coastguard Worker auto ret = iface->interfaceChain([&](const auto& types) {
55*8222fbe1SAndroid Build Coastguard Worker for (const std::string& descriptor : types) {
56*8222fbe1SAndroid Build Coastguard Worker base = tryWrap(descriptor, iface);
57*8222fbe1SAndroid Build Coastguard Worker if (base != nullptr) {
58*8222fbe1SAndroid Build Coastguard Worker break; // wrap is successful. no need to lookup further.
59*8222fbe1SAndroid Build Coastguard Worker }
60*8222fbe1SAndroid Build Coastguard Worker }
61*8222fbe1SAndroid Build Coastguard Worker });
62*8222fbe1SAndroid Build Coastguard Worker
63*8222fbe1SAndroid Build Coastguard Worker if (!ret.isOk()) {
64*8222fbe1SAndroid Build Coastguard Worker return nullptr;
65*8222fbe1SAndroid Build Coastguard Worker }
66*8222fbe1SAndroid Build Coastguard Worker
67*8222fbe1SAndroid Build Coastguard Worker // It is ensured that if this function is called with an instance of IType
68*8222fbe1SAndroid Build Coastguard Worker // then the corresponding descriptor would be in the BsConstructorMap.
69*8222fbe1SAndroid Build Coastguard Worker // This is because referencing IType implies that the interface library
70*8222fbe1SAndroid Build Coastguard Worker // defining the type has already been loaded into the current linker
71*8222fbe1SAndroid Build Coastguard Worker // namespace, and thus the library should have added an entry into the
72*8222fbe1SAndroid Build Coastguard Worker // BsConstructorMap while executing the library's constructor.
73*8222fbe1SAndroid Build Coastguard Worker return base;
74*8222fbe1SAndroid Build Coastguard Worker }
75*8222fbe1SAndroid Build Coastguard Worker
76*8222fbe1SAndroid Build Coastguard Worker } // namespace details
77*8222fbe1SAndroid Build Coastguard Worker } // namespace hardware
78*8222fbe1SAndroid Build Coastguard Worker } // namespace android
79