1 /*
2 * Copyright (C) 2020 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 #include "PowerPolicyClientBase.h"
18
19 #include <android-base/chrono_utils.h>
20 #include <android-base/logging.h>
21 #include <android/binder_manager.h>
22 #include <utils/SystemClock.h>
23
24 #include <algorithm>
25 #include <memory>
26
27 namespace android {
28 namespace frameworks {
29 namespace automotive {
30 namespace powerpolicy {
31
32 namespace aafap = ::aidl::android::frameworks::automotive::powerpolicy;
33
34 using aafap::CarPowerPolicy;
35 using aafap::CarPowerPolicyFilter;
36 using aafap::ICarPowerPolicyChangeCallback;
37 using aafap::ICarPowerPolicyServer;
38 using aafap::PowerComponent;
39 using android::uptimeMillis;
40 using android::base::Error;
41 using android::base::Result;
42 using ::ndk::ScopedAStatus;
43 using ::ndk::SpAIBinder;
44
45 namespace {
46
47 constexpr const char* kPowerPolicyServerInterface =
48 "android.frameworks.automotive.powerpolicy.ICarPowerPolicyServer/default";
49
50 constexpr std::chrono::milliseconds kPowerPolicyDaemonFindMarginalTimeMs = 500ms;
51
52 } // namespace
53
hasComponent(const std::vector<PowerComponent> & components,PowerComponent component)54 bool hasComponent(const std::vector<PowerComponent>& components, PowerComponent component) {
55 std::vector<PowerComponent>::const_iterator it =
56 std::find(components.cbegin(), components.cend(), component);
57 return it != components.cend();
58 }
59
PowerPolicyClientBase()60 PowerPolicyClientBase::PowerPolicyClientBase() :
61 mPolicyServer(nullptr),
62 mPolicyChangeCallback(nullptr),
63 mDeathRecipient(AIBinder_DeathRecipient_new(PowerPolicyClientBase::onBinderDied)),
64 mConnecting(false),
65 mDisconnecting(false) {
66 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(),
67 &PowerPolicyClientBase::onDeathRecipientUnlinked);
68 }
69
~PowerPolicyClientBase()70 PowerPolicyClientBase::~PowerPolicyClientBase() {
71 release();
72
73 // This will unlink all linked binders.
74 AIBinder_DeathRecipient_delete(mDeathRecipient.release());
75
76 // Need to wait until for each linkToDeath call, one onBinderUnlinked is called.
77 // In release, the connection thread already ends so we are sure mSelfRefCounter does not
78 // increase. We are sure mSelfRefCounter will not change once it is set to 0.
79 {
80 std::unique_lock lk(mLock);
81 mDeathRecipientLinkedCv.wait(lk, [this] { return mSelfRefCounter == 0; });
82 }
83 }
84
onDeathRecipientUnlinked(void * cookie)85 void PowerPolicyClientBase::onDeathRecipientUnlinked(void* cookie) {
86 PowerPolicyClientBase* client = static_cast<PowerPolicyClientBase*>(cookie);
87 client->handleDeathRecipientUnlinked();
88 }
89
onBinderDied(void * cookie)90 void PowerPolicyClientBase::onBinderDied(void* cookie) {
91 PowerPolicyClientBase* client = static_cast<PowerPolicyClientBase*>(cookie);
92 client->handleBinderDeath();
93 }
94
release()95 void PowerPolicyClientBase::release() {
96 SpAIBinder binder;
97 std::shared_ptr<ICarPowerPolicyServer> policyServer;
98 std::shared_ptr<ICarPowerPolicyChangeCallback> policyChangeCallback;
99 {
100 std::lock_guard<std::mutex> lk(mLock);
101
102 if (std::this_thread::get_id() == mConnectionThread.get_id()) {
103 LOG(ERROR) << "Cannot release from callback, deadlock would happen";
104 return;
105 }
106
107 // wait for existing connection thread to finish
108 mConnecting = false;
109 if (mConnectionThread.joinable()) {
110 mConnectionThread.join();
111 }
112
113 if (mPolicyServer == nullptr || mDisconnecting == true) {
114 return;
115 }
116
117 mDisconnecting = true;
118 binder = mPolicyServer->asBinder();
119 policyServer = mPolicyServer;
120 policyChangeCallback = mPolicyChangeCallback;
121 }
122
123 if (binder.get() != nullptr && AIBinder_isAlive(binder.get())) {
124 auto status = policyServer->unregisterPowerPolicyChangeCallback(policyChangeCallback);
125 if (!status.isOk()) {
126 LOG(ERROR) << "Unregister power policy change callback failed";
127 }
128 }
129
130 {
131 std::lock_guard<std::mutex> lk(mLock);
132 mPolicyServer = nullptr;
133 mPolicyChangeCallback = nullptr;
134 mDisconnecting = false;
135 }
136 }
137
init()138 void PowerPolicyClientBase::init() {
139 std::lock_guard<std::mutex> lk(mLock);
140
141 if (mConnecting) {
142 LOG(WARNING) << "Connecting in progress";
143 return;
144 }
145
146 if (mPolicyServer != nullptr) {
147 LOG(WARNING) << "Already connected";
148 return;
149 }
150
151 mConnecting = true;
152 // ensure already finished old connection thread is cleaned up before creating new one
153 if (mConnectionThread.joinable()) {
154 mConnectionThread.join();
155 }
156 mConnectionThread = std::thread([this]() {
157 Result<void> ret = connectToDaemon();
158 mConnecting = false;
159 if (!ret.ok()) {
160 LOG(WARNING) << "Connecting to car power policy daemon failed: " << ret.error();
161 onInitFailed();
162 }
163 });
164 }
165
handleBinderDeath()166 void PowerPolicyClientBase::handleBinderDeath() {
167 LOG(INFO) << "Power policy daemon died. Reconnecting...";
168 release();
169 init();
170 }
171
handleDeathRecipientUnlinked()172 void PowerPolicyClientBase::handleDeathRecipientUnlinked() {
173 LOG(INFO) << "Power policy death recipient unlinked";
174 mSelfRefCounter--;
175 mDeathRecipientLinkedCv.notify_all();
176 }
177
connectToDaemon()178 Result<void> PowerPolicyClientBase::connectToDaemon() {
179 int64_t currentUptime = uptimeMillis();
180 SpAIBinder binder(AServiceManager_waitForService(kPowerPolicyServerInterface));
181 if (binder.get() == nullptr) {
182 return Error() << "Failed to get car power policy daemon";
183 }
184 int64_t elapsedTime = uptimeMillis() - currentUptime;
185 if (elapsedTime > kPowerPolicyDaemonFindMarginalTimeMs.count()) {
186 LOG(WARNING) << "Finding power policy daemon took too long(" << elapsedTime << " ms)";
187 }
188 std::shared_ptr<ICarPowerPolicyServer> server = ICarPowerPolicyServer::fromBinder(binder);
189 if (server == nullptr) {
190 return Error() << "Failed to connect to car power policy daemon";
191 }
192 binder = this->asBinder();
193 if (binder.get() == nullptr) {
194 return Error() << "Failed to get car power policy client binder object";
195 }
196 // We pass 'this' as cookie to DeathRecipient so we need to increase ref counter to make
197 // sure we do not delete 'this' before the cookie is never used again.
198 mSelfRefCounter++;
199 auto status = ScopedAStatus::fromStatus(
200 AIBinder_linkToDeath(server->asBinder().get(), mDeathRecipient.get(), this));
201 if (!status.isOk()) {
202 return Error() << "Linking to death recipient failed";
203 }
204
205 std::shared_ptr<ICarPowerPolicyChangeCallback> client =
206 ICarPowerPolicyChangeCallback::fromBinder(binder);
207 const auto& components = getComponentsOfInterest();
208 const auto& customComponents = getCustomComponentsOfInterest();
209 CarPowerPolicyFilter filter;
210 filter.components = components;
211 filter.customComponents = customComponents;
212 status = server->registerPowerPolicyChangeCallback(client, filter);
213 if (!status.isOk()) {
214 status = ScopedAStatus::fromStatus(
215 AIBinder_unlinkToDeath(server->asBinder().get(), mDeathRecipient.get(), this));
216 if (!status.isOk()) {
217 LOG(WARNING) << "Unlinking from death recipient failed";
218 }
219 return Error() << "Register power policy change challback failed";
220 }
221
222 mPolicyServer = server;
223 mPolicyChangeCallback = client;
224
225 LOG(INFO) << "Connected to power policy daemon";
226 return {};
227 }
228
229 } // namespace powerpolicy
230 } // namespace automotive
231 } // namespace frameworks
232 } // namespace android
233