• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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