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 #define LOG_TAG "carpowerpolicyd"
18 #define DEBUG false // STOPSHIP if true.
19
20 #include "CarPowerPolicyServer.h"
21
22 #include <aidl/android/hardware/automotive/vehicle/StatusCode.h>
23 #include <aidl/android/hardware/automotive/vehicle/SubscribeOptions.h>
24 #include <aidl/android/hardware/automotive/vehicle/VehicleApPowerStateReport.h>
25 #include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
26 #include <android-base/file.h>
27 #include <android-base/stringprintf.h>
28 #include <android/binder_ibinder.h>
29 #include <android/binder_manager.h>
30 #include <android/binder_status.h>
31 #include <binder/IPCThreadState.h>
32 #include <binder/IServiceManager.h>
33 #include <hidl/HidlTransportSupport.h>
34 #include <private/android_filesystem_config.h>
35 #include <utils/String8.h>
36 #include <utils/SystemClock.h>
37 #include <utils/Timers.h>
38
39 #include <inttypes.h>
40
41 namespace android {
42 namespace frameworks {
43 namespace automotive {
44 namespace powerpolicy {
45
46 using ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicy;
47 using ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicyFilter;
48 using ::aidl::android::frameworks::automotive::powerpolicy::ICarPowerPolicyChangeCallback;
49 using ::aidl::android::frameworks::automotive::powerpolicy::PowerComponent;
50 using ::aidl::android::frameworks::automotive::powerpolicy::internal::PolicyState;
51 using ::aidl::android::hardware::automotive::vehicle::StatusCode;
52 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
53 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
54 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
55
56 using ::android::defaultServiceManager;
57 using ::android::IBinder;
58 using ::android::Looper;
59 using ::android::Mutex;
60 using ::android::status_t;
61 using ::android::String16;
62 using ::android::uptimeMillis;
63 using ::android::Vector;
64 using ::android::wp;
65 using ::android::base::Error;
66 using ::android::base::Result;
67 using ::android::base::StringAppendF;
68 using ::android::base::StringPrintf;
69 using ::android::base::WriteStringToFd;
70 using ::android::frameworks::automotive::vhal::HalPropError;
71 using ::android::frameworks::automotive::vhal::IHalPropValue;
72 using ::android::frameworks::automotive::vhal::ISubscriptionClient;
73 using ::android::frameworks::automotive::vhal::IVhalClient;
74 using ::android::hardware::hidl_vec;
75 using ::android::hardware::interfacesEqual;
76 using ::android::hardware::Return;
77 using ::android::hardware::automotive::vehicle::VhalResult;
78
79 using ::android::hidl::base::V1_0::IBase;
80 using ::ndk::ScopedAIBinder_DeathRecipient;
81 using ::ndk::ScopedAStatus;
82 using ::ndk::SharedRefBase;
83 using ::ndk::SpAIBinder;
84
85 namespace {
86
87 const int32_t MSG_CONNECT_TO_VHAL = 1; // Message to request of connecting to VHAL.
88
89 const nsecs_t kConnectionRetryIntervalNs = 200000000; // 200 milliseconds.
90 const int32_t kMaxConnectionRetry = 25; // Retry up to 5 seconds.
91
92 constexpr const char kCarServiceInterface[] = "car_service";
93 constexpr const char kCarPowerPolicyServerInterface[] =
94 "android.frameworks.automotive.powerpolicy.ICarPowerPolicyServer/default";
95 constexpr const char kCarPowerPolicySystemNotificationInterface[] =
96 "android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification/"
97 "default";
98
lookupPowerPolicyChangeCallback(const std::vector<CallbackInfo> & callbacks,const AIBinder * binder)99 std::vector<CallbackInfo>::const_iterator lookupPowerPolicyChangeCallback(
100 const std::vector<CallbackInfo>& callbacks, const AIBinder* binder) {
101 for (auto it = callbacks.begin(); it != callbacks.end(); it++) {
102 if (it->binder.get() == binder) {
103 return it;
104 }
105 }
106 return callbacks.end();
107 }
108
checkSystemPermission()109 ScopedAStatus checkSystemPermission() {
110 if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) {
111 return ScopedAStatus::fromServiceSpecificErrorWithMessage(EX_SECURITY,
112 "Calling process does not have "
113 "proper privilege");
114 }
115 return ScopedAStatus::ok();
116 }
117
118 } // namespace
119
120 std::shared_ptr<CarPowerPolicyServer> CarPowerPolicyServer::sCarPowerPolicyServer = nullptr;
121
PropertyChangeListener(CarPowerPolicyServer * service)122 PropertyChangeListener::PropertyChangeListener(CarPowerPolicyServer* service) : mService(service) {}
123
onPropertyEvent(const std::vector<std::unique_ptr<IHalPropValue>> & values)124 void PropertyChangeListener::onPropertyEvent(
125 const std::vector<std::unique_ptr<IHalPropValue>>& values) {
126 for (const auto& value : values) {
127 const std::string stringValue = value->getStringValue();
128 int32_t propId = value->getPropId();
129 if (propId == static_cast<int32_t>(VehicleProperty::POWER_POLICY_GROUP_REQ)) {
130 const auto& ret = mService->setPowerPolicyGroup(stringValue);
131 if (!ret.ok()) {
132 ALOGW("Failed to set power policy group(%s): %s", stringValue.c_str(),
133 ret.error().message().c_str());
134 }
135 } else if (propId == static_cast<int32_t>(VehicleProperty::POWER_POLICY_REQ)) {
136 const auto& ret = mService->applyPowerPolicy(stringValue,
137 /*carServiceExpected=*/false,
138 /*force=*/false);
139 if (!ret.ok()) {
140 ALOGW("Failed to apply power policy(%s): %s", stringValue.c_str(),
141 ret.error().message().c_str());
142 }
143 }
144 }
145 }
146
onPropertySetError(const std::vector<HalPropError> & errors)147 void PropertyChangeListener::onPropertySetError(
148 [[maybe_unused]] const std::vector<HalPropError>& errors) {
149 return;
150 }
151
MessageHandlerImpl(CarPowerPolicyServer * service)152 MessageHandlerImpl::MessageHandlerImpl(CarPowerPolicyServer* service) : mService(service) {}
153
handleMessage(const Message & message)154 void MessageHandlerImpl::handleMessage(const Message& message) {
155 switch (message.what) {
156 case MSG_CONNECT_TO_VHAL:
157 mService->connectToVhalHelper();
158 break;
159 default:
160 ALOGW("Unknown message: %d", message.what);
161 }
162 }
163
CarServiceNotificationHandler(CarPowerPolicyServer * service)164 CarServiceNotificationHandler::CarServiceNotificationHandler(CarPowerPolicyServer* service) :
165 mService(service) {}
166
terminate()167 void CarServiceNotificationHandler::terminate() {
168 Mutex::Autolock lock(mMutex);
169 mService = nullptr;
170 }
171
dump(int fd,const char ** args,uint32_t numArgs)172 binder_status_t CarServiceNotificationHandler::dump(int fd, const char** args, uint32_t numArgs) {
173 Mutex::Autolock lock(mMutex);
174 if (mService == nullptr) {
175 ALOGD("Skip dumping, CarPowerPolicyServer is ending");
176 return STATUS_OK;
177 }
178 return mService->dump(fd, args, numArgs);
179 }
180
notifyCarServiceReady(PolicyState * policyState)181 ScopedAStatus CarServiceNotificationHandler::notifyCarServiceReady(PolicyState* policyState) {
182 Mutex::Autolock lock(mMutex);
183 if (mService == nullptr) {
184 ALOGD("Skip notifying CarServiceReady, CarPowerPolicyServer is ending");
185 return ScopedAStatus::ok();
186 }
187 return mService->notifyCarServiceReady(policyState);
188 }
189
notifyPowerPolicyChange(const std::string & policyId,bool force)190 ScopedAStatus CarServiceNotificationHandler::notifyPowerPolicyChange(const std::string& policyId,
191 bool force) {
192 Mutex::Autolock lock(mMutex);
193 if (mService == nullptr) {
194 ALOGD("Skip notifying PowerPolicyChange, CarPowerPolicyServer is ending");
195 return ScopedAStatus::ok();
196 }
197 return mService->notifyPowerPolicyChange(policyId, force);
198 }
199
notifyPowerPolicyDefinition(const std::string & policyId,const std::vector<std::string> & enabledComponents,const std::vector<std::string> & disabledComponents)200 ScopedAStatus CarServiceNotificationHandler::notifyPowerPolicyDefinition(
201 const std::string& policyId, const std::vector<std::string>& enabledComponents,
202 const std::vector<std::string>& disabledComponents) {
203 Mutex::Autolock lock(mMutex);
204 if (mService == nullptr) {
205 ALOGD("Skip notifying PowerPolicyDefinition, CarPowerPolicyServer is ending");
206 return ScopedAStatus::ok();
207 }
208 return mService->notifyPowerPolicyDefinition(policyId, enabledComponents, disabledComponents);
209 }
210
~ISilentModeChangeHandler()211 ISilentModeChangeHandler::~ISilentModeChangeHandler() {}
212
startService(const sp<Looper> & looper)213 Result<std::shared_ptr<CarPowerPolicyServer>> CarPowerPolicyServer::startService(
214 const sp<Looper>& looper) {
215 if (sCarPowerPolicyServer != nullptr) {
216 return Error(INVALID_OPERATION) << "Cannot start service more than once";
217 }
218 std::shared_ptr<CarPowerPolicyServer> server = SharedRefBase::make<CarPowerPolicyServer>();
219 const auto& ret = server->init(looper);
220 if (!ret.ok()) {
221 return Error(ret.error().code())
222 << "Failed to start car power policy server: " << ret.error();
223 }
224 sCarPowerPolicyServer = server;
225
226 return sCarPowerPolicyServer;
227 }
228
terminateService()229 void CarPowerPolicyServer::terminateService() {
230 if (sCarPowerPolicyServer != nullptr) {
231 sCarPowerPolicyServer->terminate();
232 sCarPowerPolicyServer = nullptr;
233 }
234 }
235
CarPowerPolicyServer()236 CarPowerPolicyServer::CarPowerPolicyServer() :
237 mSilentModeHandler(this),
238 mIsPowerPolicyLocked(false),
239 mIsCarServiceInOperation(false),
240 mIsFirstConnectionToVhal(true) {
241 mMessageHandler = new MessageHandlerImpl(this);
242 mDeathRecipient = ScopedAIBinder_DeathRecipient(
243 AIBinder_DeathRecipient_new(&CarPowerPolicyServer::onBinderDied));
244 mPropertyChangeListener = std::make_unique<PropertyChangeListener>(this);
245 mLinkUnlinkImpl = std::make_unique<AIBinderLinkUnlinkImpl>();
246 }
247
248 // For test-only.
setLinkUnlinkImpl(std::unique_ptr<CarPowerPolicyServer::LinkUnlinkImpl> impl)249 void CarPowerPolicyServer::setLinkUnlinkImpl(
250 std::unique_ptr<CarPowerPolicyServer::LinkUnlinkImpl> impl) {
251 mLinkUnlinkImpl = std::move(impl);
252 }
253
getCurrentPowerPolicy(CarPowerPolicy * aidlReturn)254 ScopedAStatus CarPowerPolicyServer::getCurrentPowerPolicy(CarPowerPolicy* aidlReturn) {
255 Mutex::Autolock lock(mMutex);
256 if (!isPowerPolicyAppliedLocked()) {
257 return ScopedAStatus::
258 fromServiceSpecificErrorWithMessage(EX_ILLEGAL_STATE,
259 "The current power policy is not set");
260 }
261 *aidlReturn = *mCurrentPowerPolicyMeta.powerPolicy;
262 return ScopedAStatus::ok();
263 }
264
getPowerComponentState(PowerComponent componentId,bool * aidlReturn)265 ScopedAStatus CarPowerPolicyServer::getPowerComponentState(PowerComponent componentId,
266 bool* aidlReturn) {
267 const auto& ret = mComponentHandler.getPowerComponentState(componentId);
268 if (!ret.ok()) {
269 std::string errorMsg = ret.error().message();
270 ALOGW("getPowerComponentState(%s) failed: %s", toString(componentId).c_str(),
271 errorMsg.c_str());
272 return ScopedAStatus::fromServiceSpecificErrorWithMessage(EX_ILLEGAL_ARGUMENT,
273 errorMsg.c_str());
274 }
275 *aidlReturn = *ret;
276 return ScopedAStatus::ok();
277 }
278
registerPowerPolicyChangeCallback(const std::shared_ptr<ICarPowerPolicyChangeCallback> & callback,const CarPowerPolicyFilter & filter)279 ScopedAStatus CarPowerPolicyServer::registerPowerPolicyChangeCallback(
280 const std::shared_ptr<ICarPowerPolicyChangeCallback>& callback,
281 const CarPowerPolicyFilter& filter) {
282 Mutex::Autolock lock(mMutex);
283 pid_t callingPid = IPCThreadState::self()->getCallingPid();
284 uid_t callingUid = IPCThreadState::self()->getCallingUid();
285 SpAIBinder binder = callback->asBinder();
286 AIBinder* clientId = binder.get();
287 if (isRegisteredLocked(clientId)) {
288 std::string errorStr = StringPrintf("The callback(pid: %d, uid: %d) is already registered.",
289 callingPid, callingUid);
290 const char* errorCause = errorStr.c_str();
291 ALOGW("Cannot register a callback: %s", errorCause);
292 return ScopedAStatus::fromServiceSpecificErrorWithMessage(EX_ILLEGAL_ARGUMENT, errorCause);
293 }
294
295 std::unique_ptr<OnBinderDiedContext> context = std::make_unique<OnBinderDiedContext>(
296 OnBinderDiedContext{.server = this, .clientId = clientId});
297 binder_status_t status = mLinkUnlinkImpl->linkToDeath(clientId, mDeathRecipient.get(),
298 static_cast<void*>(context.get()));
299 if (status != STATUS_OK) {
300 std::string errorStr = StringPrintf("The given callback(pid: %d, uid: %d) is dead",
301 callingPid, callingUid);
302 const char* errorCause = errorStr.c_str();
303 ALOGW("Cannot register a callback: %s", errorCause);
304 return ScopedAStatus::fromServiceSpecificErrorWithMessage(EX_ILLEGAL_STATE, errorCause);
305 }
306 // Insert into a map to keep the context object alive.
307 mOnBinderDiedContexts[clientId] = std::move(context);
308 mPolicyChangeCallbacks.emplace_back(binder, filter, callingPid);
309
310 if (DEBUG) {
311 ALOGD("Power policy change callback(pid: %d, filter: %s) is registered", callingPid,
312 toString(filter.components).c_str());
313 }
314 return ScopedAStatus::ok();
315 }
316
unregisterPowerPolicyChangeCallback(const std::shared_ptr<ICarPowerPolicyChangeCallback> & callback)317 ScopedAStatus CarPowerPolicyServer::unregisterPowerPolicyChangeCallback(
318 const std::shared_ptr<ICarPowerPolicyChangeCallback>& callback) {
319 Mutex::Autolock lock(mMutex);
320 pid_t callingPid = IPCThreadState::self()->getCallingPid();
321 uid_t callingUid = IPCThreadState::self()->getCallingUid();
322 AIBinder* clientId = callback->asBinder().get();
323 auto it = lookupPowerPolicyChangeCallback(mPolicyChangeCallbacks, clientId);
324 if (it == mPolicyChangeCallbacks.end()) {
325 std::string errorStr =
326 StringPrintf("The callback(pid: %d, uid: %d) has not been registered", callingPid,
327 callingUid);
328 const char* errorCause = errorStr.c_str();
329 ALOGW("Cannot unregister a callback: %s", errorCause);
330 return ScopedAStatus::fromServiceSpecificErrorWithMessage(EX_ILLEGAL_ARGUMENT, errorCause);
331 }
332 if (mOnBinderDiedContexts.find(clientId) != mOnBinderDiedContexts.end()) {
333 // We don't set a callback for unlinkToDeath but need to call unlinkToDeath to clean up the
334 // registered death recipient.
335 mLinkUnlinkImpl->unlinkToDeath(clientId, mDeathRecipient.get(),
336 static_cast<void*>(mOnBinderDiedContexts[clientId].get()));
337 mOnBinderDiedContexts.erase(clientId);
338 }
339 mPolicyChangeCallbacks.erase(it);
340 if (DEBUG) {
341 ALOGD("Power policy change callback(pid: %d, uid: %d) is unregistered", callingPid,
342 callingUid);
343 }
344 return ScopedAStatus::ok();
345 }
346
notifyCarServiceReady(PolicyState * policyState)347 ScopedAStatus CarPowerPolicyServer::notifyCarServiceReady(PolicyState* policyState) {
348 ScopedAStatus status = checkSystemPermission();
349 if (!status.isOk()) {
350 return status;
351 }
352 mSilentModeHandler.stopMonitoringSilentModeHwState(/*shouldWaitThread=*/false);
353 Mutex::Autolock lock(mMutex);
354 policyState->policyId =
355 isPowerPolicyAppliedLocked() ? mCurrentPowerPolicyMeta.powerPolicy->policyId : "";
356 policyState->policyGroupId = mCurrentPolicyGroupId;
357 mIsCarServiceInOperation = true;
358 ALOGI("CarService is now responsible for power policy management");
359 return ScopedAStatus::ok();
360 }
361
notifyPowerPolicyChange(const std::string & policyId,bool force)362 ScopedAStatus CarPowerPolicyServer::notifyPowerPolicyChange(const std::string& policyId,
363 bool force) {
364 ScopedAStatus status = checkSystemPermission();
365 if (!status.isOk()) {
366 return status;
367 }
368 const auto& ret = applyPowerPolicy(policyId, /*carServiceExpected=*/true, force);
369 if (!ret.ok()) {
370 return ScopedAStatus::
371 fromServiceSpecificErrorWithMessage(EX_ILLEGAL_STATE,
372 StringPrintf("Failed to notify power policy "
373 "change: %s",
374 ret.error().message().c_str())
375 .c_str());
376 }
377 ALOGD("Policy change(%s) is notified by CarService", policyId.c_str());
378 return ScopedAStatus::ok();
379 }
380
notifyPowerPolicyDefinition(const std::string & policyId,const std::vector<std::string> & enabledComponents,const std::vector<std::string> & disabledComponents)381 ScopedAStatus CarPowerPolicyServer::notifyPowerPolicyDefinition(
382 const std::string& policyId, const std::vector<std::string>& enabledComponents,
383 const std::vector<std::string>& disabledComponents) {
384 ScopedAStatus status = checkSystemPermission();
385 if (!status.isOk()) {
386 return status;
387 }
388 const auto& ret =
389 mPolicyManager.definePowerPolicy(policyId, enabledComponents, disabledComponents);
390 if (!ret.ok()) {
391 return ScopedAStatus::
392 fromServiceSpecificErrorWithMessage(EX_ILLEGAL_ARGUMENT,
393 StringPrintf("Failed to notify power policy "
394 "definition: %s",
395 ret.error().message().c_str())
396 .c_str());
397 }
398 return ScopedAStatus::ok();
399 }
400
dump(int fd,const char ** args,uint32_t numArgs)401 status_t CarPowerPolicyServer::dump(int fd, const char** args, uint32_t numArgs) {
402 Vector<String16> argsV;
403 for (size_t i = 0; i < numArgs; i++) {
404 argsV.push(String16(args[i]));
405 }
406
407 {
408 Mutex::Autolock lock(mMutex);
409 const char* indent = " ";
410 const char* doubleIndent = " ";
411 WriteStringToFd("CAR POWER POLICY DAEMON\n", fd);
412 WriteStringToFd(StringPrintf("%sCarService is in operation: %s\n", indent,
413 mIsCarServiceInOperation ? "true" : "false"),
414 fd);
415 WriteStringToFd(StringPrintf("%sConnection to VHAL: %s\n", indent,
416 mVhalService.get() ? "connected" : "disconnected"),
417 fd);
418 WriteStringToFd(StringPrintf("%sCurrent power policy: %s\n", indent,
419 isPowerPolicyAppliedLocked()
420 ? mCurrentPowerPolicyMeta.powerPolicy->policyId.c_str()
421 : "not set"),
422 fd);
423 WriteStringToFd(StringPrintf("%sLast uptime of applying power policy: %" PRId64 "ms\n",
424 indent, mLastApplyPowerPolicyUptimeMs.value_or(-1)),
425 fd);
426 WriteStringToFd(StringPrintf("%sPending power policy ID: %s\n", indent,
427 mPendingPowerPolicyId.c_str()),
428 fd);
429 WriteStringToFd(StringPrintf("%sCurrent power policy group ID: %s\n", indent,
430 mCurrentPolicyGroupId.empty() ? "not set"
431 : mCurrentPolicyGroupId.c_str()),
432 fd);
433 WriteStringToFd(StringPrintf("%sLast uptime of setting default power policy group: "
434 "%" PRId64 "ms\n",
435 indent, mLastSetDefaultPowerPolicyGroupUptimeMs.value_or(-1)),
436 fd);
437 WriteStringToFd(StringPrintf("%sPolicy change callbacks:%s\n", indent,
438 mPolicyChangeCallbacks.size() ? "" : " none"),
439 fd);
440 for (auto& callback : mPolicyChangeCallbacks) {
441 WriteStringToFd(StringPrintf("%s- %s\n", doubleIndent,
442 callbackToString(callback).c_str()),
443 fd);
444 }
445 }
446 if (const auto& ret = mPolicyManager.dump(fd, argsV); !ret.ok()) {
447 ALOGW("Failed to dump power policy handler: %s", ret.error().message().c_str());
448 return ret.error().code();
449 }
450 if (const auto& ret = mComponentHandler.dump(fd); !ret.ok()) {
451 ALOGW("Failed to dump power component handler: %s", ret.error().message().c_str());
452 return ret.error().code();
453 }
454 if (const auto& ret = mSilentModeHandler.dump(fd, argsV); !ret.ok()) {
455 ALOGW("Failed to dump Silent Mode handler: %s", ret.error().message().c_str());
456 return ret.error().code();
457 }
458 return OK;
459 }
460
init(const sp<Looper> & looper)461 Result<void> CarPowerPolicyServer::init(const sp<Looper>& looper) {
462 AIBinder* binderCarService = AServiceManager_checkService(kCarServiceInterface);
463
464 Mutex::Autolock lock(mMutex);
465 // Before initializing power policy daemon, we need to update mIsCarServiceInOperation
466 // according to whether CPMS is running.
467 mIsCarServiceInOperation = binderCarService != nullptr;
468
469 mHandlerLooper = looper;
470 mPolicyManager.init();
471 mComponentHandler.init();
472 mSilentModeHandler.init();
473 mCarServiceNotificationHandler = SharedRefBase::make<CarServiceNotificationHandler>(this);
474
475 binder_exception_t err =
476 AServiceManager_addService(this->asBinder().get(), kCarPowerPolicyServerInterface);
477 if (err != EX_NONE) {
478 return Error(err) << "Failed to add carpowerpolicyd to ServiceManager";
479 }
480 err = AServiceManager_addService(mCarServiceNotificationHandler->asBinder().get(),
481 kCarPowerPolicySystemNotificationInterface);
482 if (err != EX_NONE) {
483 return Error(err) << "Failed to add car power policy system notification to ServiceManager";
484 }
485
486 connectToVhal();
487 return {};
488 }
489
terminate()490 void CarPowerPolicyServer::terminate() {
491 Mutex::Autolock lock(mMutex);
492 mPolicyChangeCallbacks.clear();
493 if (mVhalService != nullptr) {
494 mSubscriptionClient->unsubscribe(
495 {static_cast<int32_t>(VehicleProperty::POWER_POLICY_REQ),
496 static_cast<int32_t>(VehicleProperty::POWER_POLICY_GROUP_REQ)});
497 }
498
499 if (mCarServiceNotificationHandler != nullptr) {
500 mCarServiceNotificationHandler->terminate();
501 mCarServiceNotificationHandler = nullptr;
502 }
503
504 // Delete the deathRecipient so that all binders would be unlinked.
505 mDeathRecipient = ScopedAIBinder_DeathRecipient();
506 mSilentModeHandler.release();
507 // Remove the messages so that mMessageHandler would no longer be used.
508 mHandlerLooper->removeMessages(mMessageHandler);
509 }
510
onBinderDied(void * cookie)511 void CarPowerPolicyServer::onBinderDied(void* cookie) {
512 OnBinderDiedContext* context = reinterpret_cast<OnBinderDiedContext*>(cookie);
513 context->server->handleBinderDeath(context->clientId);
514 }
515
handleBinderDeath(const AIBinder * clientId)516 void CarPowerPolicyServer::handleBinderDeath(const AIBinder* clientId) {
517 Mutex::Autolock lock(mMutex);
518 auto it = lookupPowerPolicyChangeCallback(mPolicyChangeCallbacks, clientId);
519 if (it != mPolicyChangeCallbacks.end()) {
520 ALOGW("Power policy callback(pid: %d) died", it->pid);
521 mPolicyChangeCallbacks.erase(it);
522 }
523 mOnBinderDiedContexts.erase(clientId);
524 }
525
handleVhalDeath()526 void CarPowerPolicyServer::handleVhalDeath() {
527 {
528 Mutex::Autolock lock(mMutex);
529 ALOGW("VHAL has died.");
530 mVhalService = nullptr;
531 }
532 connectToVhal();
533 }
534
applyPowerPolicy(const std::string & policyId,const bool carServiceInOperation,const bool force)535 Result<void> CarPowerPolicyServer::applyPowerPolicy(const std::string& policyId,
536 const bool carServiceInOperation,
537 const bool force) {
538 auto policyMeta = mPolicyManager.getPowerPolicy(policyId);
539 if (!policyMeta.ok()) {
540 return Error() << "Failed to apply power policy: " << policyMeta.error().message();
541 }
542
543 std::vector<CallbackInfo> clients;
544 if (Mutex::Autolock lock(mMutex); mIsCarServiceInOperation != carServiceInOperation) {
545 return Error() << (mIsCarServiceInOperation
546 ? "After CarService starts serving, power policy cannot be "
547 "managed in car power policy daemon"
548 : "Before CarService starts serving, power policy cannot be "
549 "applied from CarService");
550 } else {
551 if (mVhalService == nullptr) {
552 ALOGI("%s is queued and will be applied after VHAL gets ready", policyId.c_str());
553 mPendingPowerPolicyId = policyId;
554 return {};
555 }
556 bool isPolicyApplied = isPowerPolicyAppliedLocked();
557 if (isPolicyApplied && mCurrentPowerPolicyMeta.powerPolicy->policyId == policyId) {
558 ALOGI("Applying policy skipped: the given policy(ID: %s) is the current policy",
559 policyId.c_str());
560 return {};
561 }
562 if (policyMeta->isPreemptive) {
563 if (isPolicyApplied && !mCurrentPowerPolicyMeta.isPreemptive) {
564 mPendingPowerPolicyId = mCurrentPowerPolicyMeta.powerPolicy->policyId;
565 }
566 mIsPowerPolicyLocked = true;
567 } else {
568 if (force) {
569 mPendingPowerPolicyId.clear();
570 mIsPowerPolicyLocked = false;
571 } else if (mIsPowerPolicyLocked) {
572 ALOGI("%s is queued and will be applied after power policy get unlocked",
573 policyId.c_str());
574 mPendingPowerPolicyId = policyId;
575 return {};
576 }
577 }
578 mCurrentPowerPolicyMeta = *policyMeta;
579 clients = mPolicyChangeCallbacks;
580 mLastApplyPowerPolicyUptimeMs = uptimeMillis();
581 }
582 CarPowerPolicyPtr policy = policyMeta->powerPolicy;
583 mComponentHandler.applyPowerPolicy(policy);
584 if (const auto& ret = notifyVhalNewPowerPolicy(policyId); !ret.ok()) {
585 ALOGW("Failed to tell VHAL the new power policy(%s): %s", policyId.c_str(),
586 ret.error().message().c_str());
587 }
588 for (auto client : clients) {
589 ICarPowerPolicyChangeCallback::fromBinder(client.binder)->onPolicyChanged(*policy);
590 }
591 ALOGI("The current power policy is %s", policyId.c_str());
592 return {};
593 }
594
setPowerPolicyGroup(const std::string & groupId)595 Result<void> CarPowerPolicyServer::setPowerPolicyGroup(const std::string& groupId) {
596 if (!mPolicyManager.isPowerPolicyGroupAvailable(groupId)) {
597 return Error() << StringPrintf("Power policy group(%s) is not available", groupId.c_str());
598 }
599 Mutex::Autolock lock(mMutex);
600 if (mIsCarServiceInOperation) {
601 return Error() << "After CarService starts serving, power policy group cannot be set in "
602 "car power policy daemon";
603 }
604 mCurrentPolicyGroupId = groupId;
605 ALOGI("The current power policy group is |%s|", groupId.c_str());
606 return {};
607 }
608
notifySilentModeChange(const bool isSilent)609 void CarPowerPolicyServer::notifySilentModeChange(const bool isSilent) {
610 std::string pendingPowerPolicyId;
611 if (Mutex::Autolock lock(mMutex); mIsCarServiceInOperation) {
612 return;
613 } else {
614 pendingPowerPolicyId = mPendingPowerPolicyId;
615 }
616 ALOGI("Silent Mode is set to %s", isSilent ? "silent" : "non-silent");
617 Result<void> ret;
618 if (isSilent) {
619 ret = applyPowerPolicy(kSystemPolicyIdNoUserInteraction,
620 /*carServiceExpected=*/false, /*force=*/false);
621 } else {
622 ret = applyPowerPolicy(pendingPowerPolicyId,
623 /*carServiceExpected=*/false, /*force=*/true);
624 }
625 if (!ret.ok()) {
626 ALOGW("Failed to apply power policy: %s", ret.error().message().c_str());
627 }
628 }
629
isRegisteredLocked(const AIBinder * binder)630 bool CarPowerPolicyServer::isRegisteredLocked(const AIBinder* binder) {
631 return lookupPowerPolicyChangeCallback(mPolicyChangeCallbacks, binder) !=
632 mPolicyChangeCallbacks.end();
633 }
634
635 // This method ensures that the attempt to connect to VHAL occurs in the main thread.
connectToVhal()636 void CarPowerPolicyServer::connectToVhal() {
637 mRemainingConnectionRetryCount = kMaxConnectionRetry;
638 mHandlerLooper->sendMessage(mMessageHandler, MSG_CONNECT_TO_VHAL);
639 }
640
641 // connectToVhalHelper is always executed in the main thread.
connectToVhalHelper()642 void CarPowerPolicyServer::connectToVhalHelper() {
643 {
644 Mutex::Autolock lock(mMutex);
645 if (mVhalService != nullptr) {
646 return;
647 }
648 }
649 std::shared_ptr<IVhalClient> vhalService = IVhalClient::tryCreate();
650 if (vhalService == nullptr) {
651 ALOGW("Failed to connect to VHAL. Retrying in %" PRId64 " ms.",
652 nanoseconds_to_milliseconds(kConnectionRetryIntervalNs));
653 mRemainingConnectionRetryCount--;
654 if (mRemainingConnectionRetryCount <= 0) {
655 ALOGE("Failed to connect to VHAL after %d attempt%s. Gave up.", kMaxConnectionRetry,
656 kMaxConnectionRetry > 1 ? "s" : "");
657 return;
658 }
659 mHandlerLooper->sendMessageDelayed(kConnectionRetryIntervalNs, mMessageHandler,
660 MSG_CONNECT_TO_VHAL);
661 return;
662 }
663 vhalService->addOnBinderDiedCallback(
664 std::make_shared<IVhalClient::OnBinderDiedCallbackFunc>([this] { handleVhalDeath(); }));
665 std::string currentPolicyId;
666 {
667 Mutex::Autolock lock(mMutex);
668 mVhalService = vhalService;
669 mSubscriptionClient = mVhalService->getSubscriptionClient(mPropertyChangeListener);
670 if (isPowerPolicyAppliedLocked()) {
671 currentPolicyId = mCurrentPowerPolicyMeta.powerPolicy->policyId;
672 }
673 }
674 /*
675 * When VHAL is first executed, a normal power management goes on. When VHAL is restarted due to
676 * some reasons, the current policy is notified to VHAL.
677 */
678 if (mIsFirstConnectionToVhal) {
679 applyInitialPowerPolicy();
680 mIsFirstConnectionToVhal = false;
681 } else if (!currentPolicyId.empty()) {
682 notifyVhalNewPowerPolicy(currentPolicyId);
683 }
684 subscribeToVhal();
685 ALOGI("Connected to VHAL");
686 return;
687 }
688
applyInitialPowerPolicy()689 void CarPowerPolicyServer::applyInitialPowerPolicy() {
690 std::string policyId;
691 std::string currentPolicyGroupId;
692 CarPowerPolicyPtr powerPolicy;
693 {
694 Mutex::Autolock lock(mMutex);
695 if (mIsCarServiceInOperation) {
696 ALOGI("Skipping initial power policy application because CarService is running");
697 return;
698 }
699 policyId = mPendingPowerPolicyId;
700 currentPolicyGroupId = mCurrentPolicyGroupId;
701 }
702 if (policyId.empty()) {
703 if (auto policy = mPolicyManager.getDefaultPowerPolicyForState(currentPolicyGroupId,
704 VehicleApPowerStateReport::
705 WAIT_FOR_VHAL);
706 policy.ok()) {
707 policyId = (*policy)->policyId;
708 } else {
709 policyId = kSystemPolicyIdInitialOn;
710 }
711 }
712 if (const auto& ret = applyPowerPolicy(policyId, /*carServiceExpected=*/false, /*force=*/false);
713 !ret.ok()) {
714 ALOGW("Cannot apply the initial power policy(%s): %s", policyId.c_str(),
715 ret.error().message().c_str());
716 return;
717 }
718 ALOGD("Policy(%s) is applied as the initial one", policyId.c_str());
719 }
720
subscribeToVhal()721 void CarPowerPolicyServer::subscribeToVhal() {
722 subscribeToProperty(static_cast<int32_t>(VehicleProperty::POWER_POLICY_REQ),
723 [this](const IHalPropValue& value) {
724 std::string stringValue = value.getStringValue();
725 if (stringValue.size() > 0) {
726 const auto& ret = applyPowerPolicy(stringValue,
727 /*carServiceExpected=*/false,
728 /*force=*/false);
729 if (!ret.ok()) {
730 ALOGW("Failed to apply power policy(%s): %s",
731 stringValue.c_str(), ret.error().message().c_str());
732 }
733 }
734 });
735 subscribeToProperty(static_cast<int32_t>(VehicleProperty::POWER_POLICY_GROUP_REQ),
736 [this](const IHalPropValue& value) {
737 std::string stringValue = value.getStringValue();
738 if (stringValue.size() > 0) {
739 const auto& ret = setPowerPolicyGroup(stringValue);
740 if (ret.ok()) {
741 Mutex::Autolock lock(mMutex);
742 mLastSetDefaultPowerPolicyGroupUptimeMs = value.getTimestamp();
743 } else {
744 ALOGW("Failed to set power policy group(%s): %s",
745 stringValue.c_str(), ret.error().message().c_str());
746 }
747 }
748 });
749 }
750
subscribeToProperty(int32_t prop,std::function<void (const IHalPropValue &)> processor)751 void CarPowerPolicyServer::subscribeToProperty(
752 int32_t prop, std::function<void(const IHalPropValue&)> processor) {
753 if (!isPropertySupported(prop)) {
754 ALOGW("Vehicle property(%d) is not supported by VHAL.", prop);
755 return;
756 }
757 std::shared_ptr<IVhalClient> vhalService;
758 {
759 Mutex::Autolock lock(mMutex);
760 if (mVhalService == nullptr) {
761 ALOGW("Failed to subscribe to property(%d): VHAL is not ready", prop);
762 return;
763 }
764 vhalService = mVhalService;
765 }
766
767 VhalResult<std::unique_ptr<IHalPropValue>> result =
768 vhalService->getValueSync(*vhalService->createHalPropValue(prop));
769
770 if (!result.ok()) {
771 ALOGW("Failed to get vehicle property(%d) value, error: %s.", prop,
772 result.error().message().c_str());
773 return;
774 }
775 processor(*result.value());
776 std::vector<SubscribeOptions> options = {
777 {.propId = prop, .areaIds = {}},
778 };
779
780 if (auto result = mSubscriptionClient->subscribe(options); !result.ok()) {
781 ALOGW("Failed to subscribe to vehicle property(%d), error: %s", prop,
782 result.error().message().c_str());
783 }
784 }
785
notifyVhalNewPowerPolicy(const std::string & policyId)786 Result<void> CarPowerPolicyServer::notifyVhalNewPowerPolicy(const std::string& policyId) {
787 int32_t prop = static_cast<int32_t>(VehicleProperty::CURRENT_POWER_POLICY);
788 if (!isPropertySupported(prop)) {
789 return Error() << StringPrintf("Vehicle property(%d) is not supported by VHAL.", prop);
790 }
791 std::shared_ptr<IVhalClient> vhalService;
792 {
793 Mutex::Autolock lock(mMutex);
794 if (mVhalService == nullptr) {
795 return Error() << "VHAL is not ready";
796 }
797 vhalService = mVhalService;
798 }
799 std::unique_ptr<IHalPropValue> propValue = vhalService->createHalPropValue(prop);
800 propValue->setStringValue(policyId);
801
802 VhalResult<void> result = vhalService->setValueSync(*propValue);
803 if (!result.ok()) {
804 return Error() << "Failed to set CURRENT_POWER_POLICY property";
805 }
806 ALOGD("Policy(%s) is notified to VHAL", policyId.c_str());
807 return {};
808 }
809
isPropertySupported(const int32_t prop)810 bool CarPowerPolicyServer::isPropertySupported(const int32_t prop) {
811 if (mSupportedProperties.count(prop) > 0) {
812 return mSupportedProperties[prop];
813 }
814 StatusCode status;
815 hidl_vec<int32_t> props = {prop};
816 std::shared_ptr<IVhalClient> vhalService;
817 {
818 Mutex::Autolock lock(mMutex);
819 if (mVhalService == nullptr) {
820 ALOGW("Failed to check if property(%d) is supported: VHAL is not ready", prop);
821 return false;
822 }
823 vhalService = mVhalService;
824 }
825 auto result = vhalService->getPropConfigs(props);
826 mSupportedProperties[prop] = result.ok();
827 return mSupportedProperties[prop];
828 }
829
isPowerPolicyAppliedLocked() const830 bool CarPowerPolicyServer::isPowerPolicyAppliedLocked() const {
831 return mCurrentPowerPolicyMeta.powerPolicy != nullptr;
832 }
833
callbackToString(const CallbackInfo & callback)834 std::string CarPowerPolicyServer::callbackToString(const CallbackInfo& callback) {
835 const std::vector<PowerComponent>& components = callback.filter.components;
836 return StringPrintf("callback(pid %d, filter: %s)", callback.pid, toString(components).c_str());
837 }
838
getPolicyChangeCallbacks()839 std::vector<CallbackInfo> CarPowerPolicyServer::getPolicyChangeCallbacks() {
840 Mutex::Autolock lock(mMutex);
841 return mPolicyChangeCallbacks;
842 }
843
countOnBinderDiedContexts()844 size_t CarPowerPolicyServer::countOnBinderDiedContexts() {
845 Mutex::Autolock lock(mMutex);
846 return mOnBinderDiedContexts.size();
847 }
848
linkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)849 binder_status_t CarPowerPolicyServer::AIBinderLinkUnlinkImpl::linkToDeath(
850 AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
851 return AIBinder_linkToDeath(binder, recipient, cookie);
852 }
853
unlinkToDeath(AIBinder * binder,AIBinder_DeathRecipient * recipient,void * cookie)854 binder_status_t CarPowerPolicyServer::AIBinderLinkUnlinkImpl::unlinkToDeath(
855 AIBinder* binder, AIBinder_DeathRecipient* recipient, void* cookie) {
856 return AIBinder_unlinkToDeath(binder, recipient, cookie);
857 }
858
859 } // namespace powerpolicy
860 } // namespace automotive
861 } // namespace frameworks
862 } // namespace android
863