• 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         if (!stopService(timeoutMs)) {
46             return {};
47         }
48         return connectToService(mServiceName);
49     }
50 
51   private:
52     class AidlDeathRecipient {
53       public:
AidlDeathRecipient(const ndk::SpAIBinder & binder)54         explicit AidlDeathRecipient(const ndk::SpAIBinder& binder)
55             : binder(binder), recipient(AIBinder_DeathRecipient_new(&binderDiedCallbackAidl)) {}
56 
linkToDeath()57         binder_status_t linkToDeath() {
58             return AIBinder_linkToDeath(binder.get(), recipient.get(), this);
59         }
60 
waitForFired(std::chrono::milliseconds timeoutMs)61         bool waitForFired(std::chrono::milliseconds timeoutMs) {
62             std::unique_lock<std::mutex> lock(mutex);
63             return condition.wait_for(lock, timeoutMs, [this]() { return fired; });
64         }
65 
66       private:
67         const ndk::SpAIBinder binder;
68         const ndk::ScopedAIBinder_DeathRecipient recipient;
69         std::mutex mutex;
70         std::condition_variable condition;
71         bool fired = false;
72 
binderDied()73         void binderDied() {
74             std::unique_lock<std::mutex> lock(mutex);
75             fired = true;
76             condition.notify_one();
77         };
78 
binderDiedCallbackAidl(void * cookie)79         static void binderDiedCallbackAidl(void* cookie) {
80             AidlDeathRecipient* self = static_cast<AidlDeathRecipient*>(cookie);
81             self->binderDied();
82         }
83     };
84 
stopService(std::chrono::milliseconds timeoutMs)85     bool stopService(std::chrono::milliseconds timeoutMs) {
86         AidlDeathRecipient deathHandler(mBinder);
87         if (STATUS_OK != deathHandler.linkToDeath()) {
88             LOG(ERROR) << "linkToDeath failed";
89             return false;
90         }
91         if (!android::base::SetProperty("sys.audio.restart.hal", "1")) {
92             LOG(ERROR) << "SetProperty failed";
93             return false;
94         }
95         if (!deathHandler.waitForFired(timeoutMs)) {
96             LOG(ERROR) << "Timeout wait for death of " << mServiceName;
97             return false;
98         }
99         return true;
100     }
101 
102     std::string mServiceName;
103     ndk::SpAIBinder mBinder;
104 };
105