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 /*overridePreemptive=*/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)182 Status CarServiceNotificationHandler::notifyPowerPolicyChange(const std::string& policyId) {
183 return mService->notifyPowerPolicyChange(policyId);
184 }
185
notifyPowerPolicyDefinition(const std::string & policyId,const std::vector<std::string> & enabledComponents,const std::vector<std::string> & disabledComponents)186 Status CarServiceNotificationHandler::notifyPowerPolicyDefinition(
187 const std::string& policyId, const std::vector<std::string>& enabledComponents,
188 const std::vector<std::string>& disabledComponents) {
189 return mService->notifyPowerPolicyDefinition(policyId, enabledComponents, disabledComponents);
190 }
191
~ISilentModeChangeHandler()192 ISilentModeChangeHandler::~ISilentModeChangeHandler() {}
193
startService(const sp<Looper> & looper)194 Result<sp<CarPowerPolicyServer>> CarPowerPolicyServer::startService(const sp<Looper>& looper) {
195 if (sCarPowerPolicyServer != nullptr) {
196 return Error(INVALID_OPERATION) << "Cannot start service more than once";
197 }
198 sp<CarPowerPolicyServer> server = new CarPowerPolicyServer();
199 const auto& ret = server->init(looper);
200 if (!ret.ok()) {
201 return Error(ret.error().code())
202 << "Failed to start car power policy server: " << ret.error();
203 }
204 sCarPowerPolicyServer = server;
205
206 return sCarPowerPolicyServer;
207 }
208
terminateService()209 void CarPowerPolicyServer::terminateService() {
210 if (sCarPowerPolicyServer != nullptr) {
211 sCarPowerPolicyServer->terminate();
212 sCarPowerPolicyServer = nullptr;
213 }
214 }
215
CarPowerPolicyServer()216 CarPowerPolicyServer::CarPowerPolicyServer() :
217 mSilentModeHandler(this),
218 mIsPowerPolicyLocked(false),
219 mIsCarServiceInOperation(false),
220 mIsFirstConnectionToVhal(false) {
221 mMessageHandler = new MessageHandlerImpl(this);
222 mBinderDeathRecipient = new BinderDeathRecipient(this);
223 mHidlDeathRecipient = new HidlDeathRecipient(this);
224 mPropertyChangeListener = new PropertyChangeListener(this);
225 mCarServiceNotificationHandler = new CarServiceNotificationHandler(this);
226 }
227
getCurrentPowerPolicy(CarPowerPolicy * aidlReturn)228 Status CarPowerPolicyServer::getCurrentPowerPolicy(CarPowerPolicy* aidlReturn) {
229 Mutex::Autolock lock(mMutex);
230 if (!isPowerPolicyAppliedLocked()) {
231 return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE,
232 "The current power policy is not set");
233 }
234 *aidlReturn = *mCurrentPowerPolicyMeta.powerPolicy;
235 return Status::ok();
236 }
237
getPowerComponentState(PowerComponent componentId,bool * aidlReturn)238 Status CarPowerPolicyServer::getPowerComponentState(PowerComponent componentId, bool* aidlReturn) {
239 const auto& ret = mComponentHandler.getPowerComponentState(componentId);
240 if (!ret.ok()) {
241 std::string errorMsg = ret.error().message();
242 ALOGW("getPowerComponentState(%s) failed: %s", toString(componentId).c_str(),
243 errorMsg.c_str());
244 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, errorMsg.c_str());
245 }
246 *aidlReturn = *ret;
247 return Status::ok();
248 }
249
registerPowerPolicyChangeCallback(const sp<ICarPowerPolicyChangeCallback> & callback,const CarPowerPolicyFilter & filter)250 Status CarPowerPolicyServer::registerPowerPolicyChangeCallback(
251 const sp<ICarPowerPolicyChangeCallback>& callback, const CarPowerPolicyFilter& filter) {
252 Mutex::Autolock lock(mMutex);
253 pid_t callingPid = IPCThreadState::self()->getCallingPid();
254 uid_t callingUid = IPCThreadState::self()->getCallingUid();
255 if (isRegisteredLocked(callback)) {
256 std::string errorStr = StringPrintf("The callback(pid: %d, uid: %d) is already registered.",
257 callingPid, callingUid);
258 const char* errorCause = errorStr.c_str();
259 ALOGW("Cannot register a callback: %s", errorCause);
260 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, errorCause);
261 }
262 sp<IBinder> binder = BnCarPowerPolicyChangeCallback::asBinder(callback);
263 status_t status = binder->linkToDeath(mBinderDeathRecipient);
264 if (status != OK) {
265 std::string errorStr = StringPrintf("The given callback(pid: %d, uid: %d) is dead",
266 callingPid, callingUid);
267 const char* errorCause = errorStr.c_str();
268 ALOGW("Cannot register a callback: %s", errorCause);
269 return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, errorCause);
270 }
271 mPolicyChangeCallbacks.emplace_back(callback, filter, callingPid);
272
273 if (DEBUG) {
274 ALOGD("Power policy change callback(pid: %d, filter: %s) is registered", callingPid,
275 toString(filter.components).c_str());
276 }
277 return Status::ok();
278 }
279
unregisterPowerPolicyChangeCallback(const sp<ICarPowerPolicyChangeCallback> & callback)280 Status CarPowerPolicyServer::unregisterPowerPolicyChangeCallback(
281 const sp<ICarPowerPolicyChangeCallback>& callback) {
282 Mutex::Autolock lock(mMutex);
283 pid_t callingPid = IPCThreadState::self()->getCallingPid();
284 uid_t callingUid = IPCThreadState::self()->getCallingUid();
285 sp<IBinder> binder = BnCarPowerPolicyChangeCallback::asBinder(callback);
286 auto it = lookupPowerPolicyChangeCallback(mPolicyChangeCallbacks, binder);
287 if (it == mPolicyChangeCallbacks.end()) {
288 std::string errorStr =
289 StringPrintf("The callback(pid: %d, uid: %d) has not been registered", callingPid,
290 callingUid);
291 const char* errorCause = errorStr.c_str();
292 ALOGW("Cannot unregister a callback: %s", errorCause);
293 return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, errorCause);
294 }
295 binder->unlinkToDeath(mBinderDeathRecipient);
296 mPolicyChangeCallbacks.erase(it);
297 if (DEBUG) {
298 ALOGD("Power policy change callback(pid: %d, uid: %d) is unregistered", callingPid,
299 callingUid);
300 }
301 return Status::ok();
302 }
303
notifyCarServiceReady(PolicyState * policyState)304 Status CarPowerPolicyServer::notifyCarServiceReady(PolicyState* policyState) {
305 Status status = checkSystemPermission();
306 if (!status.isOk()) {
307 return status;
308 }
309 mSilentModeHandler.stopMonitoringSilentModeHwState(/*shouldWaitThread=*/false);
310 Mutex::Autolock lock(mMutex);
311 policyState->policyId =
312 isPowerPolicyAppliedLocked() ? mCurrentPowerPolicyMeta.powerPolicy->policyId : "";
313 policyState->policyGroupId = mCurrentPolicyGroupId;
314 mIsCarServiceInOperation = true;
315 ALOGI("CarService is now responsible for power policy management");
316 return Status::ok();
317 }
318
notifyPowerPolicyChange(const std::string & policyId)319 Status CarPowerPolicyServer::notifyPowerPolicyChange(const std::string& policyId) {
320 Status status = checkSystemPermission();
321 if (!status.isOk()) {
322 return status;
323 }
324 const auto& ret =
325 applyPowerPolicy(policyId, /*carServiceExpected=*/true, /*overridePreemptive=*/false);
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(%s) is applied at 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 overridePreemptive)477 Result<void> CarPowerPolicyServer::applyPowerPolicy(const std::string& policyId,
478 const bool carServiceInOperation,
479 const bool overridePreemptive) {
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 (overridePreemptive) {
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, /*overridePreemptive=*/false);
563 } else {
564 ret = applyPowerPolicy(pendingPowerPolicyId,
565 /*carServiceExpected=*/false, /*overridePreemptive=*/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,
659 /*overridePreemptive=*/false);
660 !ret.ok()) {
661 ALOGW("Cannot apply the initial power policy(%s): %s", policyId.c_str(),
662 ret.error().message().c_str());
663 }
664 ALOGD("Policy(%s) is applied as the initial one", policyId.c_str());
665 }
666
subscribeToVhal()667 void CarPowerPolicyServer::subscribeToVhal() {
668 subscribeToProperty(static_cast<int32_t>(VehicleProperty::POWER_POLICY_REQ),
669 [this](const VehiclePropValue& value) {
670 if (value.value.stringValue.size() > 0) {
671 const auto& ret = applyPowerPolicy(value.value.stringValue,
672 /*carServiceExpected=*/false,
673 /*overridePreemptive=*/false);
674 if (!ret.ok()) {
675 ALOGW("Failed to apply power policy(%s): %s",
676 value.value.stringValue.c_str(),
677 ret.error().message().c_str());
678 }
679 }
680 });
681 subscribeToProperty(static_cast<int32_t>(VehicleProperty::POWER_POLICY_GROUP_REQ),
682 [this](const VehiclePropValue& value) {
683 if (value.value.stringValue.size() > 0) {
684 const auto& ret = setPowerPolicyGroup(value.value.stringValue);
685 if (ret.ok()) {
686 Mutex::Autolock lock(mMutex);
687 mLastSetDefaultPowerPolicyGroupUptimeMs = value.timestamp;
688 } else {
689 ALOGW("Failed to set power policy group(%s): %s",
690 value.value.stringValue.c_str(),
691 ret.error().message().c_str());
692 }
693 }
694 });
695 }
696
subscribeToProperty(int32_t prop,std::function<void (const VehiclePropValue &)> processor)697 void CarPowerPolicyServer::subscribeToProperty(
698 int32_t prop, std::function<void(const VehiclePropValue&)> processor) {
699 if (!isPropertySupported(prop)) {
700 ALOGW("Vehicle property(%d) is not supported by VHAL.", prop);
701 return;
702 }
703 VehiclePropValue propValue{
704 .prop = prop,
705 };
706 sp<IVehicle> vhalService;
707 {
708 Mutex::Autolock lock(mMutex);
709 if (mVhalService == nullptr) {
710 ALOGW("Failed to subscribe to property(%d): VHAL is not ready", prop);
711 return;
712 }
713 vhalService = mVhalService;
714 }
715 StatusCode status;
716 vhalService->get(propValue, [&status, &propValue](StatusCode s, const VehiclePropValue& value) {
717 status = s;
718 propValue = value;
719 });
720 if (status != StatusCode::OK) {
721 ALOGW("Failed to get vehicle property(%d) value.", prop);
722 return;
723 }
724 processor(propValue);
725 SubscribeOptions reqVhalProperties[] = {
726 {.propId = prop, .flags = SubscribeFlags::EVENTS_FROM_CAR},
727 };
728 hidl_vec<SubscribeOptions> options;
729 options.setToExternal(reqVhalProperties, arraysize(reqVhalProperties));
730 status = vhalService->subscribe(mPropertyChangeListener, options);
731 if (status != StatusCode::OK) {
732 ALOGW("Failed to subscribe to vehicle property(%d).", prop);
733 }
734 }
735
notifyVhalNewPowerPolicy(const std::string & policyId)736 Result<void> CarPowerPolicyServer::notifyVhalNewPowerPolicy(const std::string& policyId) {
737 int32_t prop = static_cast<int32_t>(VehicleProperty::CURRENT_POWER_POLICY);
738 if (!isPropertySupported(prop)) {
739 return Error() << StringPrintf("Vehicle property(%d) is not supported by VHAL.", prop);
740 }
741 VehiclePropValue propValue{
742 .prop = prop,
743 .value = {
744 .stringValue = policyId,
745 },
746 };
747 sp<IVehicle> vhalService;
748 {
749 Mutex::Autolock lock(mMutex);
750 if (mVhalService == nullptr) {
751 return Error() << "VHAL is not ready";
752 }
753 vhalService = mVhalService;
754 }
755 auto ret = vhalService->set(propValue);
756 if (!ret.isOk() || ret != StatusCode::OK) {
757 return Error() << "Failed to set CURRENT_POWER_POLICY property";
758 }
759 ALOGD("Policy(%s) is notified to VHAL", policyId.c_str());
760 return {};
761 }
762
isPropertySupported(const int32_t prop)763 bool CarPowerPolicyServer::isPropertySupported(const int32_t prop) {
764 if (mSupportedProperties.count(prop) > 0) {
765 return mSupportedProperties[prop];
766 }
767 StatusCode status;
768 hidl_vec<int32_t> props = {prop};
769 sp<IVehicle> vhalService;
770 {
771 Mutex::Autolock lock(mMutex);
772 if (mVhalService == nullptr) {
773 ALOGW("Failed to check if property(%d) is supported: VHAL is not ready", prop);
774 return false;
775 }
776 vhalService = mVhalService;
777 }
778 vhalService->getPropConfigs(props,
779 [&status](StatusCode s,
780 hidl_vec<VehiclePropConfig> /*propConfigs*/) {
781 status = s;
782 });
783 mSupportedProperties[prop] = status == StatusCode::OK;
784 return mSupportedProperties[prop];
785 }
786
isPowerPolicyAppliedLocked() const787 bool CarPowerPolicyServer::isPowerPolicyAppliedLocked() const {
788 return mCurrentPowerPolicyMeta.powerPolicy != nullptr;
789 }
790
791 } // namespace powerpolicy
792 } // namespace automotive
793 } // namespace frameworks
794 } // namespace android
795