• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "nncompiled_cache.h"
17 
18 #include <unistd.h>
19 #include <functional>
20 #include <memory>
21 #include <limits>
22 #include <cstdio>
23 #include <securec.h>
24 
25 #include "utils.h"
26 #include "backend_manager.h"
27 #include "nnbackend.h"
28 
29 namespace OHOS {
30 namespace NeuralNetworkRuntime {
31 constexpr int32_t NULL_PTR_LENGTH = 0;
32 constexpr int32_t NUMBER_CACHE_INFO_MEMBERS = 3;
33 constexpr int32_t NUMBER_CACHE_INFO_EXTENSION_MEMBERS = 2;
34 constexpr int32_t HEX_UNIT = 16;
35 constexpr size_t MAX_CACHE_SIZE = 2 * 1024 * 1024; // 限制最大校验内存为2MB
36 constexpr char ROOT_DIR_STR = '/';
37 constexpr char DOUBLE_SLASH_STR[] = "//";
38 
Save(const std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches,const std::string & cacheDir,uint32_t version)39 OH_NN_ReturnCode NNCompiledCache::Save(const std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches,
40                                        const std::string& cacheDir,
41                                        uint32_t version)
42 {
43     if (caches.empty()) {
44         LOGE("[NNCompiledCache] Save failed, caches is empty.");
45         return OH_NN_INVALID_PARAMETER;
46     }
47 
48     if (m_device == nullptr) {
49         LOGE("[NNCompiledCache] Save failed, m_device is empty.");
50         return OH_NN_INVALID_PARAMETER;
51     }
52 
53     OH_NN_ReturnCode ret = GenerateCacheFiles(caches, cacheDir, version);
54     if (ret != OH_NN_SUCCESS) {
55         LOGE("[NNCompiledCache] Save failed, error happened when calling GenerateCacheFiles.");
56         return ret;
57     }
58 
59     return OH_NN_SUCCESS;
60 }
61 
CheckCache(const std::string & cacheDir,uint32_t version,std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches)62 OH_NN_ReturnCode NNCompiledCache::CheckCache(const std::string& cacheDir,
63                                              uint32_t version,
64                                              std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches)
65 {
66     if (cacheDir.empty()) {
67         LOGE("[NNCompiledCache] Restore failed, cacheDir is empty.");
68         return OH_NN_INVALID_PARAMETER;
69     }
70 
71     if (!caches.empty()) {
72         LOGE("[NNCompiledCache] Restore failed, caches is not empty.");
73         return OH_NN_INVALID_PARAMETER;
74     }
75 
76     if (m_device == nullptr) {
77         LOGE("[NNCompiledCache] Restore failed, m_device is empty.");
78         return OH_NN_INVALID_PARAMETER;
79     }
80     return OH_NN_SUCCESS;
81 }
82 
Restore(const std::string & cacheDir,uint32_t version,std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches)83 OH_NN_ReturnCode NNCompiledCache::Restore(const std::string& cacheDir,
84                                           uint32_t version,
85                                           std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches)
86 {
87     OH_NN_ReturnCode ret = CheckCache(cacheDir, version, caches);
88     if (ret != OH_NN_SUCCESS) {
89         return ret;
90     }
91 
92     std::string cacheInfoPath = cacheDir + "/" + m_modelName + "cache_info.nncache";
93     char path[PATH_MAX];
94     if (realpath(cacheInfoPath.c_str(), path) == nullptr) {
95         LOGE("[NNCompiledCache] Restore failed, fail to get the real path of cacheInfoPath.");
96         return OH_NN_INVALID_PARAMETER;
97     }
98     if (access(path, F_OK) != 0) {
99         LOGE("[NNCompiledCache] Restore failed, cacheInfoPath is not exist.");
100         return OH_NN_INVALID_PARAMETER;
101     }
102 
103     NNCompiledCacheInfo cacheInfo;
104     ret = CheckCacheInfo(cacheInfo, path);
105     if (ret != OH_NN_SUCCESS) {
106         LOGE("[NNCompiledCache] Restore failed, error happened when calling CheckCacheInfo.");
107         return ret;
108     }
109 
110     if (static_cast<int64_t>(version) > cacheInfo.version) {
111         LOGE("[NNCompiledCache] Restore failed, version is not match.");
112         return OH_NN_INVALID_FILE;
113     }
114 
115     if (static_cast<int64_t>(version) < cacheInfo.version) {
116         LOGE("[NNCompiledCache] Restore failed, the current version is lower than the cache files, "
117              "please set a higher version.");
118         return OH_NN_OPERATION_FORBIDDEN;
119     }
120 
121     for (uint32_t i = 0; i < cacheInfo.fileNumber; ++i) {
122         std::string cacheModelPath = cacheDir + "/" + m_modelName + std::to_string(i) + ".nncache";
123         OHOS::NeuralNetworkRuntime::Buffer modelBuffer;
124         ret = ReadCacheModelFile(cacheModelPath, modelBuffer);
125         if (ret != OH_NN_SUCCESS) {
126             LOGE("[NNCompiledCache] Restore failed, error happened when calling ReadCacheModelFile.");
127             return OH_NN_INVALID_FILE;
128         }
129 
130         if (GetCrc16(static_cast<char*>(modelBuffer.data), modelBuffer.length) !=
131             cacheInfo.modelCheckSum[i]) {
132             LOGE("[NNCompiledCache] Restore failed, the cache model file %{public}s has been changed.",
133                  cacheModelPath.c_str());
134             munmap(modelBuffer.data, modelBuffer.length);
135             close(modelBuffer.fd);
136             return OH_NN_INVALID_FILE;
137         }
138 
139         caches.emplace_back(std::move(modelBuffer));
140     }
141 
142     return ret;
143 }
144 
SetBackend(size_t backendID)145 OH_NN_ReturnCode NNCompiledCache::SetBackend(size_t backendID)
146 {
147     BackendManager& backendManager = BackendManager::GetInstance();
148     std::shared_ptr<Backend> backend = backendManager.GetBackend(backendID);
149     if (backend == nullptr) {
150         LOGE("[NNCompiledCache] SetBackend failed, backend with backendID %{public}zu is not exist.", backendID);
151         return OH_NN_INVALID_PARAMETER;
152     }
153 
154     std::shared_ptr<NNBackend> nnBackend = std::reinterpret_pointer_cast<NNBackend>(backend);
155     m_device = nnBackend->GetDevice();
156     if (m_device == nullptr) {
157         LOGE("[NNCompiledCache] SetBackend failed, device with backendID %{public}zu is not exist.", backendID);
158         return OH_NN_FAILED;
159     }
160 
161     m_backendID = backendID;
162     return OH_NN_SUCCESS;
163 }
164 
SetModelName(const std::string & modelName)165 void NNCompiledCache::SetModelName(const std::string& modelName)
166 {
167     m_modelName = modelName;
168 }
169 
SetIsExceedRamLimit(const bool isExceedRamLimit)170 void NNCompiledCache::SetIsExceedRamLimit(const bool isExceedRamLimit)
171 {
172     m_isExceedRamLimit = isExceedRamLimit;
173 }
174 
GenerateCacheFiles(const std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches,const std::string & cacheDir,uint32_t version) const175 OH_NN_ReturnCode NNCompiledCache::GenerateCacheFiles(const std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches,
176                                                      const std::string& cacheDir,
177                                                      uint32_t version) const
178 {
179     const size_t cacheNumber = caches.size();
180     uint32_t cacheSize = NUMBER_CACHE_INFO_MEMBERS + cacheNumber + NUMBER_CACHE_INFO_EXTENSION_MEMBERS;
181     nlohmann::json cacheInfo;
182 
183     OH_NN_ReturnCode ret = GenerateCacheModel(caches, cacheInfo, cacheDir, version);
184     if (ret != OH_NN_SUCCESS) {
185         LOGE("[NNCompiledCache] GenerateCacheFiles failed, error happened when calling GenerateCacheModel.");
186         return ret;
187     }
188 
189     uint32_t infoCharNumber = cacheSize * sizeof(uint64_t);
190     ret = WriteCacheInfo(infoCharNumber, cacheInfo, cacheDir);
191     if (ret != OH_NN_SUCCESS) {
192         LOGE("[NNCompiledCache] GenerateCacheFiles failed, error happened when calling WriteCacheInfo.");
193         return ret;
194     }
195 
196     return OH_NN_SUCCESS;
197 }
198 
GenerateCacheModel(const std::vector<OHOS::NeuralNetworkRuntime::Buffer> & caches,nlohmann::json & cacheInfo,const std::string & cacheDir,uint32_t version) const199 OH_NN_ReturnCode NNCompiledCache::GenerateCacheModel(const std::vector<OHOS::NeuralNetworkRuntime::Buffer>& caches,
200                                                      nlohmann::json& cacheInfo,
201                                                      const std::string& cacheDir,
202                                                      uint32_t version) const
203 {
204     size_t cacheNumber = caches.size();
205     if (cacheNumber == 0 || cacheNumber > NN_CACHE_FILE_NUMBER_MAX) {
206         LOGE("[NNCompiledCache] Caches size is equal 0 or greater than 100.");
207         return OH_NN_FAILED;
208     }
209 
210     cacheInfo["data"]["fileNumber"] = static_cast<int64_t>(cacheNumber);
211     cacheInfo["data"]["version"] = static_cast<int64_t>(version);
212     cacheInfo["data"]["deviceId"] = static_cast<int64_t>(m_backendID); // Should call SetBackend first.
213 
214     // standardize the input dir
215     OH_NN_ReturnCode ret = OH_NN_SUCCESS;
216     char path[PATH_MAX];
217     if (realpath(cacheDir.c_str(), path) == nullptr) {
218         LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to get the real path of cacheDir.");
219         return OH_NN_INVALID_PARAMETER;
220     }
221 
222     // verify the Standardized path available
223     ret = VerifyCachePath(path);
224     if (ret != OH_NN_SUCCESS) {
225         LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to verify the file path of cacheDir.");
226         return ret;
227     }
228 
229     std::string cachePath = path;
230     for (size_t i = 0; i < cacheNumber; ++i) {
231         std::string cacheModelFile = cachePath + "/" + m_modelName + std::to_string(i) + ".nncache";
232         std::ofstream cacheModelStream(cacheModelFile, std::ios::binary | std::ios::out | std::ios::trunc);
233         if (cacheModelStream.fail()) {
234             LOGE("[NNCompiledCache] GenerateCacheModel failed, model cache file is invalid.");
235             return OH_NN_INVALID_PARAMETER;
236         }
237 
238         uint64_t checkSum =
239             static_cast<int64_t>(GetCrc16(static_cast<char*>(caches[i].data), caches[i].length));
240         cacheInfo["data"]["modelCheckSum"][i] = checkSum;
241         if (!cacheModelStream.write(static_cast<const char*>(caches[i].data), caches[i].length)) {
242             LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to write cache model.");
243             cacheModelStream.close();
244             return OH_NN_SAVE_CACHE_EXCEPTION;
245         };
246 
247         cacheModelStream.close();
248     }
249 
250     int currentOpVersion = 0;
251     ret = m_device->ReadOpVersion(currentOpVersion);
252     if (ret != OH_NN_SUCCESS) {
253         LOGE("[NNCompiledCache] GenerateCacheModel failed, fail to read op version.");
254         return ret;
255     }
256     cacheInfo["data"]["opVersion"] = currentOpVersion;
257 
258     cacheInfo["data"]["isExceedRamLimit"] = m_isExceedRamLimit ? 1 : 0;
259 
260     const size_t dataLength = cacheInfo["data"].dump().length();
261     char cacheInfoData[dataLength + 1];
262     if (strncpy_s(cacheInfoData, dataLength+1, cacheInfo["data"].dump().c_str(), dataLength) != 0) {
263         LOGE("ParseStr failed due to strncpy_s error");
264         return OH_NN_INVALID_PARAMETER;
265     }
266 
267     cacheInfo["CheckSum"] = static_cast<int64_t>(CacheInfoGetCrc16(cacheInfoData, dataLength));
268 
269     return OH_NN_SUCCESS;
270 }
271 
WriteCacheInfo(uint32_t cacheSize,nlohmann::json & cacheInfo,const std::string & cacheDir) const272 OH_NN_ReturnCode NNCompiledCache::WriteCacheInfo(uint32_t cacheSize,
273                                                  nlohmann::json& cacheInfo,
274                                                  const std::string& cacheDir) const
275 {
276     // standardize the input dir
277     char path[PATH_MAX];
278     if (realpath(cacheDir.c_str(), path) == nullptr) {
279         LOGE("[NNCompiledCache] WriteCacheInfo failed, fail to get the real path of cacheDir.");
280         return OH_NN_INVALID_PARAMETER;
281     }
282 
283     // verify the Standardized path available
284     OH_NN_ReturnCode ret = VerifyCachePath(path);
285     if (ret != OH_NN_SUCCESS) {
286         LOGE("[NNCompiledCache] WriteCacheInfo failed, fail to verify the file path of cacheDir.");
287         return ret;
288     }
289 
290     std::string cachePath = path;
291     std::string cacheInfoPath = cachePath + "/" + m_modelName + "cache_info.nncache";
292     std::ofstream cacheInfoStream(cacheInfoPath, std::ios::binary | std::ios::out | std::ios::trunc);
293     if (cacheInfoStream.fail()) {
294         LOGE("[NNCompiledCache] WriteCacheInfo failed, model cache info file is invalid.");
295         return OH_NN_INVALID_FILE;
296     }
297 
298     cacheInfoStream << cacheInfo << std::endl;
299 
300     cacheInfoStream.close();
301     return OH_NN_SUCCESS;
302 }
303 
CheckCacheInfo(NNCompiledCacheInfo & modelCacheInfo,const std::string & cacheInfoPath) const304 OH_NN_ReturnCode NNCompiledCache::CheckCacheInfo(NNCompiledCacheInfo& modelCacheInfo,
305                                                  const std::string& cacheInfoPath) const
306 {
307     // cacheInfoPath is validated outside.
308     std::ifstream infoCacheFile(cacheInfoPath.c_str(), std::ios::in | std::ios::binary);
309     if (!infoCacheFile) {
310         LOGE("[NNCompiledCache] CheckCacheInfo failed, error happened when opening cache info file.");
311         return OH_NN_INVALID_FILE;
312     }
313 
314     std::string content((std::istreambuf_iterator<char>(infoCacheFile)), std::istreambuf_iterator<char>());
315     infoCacheFile.close();
316     if (!nlohmann::json::accept(content)) {
317         LOGE("[NNCompiledCache] CheckCacheInfo JSON parse error");
318         return OH_NN_INVALID_FILE;
319     }
320 
321     // Parse the JSON string
322     nlohmann::json j = nlohmann::json::parse(content);
323     // modelCacheInfo.deviceId type is int64_t,
324     // it is transformed from size_t value, so the transform here will not truncate value.
325     if (j.find("data") == j.end()) {
326         LOGE("[NNCompiledCache] CheckCacheInfo read cache info file failed.");
327         return OH_NN_INVALID_FILE;
328     }
329 
330     if (j["data"].find("deviceId") == j["data"].end()) {
331         LOGE("[NNCompiledCache] CheckCacheInfo read deviceId from cache info file failed.");
332         return OH_NN_INVALID_FILE;
333     }
334     modelCacheInfo.deviceId = j["data"]["deviceId"].get<int64_t>();
335 
336     if (j["data"].find("version") == j["data"].end()) {
337         LOGE("[NNCompiledCache] CheckCacheInfo read version from cache info file failed.");
338         return OH_NN_INVALID_FILE;
339     }
340     modelCacheInfo.version = j["data"]["version"].get<int64_t>();
341 
342     size_t deviceId = static_cast<size_t>(modelCacheInfo.deviceId);
343     if (deviceId != m_backendID) {
344         LOGE("[NNCompiledCache] CheckCacheInfo failed. The deviceId in the cache files "
345              "is different from current deviceId,"
346              "please change the cache directory or current deviceId.");
347         return OH_NN_INVALID_FILE;
348     }
349 
350     if (j["data"].find("fileNumber") == j["data"].end()) {
351         LOGE("[NNCompiledCache] CheckCacheInfo read fileNumber from cache info file failed.");
352         return OH_NN_INVALID_FILE;
353     }
354     modelCacheInfo.fileNumber = j["data"]["fileNumber"].get<int64_t>();
355 
356     return CheckCacheInfoExtension(modelCacheInfo, j);
357 }
358 
CheckCacheInfoExtension(NNCompiledCacheInfo & modelCacheInfo,nlohmann::json & j) const359 OH_NN_ReturnCode NNCompiledCache::CheckCacheInfoExtension(NNCompiledCacheInfo& modelCacheInfo,
360                                                           nlohmann::json& j) const
361 {
362     const size_t dataLength = j["data"].dump().length();
363     char jData[dataLength + 1];
364     if (strncpy_s(jData, dataLength+1, j["data"].dump().c_str(), dataLength) != 0) {
365         LOGE("[NNCompiledCache] ParseStr failed due to strncpy_s error.");
366         return OH_NN_INVALID_FILE;
367     }
368 
369     if (j.find("CheckSum") == j.end()) {
370         LOGE("[NNCompiledCache] read CheckSum from cache info file failed.");
371         return OH_NN_INVALID_FILE;
372     }
373 
374     if (static_cast<int64_t>(CacheInfoGetCrc16(jData, dataLength)) != j["CheckSum"].get<int64_t>()) {
375         LOGE("[NNCompiledCache] cache_info CheckSum is not correct.");
376         return OH_NN_INVALID_FILE;
377     }
378     std::vector<int64_t> modelCheckSum;
379     modelCheckSum.resize(modelCacheInfo.fileNumber);
380     modelCacheInfo.modelCheckSum.resize(modelCacheInfo.fileNumber);
381     if (j["data"].find("modelCheckSum") == j["data"].end()) {
382         LOGE("[NNCompiledCache] CheckCacheInfo read modelCheckSum from cache file failed.");
383         return OH_NN_INVALID_FILE;
384     }
385     for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) {
386         modelCheckSum[i] = static_cast<int64_t>(j["data"]["modelCheckSum"][i]);
387     }
388 
389     for (uint32_t i = 0; i < modelCacheInfo.fileNumber; ++i) {
390         modelCacheInfo.modelCheckSum[i] = static_cast<unsigned short>(modelCheckSum[i]);
391     }
392 
393     if (j["data"].find("opVersion") == j["data"].end()) {
394         LOGW("[NNCompiledCache] CheckCacheInfo read opVersion from cache info file failed.");
395     } else {
396         modelCacheInfo.opVersion = j["data"]["opVersion"].get<int64_t>();
397     }
398 
399     if (j["data"].find("isExceedRamLimit") == j["data"].end()) {
400         LOGE("[NNCompiledCache] CheckCacheInfo read isExceedRamLimit from cache info file failed.");
401         return OH_NN_INVALID_FILE;
402     } else {
403         modelCacheInfo.isExceedRamLimit = j["data"]["isExceedRamLimit"].get<int64_t>();
404     }
405 
406     return OH_NN_SUCCESS;
407 }
408 
ReadCacheModelFile(const std::string & filePath,OHOS::NeuralNetworkRuntime::Buffer & cache)409 OH_NN_ReturnCode NNCompiledCache::ReadCacheModelFile(const std::string& filePath,
410                                                      OHOS::NeuralNetworkRuntime::Buffer& cache)
411 {
412     char path[PATH_MAX];
413     if (realpath(filePath.c_str(), path) == nullptr) {
414         LOGE("[NNCompiledCache] ReadCacheModelFile failed, fail to get the real path of filePath.");
415         return OH_NN_INVALID_PARAMETER;
416     }
417     if (access(path, 0) != 0) {
418         LOGE("[NNCompiledCache] ReadCacheModelFile failed, filePath is not exist.");
419         return OH_NN_INVALID_PARAMETER;
420     }
421 
422     int fd = open(path, O_RDONLY);
423     if (fd == -1) {
424         LOGE("[NNCompiledCache] ReadCacheModelFile failed, file fopen failed.");
425         return OH_NN_INVALID_FILE;
426     }
427 
428     struct stat sb;
429     if (fstat(fd, &sb) == -1) {
430         close(fd);
431         LOGE("[NNCompiledCache] ReadCacheModelFile failed, get file %{public}s state failed.", filePath.c_str());
432         return OH_NN_MEMORY_ERROR;
433     }
434 
435     off_t fsize = sb.st_size;
436 
437     void *ptr = mmap(nullptr, fsize, PROT_READ, MAP_SHARED, fd, 0);
438     if (ptr == MAP_FAILED) {
439         LOGE("[NNCompiledCache] ReadCacheModelFile failed, failed to mmap file.");
440         close(fd);
441         return OH_NN_INVALID_FILE;
442     }
443 
444     cache.data = ptr;
445     cache.length = static_cast<size_t>(fsize); // fsize should be non-negative, safe to cast.
446     cache.fd = fd;
447     return OH_NN_SUCCESS;
448 }
449 
GetCrc16(char * buffer,size_t length) const450 unsigned short NNCompiledCache::GetCrc16(char* buffer, size_t length) const
451 {
452     unsigned int sum = 0;
453 
454     if (buffer == nullptr) {
455         return static_cast<unsigned short>(~sum);
456     }
457 
458     if (length < MAX_CACHE_SIZE) {
459         while (length > 1) {
460             sum += *(reinterpret_cast<unsigned short*>(buffer));
461             length -= sizeof(unsigned short);
462             buffer += sizeof(unsigned short);
463         }
464     } else {
465         size_t step = length / MAX_CACHE_SIZE;
466         while (length > sizeof(unsigned short) * step + 1) {
467             sum += *(reinterpret_cast<unsigned short*>(buffer));
468             length -= step * sizeof(unsigned short);
469             buffer += step * sizeof(unsigned short);
470         }
471     }
472 
473     if (length > 0) {
474         buffer += length - 1;
475         sum += *(reinterpret_cast<unsigned char*>(buffer));
476     }
477 
478     while (sum >> HEX_UNIT) {
479         sum = (sum >> HEX_UNIT) + (sum & 0xffff);
480     }
481 
482     return static_cast<unsigned short>(~sum);
483 }
484 
GetCacheFileLength(FILE * pFile,long & fileSize) const485 OH_NN_ReturnCode NNCompiledCache::GetCacheFileLength(FILE* pFile, long& fileSize) const
486 {
487     int ret = fseek(pFile, 0L, SEEK_END);
488     if (ret != 0) {
489         LOGE("[NNCompiledCache] GetCacheFileLength failed, fail to set the position of the next character "
490              "to be extracted from the input stream.");
491         return OH_NN_FAILED;
492     }
493 
494     long handleValue = ftell(pFile);
495     if (handleValue == -1) {
496         LOGE("[NNCompiledCache] GetCacheFileLength failed, fail to get position of the input stream.");
497         return OH_NN_INVALID_FILE;
498     }
499 
500     if (handleValue == NULL_PTR_LENGTH) {
501         LOGE("[NNCompiledCache] GetCacheFileLength failed, unable to read huge or empty input stream, "
502              "get cache file size=%{public}ld",
503              handleValue);
504         return OH_NN_INVALID_FILE;
505     }
506 
507     fileSize = handleValue;
508     return OH_NN_SUCCESS;
509 }
510 
VerifyCachePath(const std::string & cachePath) const511 OH_NN_ReturnCode NNCompiledCache::VerifyCachePath(const std::string& cachePath) const
512 {
513     // exception: input path is not start with '/'.
514     if (cachePath.find(ROOT_DIR_STR) != size_t(0)) {
515         LOGE("[NNCompiledCache] VerifyCachePath failed, input file dir=%{public}s is invalid, "
516              "should start with '/'.",
517              cachePath.c_str());
518         return OH_NN_INVALID_FILE;
519     }
520 
521     // exception: input path contains continuous double '/'.
522     if (cachePath.find(DOUBLE_SLASH_STR) != std::string::npos) {
523         LOGE("[NNCompiledCache] VerifyCachePath failed, input file dir=%{public}s is invalid, "
524              "containing double '/'.",
525              cachePath.c_str());
526         return OH_NN_INVALID_FILE;
527     }
528 
529     return OH_NN_SUCCESS;
530 }
531 
ReleaseCacheBuffer(std::vector<Buffer> & buffers)532 void NNCompiledCache::ReleaseCacheBuffer(std::vector<Buffer>& buffers)
533 {
534     for (auto buffer : buffers) {
535         munmap(buffer.data, buffer.length);
536         close(buffer.fd);
537     }
538     buffers.clear();
539 }
540 } // namespace NeuralNetworkRuntime
541 } // namespace OHOS
542