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 "PolicyManager.h"
21
22 #include "android-base/parseint.h"
23
24 #include <android-base/file.h>
25 #include <android-base/stringprintf.h>
26 #include <android-base/strings.h>
27 #include <utils/Log.h>
28
29 #include <tinyxml2.h>
30
31 #include <cstring>
32 #include <unordered_set>
33 #include <vector>
34
35 namespace android {
36 namespace frameworks {
37 namespace automotive {
38 namespace powerpolicy {
39
40 using ::aidl::android::frameworks::automotive::powerpolicy::CarPowerPolicy;
41 using ::aidl::android::frameworks::automotive::powerpolicy::PowerComponent;
42 using ::aidl::android::hardware::automotive::vehicle::VehicleApPowerStateReport;
43 using ::android::base::Error;
44 using ::android::base::Result;
45 using ::android::base::StartsWith;
46 using ::android::base::StringAppendF;
47 using ::android::base::StringPrintf;
48 using ::android::base::WriteStringToFd;
49 using ::tinyxml2::XML_SUCCESS;
50 using ::tinyxml2::XMLDocument;
51 using ::tinyxml2::XMLElement;
52
53 namespace {
54
55 // Vendor power policy filename.
56 constexpr const char kVendorPolicyFile[] = "/vendor/etc/automotive/power_policy.xml";
57
58 // Tags and attributes in vendor power policy XML file.
59 constexpr const char kTagRoot[] = "powerPolicy";
60 constexpr const char kTagPolicyGroups[] = "policyGroups";
61 constexpr const char kTagPolicyGroup[] = "policyGroup";
62 constexpr const char kTagDefaultPolicy[] = "defaultPolicy";
63 constexpr const char kTagNoDefaultPolicy[] = "noDefaultPolicy";
64 constexpr const char kTagPolicies[] = "policies";
65 constexpr const char kTagPolicy[] = "policy";
66 constexpr const char kTagOtherComponents[] = "otherComponents";
67 constexpr const char kTagComponent[] = "component";
68 constexpr const char kTagSystemPolicyOverrides[] = "systemPolicyOverrides";
69 constexpr const char kAttrBehavior[] = "behavior";
70 constexpr const char kAttrId[] = "id";
71 constexpr const char kAttrState[] = "state";
72 constexpr const char kAttrDefaultPolicyGroup[] = "defaultPolicyGroup";
73 constexpr const char kTagCustomComponents[] = "customComponents";
74 constexpr const char kTagCustomComponent[] = "customComponent";
75 constexpr const char kAttrValue[] = "value";
76 // Power states.
77 constexpr const char kPowerStateOn[] = "on";
78 constexpr const char kPowerStateOff[] = "off";
79 constexpr const char kPowerStateUntouched[] = "untouched";
80
81 // Power transitions that a power policy can be applied with.
82 constexpr const char kPowerTransitionWaitForVhal[] = "WaitForVHAL";
83 constexpr const char kPowerTransitionOn[] = "On";
84
85 const PowerComponent INVALID_POWER_COMPONENT = static_cast<PowerComponent>(-1);
86 const int32_t INVALID_CUSTOM_POWER_COMPONENT = -1;
87 const int32_t MINIMUM_CUSTOM_COMPONENT_VALUE =
88 static_cast<int>(PowerComponent::MINIMUM_CUSTOM_COMPONENT_VALUE);
89 const int32_t INVALID_VEHICLE_POWER_STATE = -1;
90
91 constexpr const char kPowerComponentPrefix[] = "POWER_COMPONENT_";
92 constexpr const char kSystemPolicyPrefix[] = "system_power_policy_";
93
94 // System power policy definition: ID, enabled components, and disabled components.
95 const std::vector<PowerComponent> kNoUserInteractionEnabledComponents =
96 {PowerComponent::WIFI, PowerComponent::CELLULAR, PowerComponent::ETHERNET,
97 PowerComponent::TRUSTED_DEVICE_DETECTION, PowerComponent::CPU};
98 const std::vector<PowerComponent> kNoUserInteractionDisabledComponents =
99 {PowerComponent::AUDIO,
100 PowerComponent::MEDIA,
101 PowerComponent::DISPLAY,
102 PowerComponent::BLUETOOTH,
103 PowerComponent::PROJECTION,
104 PowerComponent::NFC,
105 PowerComponent::INPUT,
106 PowerComponent::VOICE_INTERACTION,
107 PowerComponent::VISUAL_INTERACTION,
108 PowerComponent::LOCATION,
109 PowerComponent::MICROPHONE};
110 const std::vector<PowerComponent> kAllComponents = {PowerComponent::AUDIO,
111 PowerComponent::MEDIA,
112 PowerComponent::DISPLAY,
113 PowerComponent::BLUETOOTH,
114 PowerComponent::WIFI,
115 PowerComponent::CELLULAR,
116 PowerComponent::ETHERNET,
117 PowerComponent::PROJECTION,
118 PowerComponent::NFC,
119 PowerComponent::INPUT,
120 PowerComponent::VOICE_INTERACTION,
121 PowerComponent::VISUAL_INTERACTION,
122 PowerComponent::TRUSTED_DEVICE_DETECTION,
123 PowerComponent::LOCATION,
124 PowerComponent::MICROPHONE,
125 PowerComponent::CPU};
126 const std::vector<PowerComponent> kInitialOnComponents = {PowerComponent::AUDIO,
127 PowerComponent::DISPLAY,
128 PowerComponent::CPU};
129 const std::vector<PowerComponent> kNoComponents;
130 const std::vector<PowerComponent> kSuspendPrepDisabledComponents = {PowerComponent::AUDIO,
131 PowerComponent::BLUETOOTH,
132 PowerComponent::WIFI,
133 PowerComponent::LOCATION,
134 PowerComponent::MICROPHONE,
135 PowerComponent::CPU};
136 const std::unordered_set<PowerComponent> kNoUserInteractionConfigurableComponents =
137 {PowerComponent::BLUETOOTH, PowerComponent::NFC, PowerComponent::TRUSTED_DEVICE_DETECTION};
138
iterateAllPowerComponents(const std::function<bool (PowerComponent)> & processor)139 void iterateAllPowerComponents(const std::function<bool(PowerComponent)>& processor) {
140 for (const auto component : ::ndk::enum_range<PowerComponent>()) {
141 if (component >= PowerComponent::MINIMUM_CUSTOM_COMPONENT_VALUE) {
142 continue;
143 }
144 if (!processor(component)) {
145 break;
146 }
147 }
148 }
149
toPowerComponent(std::string_view id,std::string_view prefix)150 PowerComponent toPowerComponent(std::string_view id, std::string_view prefix) {
151 if (!StartsWith(id, prefix)) {
152 return INVALID_POWER_COMPONENT;
153 }
154 std::string_view componentId = id.substr(prefix.size());
155 PowerComponent matchedComponent = INVALID_POWER_COMPONENT;
156 iterateAllPowerComponents([componentId, &matchedComponent](PowerComponent component) -> bool {
157 if (componentId == toString(component)) {
158 matchedComponent = component;
159 return false;
160 }
161 return true;
162 });
163 return matchedComponent;
164 }
165
toCustomPowerComponent(const std::unordered_map<std::string,int> & customComponents,const std::string_view & id)166 int toCustomPowerComponent(const std::unordered_map<std::string, int>& customComponents,
167 const std::string_view& id) {
168 if (customComponents.size() == 0) {
169 return INVALID_CUSTOM_POWER_COMPONENT;
170 }
171 return customComponents.count(std::string(id)) > 0 ? customComponents.at(std::string(id))
172 : INVALID_CUSTOM_POWER_COMPONENT;
173 }
174
safePtrPrint(const char * ptr)175 const char* safePtrPrint(const char* ptr) {
176 return ptr == nullptr ? "nullptr" : ptr;
177 }
178
toVehiclePowerState(const char * state)179 int32_t toVehiclePowerState(const char* state) {
180 if (!strcmp(state, kPowerTransitionWaitForVhal)) {
181 return static_cast<int32_t>(VehicleApPowerStateReport::WAIT_FOR_VHAL);
182 }
183 if (!strcmp(state, kPowerTransitionOn)) {
184 return static_cast<int32_t>(VehicleApPowerStateReport::ON);
185 }
186 return INVALID_VEHICLE_POWER_STATE;
187 }
188
isValidPowerState(int32_t state)189 bool isValidPowerState(int32_t state) {
190 return state != INVALID_VEHICLE_POWER_STATE;
191 }
192
logXmlError(const std::string & errMsg)193 void logXmlError(const std::string& errMsg) {
194 ALOGW("Proceed without registered policies: %s", errMsg.c_str());
195 }
196
readComponents(const XMLElement * pPolicy,CarPowerPolicyPtr policy,std::unordered_set<PowerComponent> * visited,std::unordered_set<int> * visitedCustomComponents,const std::unordered_map<std::string,int> & customComponents)197 Result<void> readComponents(const XMLElement* pPolicy, CarPowerPolicyPtr policy,
198 std::unordered_set<PowerComponent>* visited,
199 std::unordered_set<int>* visitedCustomComponents,
200 const std::unordered_map<std::string, int>& customComponents) {
201 auto updateVisitedComponents = [](const auto& componentId, auto* visitedComponents) {
202 visitedComponents->insert(componentId);
203 };
204
205 auto updateComponentState = [](const auto& componentId, const auto& powerState,
206 auto* enabledComponents,
207 auto* disabledComponents) -> Result<void> {
208 if (!strcmp(powerState, kPowerStateOn)) {
209 enabledComponents->push_back(componentId);
210 } else if (!strcmp(powerState, kPowerStateOff)) {
211 disabledComponents->push_back(componentId);
212 } else {
213 return Error() << StringPrintf("XML configuration has invalid value(%s) in |%s| tag",
214 safePtrPrint(powerState), kTagComponent);
215 }
216 return {};
217 };
218 for (const XMLElement* pComponent = pPolicy->FirstChildElement(kTagComponent);
219 pComponent != nullptr; pComponent = pComponent->NextSiblingElement(kTagComponent)) {
220 const char* id;
221 if (pComponent->QueryStringAttribute(kAttrId, &id) != XML_SUCCESS) {
222 return Error() << StringPrintf("Failed to read |%s| attribute in |%s| tag", kAttrId,
223 kTagComponent);
224 }
225 PowerComponent componentId = toPowerComponent(id, kPowerComponentPrefix);
226 int customComponentId = INVALID_CUSTOM_POWER_COMPONENT;
227 if (componentId == INVALID_POWER_COMPONENT) {
228 customComponentId = toCustomPowerComponent(customComponents, id);
229 }
230
231 if (componentId == INVALID_POWER_COMPONENT &&
232 customComponentId == INVALID_CUSTOM_POWER_COMPONENT) {
233 return Error() << StringPrintf("XML configuration has invalid value(%s) in |%s| "
234 "attribute of |%s| tag",
235 safePtrPrint(id), kAttrId, kTagComponent);
236 }
237
238 if ((componentId != INVALID_POWER_COMPONENT && visited->count(componentId) > 0) ||
239 (customComponentId != INVALID_CUSTOM_POWER_COMPONENT &&
240 visitedCustomComponents->count(customComponentId) > 0)) {
241 return Error() << StringPrintf("XML configuration has duplicated component(%s) in |%s| "
242 "attribute of |%s| tag",
243 toString(componentId).c_str(), kAttrId, kTagComponent);
244 }
245
246 if (componentId != INVALID_POWER_COMPONENT) {
247 updateVisitedComponents(componentId, visited);
248 } else if (customComponentId >= MINIMUM_CUSTOM_COMPONENT_VALUE) {
249 updateVisitedComponents(customComponentId, visitedCustomComponents);
250 }
251
252 const char* powerState = pComponent->GetText();
253 Result<void> result{};
254 if (componentId != INVALID_POWER_COMPONENT) {
255 result = updateComponentState(componentId, powerState, &policy->enabledComponents,
256 &policy->disabledComponents);
257 } else if (customComponentId >= MINIMUM_CUSTOM_COMPONENT_VALUE) {
258 result = updateComponentState(customComponentId, powerState,
259 &policy->enabledCustomComponents,
260 &policy->disabledCustomComponents);
261 }
262
263 if (!result.ok()) {
264 return result.error();
265 }
266 }
267 return {};
268 }
269
readOtherComponents(const XMLElement * pPolicy,CarPowerPolicyPtr policy,const std::unordered_set<PowerComponent> & visited,const std::unordered_map<std::string,int> & customComponents,const std::unordered_set<int> & visitedCustomComponents)270 Result<void> readOtherComponents(const XMLElement* pPolicy, CarPowerPolicyPtr policy,
271 const std::unordered_set<PowerComponent>& visited,
272 const std::unordered_map<std::string, int>& customComponents,
273 const std::unordered_set<int>& visitedCustomComponents) {
274 const char* otherComponentBehavior = kPowerStateUntouched;
275 const XMLElement* pElement = pPolicy->FirstChildElement(kTagOtherComponents);
276 if (pElement != nullptr) {
277 if (pElement->QueryStringAttribute(kAttrBehavior, &otherComponentBehavior) != XML_SUCCESS) {
278 return Error() << StringPrintf("Failed to read |%s| attribute in |%s| tag",
279 kAttrBehavior, kTagOtherComponents);
280 }
281 }
282
283 std::vector<int> customComponentsVector;
284 customComponentsVector.reserve(customComponents.size());
285 std::transform(customComponents.begin(), customComponents.end(),
286 std::back_inserter(customComponentsVector),
287 [](const auto& element) { return element.second; });
288
289 if (!strcmp(otherComponentBehavior, kPowerStateOn)) {
290 iterateAllPowerComponents([&visited, &policy](PowerComponent component) -> bool {
291 if (visited.count(component) == 0) {
292 policy->enabledComponents.push_back(component);
293 }
294 return true;
295 });
296
297 std::copy_if(customComponentsVector.begin(), customComponentsVector.end(),
298 std::back_inserter(policy->enabledCustomComponents),
299 [&visitedCustomComponents](int componentId) {
300 return visitedCustomComponents.count(componentId) == 0;
301 });
302 } else if (!strcmp(otherComponentBehavior, kPowerStateOff)) {
303 iterateAllPowerComponents([&visited, &policy](PowerComponent component) -> bool {
304 if (visited.count(component) == 0) {
305 policy->disabledComponents.push_back(component);
306 }
307 return true;
308 });
309 std::copy_if(customComponentsVector.begin(), customComponentsVector.end(),
310 std::back_inserter(policy->disabledCustomComponents),
311 [&visitedCustomComponents](int componentId) {
312 return visitedCustomComponents.count(componentId) == 0;
313 });
314 } else if (!strcmp(otherComponentBehavior, kPowerStateUntouched)) {
315 // Do nothing
316 } else {
317 return Error() << StringPrintf("XML configuration has invalid value(%s) in |%s| attribute "
318 "of |%s| tag",
319 safePtrPrint(otherComponentBehavior), kAttrBehavior,
320 kTagOtherComponents);
321 }
322 return {};
323 }
324
readPolicies(const XMLElement * pRoot,const char * tag,bool includeOtherComponents,const std::unordered_map<std::string,int> & customComponents)325 Result<std::vector<CarPowerPolicyPtr>> readPolicies(
326 const XMLElement* pRoot, const char* tag, bool includeOtherComponents,
327 const std::unordered_map<std::string, int>& customComponents) {
328 std::vector<CarPowerPolicyPtr> policies;
329 const XMLElement* pPolicies = pRoot->FirstChildElement(tag);
330 if (pPolicies == nullptr) {
331 return std::vector<CarPowerPolicyPtr>();
332 }
333 for (const XMLElement* pPolicy = pPolicies->FirstChildElement(kTagPolicy); pPolicy != nullptr;
334 pPolicy = pPolicy->NextSiblingElement(kTagPolicy)) {
335 std::unordered_set<PowerComponent> visited;
336 std::unordered_set<int> visitedCustomComponents;
337
338 const char* policyId;
339 if (pPolicy->QueryStringAttribute(kAttrId, &policyId) != XML_SUCCESS) {
340 return Error() << StringPrintf("Failed to read |%s| attribute in |%s| tag", kAttrId,
341 kTagPolicy);
342 }
343 if (includeOtherComponents && isSystemPowerPolicy(policyId)) {
344 return Error() << "Policy ID should not start with \"system_power_policy_\"";
345 }
346 auto policy = std::make_shared<CarPowerPolicy>();
347 policy->policyId = policyId;
348
349 auto ret = readComponents(pPolicy, policy, &visited, &visitedCustomComponents,
350 customComponents);
351 if (!ret.ok()) {
352 return ret.error();
353 }
354 if (includeOtherComponents) {
355 ret = readOtherComponents(pPolicy, policy, visited, customComponents,
356 visitedCustomComponents);
357 if (!ret.ok()) {
358 return ret.error();
359 }
360 }
361 policies.push_back(policy);
362 }
363 return policies;
364 }
365
readPolicyGroup(const XMLElement * pPolicyGroup,const std::unordered_map<std::string,CarPowerPolicyPtr> & registeredPowerPolicies)366 Result<PolicyGroup> readPolicyGroup(
367 const XMLElement* pPolicyGroup,
368 const std::unordered_map<std::string, CarPowerPolicyPtr>& registeredPowerPolicies) {
369 PolicyGroup policyGroup;
370 for (const XMLElement* pDefaultPolicy = pPolicyGroup->FirstChildElement(kTagDefaultPolicy);
371 pDefaultPolicy != nullptr;
372 pDefaultPolicy = pDefaultPolicy->NextSiblingElement(kTagDefaultPolicy)) {
373 const char* state;
374 if (pDefaultPolicy->QueryStringAttribute(kAttrState, &state) != XML_SUCCESS) {
375 return Error() << StringPrintf("Failed to read |%s| attribute in |%s| tag", kAttrState,
376 kTagDefaultPolicy);
377 }
378 int32_t powerState = toVehiclePowerState(state);
379 if (!isValidPowerState(powerState)) {
380 return Error() << StringPrintf("Target state(%s) is not valid", state);
381 }
382 const char* policyId;
383 if (pDefaultPolicy->QueryStringAttribute(kAttrId, &policyId) != XML_SUCCESS) {
384 return Error() << StringPrintf("Failed to read |%s| attribute in |%s| tag", kAttrId,
385 kTagDefaultPolicy);
386 }
387 if (registeredPowerPolicies.count(policyId) == 0) {
388 return Error() << StringPrintf("Policy(id: %s) is not registered", policyId);
389 }
390 policyGroup.emplace(powerState, policyId);
391 }
392 for (const XMLElement* pNoPolicy = pPolicyGroup->FirstChildElement(kTagNoDefaultPolicy);
393 pNoPolicy != nullptr; pNoPolicy = pNoPolicy->NextSiblingElement(kTagNoDefaultPolicy)) {
394 const char* state;
395 if (pNoPolicy->QueryStringAttribute(kAttrState, &state) != XML_SUCCESS) {
396 return Error() << StringPrintf("Failed to read |%s| attribute in |%s| tag", kAttrState,
397 kTagNoDefaultPolicy);
398 }
399 int32_t powerState = toVehiclePowerState(state);
400 if (!isValidPowerState(powerState)) {
401 return Error() << StringPrintf("Target state(%s) is not valid", state);
402 }
403 if (policyGroup.count(powerState) > 0) {
404 return Error()
405 << StringPrintf("Target state(%s) is specified both in |%s| and |%s| tags",
406 state, kTagDefaultPolicy, kTagNoDefaultPolicy);
407 }
408 }
409 return policyGroup;
410 }
411
412 struct PolicyGroups {
413 std::unordered_map<std::string, PolicyGroup> groups;
414 std::string defaultGroup;
415 };
416
readPolicyGroups(const XMLElement * pRoot,const std::unordered_map<std::string,CarPowerPolicyPtr> & registeredPowerPolicies)417 Result<PolicyGroups> readPolicyGroups(
418 const XMLElement* pRoot,
419 const std::unordered_map<std::string, CarPowerPolicyPtr>& registeredPowerPolicies) {
420 const XMLElement* pPolicyGroups = pRoot->FirstChildElement(kTagPolicyGroups);
421
422 PolicyGroups policyGroups;
423
424 if (pPolicyGroups == nullptr) {
425 return policyGroups;
426 }
427
428 const char* pDefaultPolicyGroupId = nullptr;
429 pPolicyGroups->QueryStringAttribute(kAttrDefaultPolicyGroup, &pDefaultPolicyGroupId);
430 if (pDefaultPolicyGroupId != nullptr) {
431 policyGroups.defaultGroup = pDefaultPolicyGroupId;
432 }
433
434 for (const XMLElement* pPolicyGroup = pPolicyGroups->FirstChildElement(kTagPolicyGroup);
435 pPolicyGroup != nullptr;
436 pPolicyGroup = pPolicyGroup->NextSiblingElement(kTagPolicyGroup)) {
437 const char* policyGroupId;
438 if (pPolicyGroup->QueryStringAttribute(kAttrId, &policyGroupId) != XML_SUCCESS) {
439 return Error() << StringPrintf("Failed to read |%s| attribute in |%s| tag", kAttrId,
440 kTagPolicyGroup);
441 }
442 const auto& policyGroup = readPolicyGroup(pPolicyGroup, registeredPowerPolicies);
443 if (!policyGroup.ok()) {
444 return Error() << policyGroup.error();
445 }
446 policyGroups.groups.emplace(policyGroupId, *policyGroup);
447 }
448 return policyGroups;
449 }
450
isConfigurableComponent(PowerComponent component)451 bool isConfigurableComponent(PowerComponent component) {
452 return kNoUserInteractionConfigurableComponents.count(component) > 0;
453 }
454
checkConfigurableComponents(const std::vector<PowerComponent> & components)455 Result<void> checkConfigurableComponents(const std::vector<PowerComponent>& components) {
456 for (auto component : components) {
457 if (!isConfigurableComponent(component)) {
458 return Error()
459 << StringPrintf("Component(%s) is not configurable in system power policy.",
460 toString(component).c_str());
461 }
462 }
463 return {};
464 }
465
readSystemPolicyOverrides(const XMLElement * pRoot,const std::unordered_map<std::string,int> & customComponents)466 Result<std::vector<CarPowerPolicyPtr>> readSystemPolicyOverrides(
467 const XMLElement* pRoot, const std::unordered_map<std::string, int>& customComponents) {
468 const auto& systemPolicyOverrides =
469 readPolicies(pRoot, kTagSystemPolicyOverrides, false, customComponents);
470 if (!systemPolicyOverrides.ok()) {
471 return Error() << systemPolicyOverrides.error().message();
472 }
473 for (auto policy : *systemPolicyOverrides) {
474 if (policy->policyId != kSystemPolicyIdNoUserInteraction) {
475 return Error() << StringPrintf("System power policy(%s) is not supported.",
476 policy->policyId.c_str());
477 }
478 auto ret = checkConfigurableComponents(policy->enabledComponents);
479 if (!ret.ok()) {
480 return ret.error();
481 }
482 ret = checkConfigurableComponents(policy->disabledComponents);
483 if (!ret.ok()) {
484 return ret.error();
485 }
486 }
487 return systemPolicyOverrides;
488 }
489
readCustomComponents(const XMLElement * pRoot)490 Result<std::unordered_map<std::string, int>> readCustomComponents(const XMLElement* pRoot) {
491 const XMLElement* pCustomComponents = pRoot->FirstChildElement(kTagCustomComponents);
492 std::unordered_map<std::string, int> customComponentsMap;
493
494 if (pCustomComponents == nullptr) {
495 return {};
496 }
497
498 for (const XMLElement* pCustomComponent =
499 pCustomComponents->FirstChildElement(kTagCustomComponent);
500 pCustomComponent != nullptr;
501 pCustomComponent = pCustomComponent->NextSiblingElement(kTagCustomComponent)) {
502 const char* componentName = pCustomComponent->GetText();
503
504 int value = 0;
505 pCustomComponent->QueryIntAttribute(kAttrValue, &value);
506
507 if (value < MINIMUM_CUSTOM_COMPONENT_VALUE) {
508 // log error
509 logXmlError(StringPrintf("Component value is not in allowed range. componentName = "
510 "%s, value = %d",
511 componentName, value));
512 return Error() << StringPrintf("Component value is not in allowed range");
513 }
514 customComponentsMap.insert({componentName, value});
515 }
516
517 return customComponentsMap;
518 }
519
520 // configureComponents assumes that previously validated components are passed.
configureComponents(const std::vector<PowerComponent> & configComponents,std::vector<PowerComponent> * componentsAddedTo,std::vector<PowerComponent> * componentsRemovedFrom)521 void configureComponents(const std::vector<PowerComponent>& configComponents,
522 std::vector<PowerComponent>* componentsAddedTo,
523 std::vector<PowerComponent>* componentsRemovedFrom) {
524 for (const auto component : configComponents) {
525 auto it = std::find(componentsAddedTo->begin(), componentsAddedTo->end(), component);
526 if (it == componentsAddedTo->end()) {
527 componentsAddedTo->push_back(component);
528 }
529 it = std::find(componentsRemovedFrom->begin(), componentsRemovedFrom->end(), component);
530 if (it != componentsRemovedFrom->end()) {
531 componentsRemovedFrom->erase(it);
532 }
533 }
534 }
535
stringsToComponents(const std::vector<std::string> & arr,std::vector<PowerComponent> * components,std::vector<int> * customComponents)536 Result<void> stringsToComponents(const std::vector<std::string>& arr,
537 std::vector<PowerComponent>* components,
538 std::vector<int>* customComponents) {
539 for (const auto& c : arr) {
540 const char* component = c.c_str();
541 PowerComponent componentId = toPowerComponent(component, "");
542 if (componentId == INVALID_POWER_COMPONENT) {
543 int customComponentId = 0;
544 bool result = android::base::ParseInt(component, &customComponentId);
545 if (!result || customComponentId < MINIMUM_CUSTOM_COMPONENT_VALUE) {
546 return Error() << StringPrintf("%s is not a valid component", component);
547 }
548 customComponents->push_back(customComponentId);
549 } else {
550 components->push_back(componentId);
551 }
552 }
553 return {};
554 }
555
createPolicy(const char * policyId,const std::vector<PowerComponent> & enabledComponents,const std::vector<PowerComponent> & disabledComponents,const std::vector<int> & enabledCustomComponents,const std::vector<int> & disabledCustomComponents)556 CarPowerPolicyPtr createPolicy(const char* policyId,
557 const std::vector<PowerComponent>& enabledComponents,
558 const std::vector<PowerComponent>& disabledComponents,
559 const std::vector<int>& enabledCustomComponents,
560 const std::vector<int>& disabledCustomComponents) {
561 CarPowerPolicyPtr policy = std::make_shared<CarPowerPolicy>();
562 policy->policyId = policyId;
563 policy->enabledComponents = enabledComponents;
564 policy->disabledComponents = disabledComponents;
565 policy->disabledCustomComponents = disabledCustomComponents;
566 policy->enabledCustomComponents = enabledCustomComponents;
567 return policy;
568 }
569
570 } // namespace
571
toString(const std::vector<PowerComponent> & components)572 std::string toString(const std::vector<PowerComponent>& components) {
573 size_t size = components.size();
574 if (size == 0) {
575 return "none";
576 }
577 std::string filterStr = toString(components[0]);
578 for (size_t i = 1; i < size; i++) {
579 StringAppendF(&filterStr, ", %s", toString(components[i]).c_str());
580 }
581 return filterStr;
582 }
583
toString(const CarPowerPolicy & policy)584 std::string toString(const CarPowerPolicy& policy) {
585 return StringPrintf("%s(enabledComponents: %s, disabledComponents: %s)",
586 policy.policyId.c_str(), toString(policy.enabledComponents).c_str(),
587 toString(policy.disabledComponents).c_str());
588 }
589
isSystemPowerPolicy(const std::string & policyId)590 bool isSystemPowerPolicy(const std::string& policyId) {
591 return StartsWith(policyId, kSystemPolicyPrefix);
592 }
593
init()594 void PolicyManager::init() {
595 initRegularPowerPolicy(/*override=*/true);
596 mPolicyGroups.clear();
597 initPreemptivePowerPolicy();
598 readPowerPolicyConfiguration();
599 }
600
getPowerPolicy(const std::string & policyId) const601 Result<CarPowerPolicyMeta> PolicyManager::getPowerPolicy(const std::string& policyId) const {
602 if (mRegisteredPowerPolicies.count(policyId) > 0) {
603 return CarPowerPolicyMeta{
604 .powerPolicy = mRegisteredPowerPolicies.at(policyId),
605 .isPreemptive = false,
606 };
607 }
608 if (mPreemptivePowerPolicies.count(policyId) > 0) {
609 return CarPowerPolicyMeta{
610 .powerPolicy = mPreemptivePowerPolicies.at(policyId),
611 .isPreemptive = true,
612 };
613 }
614 return Error() << StringPrintf("Power policy(id: %s) is not found", policyId.c_str());
615 }
616
getDefaultPowerPolicyForState(const std::string & groupId,VehicleApPowerStateReport state) const617 Result<CarPowerPolicyPtr> PolicyManager::getDefaultPowerPolicyForState(
618 const std::string& groupId, VehicleApPowerStateReport state) const {
619 auto groupIdToUse = groupId.empty() ? mDefaultPolicyGroup : groupId;
620
621 if (mPolicyGroups.count(groupIdToUse) == 0) {
622 return Error() << StringPrintf("Power policy group %s is not found", groupIdToUse.c_str());
623 }
624
625 PolicyGroup policyGroup = mPolicyGroups.at(groupIdToUse);
626 int32_t key = static_cast<int32_t>(state);
627 if (policyGroup.count(key) == 0) {
628 return Error() << StringPrintf("Policy for %s is not found", toString(state).c_str());
629 }
630 return mRegisteredPowerPolicies.at(policyGroup.at(key));
631 }
632
isPowerPolicyGroupAvailable(const std::string & groupId) const633 bool PolicyManager::isPowerPolicyGroupAvailable(const std::string& groupId) const {
634 return mPolicyGroups.count(groupId) > 0;
635 }
636
isPreemptivePowerPolicy(const std::string & policyId) const637 bool PolicyManager::isPreemptivePowerPolicy(const std::string& policyId) const {
638 return mPreemptivePowerPolicies.count(policyId) > 0;
639 }
640
definePowerPolicy(const std::string & policyId,const std::vector<std::string> & enabledComponents,const std::vector<std::string> & disabledComponents)641 Result<void> PolicyManager::definePowerPolicy(const std::string& policyId,
642 const std::vector<std::string>& enabledComponents,
643 const std::vector<std::string>& disabledComponents) {
644 if (mRegisteredPowerPolicies.count(policyId) > 0) {
645 return Error() << StringPrintf("%s is already registered", policyId.c_str());
646 }
647 auto policy = std::make_shared<CarPowerPolicy>();
648 policy->policyId = policyId;
649 auto ret = stringsToComponents(enabledComponents, &policy->enabledComponents,
650 &policy->enabledCustomComponents);
651 if (!ret.ok()) {
652 return ret;
653 }
654 ret = stringsToComponents(disabledComponents, &policy->disabledComponents,
655 &policy->disabledCustomComponents);
656 if (!ret.ok()) {
657 return ret;
658 }
659 mRegisteredPowerPolicies.emplace(policyId, policy);
660 return {};
661 }
662
dump(int fd,const Vector<String16> &)663 Result<void> PolicyManager::dump(int fd, const Vector<String16>& /*args*/) {
664 const char* indent = " ";
665 const char* doubleIndent = " ";
666 const char* tripleIndent = " ";
667
668 WriteStringToFd(StringPrintf("%sRegistered power policies:%s\n", indent,
669 mRegisteredPowerPolicies.size() ? "" : " none"),
670 fd);
671 for (auto& it : mRegisteredPowerPolicies) {
672 WriteStringToFd(StringPrintf("%s- %s\n", doubleIndent, toString(*it.second).c_str()), fd);
673 }
674 WriteStringToFd(StringPrintf("%sPower policy groups:%s\n", indent,
675 mPolicyGroups.size() ? "" : " none"),
676 fd);
677 for (auto& itGroup : mPolicyGroups) {
678 WriteStringToFd(StringPrintf("%s%s\n", doubleIndent, itGroup.first.c_str()), fd);
679 for (auto& itMapping : itGroup.second) {
680 VehicleApPowerStateReport state =
681 static_cast<VehicleApPowerStateReport>(itMapping.first);
682 WriteStringToFd(StringPrintf("%s- %s --> %s\n", tripleIndent, toString(state).c_str(),
683 itMapping.second.c_str()),
684 fd);
685 }
686 }
687 WriteStringToFd(StringPrintf("%sNo user interaction power policy: %s\n", indent,
688 toString(*mPreemptivePowerPolicies.at(
689 kSystemPolicyIdNoUserInteraction))
690 .c_str()),
691 fd);
692 return {};
693 }
694
readPowerPolicyConfiguration()695 void PolicyManager::readPowerPolicyConfiguration() {
696 XMLDocument xmlDoc;
697 xmlDoc.LoadFile(kVendorPolicyFile);
698 if (xmlDoc.ErrorID() != XML_SUCCESS) {
699 logXmlError(StringPrintf("Failed to read and/or parse %s", kVendorPolicyFile));
700 return;
701 }
702 readPowerPolicyFromXml(xmlDoc);
703 }
704
readPowerPolicyFromXml(const XMLDocument & xmlDoc)705 void PolicyManager::readPowerPolicyFromXml(const XMLDocument& xmlDoc) {
706 const XMLElement* pRootElement = xmlDoc.RootElement();
707 if (!pRootElement || strcmp(pRootElement->Name(), kTagRoot)) {
708 logXmlError(StringPrintf("XML file is not in the required format"));
709 return;
710 }
711
712 const auto& customComponents = readCustomComponents(pRootElement);
713 if (!customComponents.ok()) {
714 logXmlError(StringPrintf("Reading custom components failed: %s",
715 customComponents.error().message().c_str()));
716 return;
717 }
718
719 mCustomComponents = *customComponents;
720 const auto& registeredPolicies =
721 readPolicies(pRootElement, kTagPolicies, true, mCustomComponents);
722
723 if (!registeredPolicies.ok()) {
724 logXmlError(StringPrintf("Reading policies failed: %s",
725 registeredPolicies.error().message().c_str()));
726 return;
727 }
728 std::unordered_map<std::string, CarPowerPolicyPtr> registeredPoliciesMap;
729 for (auto policy : *registeredPolicies) {
730 registeredPoliciesMap.emplace(policy->policyId, policy);
731 }
732
733 const auto& policyGroups = readPolicyGroups(pRootElement, registeredPoliciesMap);
734 if (!policyGroups.ok()) {
735 logXmlError(StringPrintf("Reading power policy groups for power state failed: %s",
736 policyGroups.error().message().c_str()));
737 return;
738 }
739 const auto& systemPolicyOverrides = readSystemPolicyOverrides(pRootElement, mCustomComponents);
740 if (!systemPolicyOverrides.ok()) {
741 logXmlError(StringPrintf("Reading system power policy overrides failed: %s",
742 systemPolicyOverrides.error().message().c_str()));
743 return;
744 }
745
746 mRegisteredPowerPolicies = registeredPoliciesMap;
747 initRegularPowerPolicy(/*override=*/false);
748 mPolicyGroups = policyGroups->groups;
749 mDefaultPolicyGroup = policyGroups->defaultGroup;
750 // TODO(b/273315694) check if custom components in policies are defined
751 reconstructNoUserInteractionPolicy(*systemPolicyOverrides);
752 }
753
reconstructNoUserInteractionPolicy(const std::vector<CarPowerPolicyPtr> & policyOverrides)754 void PolicyManager::reconstructNoUserInteractionPolicy(
755 const std::vector<CarPowerPolicyPtr>& policyOverrides) {
756 CarPowerPolicyPtr systemPolicy = mPreemptivePowerPolicies.at(kSystemPolicyIdNoUserInteraction);
757 for (auto policy : policyOverrides) {
758 configureComponents(policy->enabledComponents, &systemPolicy->enabledComponents,
759 &systemPolicy->disabledComponents);
760 configureComponents(policy->disabledComponents, &systemPolicy->disabledComponents,
761 &systemPolicy->enabledComponents);
762 }
763 }
764
initRegularPowerPolicy(bool override)765 void PolicyManager::initRegularPowerPolicy(bool override) {
766 if (override) {
767 mRegisteredPowerPolicies.clear();
768 }
769 mRegisteredPowerPolicies.emplace(kSystemPolicyIdAllOn,
770 createPolicy(kSystemPolicyIdAllOn, kAllComponents,
771 kNoComponents, {}, {}));
772
773 std::vector<PowerComponent> initialOnDisabledComponents;
774 for (const auto component : ::ndk::enum_range<PowerComponent>()) {
775 if (component >= PowerComponent::MINIMUM_CUSTOM_COMPONENT_VALUE) {
776 continue;
777 }
778 if (std::find(kInitialOnComponents.begin(), kInitialOnComponents.end(), component) ==
779 kInitialOnComponents.end()) {
780 initialOnDisabledComponents.push_back(component);
781 }
782 }
783 mRegisteredPowerPolicies.emplace(kSystemPolicyIdInitialOn,
784 createPolicy(kSystemPolicyIdInitialOn, kInitialOnComponents,
785 initialOnDisabledComponents, {}, {}));
786 }
787
initPreemptivePowerPolicy()788 void PolicyManager::initPreemptivePowerPolicy() {
789 mPreemptivePowerPolicies.clear();
790 mPreemptivePowerPolicies.emplace(kSystemPolicyIdNoUserInteraction,
791 createPolicy(kSystemPolicyIdNoUserInteraction,
792 kNoUserInteractionEnabledComponents,
793 kNoUserInteractionDisabledComponents, {}, {}));
794 mPreemptivePowerPolicies.emplace(kSystemPolicyIdSuspendPrep,
795 createPolicy(kSystemPolicyIdSuspendPrep, kNoComponents,
796 kSuspendPrepDisabledComponents, {}, {}));
797 }
798
getDefaultPolicyGroup() const799 std::string PolicyManager::getDefaultPolicyGroup() const {
800 return mDefaultPolicyGroup;
801 }
802
803 } // namespace powerpolicy
804 } // namespace automotive
805 } // namespace frameworks
806 } // namespace android
807