1 /*
2  * Copyright (c) 2021-2024 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 "dcamera_utils_tools.h"
17 
18 #include <chrono>
19 #include <dlfcn.h>
20 #include <string>
21 #include <sstream>
22 #include <ostream>
23 
24 #include "distributed_camera_constants.h"
25 #include "distributed_camera_errno.h"
26 #include "distributed_hardware_log.h"
27 #include "parameter.h"
28 
29 #include "softbus_bus_center.h"
30 
31 namespace OHOS {
32 namespace DistributedHardware {
33 namespace {
34 const std::string YUV_LIB_PATH = "libyuv.z.so";
35 const std::string GET_IMAGE_CONVERTER_FUNC = "GetImageConverter";
36 }
37 
38 #ifdef DCAMERA_MMAP_RESERVE
39 using GetImageConverterFunc = OHOS::OpenSourceLibyuv::ImageConverter (*)();
40 #endif
41 
42 const uint32_t OFFSET2 = 2;
43 const uint32_t OFFSET4 = 4;
44 const uint32_t OFFSET6 = 6;
45 const uint8_t PARAM_FC = 0xfc;
46 const uint8_t PARAM_03 = 0x03;
47 const uint8_t PARAM_F0 = 0xf0;
48 const uint8_t PARAM_0F = 0x0f;
49 const uint8_t PARAM_C0 = 0xc0;
50 const uint8_t PARAM_3F = 0x3f;
51 const int INDEX_FIRST = 0;
52 const int INDEX_SECOND = 1;
53 const int INDEX_THIRD = 2;
54 const int INDEX_FORTH = 3;
GetLocalDeviceNetworkId(std::string & networkId)55 int32_t GetLocalDeviceNetworkId(std::string& networkId)
56 {
57     NodeBasicInfo basicInfo = { { 0 } };
58     int32_t ret = GetLocalNodeDeviceInfo(DCAMERA_PKG_NAME.c_str(), &basicInfo);
59     if (ret != DCAMERA_OK) {
60         DHLOGE("GetLocalNodeDeviceInfo failed ret: %{public}d", ret);
61         return ret;
62     }
63 
64     networkId = std::string(basicInfo.networkId);
65     return DCAMERA_OK;
66 }
67 
GetNowTimeStampMs()68 int64_t GetNowTimeStampMs()
69 {
70     std::chrono::milliseconds nowMs = std::chrono::duration_cast<std::chrono::milliseconds>(
71         std::chrono::system_clock::now().time_since_epoch());
72     return nowMs.count();
73 }
74 
GetNowTimeStampUs()75 int64_t GetNowTimeStampUs()
76 {
77     std::chrono::microseconds nowUs = std::chrono::duration_cast<std::chrono::microseconds>(
78         std::chrono::system_clock::now().time_since_epoch());
79     return nowUs.count();
80 }
81 
GetAlignedHeight(int32_t width)82 int32_t GetAlignedHeight(int32_t width)
83 {
84     int32_t alignedBits = 32;
85     int32_t alignedHeight = width;
86     if (alignedHeight % alignedBits != 0) {
87         alignedHeight = ((alignedHeight / alignedBits) + 1) * alignedBits;
88     }
89     return alignedHeight;
90 }
91 
Base64Encode(const unsigned char * toEncode,unsigned int len)92 std::string Base64Encode(const unsigned char *toEncode, unsigned int len)
93 {
94     std::string ret = "";
95     if (len == 0 || toEncode == nullptr) {
96         DHLOGE("toEncode is null or len is zero.");
97         return ret;
98     }
99     int32_t length = static_cast<int32_t>(len);
100     uint32_t i = 0;
101     unsigned char charArray3[3];
102     unsigned char charArray4[4];
103 
104     while (length--) {
105         charArray3[i++] = *(toEncode++);
106         if (i == sizeof(charArray3)) {
107             charArray4[INDEX_FIRST] = (charArray3[INDEX_FIRST] & PARAM_FC) >> OFFSET2;
108             charArray4[INDEX_SECOND] = ((charArray3[INDEX_FIRST] & PARAM_03) << OFFSET4) +
109                 ((charArray3[INDEX_SECOND] & PARAM_F0) >> OFFSET4);
110             charArray4[INDEX_THIRD] = ((charArray3[INDEX_SECOND] & PARAM_0F) << OFFSET2) +
111                 ((charArray3[INDEX_THIRD] & PARAM_C0) >> OFFSET6);
112             charArray4[INDEX_FORTH] = charArray3[INDEX_THIRD] & PARAM_3F;
113             for (i = 0; i < sizeof(charArray4); i++) {
114                 ret += BASE_64_CHARS[charArray4[i]];
115             }
116             i = 0;
117         }
118     }
119 
120     if (i > 0) {
121         uint32_t j = 0;
122         for (j = i; j < sizeof(charArray3); j++) {
123             charArray3[j] = '\0';
124         }
125         charArray4[INDEX_FIRST] = (charArray3[INDEX_FIRST] & PARAM_FC) >> OFFSET2;
126         charArray4[INDEX_SECOND] = ((charArray3[INDEX_FIRST] & PARAM_03) << OFFSET4) +
127             ((charArray3[INDEX_SECOND] & PARAM_F0) >> OFFSET4);
128         charArray4[INDEX_THIRD] = ((charArray3[INDEX_SECOND] & PARAM_0F) << OFFSET2) +
129             ((charArray3[INDEX_THIRD] & PARAM_C0) >> OFFSET6);
130         charArray4[INDEX_FORTH] = charArray3[INDEX_THIRD] & PARAM_3F;
131         for (j = 0; j < i + 1; j++) {
132             ret += BASE_64_CHARS[charArray4[j]];
133         }
134         while (i++ < sizeof(charArray3)) {
135             ret += '=';
136         }
137     }
138     return ret;
139 }
140 
Base64Decode(const std::string & basicString)141 std::string Base64Decode(const std::string& basicString)
142 {
143     std::string ret = "";
144     if (basicString.empty()) {
145         DHLOGE("basicString is empty.");
146         return ret;
147     }
148     uint32_t i = 0;
149     int index = 0;
150     int len = static_cast<int>(basicString.size());
151     unsigned char charArray3[3];
152     unsigned char charArray4[4];
153 
154     while (len-- && (basicString[index] != '=') && IsBase64(basicString[index])) {
155         charArray4[i++] = basicString[index];
156         index++;
157         if (i == sizeof(charArray4)) {
158             for (i = 0; i < sizeof(charArray4); i++) {
159                 charArray4[i] = BASE_64_CHARS.find(charArray4[i]);
160             }
161             charArray3[INDEX_FIRST] = (charArray4[INDEX_FIRST] << OFFSET2) +
162                 ((charArray4[INDEX_SECOND] & 0x30) >> OFFSET4);
163             charArray3[INDEX_SECOND] = ((charArray4[INDEX_SECOND] & 0xf) << OFFSET4) +
164                 ((charArray4[INDEX_THIRD] & 0x3c) >> OFFSET2);
165             charArray3[INDEX_THIRD] = ((charArray4[INDEX_THIRD] & 0x3) << OFFSET6) + charArray4[INDEX_FORTH];
166             for (i = 0; i < sizeof(charArray3); i++) {
167                 ret += charArray3[i];
168             }
169             i = 0;
170         }
171     }
172 
173     if (i > 0) {
174         uint32_t j = 0;
175         for (j = i; j < sizeof(charArray4); j++) {
176             charArray4[j] = 0;
177         }
178         for (j = 0; j < sizeof(charArray4); j++) {
179             charArray4[j] = BASE_64_CHARS.find(charArray4[j]);
180         }
181         charArray3[INDEX_FIRST] = (charArray4[INDEX_FIRST] << OFFSET2) +
182             ((charArray4[INDEX_SECOND] & 0x30) >> OFFSET4);
183         charArray3[INDEX_SECOND] = ((charArray4[INDEX_SECOND] & 0xf) << OFFSET4) +
184             ((charArray4[INDEX_THIRD] & 0x3c) >> OFFSET2);
185         charArray3[INDEX_THIRD] = ((charArray4[INDEX_THIRD] & 0x3) << OFFSET6) + charArray4[INDEX_FORTH];
186         for (j = 0; j < i - 1; j++) {
187             ret += charArray3[j];
188         }
189     }
190     return ret;
191 }
192 
IsBase64(unsigned char c)193 bool IsBase64(unsigned char c)
194 {
195     return (isalnum(c) || (c == '+') || (c == '/'));
196 }
197 
DumpBufferToFile(const std::string fileName,uint8_t * buffer,size_t bufSize)198 void DumpBufferToFile(const std::string fileName, uint8_t *buffer, size_t bufSize)
199 {
200     if (fileName.empty() || buffer == nullptr) {
201         DHLOGE("dumpsaving : input param err.");
202         return;
203     }
204     char path[PATH_MAX + 1] = {0x00};
205     if (fileName.length() > PATH_MAX || realpath(fileName.c_str(), path) == nullptr) {
206         DHLOGE("The file path is invalid.");
207         return;
208     }
209     std::ofstream ofs(path, std::ios::binary | std::ios::out | std::ios::app);
210     if (!ofs.is_open()) {
211         DHLOGE("dumpsaving : open file failed.");
212         return;
213     }
214     ofs.write(reinterpret_cast<const char*>(buffer), bufSize);
215     ofs.close();
216     return;
217 }
218 
IsUnderDumpMaxSize(const std::string fileName)219 int32_t IsUnderDumpMaxSize(const std::string fileName)
220 {
221     if (fileName.empty()) {
222         DHLOGE("dumpsaving : input fileName empty.");
223         return DCAMERA_INIT_ERR;
224     }
225     char path[PATH_MAX + 1] = {0x00};
226     if (fileName.length() > PATH_MAX || realpath(fileName.c_str(), path) == nullptr) {
227         DHLOGE("The file path is invalid.");
228         return DCAMERA_INIT_ERR;
229     }
230     std::ofstream ofs(path, std::ios::binary | std::ios::out | std::ios::app);
231     if (!ofs.is_open()) {
232         DHLOGE("dumpsaving : open file failed.");
233         return DCAMERA_INIT_ERR;
234     }
235     ofs.seekp(0, std::ios::end);
236     std::ofstream::pos_type fileSize = ofs.tellp();
237     if (fileSize < 0) {
238         DHLOGE("filesize get err");
239         fileSize = 0;
240         return DCAMERA_INIT_ERR;
241     }
242     ofs.close();
243     if (static_cast<int32_t>(fileSize) <= DUMP_FILE_MAX_SIZE) {
244         return DCAMERA_OK;
245     } else {
246         return DCAMERA_BAD_VALUE;
247     }
248 }
249 
250 #ifdef DCAMERA_MMAP_RESERVE
251 IMPLEMENT_SINGLE_INSTANCE(ConverterHandle);
InitConverter()252 void ConverterHandle::InitConverter()
253 {
254     dlHandler_ = dlopen(YUV_LIB_PATH.c_str(), RTLD_LAZY | RTLD_NODELETE);
255     if (dlHandler_ == nullptr) {
256         DHLOGE("Dlopen failed.");
257         return;
258     }
259     GetImageConverterFunc getConverter = (GetImageConverterFunc)dlsym(dlHandler_, GET_IMAGE_CONVERTER_FUNC.c_str());
260     if (getConverter == nullptr) {
261         DHLOGE("Function of converter is null, failed reason: %s.", dlerror());
262         dlclose(dlHandler_);
263         dlHandler_ = nullptr;
264         return;
265     }
266     converter_ = getConverter();
267     isInited_.store(true);
268     DHLOGI("Initialize image converter success.");
269 }
270 
DeInitConverter()271 void ConverterHandle::DeInitConverter()
272 {
273     if (dlHandler_) {
274         dlclose(dlHandler_);
275         dlHandler_ = nullptr;
276     }
277     isInited_.store(false);
278 }
279 
GetHandle()280 const OHOS::OpenSourceLibyuv::ImageConverter& ConverterHandle::GetHandle()
281 {
282     if (!isInited_.load()) {
283         InitConverter();
284     }
285     return converter_;
286 }
287 #endif
288 
289 template <typename T>
GetSysPara(const char * key,T & value)290 bool GetSysPara(const char *key, T &value)
291 {
292     CHECK_AND_RETURN_RET_LOG(key == nullptr, false, "key is nullptr");
293     char paraValue[30] = {0}; // 30 for system parameter
294     auto res = GetParameter(key, "-1", paraValue, sizeof(paraValue));
295 
296     CHECK_AND_RETURN_RET_LOG(res <= 0, false, "GetParameter fail, key:%{public}s res:%{public}d", key, res);
297     DHLOGD("GetSysPara key:%{public}s value:%{public}s", key, paraValue);
298     std::stringstream valueStr;
299     valueStr << paraValue;
300     valueStr >> value;
301     return true;
302 }
303 
304 template bool GetSysPara(const char *key, int32_t &value);
305 template bool GetSysPara(const char *key, uint32_t &value);
306 template bool GetSysPara(const char *key, int64_t &value);
307 template bool GetSysPara(const char *key, std::string &value);
308 
309 std::map<std::string, std::string> DumpFileUtil::g_lastPara = {};
310 
OpenDumpFileInner(std::string para,std::string fileName)311 FILE *DumpFileUtil::OpenDumpFileInner(std::string para, std::string fileName)
312 {
313     std::string filePath = DUMP_SERVICE_DIR + fileName;
314     std::string dumpPara;
315     FILE *dumpFile = nullptr;
316     char path[PATH_MAX + 1] = {0x00};
317     if (filePath.length() > PATH_MAX || realpath(filePath.c_str(), path) == nullptr) {
318         DHLOGE("The file path is invalid.");
319         return dumpFile;
320     }
321     bool res = GetSysPara(para.c_str(), dumpPara);
322     if (!res || dumpPara.empty()) {
323         DHLOGI("%{public}s is not set, dump dcamera is not required", para.c_str());
324         g_lastPara[para] = dumpPara;
325         return dumpFile;
326     }
327     DHLOGD("%{public}s = %{public}s, filePath: %{public}s", para.c_str(), dumpPara.c_str(), path);
328     if (dumpPara == "w") {
329         dumpFile = fopen(path, "wb+");
330         CHECK_AND_RETURN_RET_LOG(dumpFile == nullptr, dumpFile, "Error opening dump file!");
331     } else if (dumpPara == "a") {
332         dumpFile = fopen(path, "ab+");
333         CHECK_AND_RETURN_RET_LOG(dumpFile == nullptr, dumpFile, "Error opening dump file!");
334     }
335     g_lastPara[para] = dumpPara;
336     return dumpFile;
337 }
338 
WriteDumpFile(FILE * dumpFile,void * buffer,size_t bufferSize)339 void DumpFileUtil::WriteDumpFile(FILE *dumpFile, void *buffer, size_t bufferSize)
340 {
341     if (dumpFile == nullptr) {
342         return;
343     }
344     CHECK_AND_RETURN_LOG(buffer == nullptr, "Invalid write param");
345     size_t writeResult = fwrite(buffer, 1, bufferSize, dumpFile);
346     CHECK_AND_RETURN_LOG(writeResult != bufferSize, "Failed to write the file.");
347 }
348 
CloseDumpFile(FILE ** dumpFile)349 void DumpFileUtil::CloseDumpFile(FILE **dumpFile)
350 {
351     if (*dumpFile) {
352         fclose(*dumpFile);
353         *dumpFile = nullptr;
354     }
355 }
356 
ChangeDumpFileState(std::string para,FILE ** dumpFile,std::string filePath)357 void DumpFileUtil::ChangeDumpFileState(std::string para, FILE **dumpFile, std::string filePath)
358 {
359     CHECK_AND_RETURN_LOG(*dumpFile == nullptr, "Invalid file para");
360     CHECK_AND_RETURN_LOG(g_lastPara[para] != "w" || g_lastPara[para] != "a", "Invalid input para");
361     std::string dumpPara;
362     bool res = GetSysPara(para.c_str(), dumpPara);
363     if (!res || dumpPara.empty()) {
364         DHLOGE("get %{public}s fail", para.c_str());
365     }
366     if (g_lastPara[para] == "w" && dumpPara == "w") {
367         return;
368     }
369     CloseDumpFile(dumpFile);
370     OpenDumpFile(para, filePath, dumpFile);
371 }
372 
OpenDumpFile(std::string para,std::string fileName,FILE ** file)373 void DumpFileUtil::OpenDumpFile(std::string para, std::string fileName, FILE **file)
374 {
375     if (*file != nullptr) {
376         DumpFileUtil::ChangeDumpFileState(para, file, fileName);
377         return;
378     }
379 
380     if (para == DUMP_SERVER_PARA) {
381         *file = DumpFileUtil::OpenDumpFileInner(para, fileName);
382     }
383 }
384 } // namespace DistributedHardware
385 } // namespace OHOS
386