1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "xpower_plugin.h"
16
17 #include <dlfcn.h>
18 #include <unistd.h>
19
20 #include <iomanip>
21 #include <iostream>
22 #include <sstream>
23
24 #include "common.h"
25 #include "securec.h"
26
27 namespace {
28 constexpr size_t MAX_QUEUE_SIZE = 2000;
29 constexpr uint32_t WAIT_DURATION = 100;
30 constexpr int32_t AID_HAP_START = 20010000;
31 constexpr int32_t AID_HAP_END = 21065535;
32 } // namespace
XpowerPlugin()33 XpowerPlugin::XpowerPlugin()
34 {
35 procMesTypeMapping_.insert({XpowerMessageType::REAL_BATTERY, OptimizeMessageType::MESSAGE_REAL_BATTERY});
36 procMesTypeMapping_.insert({XpowerMessageType::APP_STATISTIC, OptimizeMessageType::MESSAGE_APP_STATISTIC});
37 procMesTypeMapping_.insert({XpowerMessageType::APP_DETAIL, OptimizeMessageType::MESSAGE_APP_DETAIL});
38 procMesTypeMapping_.insert({XpowerMessageType::COMPONENT_TOP, OptimizeMessageType::MESSAGE_COMPONENT_TOP});
39 procMesTypeMapping_.insert({XpowerMessageType::ABNORMAL_EVENTS, OptimizeMessageType::MESSAGE_ABNORMAL_EVENTS});
40 procMesTypeMapping_.insert({XpowerMessageType::THERMAL_REPORT, OptimizeMessageType::MESSAGE_THERMAL_REPORT});
41 }
42
~XpowerPlugin()43 XpowerPlugin::~XpowerPlugin()
44 {
45 if (powerClientHandle_ != nullptr) {
46 dlclose(powerClientHandle_);
47 powerClientHandle_ = nullptr;
48 }
49 }
50
Start(const uint8_t * configData,uint32_t configSize)51 int XpowerPlugin::Start(const uint8_t *configData, uint32_t configSize)
52 {
53 PROFILER_LOG_INFO(LOG_CORE, "%s:config data -->configSize=%d", __func__, configSize);
54 CHECK_TRUE(configData != nullptr, -1, "XpowerPlugin error: param invalid!!!");
55 // 反序列化
56 CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, -1, "%s:parseFromArray failed!", __func__);
57 uint32_t messageType = static_cast<uint32_t>(OptimizeMessageType::MESSAGE_OPTIMIZE_STOP);
58 std::string bundleName = protoConfig_.bundle_name();
59 // Get message type
60 if (protoConfig_.message_type().size() > 0) {
61 for (int i = 0; i < protoConfig_.message_type().size(); i++) {
62 uint32_t mesType = procMesTypeMapping_[static_cast<XpowerMessageType>(protoConfig_.message_type(i))];
63 messageType |= mesType;
64 }
65 }
66 if (messageType == 0) {
67 PROFILER_LOG_ERROR(LOG_CORE, "XpowerPlugin error : messageType is empty!");
68 return -1;
69 }
70 PROFILER_LOG_INFO(LOG_CORE, "bundleName is %s,messagetype is %d", bundleName.c_str(), messageType);
71 if ((messageType & OptimizeMessageType::MESSAGE_APP_STATISTIC) != 0 ||
72 (messageType & OptimizeMessageType::MESSAGE_APP_DETAIL) != 0 ||
73 (messageType & OptimizeMessageType::MESSAGE_ABNORMAL_EVENTS) != 0) {
74 if (bundleName.empty()) {
75 PROFILER_LOG_ERROR(LOG_CORE, "XpowerPlugin error : bundle name is empty!");
76 return -1;
77 }
78 // check bundleName
79 int32_t uid = COMMON::GetPackageUid(bundleName);
80 if (uid < AID_HAP_START || uid > AID_HAP_END) {
81 PROFILER_LOG_ERROR(LOG_CORE, "the bundle name %s is not supported", bundleName.c_str());
82 return -1;
83 }
84 }
85 if ((messageType & OptimizeMessageType::MESSAGE_APP_DETAIL) != 0) {
86 int processId = -1;
87 bool isExsit = COMMON::IsProcessExist(bundleName, processId);
88 if (!isExsit) {
89 PROFILER_LOG_ERROR(LOG_CORE, "%s:the process %s does not exist.", __func__, bundleName.c_str());
90 return -1;
91 }
92 }
93 dataQueuePtr_ = std::make_shared<PowerMessageQueue>(MAX_QUEUE_SIZE);
94 // 加载对应so 库文件
95 if (!StartPowerManager(messageType, bundleName)) {
96 PROFILER_LOG_ERROR(LOG_CORE, "start power manager failed!");
97 return -1;
98 }
99 PROFILER_LOG_INFO(LOG_CORE, "finish register the callback function:%s", __func__);
100 return 0;
101 }
102
StartPowerManager(std::uint32_t messageType,std::string & bundleName)103 bool XpowerPlugin::StartPowerManager(std::uint32_t messageType, std::string &bundleName)
104 {
105 if (powerClientHandle_ == nullptr) {
106 powerClientHandle_ = dlopen("libxpower_manager_client.z.so", RTLD_LAZY);
107 }
108 if (powerClientHandle_ == nullptr) {
109 PROFILER_LOG_ERROR(LOG_CORE, "%s :fail to open libxpower_manager_client.z.so", __func__);
110 return false;
111 }
112 // 注册回调
113 StartOptimizeMode startOptimizeMode = (StartOptimizeMode)dlsym(powerClientHandle_, "StartOptimizeC");
114 if (startOptimizeMode == nullptr) {
115 PROFILER_LOG_ERROR(LOG_CORE, "Failed to dlsy startOptimizeMode");
116 return false;
117 }
118 config_.messageType = messageType;
119 config_.packageName = bundleName;
120 config_.callback = std::bind(&XpowerPlugin::OptimizeCallback, this, std::placeholders::_1, std::placeholders::_2,
121 std::placeholders::_3);
122 listenerHandle_ = startOptimizeMode(config_);
123 if (listenerHandle_ == nullptr) {
124 PROFILER_LOG_ERROR(LOG_CORE, "Failed to startOptimizeMode");
125 return false;
126 }
127 return true;
128 }
129
OptimizeCallback(const std::uint32_t messageType,const uint8_t * protoData,size_t protoSize)130 void XpowerPlugin::OptimizeCallback(const std::uint32_t messageType, const uint8_t *protoData, size_t protoSize)
131 {
132 if (protoData == nullptr || protoSize <= 0) {
133 PROFILER_LOG_ERROR(LOG_CORE, "the power message is invalid !");
134 return;
135 }
136 // write protoData to file
137 if (resultWriter_ != nullptr && resultWriter_->isProtobufSerialize) {
138 resultWriter_->write(resultWriter_, protoData, protoSize);
139 resultWriter_->flush(resultWriter_);
140 }
141 if (dataQueuePtr_->Size() >= MAX_QUEUE_SIZE) {
142 PROFILER_LOG_ERROR(LOG_CORE, "The buffer queue is full,discard message");
143 return;
144 }
145 // 拷贝
146 auto rawData = std::make_shared<PowerOptimizeData>();
147 rawData->baseData = std::make_unique<uint8_t[]>(protoSize);
148 if (memcpy_s(rawData->baseData.get(), protoSize, protoData, protoSize) != EOK) {
149 PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s raw powerdata failed!");
150 return;
151 }
152 rawData->length = protoSize;
153 rawData->messageType = messageType;
154 dataQueuePtr_->PushBack(rawData);
155 }
156
Report(uint8_t * data,uint32_t dataSize)157 int XpowerPlugin::Report(uint8_t *data, uint32_t dataSize)
158 {
159 if (dataQueuePtr_->Empty()) {
160 return 0;
161 }
162 std::shared_ptr<PowerOptimizeData> result = nullptr;
163 if (!dataQueuePtr_->WaitAndPop(result, std::chrono::milliseconds(WAIT_DURATION))) {
164 PROFILER_LOG_ERROR(LOG_CORE, "fetch data error!");
165 return 0;
166 }
167 if (result == nullptr) {
168 PROFILER_LOG_ERROR(LOG_CORE, "fetch data error!");
169 return 0;
170 }
171 if (result->length > dataSize) {
172 return -result->length;
173 }
174 CHECK_TRUE(memcpy_s(data, dataSize, result->baseData.get(), result->length) == EOK, 0, "memcpy_s raw data failed!");
175 return result->length;
176 }
177
SetWriter(WriterStruct * writer)178 void XpowerPlugin::SetWriter(WriterStruct *writer)
179 {
180 resultWriter_ = writer;
181 }
182
Stop()183 int XpowerPlugin::Stop()
184 {
185 PROFILER_LOG_INFO(LOG_CORE, "%s:begin to stop xpower plugin", __func__);
186 StopOptimizeMode stopOptimizeMode = (StopOptimizeMode)dlsym(powerClientHandle_, "StopOptimizeC");
187 if (stopOptimizeMode == nullptr) {
188 PROFILER_LOG_ERROR(LOG_CORE, "Faile to dlsym StopOptimizeC");
189 return -1;
190 }
191 if (listenerHandle_ != nullptr) {
192 stopOptimizeMode(listenerHandle_);
193 PROFILER_LOG_INFO(LOG_CORE, "stop xpower plugin callback");
194 }
195 if (dataQueuePtr_ != nullptr) {
196 dataQueuePtr_->ShutDown();
197 }
198 PROFILER_LOG_INFO(LOG_CORE, "%s:stop xpower plugin success", __func__);
199 return 0;
200 }
201