• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "PowerPolicyClientBase.h"
18 
19 #include <android-base/chrono_utils.h>
20 #include <android-base/logging.h>
21 #include <android/binder_manager.h>
22 #include <utils/SystemClock.h>
23 
24 #include <algorithm>
25 #include <memory>
26 
27 namespace android {
28 namespace frameworks {
29 namespace automotive {
30 namespace powerpolicy {
31 
32 namespace aafap = ::aidl::android::frameworks::automotive::powerpolicy;
33 
34 using aafap::CarPowerPolicy;
35 using aafap::CarPowerPolicyFilter;
36 using aafap::ICarPowerPolicyChangeCallback;
37 using aafap::ICarPowerPolicyServer;
38 using aafap::PowerComponent;
39 using android::uptimeMillis;
40 using android::base::Error;
41 using android::base::Result;
42 using ::ndk::ScopedAStatus;
43 using ::ndk::SpAIBinder;
44 
45 namespace {
46 
47 constexpr const char* kPowerPolicyServerInterface =
48         "android.frameworks.automotive.powerpolicy.ICarPowerPolicyServer/default";
49 
50 constexpr std::chrono::milliseconds kPowerPolicyDaemomFindMarginalTimeMs = 500ms;
51 constexpr int32_t kMaxConnectionAttempt = 5;
52 
53 }  // namespace
54 
hasComponent(const std::vector<PowerComponent> & components,PowerComponent component)55 bool hasComponent(const std::vector<PowerComponent>& components, PowerComponent component) {
56     std::vector<PowerComponent>::const_iterator it =
57             std::find(components.cbegin(), components.cend(), component);
58     return it != components.cend();
59 }
60 
PowerPolicyClientBase()61 PowerPolicyClientBase::PowerPolicyClientBase() :
62       mDeathRecipient(AIBinder_DeathRecipient_new(PowerPolicyClientBase::onBinderDied)) {}
63 
~PowerPolicyClientBase()64 PowerPolicyClientBase::~PowerPolicyClientBase() {
65     if (mPolicyServer != nullptr) {
66         auto status =
67                 ScopedAStatus::fromStatus(AIBinder_unlinkToDeath(mPolicyServer->asBinder().get(),
68                                                                  mDeathRecipient.get(), nullptr));
69         if (!status.isOk()) {
70             LOG(WARNING) << "Unlinking from death recipient failed";
71         }
72     }
73 }
74 
onBinderDied(void * cookie)75 void PowerPolicyClientBase::onBinderDied(void* cookie) {
76     PowerPolicyClientBase* client = static_cast<PowerPolicyClientBase*>(cookie);
77     client->handleBinderDeath();
78 }
79 
init()80 void PowerPolicyClientBase::init() {
81     mConnectionThread = std::thread([this]() {
82         Result<void> ret;
83         int attemptCount = 1;
84         while (attemptCount <= kMaxConnectionAttempt) {
85             ret = connectToDaemon();
86             if (ret.ok()) {
87                 return;
88             }
89             LOG(WARNING) << "Connection attempt #" << attemptCount << " failed: " << ret.error();
90             attemptCount++;
91         }
92         onInitFailed();
93     });
94 }
95 
handleBinderDeath()96 void PowerPolicyClientBase::handleBinderDeath() {
97     LOG(INFO) << "Power policy daemon died. Reconnecting...";
98     {
99         std::unique_lock writeLock(mRWMutex);
100         mPolicyServer = nullptr;
101     }
102     init();
103 }
104 
connectToDaemon()105 Result<void> PowerPolicyClientBase::connectToDaemon() {
106     {
107         std::shared_lock readLock(mRWMutex);
108         if (mPolicyServer.get() != nullptr) {
109             LOG(INFO) << "Power policy daemon is already connected";
110             return {};
111         }
112     }
113     int64_t currentUptime = uptimeMillis();
114     SpAIBinder binder(AServiceManager_getService(kPowerPolicyServerInterface));
115     if (binder.get() == nullptr) {
116         return Error() << "Failed to get car power policy daemon";
117     }
118     int64_t elapsedTime = uptimeMillis() - currentUptime;
119     if (elapsedTime > kPowerPolicyDaemomFindMarginalTimeMs.count()) {
120         LOG(WARNING) << "Finding power policy daemon took too long(" << elapsedTime << " ms)";
121     }
122     std::shared_ptr<ICarPowerPolicyServer> server = ICarPowerPolicyServer::fromBinder(binder);
123     if (server == nullptr) {
124         return Error() << "Failed to connect to car power policy daemon";
125     }
126     binder = this->asBinder();
127     if (binder.get() == nullptr) {
128         return Error() << "Failed to get car power policy client binder object";
129     }
130     auto status = ScopedAStatus::fromStatus(
131             AIBinder_linkToDeath(server->asBinder().get(), mDeathRecipient.get(), this));
132     if (!status.isOk()) {
133         return Error() << "Linking to death recipient failed";
134     }
135 
136     std::shared_ptr<ICarPowerPolicyChangeCallback> client =
137             ICarPowerPolicyChangeCallback::fromBinder(binder);
138     const auto& components = getComponentsOfInterest();
139     CarPowerPolicyFilter filter;
140     filter.components = components;
141     status = server->registerPowerPolicyChangeCallback(client, filter);
142     if (!status.isOk()) {
143         status = ScopedAStatus::fromStatus(AIBinder_unlinkToDeath(server->asBinder().get(),
144                 mDeathRecipient.get(), nullptr));
145         if (!status.isOk()) {
146             LOG(WARNING) << "Unlinking from death recipient failed";
147         }
148         return Error() << "Register power policy change challback failed";
149     }
150 
151     {
152         std::unique_lock writeLock(mRWMutex);
153         mPolicyServer = server;
154     }
155 
156     LOG(INFO) << "Connected to power policy daemon";
157     return {};
158 }
159 
160 }  // namespace powerpolicy
161 }  // namespace automotive
162 }  // namespace frameworks
163 }  // namespace android
164