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 kPowerPolicyDaemomFindMarginalTimeMs = 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
onDeathRecipientUnlinked(void * cookie)74 void PowerPolicyClientBase::onDeathRecipientUnlinked(void* cookie) {
75 PowerPolicyClientBase* client = static_cast<PowerPolicyClientBase*>(cookie);
76 client->handleDeathRecipientUnlinked();
77 }
78
onBinderDied(void * cookie)79 void PowerPolicyClientBase::onBinderDied(void* cookie) {
80 PowerPolicyClientBase* client = static_cast<PowerPolicyClientBase*>(cookie);
81 client->handleBinderDeath();
82 }
83
release()84 void PowerPolicyClientBase::release() {
85 SpAIBinder binder;
86 std::shared_ptr<ICarPowerPolicyServer> policyServer;
87 std::shared_ptr<ICarPowerPolicyChangeCallback> policyChangeCallback;
88 {
89 std::lock_guard<std::mutex> lk(mLock);
90
91 if (std::this_thread::get_id() == mConnectionThread.get_id()) {
92 LOG(ERROR) << "Cannot release from callback, deadlock would happen";
93 return;
94 }
95
96 // wait for existing connection thread to finish
97 mConnecting = false;
98 if (mConnectionThread.joinable()) {
99 mConnectionThread.join();
100 }
101
102 if (mPolicyServer == nullptr || mDisconnecting == true) {
103 return;
104 }
105
106 mDisconnecting = true;
107 binder = mPolicyServer->asBinder();
108 policyServer = mPolicyServer;
109 policyChangeCallback = mPolicyChangeCallback;
110 }
111
112 if (binder.get() != nullptr && AIBinder_isAlive(binder.get())) {
113 auto status = policyServer->unregisterPowerPolicyChangeCallback(policyChangeCallback);
114 if (!status.isOk()) {
115 LOG(ERROR) << "Unregister power policy change callback failed";
116 }
117
118 status = ScopedAStatus::fromStatus(
119 AIBinder_unlinkToDeath(binder.get(), mDeathRecipient.get(), this));
120 if (!status.isOk()) {
121 LOG(WARNING) << "Unlinking from death recipient failed";
122 }
123
124 // Need to wait until onUnlinked to be called.
125 {
126 std::unique_lock lk(mLock);
127 mDeathRecipientLinkedCv.wait(lk, [this] { return !mDeathRecipientLinked; });
128 }
129 }
130
131 {
132 std::lock_guard<std::mutex> lk(mLock);
133 mPolicyServer = nullptr;
134 mPolicyChangeCallback = nullptr;
135 mDisconnecting = false;
136 }
137 }
138
init()139 void PowerPolicyClientBase::init() {
140 std::lock_guard<std::mutex> lk(mLock);
141
142 if (mConnecting) {
143 LOG(WARNING) << "Connecting in progress";
144 return;
145 }
146
147 if (mPolicyServer != nullptr) {
148 LOG(WARNING) << "Already connected";
149 return;
150 }
151
152 mConnecting = true;
153 // ensure already finished old connection thread is cleaned up before creating new one
154 if (mConnectionThread.joinable()) {
155 mConnectionThread.join();
156 }
157 mConnectionThread = std::thread([this]() {
158 Result<void> ret = connectToDaemon();
159 mConnecting = false;
160 if (!ret.ok()) {
161 LOG(WARNING) << "Connecting to car power policy daemon failed: " << ret.error();
162 onInitFailed();
163 }
164 });
165 }
166
handleBinderDeath()167 void PowerPolicyClientBase::handleBinderDeath() {
168 LOG(INFO) << "Power policy daemon died. Reconnecting...";
169 release();
170 init();
171 }
172
handleDeathRecipientUnlinked()173 void PowerPolicyClientBase::handleDeathRecipientUnlinked() {
174 LOG(INFO) << "Power policy death recipient unlinked";
175 {
176 std::lock_guard<std::mutex> lk(mLock);
177 mDeathRecipientLinked = false;
178 }
179 mDeathRecipientLinkedCv.notify_all();
180 }
181
connectToDaemon()182 Result<void> PowerPolicyClientBase::connectToDaemon() {
183 int64_t currentUptime = uptimeMillis();
184 SpAIBinder binder(AServiceManager_waitForService(kPowerPolicyServerInterface));
185 if (binder.get() == nullptr) {
186 return Error() << "Failed to get car power policy daemon";
187 }
188 int64_t elapsedTime = uptimeMillis() - currentUptime;
189 if (elapsedTime > kPowerPolicyDaemomFindMarginalTimeMs.count()) {
190 LOG(WARNING) << "Finding power policy daemon took too long(" << elapsedTime << " ms)";
191 }
192 std::shared_ptr<ICarPowerPolicyServer> server = ICarPowerPolicyServer::fromBinder(binder);
193 if (server == nullptr) {
194 return Error() << "Failed to connect to car power policy daemon";
195 }
196 binder = this->asBinder();
197 if (binder.get() == nullptr) {
198 return Error() << "Failed to get car power policy client binder object";
199 }
200 mDeathRecipientLinked = true;
201 auto status = ScopedAStatus::fromStatus(
202 AIBinder_linkToDeath(server->asBinder().get(), mDeathRecipient.get(), this));
203 if (!status.isOk()) {
204 return Error() << "Linking to death recipient failed";
205 }
206
207 std::shared_ptr<ICarPowerPolicyChangeCallback> client =
208 ICarPowerPolicyChangeCallback::fromBinder(binder);
209 const auto& components = getComponentsOfInterest();
210 const auto& customComponents = getCustomComponentsOfInterest();
211 CarPowerPolicyFilter filter;
212 filter.components = components;
213 filter.customComponents = customComponents;
214 status = server->registerPowerPolicyChangeCallback(client, filter);
215 if (!status.isOk()) {
216 status = ScopedAStatus::fromStatus(
217 AIBinder_unlinkToDeath(server->asBinder().get(), mDeathRecipient.get(), this));
218 if (!status.isOk()) {
219 LOG(WARNING) << "Unlinking from death recipient failed";
220 }
221 return Error() << "Register power policy change challback failed";
222 }
223
224 mPolicyServer = server;
225 mPolicyChangeCallback = client;
226
227 LOG(INFO) << "Connected to power policy daemon";
228 return {};
229 }
230
231 } // namespace powerpolicy
232 } // namespace automotive
233 } // namespace frameworks
234 } // namespace android
235