• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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