HybridInterface.cpp revision 3249cc0d8767bd3dadd055836a49d83b90bc6ae4
1/*
2 * Copyright (C) 2017 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_TAG "HybridInterface"
18
19#include <utils/Log.h>
20#include <hidl/HybridInterface.h>
21#include <hidl/HidlSupport.h>
22#include <android/hidl/token/1.0/ITokenManager.h>
23
24namespace android {
25
26using ::android::hidl::token::V1_0::ITokenManager;
27
28namespace {
29
30std::mutex gTokenManagerLock;
31sp<ITokenManager> gTokenManager = nullptr;
32
33struct TokenManagerDeathRecipient : public hardware::hidl_death_recipient {
34    void serviceDied(uint64_t, const wp<HInterface>&) {
35        std::lock_guard<std::mutex> lock(gTokenManagerLock);
36        gTokenManager = nullptr;
37    }
38};
39
40sp<TokenManagerDeathRecipient> gTokenManagerDeathRecipient =
41    new TokenManagerDeathRecipient();
42
43bool isBadTokenManager() {
44    if (gTokenManager != nullptr) {
45        return false;
46    }
47    gTokenManager = ITokenManager::getService();
48    if (gTokenManager == nullptr) {
49        ALOGE("Cannot retrieve TokenManager.");
50        return true;
51    }
52    auto transaction = gTokenManager->linkToDeath(
53            gTokenManagerDeathRecipient, 0);
54    if (!transaction.isOk()) {
55        ALOGE("Cannot observe TokenManager's death.");
56        gTokenManager = nullptr;
57        return true;
58    }
59    return false;
60}
61
62template <typename ReturnType>
63bool isBadTransaction(hardware::Return<ReturnType>& transaction) {
64    if (transaction.isOk()) {
65        return false;
66    }
67    ALOGE("TokenManager's transaction error: %s",
68            transaction.description().c_str());
69    gTokenManager->unlinkToDeath(gTokenManagerDeathRecipient).isOk();
70    gTokenManager = nullptr;
71    return true;
72}
73
74} // unnamed namespace
75
76sp<HInterface> retrieveHalInterface(const HalToken& token) {
77    hardware::Return<sp<HInterface> > transaction(nullptr);
78    {
79        std::lock_guard<std::mutex> lock(gTokenManagerLock);
80        if (isBadTokenManager()) {
81            return nullptr;
82        }
83        transaction = gTokenManager->get(token);
84        if (isBadTransaction(transaction)) {
85            return nullptr;
86        }
87    }
88    return static_cast<sp<HInterface> >(transaction);
89}
90
91bool createHalToken(const sp<HInterface>& interface, HalToken* token) {
92    hardware::Return<void> transaction;
93    {
94        std::lock_guard<std::mutex> lock(gTokenManagerLock);
95        if (isBadTokenManager()) {
96            return false;
97        }
98        transaction = gTokenManager->createToken(interface, [&](const HalToken &newToken) {
99            *token = newToken;
100        });
101    }
102    return !isBadTransaction(transaction);
103}
104
105bool deleteHalToken(const HalToken& token) {
106    hardware::Return<bool> transaction(false);
107    {
108        std::lock_guard<std::mutex> lock(gTokenManagerLock);
109        if (isBadTokenManager()) {
110            return false;
111        }
112        transaction = gTokenManager->unregister(token);
113        if (isBadTransaction(transaction)) {
114            return false;
115        }
116    }
117    return static_cast<bool>(transaction);
118}
119
120}; // namespace android
121
122