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