Home | History | Annotate | Download | only in utils
      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 
     24 namespace android {
     25 
     26 using ::android::hidl::token::V1_0::ITokenManager;
     27 
     28 namespace {
     29 
     30 std::mutex gTokenManagerLock;
     31 sp<ITokenManager> gTokenManager = nullptr;
     32 
     33 struct 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 
     40 sp<TokenManagerDeathRecipient> gTokenManagerDeathRecipient =
     41     new TokenManagerDeathRecipient();
     42 
     43 bool 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 
     62 template <typename ReturnType>
     63 bool 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 
     76 sp<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 
     91 bool 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 
    105 bool 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