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 "camera_rotate_param_manager.h"
17
18 #include <iostream>
19 #include <fstream>
20 #include <filesystem>
21 #include <common_event_data.h>
22 #include <common_event_manager.h>
23 #include <common_event_support.h>
24 #include "common_event_subscriber.h"
25 #include "camera_util.h"
26 #include "camera_log.h"
27
28 namespace OHOS {
29 namespace CameraStandard {
30
31 namespace {
32 static int32_t RETRY_SUBSCRIBER = 3;
33 static const int8_t DECIMAL = 10;
34 const bool NEED_PARAM_VERIFY = true;
35 const std::string CONFIG_FILE_NAME = "camera_rotate_strategy.xml";
36 const std::string CAMERA_CFG_PATH = "/sys_prod/etc/camera/" + CONFIG_FILE_NAME;
37 const std::string EVENT_INFO_TYPE = "type";
38 const std::string EVENT_INFO_SUBTYPE = "subtype";
39 const std::string RECEIVE_UPDATE_PERMISSION = "ohos.permission.RECEIVE_UPDATE_MESSAGE";
40 const std::string CONFIG_UPDATED_ACTION = "usual.event.DUE_SA_CFG_UPDATED";
41 const std::string CONFIG_TYPE = "camera";
42
43 const char* XML_CAMERA_STRATEGY = "strategy";
44 const char* XML_CAMERA_BUDLE_NAME = "bundleName";
45 const char* XML_CAMERA_WIDE_VALUE = "wideValue";
46 const char* XML_CAMERA_ROTATE_DEGREE = "rotateDegree";
47 const char* XML_CAMERA_FPS = "fps";
48 }
49 // LCOV_EXCL_START
GetInstance()50 CameraRoateParamManager& CameraRoateParamManager::GetInstance()
51 {
52 static CameraRoateParamManager instance;
53 return instance;
54 }
55
InitParam()56 void CameraRoateParamManager::InitParam()
57 {
58 MEDIA_INFO_LOG("InitParam");
59 if (paramReader == nullptr) {
60 paramReader = std::make_shared<CameraRoateParamReader>();
61 }
62 if (paramReader != nullptr) {
63 std::string cloudVersion = paramReader->GetPathVersion(); // 云推版本号
64 std::vector<std::string> cloudVersionNum;
65 CHECK_RETURN_ELOG(!paramReader->VersionStrToNumber(cloudVersion, cloudVersionNum),
66 "VersionStrToNumber error , pathVersion is invalid");
67 std::string localVersion = LoadVersion(); // 本地参数版本号/system/etc/camera/version.txt
68 std::vector<std::string> localVersionNum;
69 CHECK_RETURN_ELOG(!paramReader->VersionStrToNumber(localVersion, localVersionNum),
70 "VersionStrToNumber error , currentVersion is invalid");
71 MEDIA_INFO_LOG(
72 "currentVersion: %{public}s pathVersion :%{public}s", localVersion.c_str(), cloudVersion.c_str());
73 if (paramReader->CompareVersion(localVersionNum, cloudVersionNum)) {
74 ReloadParam();
75 }
76 }
77 LoadParamStr(); // 读取本地配置
78 };
79
ReloadParam()80 void CameraRoateParamManager::ReloadParam()
81 {
82 MEDIA_DEBUG_LOG("called");
83 CHECK_RETURN_ELOG(paramReader == nullptr, "paramReader is nullptr");
84 std::string path = paramReader->GetConfigFilePath();
85 MEDIA_INFO_LOG("GetConfigFilePath, path: %{public}s ", path.c_str());
86 // 判断是路径是否在下载路径, 下载路径需要增加安全校验
87 if (NEED_PARAM_VERIFY && path.find(PARAM_UPDATE_ABS_PATH) != std::string::npos) {
88 VerifyCloudFile(PARAM_SERVICE_INSTALL_PATH + CAMERA_ROTATE_CFG_DIR);
89 }
90 };
91
VerifyCloudFile(const std::string & prePath)92 void CameraRoateParamManager::VerifyCloudFile(const std::string& prePath)
93 {
94 CHECK_RETURN_ELOG(paramReader == nullptr, "paramReader is nullptr");
95 // 校验参数签名是否合法
96 std::string certFile = prePath + "/CERT.ENC"; // 获取签名文件
97 std::string verifyFile = prePath + "/CERT.SF"; // 获取待验证的文件
98 std::string manifestFile = prePath + "/MANIFEST.MF"; // 文件列表文件
99 std::lock_guard<std::mutex> lock(mutxVerify);
100 CHECK_RETURN_ELOG(!paramReader->VerifyCertSfFile(certFile, verifyFile, manifestFile),
101 " VerifyCertSfFile error , param is invalid");
102 std::string cfgDir = PARAM_SERVICE_INSTALL_PATH + CAMERA_ROTATE_CFG_DIR;
103 // 校验参数文件是否合法
104 CHECK_RETURN_ELOG(
105 !paramReader->VerifyParamFile(cfgDir, VERSION_FILE_NAME), "verify version file error , param is invalid");
106 CHECK_RETURN_ELOG(
107 !paramReader->VerifyParamFile(cfgDir, CONFIG_FILE_NAME), "verify param file error , param is invalid");
108 // 拷贝参数到本地
109 CopyFileToLocal();
110 }
111
CopyFileToLocal()112 void CameraRoateParamManager::CopyFileToLocal()
113 {
114 if (!DoCopy(PARAM_SERVICE_INSTALL_PATH + CAMERA_ROTATE_CFG_DIR + VERSION_FILE_NAME,
115 CAMERA_SERVICE_ABS_PATH + VERSION_FILE_NAME)) {
116 MEDIA_ERR_LOG("version.txt copy to local error");
117 return;
118 }
119 if (!DoCopy(PARAM_SERVICE_INSTALL_PATH + CAMERA_ROTATE_CFG_DIR + CONFIG_FILE_NAME,
120 CAMERA_SERVICE_ABS_PATH + CONFIG_FILE_NAME)) {
121 MEDIA_ERR_LOG("ofbs_config.json copy to local error");
122 return;
123 }
124 MEDIA_INFO_LOG("CopyFileToLocal success");
125 }
126
DoCopy(const std::string & src,const std::string & des)127 bool CameraRoateParamManager::DoCopy(const std::string& src, const std::string& des)
128 {
129 CHECK_RETURN_RET_ELOG(!CheckPathExist(src.c_str()), false, "srcPath is invalid");
130 if (CheckPathExist(des.c_str())) {
131 MEDIA_INFO_LOG("des has file");
132 CHECK_RETURN_RET_ELOG(!RemoveFile(des), false, "rm des file error");
133 }
134 std::filesystem::path sPath(src);
135 std::filesystem::path dPath(des);
136 std::error_code errNo;
137 const auto copyOptions = std::filesystem::copy_options::overwrite_existing |
138 std::filesystem::copy_options::recursive |
139 std::filesystem::copy_options::skip_symlinks;
140 std::filesystem::copy(sPath, dPath, copyOptions, errNo);
141 // if has some error in copy, record errno
142 CHECK_RETURN_RET_ELOG(errNo.value(), false, "copy failed errno:%{public}d", errNo.value());
143 MEDIA_INFO_LOG("copy success");
144 return true;
145 }
146
LoadVersion()147 std::string CameraRoateParamManager::LoadVersion()
148 {
149 CHECK_RETURN_RET_ELOG(paramReader == nullptr, "", "paramReader is nullptr");
150 std::string filePath = CAMERA_SERVICE_ABS_PATH + VERSION_FILE_NAME; // 优先沙箱找
151 std::ifstream file(filePath);
152 if (!file.good()) {
153 return paramReader->GetVersionInfoStr(ABS_CONTENT_FILE_PATH + VERSION_FILE_NAME); // 服务配置路径
154 }
155 return paramReader->GetVersionInfoStr(filePath);
156 }
157
LoadParamStr()158 void CameraRoateParamManager::LoadParamStr()
159 {
160 std::string filePath = CAMERA_SERVICE_ABS_PATH + CONFIG_FILE_NAME;
161 std::ifstream file(filePath);
162 if (!file.good()) {
163 LoadConfiguration(CAMERA_CFG_PATH);
164 return;
165 }
166 LoadConfiguration(filePath);
167 }
168
LoadConfiguration(const std::string & filepath)169 bool CameraRoateParamManager::LoadConfiguration(const std::string &filepath)
170 {
171 curNode_ = CameraXmlNode::Create();
172 int32_t ret = curNode_->Config(filepath.c_str(), nullptr, 0);
173 CHECK_RETURN_RET_ELOG(ret != CAMERA_OK, false, "Not found camera_rotate_strategy.xml!");
174 {
175 std::lock_guard<std::mutex> lock(strategyInfosMutex_);
176 cameraRotateStrategyInfos_.clear();
177 }
178 bool result = ParseInternal(curNode_->GetCopyNode());
179 CHECK_RETURN_RET_ELOG(!result, false, "Camera rotate strategy xml parse failed.");
180 Destroy();
181 return true;
182 }
183
Destroy()184 void CameraRoateParamManager::Destroy()
185 {
186 curNode_->FreeDoc();
187 curNode_->CleanUpParser();
188 }
189
ParseInternal(std::shared_ptr<CameraXmlNode> curNode)190 bool CameraRoateParamManager::ParseInternal(std::shared_ptr<CameraXmlNode> curNode)
191 {
192 for (; curNode->IsNodeValid(); curNode->MoveToNext()) {
193 if (!curNode->IsElementNode()) {
194 continue;
195 }
196 if (curNode->CompareName(XML_CAMERA_STRATEGY)) {
197 ParserStrategyInfo(curNode->GetCopyNode());
198 } else {
199 ParseInternal(curNode->GetChildrenNode());
200 }
201 }
202 return true;
203 }
204
ParserStrategyInfo(std::shared_ptr<CameraXmlNode> curNode)205 void CameraRoateParamManager::ParserStrategyInfo(std::shared_ptr<CameraXmlNode> curNode)
206 {
207 std::lock_guard<std::mutex> lock(strategyInfosMutex_);
208 if (curNode->IsNodeValid() && curNode->IsElementNode()) {
209 CameraRotateStrategyInfo info = {};
210 curNode->GetProp(XML_CAMERA_BUDLE_NAME, info.bundleName);
211
212 std::string pValue;
213 float wideValue = -1.0;
214 curNode->GetProp(XML_CAMERA_WIDE_VALUE, pValue);
215 char* endPtr;
216 wideValue = std::strtof(pValue.c_str(), &endPtr);
217 if (*endPtr != '\0' || pValue.empty()) {
218 wideValue = -1.0;
219 }
220 info.wideValue = wideValue;
221 endPtr = nullptr;
222
223 int rotateDegree = -1;
224 curNode->GetProp(XML_CAMERA_ROTATE_DEGREE, pValue);
225 long result = strtol(pValue.c_str(), &endPtr, DECIMAL);
226
227 if (*endPtr != '\0' || pValue.empty()) {
228 rotateDegree = -1;
229 } else {
230 rotateDegree = static_cast<int16_t>(result);
231 }
232 info.rotateDegree = rotateDegree;
233
234 int16_t fps = -1;
235 curNode->GetProp(XML_CAMERA_FPS, pValue);
236 endPtr = nullptr;
237 result = strtol(pValue.c_str(), &endPtr, DECIMAL);
238
239 if (*endPtr != '\0' || pValue.empty()) {
240 fps = -1;
241 } else {
242 fps = static_cast<int16_t>(result);
243 }
244 info.fps = fps;
245 cameraRotateStrategyInfos_.push_back(info);
246 MEDIA_INFO_LOG("ParserStrategyInfo: bundleName:%{public}s, wideValue:%{public}f, "
247 "rotateDegree:%{public}d, fps:%{public}d",
248 info.bundleName.c_str(), info.wideValue, info.rotateDegree, info.fps);
249 }
250 }
251
InitDefaultConfig()252 void CameraRoateParamManager::InitDefaultConfig()
253 {
254 totalFeatureSwitch = 1;
255 cameraRotateStrategyInfos_.clear();
256 }
257
GetCameraRotateStrategyInfos()258 std::vector<CameraRotateStrategyInfo> CameraRoateParamManager::GetCameraRotateStrategyInfos()
259 {
260 return cameraRotateStrategyInfos_;
261 }
262
SubscriberEvent()263 void CameraRoateParamManager::SubscriberEvent()
264 {
265 MEDIA_INFO_LOG("SubscriberEvent start.");
266 // 可以添加多个事件监听
267 handleEventFunc_["usual.event.DUE_SA_CFG_UPDATED"] = &CameraRoateParamManager::HandleParamUpdate;
268 for (auto it = handleEventFunc_.begin(); it != handleEventFunc_.end(); ++it) {
269 MEDIA_INFO_LOG("Add event: %{public}s", it->first.c_str());
270 eventHandles_.emplace(it->first, std::bind(it->second, this, std::placeholders::_1));
271 }
272 CHECK_RETURN_ELOG(subscriber_, "Common Event is already subscribered!");
273 EventFwk::MatchingSkills matchingSkills;
274 for (auto &event : handleEventFunc_) {
275 MEDIA_INFO_LOG("Add event: %{public}s", event.first.c_str());
276 matchingSkills.AddEvent(event.first);
277 }
278 EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
279 subscribeInfo.SetPermission(RECEIVE_UPDATE_PERMISSION);
280 subscriber_ = std::make_shared<ParamCommonEventSubscriber>(subscribeInfo, *this);
281
282 int32_t retry = RETRY_SUBSCRIBER;
283 do {
284 bool subscribeResult = EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber_);
285 if (subscribeResult) {
286 MEDIA_INFO_LOG("SubscriberEvent success.");
287 return;
288 } else {
289 MEDIA_ERR_LOG("SubscriberEvent failed, retry %{public}d", retry);
290 retry--;
291 sleep(1);
292 }
293 } while (retry);
294 MEDIA_INFO_LOG("SubscriberEvent failed.");
295 }
296
UnSubscriberEvent()297 void CameraRoateParamManager::UnSubscriberEvent()
298 {
299 MEDIA_INFO_LOG("UnSubscriberEvent start.");
300 eventHandles_.clear();
301 handleEventFunc_.clear();
302 if (subscriber_) {
303 bool subscribeResult = EventFwk::CommonEventManager::UnSubscribeCommonEvent(subscriber_);
304 MEDIA_INFO_LOG("subscribeResult = %{public}d", subscribeResult);
305 subscriber_ = nullptr;
306 }
307 MEDIA_INFO_LOG("UnSubscriberEvent end.");
308 }
309
OnReceiveEvent(const AAFwk::Want & want)310 void CameraRoateParamManager::OnReceiveEvent(const AAFwk::Want &want)
311 {
312 std::string action = want.GetAction();
313 auto it = eventHandles_.find(action);
314 if (it == eventHandles_.end()) {
315 MEDIA_INFO_LOG("Ignore event: %{public}s", action.c_str());
316 return;
317 }
318 MEDIA_INFO_LOG("Handle event: %{public}s", action.c_str());
319 it->second(want);
320 }
321
HandleParamUpdate(const AAFwk::Want & want) const322 void CameraRoateParamManager::HandleParamUpdate(const AAFwk::Want &want) const
323 {
324 std::string action = want.GetAction();
325 std::string type = want.GetStringParam(EVENT_INFO_TYPE);
326 std::string subtype = want.GetStringParam(EVENT_INFO_SUBTYPE);
327 MEDIA_INFO_LOG("recive param update event: %{public}s ,%{public}s ,%{public}s ", action.c_str(), type.c_str(),
328 subtype.c_str());
329 if (action != CONFIG_UPDATED_ACTION || type != CONFIG_TYPE) {
330 MEDIA_ERR_LOG("invalid param update info: %{public}s, %{public}s, %{public}s",
331 action.c_str(), type.c_str(), subtype.c_str());
332 return;
333 }
334 CameraRoateParamManager::GetInstance().InitParam();
335 }
336 // LCOV_EXCL_STOP
337 }
338 }
339