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