• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 Huawei Device Co., Ltd.
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 
16 #include "mtp_dfx_reporter.h"
17 
18 #include <set>
19 #include <thread>
20 #include <map>
21 
22 #include "hisysevent.h"
23 #include "media_log.h"
24 #include "medialibrary_errno.h"
25 #include "mtp_manager.h"
26 #include "mtp_constants.h"
27 
28 namespace OHOS {
29 namespace Media {
30 using namespace std;
31 static constexpr char MEDIA_LIBRARY[] = "MEDIALIBRARY";
32 constexpr int32_t MTP_MODE = 1;
33 constexpr int32_t PTP_MODE = 2;
34 static std::mutex mutex;
35 static std::unordered_map<std::string, FileCountInfo> fileCountInfoMap;
36 static std::unordered_map<uint16_t, std::pair<int32_t, int32_t>> operationStats;
37 constexpr int32_t MAX_FILE_COUNT_INFO = 50;
38 const std::string GARBLE = "*";
39 constexpr uint32_t GARBLE_SMALL = 3;
40 constexpr uint32_t GARBLE_LARGE = 8;
41 constexpr uint32_t GARBLE_LAST_TWO = 2;
42 constexpr uint32_t GARBLE_LAST_ONE = 1;
43 static const char *UTF16_CERROR = "__CONVERSION_ERROR__";
44 static const char16_t *g_utf8Cerror = u"__CONVERSION_ERROR__";
45 
46 static const std::vector<std::pair<uint16_t, std::string>> ObjMediaPropTypeMap = {
47     {MTP_OPERATION_GET_OBJECT_HANDLES_CODE, "MTP_GET_OBJECT_HANDLES_INFO"},
48     {MTP_OPERATION_GET_OBJECT_CODE, "MTP_GET_OBJECT_INFO"},
49     {MTP_OPERATION_GET_PARTIAL_OBJECT_CODE, "MTP_GET_PARTIAL_OBJECT_INFO"},
50     {MTP_OPERATION_DELETE_OBJECT_CODE, "MTP_DELETE_OBJECT_INFO"},
51     {MTP_OPERATION_SEND_OBJECT_CODE, "MTP_SEND_OBJECT_INFO"},
52     {MTP_OPERATION_SET_OBJECT_PROP_VALUE_CODE, "MTP_SET_OBJECT_PROP_VALUE_INFO"},
53     {MTP_OPERATION_MOVE_OBJECT_CODE, "MTP_MOVE_OBJECT_INFO"},
54     {MTP_OPERATION_COPY_OBJECT_CODE, "MTP_COPY_OBJECT_INFO"}
55 };
56 
GetInstance()57 MtpDfxReporter &MtpDfxReporter::GetInstance()
58 {
59     static MtpDfxReporter instance;
60     return instance;
61 }
62 
Init()63 void MtpDfxReporter::Init()
64 {
65     MEDIA_INFO_LOG("MtpDfxReporter::Init");
66     std::lock_guard<std::mutex> lock(mutex);
67     std::unordered_map<std::string, FileCountInfo>().swap(fileCountInfoMap);
68     std::unordered_map<uint16_t, std::pair<int32_t, int32_t>>().swap(operationStats);
69     for (const auto& key : ObjMediaPropTypeMap) {
70         operationStats[key.first] = {0, 0};
71     }
72     lastReadResult_ = 0;
73 }
74 
DoFileCountInfoStatistics(const FileCountInfo & fileCountInfo)75 void MtpDfxReporter::DoFileCountInfoStatistics(const FileCountInfo &fileCountInfo)
76 {
77     std::lock_guard<std::mutex> lock(mutex);
78     auto it = fileCountInfoMap.find(fileCountInfo.albumName);
79     if (it == fileCountInfoMap.end()) {
80         fileCountInfoMap[fileCountInfo.albumName] = fileCountInfo;
81         return;
82     }
83     it->second.pictureCount = fileCountInfo.pictureCount;
84     it->second.videoCount = fileCountInfo.videoCount;
85     it->second.normalCount = fileCountInfo.normalCount;
86     it->second.livePhotoCount = fileCountInfo.livePhotoCount;
87     it->second.onlyInCloudPhotoCount = fileCountInfo.onlyInCloudPhotoCount;
88     it->second.burstCount = fileCountInfo.burstCount;
89     it->second.burstTotalCount = fileCountInfo.burstTotalCount;
90 }
91 
IsKeyInObjMediaPropTypeMap(uint16_t key)92 static bool IsKeyInObjMediaPropTypeMap(uint16_t key)
93 {
94     auto it = std::find_if(ObjMediaPropTypeMap.begin(), ObjMediaPropTypeMap.end(),
95         [key](const std::pair<uint16_t, std::string>& item) {
96             return item.first == key;
97         });
98 
99     return it != ObjMediaPropTypeMap.end();
100 }
101 
DoOperationResultStatistics(uint16_t operation,uint16_t responseCode)102 void MtpDfxReporter::DoOperationResultStatistics(uint16_t operation, uint16_t responseCode)
103 {
104     if (IsKeyInObjMediaPropTypeMap(operation)) {
105         std::lock_guard<std::mutex> lock(mutex);
106         if (responseCode == MTP_OK_CODE) {
107             operationStats[operation].first++;
108         } else {
109             operationStats[operation].second++;
110         }
111     }
112 }
113 
DoFileCountInfoDfxReporter(int32_t mtpMode,std::vector<std::string> & result)114 void MtpDfxReporter::DoFileCountInfoDfxReporter(int32_t mtpMode, std::vector<std::string> &result)
115 {
116     int ret = HiSysEventWrite(
117         MEDIA_LIBRARY,
118         "MEDIALIB_MTP_PTP_SYNC_RESULT",
119         HiviewDFX::HiSysEvent::EventType::STATISTIC,
120         "MTP_MODE", mtpMode,
121         "FILE_COUNT_INFO", result);
122     if (ret != 0) {
123         MEDIA_ERR_LOG("DoBatchFileCountInfoDfxReporter error:%{public}d", ret);
124     }
125 }
126 
DoBatchFileCountInfoDfxReporter(int32_t mtpMode)127 void MtpDfxReporter::DoBatchFileCountInfoDfxReporter(int32_t mtpMode)
128 {
129     vector<std::string> result;
130     std::lock_guard<std::mutex> lock(mutex);
131     uint32_t count = 0;
132     for (const auto& [key, info] : fileCountInfoMap) {
133         string albumName = GetSafeAlbumNameWhenChinese(key);
134         string resultStr = std::move(albumName) + "," + to_string(info.pictureCount) + "," +
135             to_string(info.videoCount) + "," + to_string(info.normalCount) + "," +
136             to_string(info.livePhotoCount) + "," + to_string(info.onlyInCloudPhotoCount) + "," +
137             to_string(info.burstCount) + "," + to_string(info.burstTotalCount);
138         result.push_back(resultStr);
139         count++;
140         if (count >= MAX_FILE_COUNT_INFO) {
141             count = 0;
142             DoFileCountInfoDfxReporter(mtpMode, result);
143             result.clear();
144         }
145     }
146     MEDIA_INFO_LOG("MtpDfxReporter:DoBatchFileCountInfoDfxReporter result.size():%{public}zu", result.size());
147     if (result.size() > 0) {
148         DoFileCountInfoDfxReporter(mtpMode, result);
149     }
150     std::unordered_map<std::string, FileCountInfo>().swap(fileCountInfoMap);
151 }
152 
DoOperationResultDfxReporter(int32_t mtpMode)153 void MtpDfxReporter::DoOperationResultDfxReporter(int32_t mtpMode)
154 {
155     std::vector<std::pair<std::string, std::vector<int32_t>>> stats;
156     {
157         std::lock_guard<std::mutex> lock(mutex);
158         for (const auto& mapping : ObjMediaPropTypeMap) {
159             uint16_t operationCode = mapping.first;
160             const std::string& keyName = mapping.second;
161             std::vector<int32_t> operationInfoCount = {
162                 operationStats[operationCode].first,
163                 operationStats[operationCode].second
164             };
165             stats.emplace_back(keyName, operationInfoCount);
166         }
167     }
168 
169     int ret = HiSysEventWrite(
170         MEDIA_LIBRARY,
171         "MEDIALIB_MTP_OPERATION_RESULT",
172         HiviewDFX::HiSysEvent::EventType::STATISTIC,
173         "MTP_MODE", mtpMode,
174         stats[GET_OBJECT_HANDLES].first.c_str(), stats[GET_OBJECT_HANDLES].second,
175         stats[GET_OBJECT].first.c_str(), stats[GET_OBJECT].second,
176         stats[GET_PARTIAL_OBJECT].first.c_str(), stats[GET_PARTIAL_OBJECT].second,
177         stats[DELETE_OBJECT].first.c_str(), stats[DELETE_OBJECT].second,
178         stats[SEND_OBJECT].first.c_str(), stats[SEND_OBJECT].second,
179         stats[SET_OBJECT_PROP_VALUE].first.c_str(), stats[SET_OBJECT_PROP_VALUE].second,
180         stats[MOVE_OBJECT].first.c_str(), stats[MOVE_OBJECT].second,
181         stats[COPY_OBJECT].first.c_str(), stats[COPY_OBJECT].second
182     );
183     if (ret != 0) {
184         MEDIA_ERR_LOG("DoOperationResultDfxReporter error:%{public}d", ret);
185     }
186     {
187         std::lock_guard<std::mutex> lock(mutex);
188         std::unordered_map<uint16_t, std::pair<int32_t, int32_t>>().swap(operationStats);
189     }
190 }
191 
NotifyDoDfXReporter(int32_t mtpMode)192 void MtpDfxReporter::NotifyDoDfXReporter(int32_t mtpMode)
193 {
194     MEDIA_INFO_LOG("MtpDfxReporter:NotifyDoDfXReporter mtpMode:%{public}d", mtpMode);
195     std::thread([&, mtpMode]() {
196         DoBatchFileCountInfoDfxReporter(mtpMode);
197         DoOperationResultDfxReporter(mtpMode);
198     }).detach();
199 }
200 
DoSendResponseResultDfxReporter(uint16_t operationCode,int32_t operationResult,uint64_t duration,int32_t operationMode)201 void MtpDfxReporter::DoSendResponseResultDfxReporter(uint16_t operationCode, int32_t operationResult,
202     uint64_t duration, int32_t operationMode)
203 {
204     if (operationResult == 0) {
205         return;
206     }
207     if (operationMode == readmode && operationResult == E_USB_DISCONNECT) {
208         if (lastReadResult_ == E_USB_DISCONNECT) {
209             MEDIA_DEBUG_LOG("DoSendResponseResultDfxReporter is called, operationResult is E_USB_DISCONNECT");
210             return;
211         }
212         lastReadResult_ = operationResult;
213     }
214     MEDIA_INFO_LOG("MtpDfxReporter operationCode:0x%{public}x, operationResult:%{public}d", operationCode,
215         operationResult);
216     int32_t mtpMode;
217     if (MtpManager::GetInstance().IsMtpMode()) {
218         mtpMode = MTP_MODE;
219     } else {
220         mtpMode = PTP_MODE;
221     }
222     int ret = HiSysEventWrite(
223         MEDIA_LIBRARY,
224         "MEDIALIB_MTP_PTP_SEND_RESPONSE",
225         HiviewDFX::HiSysEvent::EventType::STATISTIC,
226         "MTP_MODE", mtpMode,
227         "OPERATION_CODE", operationCode,
228         "OPERATION_RESULT", operationResult,
229         "OPERATION_COST_TIME", duration,
230         "OPERATION_MODE", operationMode);
231     if (ret != 0) {
232         MEDIA_ERR_LOG("DoSendResponseResultDfxReporter error:%{public}d", ret);
233     }
234 }
235 
Str8ToStr16(const std::string & inputStr)236 static std::u16string Str8ToStr16(const std::string &inputStr)
237 {
238     if (inputStr.empty()) {
239         return u"";
240     }
241     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(UTF16_CERROR, g_utf8Cerror);
242     std::u16string result = convert.from_bytes(inputStr);
243     return result == g_utf8Cerror ? u"" : result;
244 }
245 
Str16ToStr8(const std::u16string & inputStr)246 static std::string Str16ToStr8(const std::u16string &inputStr)
247 {
248     if (inputStr.empty()) {
249         return "";
250     }
251     std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(UTF16_CERROR, g_utf8Cerror);
252     std::string result = convert.to_bytes(inputStr);
253     return result == UTF16_CERROR ? "" : result;
254 }
255 
GetSafeAlbumNameWhenChinese(const string & albumName)256 string MtpDfxReporter::GetSafeAlbumNameWhenChinese(const string &albumName)
257 {
258     MEDIA_INFO_LOG("MtpDfxReporter:GetSafeAlbumNameWhenChinese");
259     CHECK_AND_RETURN_RET_LOG(!albumName.empty(), "", "input albumName is empty");
260     std::u16string wideStr = Str8ToStr16(albumName);
261     uint32_t length = wideStr.size();
262     if (length <= 0) {
263         return GARBLE;
264     }
265     std::u16string safeAlbumName;
266     if (length <= GARBLE_SMALL) {
267         safeAlbumName = wideStr.substr(length - GARBLE_LAST_ONE);
268     } else if (length > GARBLE_LARGE) {
269         safeAlbumName = wideStr.substr(GARBLE_LARGE);
270     } else {
271         safeAlbumName = wideStr.substr(length - GARBLE_LAST_TWO);
272     }
273     return GARBLE + Str16ToStr8(safeAlbumName);
274 }
275 } // namespace Media
276 } // namespace OHOS
277