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
GetCmdArgs(const XpowerConfig & traceConfig)51 std::string XpowerPlugin::GetCmdArgs(const XpowerConfig& traceConfig)
52 {
53 std::stringstream args;
54 args << "bundle_name: " << traceConfig.bundle_name() << ", ";
55
56 for (const auto& type : traceConfig.message_type()) {
57 args << "type: " << std::to_string(type) << ", ";
58 }
59 return args.str();
60 }
61
Start(const uint8_t * configData,uint32_t configSize)62 int XpowerPlugin::Start(const uint8_t *configData, uint32_t configSize)
63 {
64 PROFILER_LOG_INFO(LOG_CORE, "%s:config data -->configSize=%d", __func__, configSize);
65 CHECK_TRUE(configData != nullptr, -1, "XpowerPlugin error: param invalid!!!");
66 // 反序列化
67 CHECK_TRUE(protoConfig_.ParseFromArray(configData, configSize) > 0, -1, "%s:parseFromArray failed!", __func__);
68 uint32_t messageType = static_cast<uint32_t>(OptimizeMessageType::MESSAGE_OPTIMIZE_STOP);
69 std::string bundleName = protoConfig_.bundle_name();
70 // Get message type
71 if (protoConfig_.message_type().size() > 0) {
72 for (int i = 0; i < protoConfig_.message_type().size(); i++) {
73 uint32_t mesType = procMesTypeMapping_[static_cast<XpowerMessageType>(protoConfig_.message_type(i))];
74 messageType |= mesType;
75 }
76 }
77 auto args = GetCmdArgs(protoConfig_);
78 if (messageType == 0) {
79 PROFILER_LOG_ERROR(LOG_CORE, "XpowerPlugin error : messageType is empty!");
80 COMMON::PluginWriteToHisysevent("xpower_plugin", "sh", args, COMMON::ErrorType::RET_MSG_EMPTY,
81 "messageType is empty");
82 return -1;
83 }
84 PROFILER_LOG_INFO(LOG_CORE, "bundleName is %s,messagetype is %d", bundleName.c_str(), messageType);
85 if ((messageType & OptimizeMessageType::MESSAGE_APP_STATISTIC) != 0 ||
86 (messageType & OptimizeMessageType::MESSAGE_APP_DETAIL) != 0 ||
87 (messageType & OptimizeMessageType::MESSAGE_ABNORMAL_EVENTS) != 0) {
88 if (bundleName.empty()) {
89 PROFILER_LOG_ERROR(LOG_CORE, "XpowerPlugin error : bundle name is empty!");
90 COMMON::PluginWriteToHisysevent("xpower_plugin", "sh", args, COMMON::ErrorType::RET_MSG_EMPTY,
91 "bundle name is empty");
92 return -1;
93 }
94 // check bundleName
95 int32_t uid = COMMON::GetPackageUid(bundleName);
96 if (uid < AID_HAP_START || uid > AID_HAP_END) {
97 PROFILER_LOG_ERROR(LOG_CORE, "the bundle name %s is not supported", bundleName.c_str());
98 COMMON::PluginWriteToHisysevent("xpower_plugin", "sh", args, COMMON::ErrorType::RET_NOT_SUPPORT,
99 "bundle name is not supported");
100 return -1;
101 }
102 }
103 if ((messageType & OptimizeMessageType::MESSAGE_APP_DETAIL) != 0) {
104 int processId = -1;
105 bool isExsit = COMMON::IsProcessExist(bundleName, processId);
106 if (!isExsit) {
107 PROFILER_LOG_ERROR(LOG_CORE, "%s:the process %s does not exist.", __func__, bundleName.c_str());
108 COMMON::PluginWriteToHisysevent("xpower_plugin", "sh", args, COMMON::ErrorType::RET_INVALID_PID,
109 "the process does not exist");
110 return -1;
111 }
112 }
113 dataQueuePtr_ = std::make_shared<PowerMessageQueue>(MAX_QUEUE_SIZE);
114 // 加载对应so 库文件
115 if (!StartPowerManager(messageType, bundleName)) {
116 PROFILER_LOG_ERROR(LOG_CORE, "start power manager failed!");
117 COMMON::PluginWriteToHisysevent("xpower_plugin", "sh", args, COMMON::ErrorType::RET_FAIL,
118 "start power manager failed");
119 return -1;
120 }
121 int ret = COMMON::PluginWriteToHisysevent("xpower_plugin", "sh", args, COMMON::ErrorType::RET_SUCC, "success");
122 PROFILER_LOG_INFO(LOG_CORE, "finish register the callback function:%s, hisysevent report xpower_plugin ret: %d.",
123 __func__, ret);
124 return 0;
125 }
126
StartPowerManager(std::uint32_t messageType,std::string & bundleName)127 bool XpowerPlugin::StartPowerManager(std::uint32_t messageType, std::string &bundleName)
128 {
129 if (powerClientHandle_ == nullptr) {
130 powerClientHandle_ = dlopen("libxpower_manager_client.z.so", RTLD_LAZY);
131 }
132 if (powerClientHandle_ == nullptr) {
133 PROFILER_LOG_ERROR(LOG_CORE, "%s :fail to open libxpower_manager_client.z.so", __func__);
134 return false;
135 }
136 // 注册回调
137 StartOptimizeMode startOptimizeMode = (StartOptimizeMode)dlsym(powerClientHandle_, "StartOptimizeC");
138 if (startOptimizeMode == nullptr) {
139 PROFILER_LOG_ERROR(LOG_CORE, "Failed to dlsy startOptimizeMode");
140 return false;
141 }
142 config_.messageType = messageType;
143 config_.packageName = bundleName;
144 config_.callback = std::bind(&XpowerPlugin::OptimizeCallback, this, std::placeholders::_1, std::placeholders::_2,
145 std::placeholders::_3);
146 listenerHandle_ = startOptimizeMode(config_);
147 if (listenerHandle_ == nullptr) {
148 PROFILER_LOG_ERROR(LOG_CORE, "Failed to startOptimizeMode");
149 return false;
150 }
151 return true;
152 }
153
OptimizeCallback(const std::uint32_t messageType,const uint8_t * protoData,size_t protoSize)154 void XpowerPlugin::OptimizeCallback(const std::uint32_t messageType, const uint8_t *protoData, size_t protoSize)
155 {
156 if (protoData == nullptr || protoSize <= 0) {
157 PROFILER_LOG_ERROR(LOG_CORE, "the power message is invalid !");
158 return;
159 }
160 // write protoData to file
161 if (resultWriter_ != nullptr && resultWriter_->isProtobufSerialize) {
162 resultWriter_->write(resultWriter_, protoData, protoSize);
163 resultWriter_->flush(resultWriter_);
164 }
165 if (dataQueuePtr_->Size() >= MAX_QUEUE_SIZE) {
166 PROFILER_LOG_ERROR(LOG_CORE, "The buffer queue is full,discard message");
167 return;
168 }
169 // 拷贝
170 auto rawData = std::make_shared<PowerOptimizeData>();
171 rawData->baseData = std::make_unique<uint8_t[]>(protoSize);
172 if (memcpy_s(rawData->baseData.get(), protoSize, protoData, protoSize) != EOK) {
173 PROFILER_LOG_ERROR(LOG_CORE, "memcpy_s raw powerdata failed!");
174 return;
175 }
176 rawData->length = protoSize;
177 rawData->messageType = messageType;
178 dataQueuePtr_->PushBack(rawData);
179 }
180
Report(uint8_t * data,uint32_t dataSize)181 int XpowerPlugin::Report(uint8_t *data, uint32_t dataSize)
182 {
183 if (dataQueuePtr_->Empty()) {
184 return 0;
185 }
186 std::shared_ptr<PowerOptimizeData> result = nullptr;
187 if (!dataQueuePtr_->WaitAndPop(result, std::chrono::milliseconds(WAIT_DURATION))) {
188 PROFILER_LOG_ERROR(LOG_CORE, "fetch data error!");
189 return 0;
190 }
191 if (result == nullptr) {
192 PROFILER_LOG_ERROR(LOG_CORE, "fetch data error!");
193 return 0;
194 }
195 if (result->length > dataSize) {
196 return -result->length;
197 }
198 CHECK_TRUE(memcpy_s(data, dataSize, result->baseData.get(), result->length) == EOK, 0, "memcpy_s raw data failed!");
199 return result->length;
200 }
201
SetWriter(WriterStruct * writer)202 void XpowerPlugin::SetWriter(WriterStruct *writer)
203 {
204 resultWriter_ = writer;
205 }
206
Stop()207 int XpowerPlugin::Stop()
208 {
209 PROFILER_LOG_INFO(LOG_CORE, "%s:begin to stop xpower plugin", __func__);
210 StopOptimizeMode stopOptimizeMode = (StopOptimizeMode)dlsym(powerClientHandle_, "StopOptimizeC");
211 if (stopOptimizeMode == nullptr) {
212 PROFILER_LOG_ERROR(LOG_CORE, "Faile to dlsym StopOptimizeC");
213 return -1;
214 }
215 if (listenerHandle_ != nullptr) {
216 stopOptimizeMode(listenerHandle_);
217 PROFILER_LOG_INFO(LOG_CORE, "stop xpower plugin callback");
218 }
219 if (dataQueuePtr_ != nullptr) {
220 dataQueuePtr_->ShutDown();
221 }
222 PROFILER_LOG_INFO(LOG_CORE, "%s:stop xpower plugin success", __func__);
223 return 0;
224 }
225