1 /* 2 * Copyright (C) 2022 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 #pragma once 18 19 #include <condition_variable> 20 #include <memory> 21 #include <mutex> 22 23 #include <android-base/properties.h> 24 #include <android/binder_auto_utils.h> 25 #include <android/binder_manager.h> 26 #include <android/binder_process.h> 27 28 #include <android-base/logging.h> 29 30 class AudioHalBinderServiceUtil { 31 public: connectToService(const std::string & serviceName)32 ndk::SpAIBinder connectToService(const std::string& serviceName) { 33 mServiceName = serviceName; 34 mBinder = ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())); 35 if (mBinder == nullptr) { 36 LOG(ERROR) << "Failed to get service " << serviceName; 37 } else { 38 LOG(DEBUG) << "Succeeded to get service " << serviceName; 39 } 40 return mBinder; 41 } 42 43 ndk::SpAIBinder restartService( 44 std::chrono::milliseconds timeoutMs = std::chrono::milliseconds(3000)) { 45 mDeathHandler.reset(new AidlDeathRecipient(mBinder)); 46 if (STATUS_OK != mDeathHandler->linkToDeath()) { 47 LOG(ERROR) << "linkToDeath failed"; 48 return nullptr; 49 } 50 if (!android::base::SetProperty("sys.audio.restart.hal", "1")) { 51 LOG(ERROR) << "SetProperty failed"; 52 return nullptr; 53 } 54 if (!mDeathHandler->waitForFired(timeoutMs)) { 55 LOG(ERROR) << "Timeout wait for death"; 56 return nullptr; 57 } 58 mDeathHandler.reset(); 59 return connectToService(mServiceName); 60 } 61 62 private: 63 class AidlDeathRecipient { 64 public: AidlDeathRecipient(const ndk::SpAIBinder & binder)65 explicit AidlDeathRecipient(const ndk::SpAIBinder& binder) 66 : binder(binder), recipient(AIBinder_DeathRecipient_new(&binderDiedCallbackAidl)) {} 67 linkToDeath()68 binder_status_t linkToDeath() { 69 return AIBinder_linkToDeath(binder.get(), recipient.get(), this); 70 } 71 waitForFired(std::chrono::milliseconds timeoutMs)72 bool waitForFired(std::chrono::milliseconds timeoutMs) { 73 std::unique_lock<std::mutex> lock(mutex); 74 condition.wait_for(lock, timeoutMs, [this]() { return fired; }); 75 return fired; 76 } 77 78 private: 79 const ndk::SpAIBinder binder; 80 const ndk::ScopedAIBinder_DeathRecipient recipient; 81 std::mutex mutex; 82 std::condition_variable condition; 83 bool fired = false; 84 binderDied()85 void binderDied() { 86 std::unique_lock<std::mutex> lock(mutex); 87 fired = true; 88 condition.notify_one(); 89 }; 90 binderDiedCallbackAidl(void * cookie)91 static void binderDiedCallbackAidl(void* cookie) { 92 AidlDeathRecipient* self = static_cast<AidlDeathRecipient*>(cookie); 93 self->binderDied(); 94 } 95 }; 96 97 std::string mServiceName; 98 ndk::SpAIBinder mBinder; 99 std::unique_ptr<AidlDeathRecipient> mDeathHandler; 100 }; 101