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