• 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 
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