• 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 "mechbody_controller_service.h"
17 
18 #include "cJSON.h"
19 #include <string>
20 
21 #include "accesstoken_kit.h"
22 #include "ble_send_manager.h"
23 #include "mechbody_controller_log.h"
24 #include "mechbody_controller_utils.h"
25 #include "mc_controller_manager.h"
26 #include "mc_controller_ipc_death_listener.h"
27 #include "mechbody_controller_ipc_interface_code.h"
28 #include "tokenid_kit.h"
29 
30 namespace OHOS {
31 namespace MechBodyController {
32 namespace {
33     const std::string TAG = "MechBodyControllerService";
34     const std::string PERMISSION_NAME = "ohos.permission.CONNECT_MECHANIC_HARDWARE";
35 }
36 
GetInstance()37 MechBodyControllerService& MechBodyControllerService::GetInstance()
38 {
39     static auto instance = new MechBodyControllerService();
40     return *instance;
41 }
42 
43 const bool REGISTER_RESULT =
44         SystemAbility::MakeAndRegisterAbility(&MechBodyControllerService::GetInstance());
45 
MechBodyControllerService()46 MechBodyControllerService::MechBodyControllerService() : SystemAbility(MECH_SERVICE_SA_ID, true)
47 {
48 }
49 
~MechBodyControllerService()50 MechBodyControllerService::~MechBodyControllerService()
51 {
52     HILOGI("~MechBodyControllerService.");
53 }
54 
OnStart()55 void MechBodyControllerService::OnStart()
56 {
57     // LCOV_EXCL_START
58     HILOGI("MechBodyControllerService start.");
59     bool res = Publish(this);
60     if (!res) {
61         HILOGE("MechBodyControllerService start failed.");
62     }
63     MechConnectManager::GetInstance().Init();
64 
65     if (sendAdapter_ == nullptr) {
66         sendAdapter_ = std::make_shared<TransportSendAdapter>();
67         sendAdapter_->RegisterBluetoothListener();
68     }
69     BleSendManager::GetInstance().Init();
70 
71     HILOGI("MechBodyControllerService start end.");
72     // LCOV_EXCL_STOP
73 }
74 
OnStop()75 void MechBodyControllerService::OnStop()
76 {
77     if (sendAdapter_ != nullptr) {
78         sendAdapter_->UnRegisterBluetoothListener();
79         sendAdapter_ = nullptr;
80     }
81     BleSendManager::GetInstance().UnInit();
82     McCameraTrackingController::GetInstance().UnInit();
83     MechConnectManager::GetInstance().UnInit();
84 }
85 
RegisterAttachStateChangeCallback(const sptr<IRemoteObject> callback)86 int32_t MechBodyControllerService::RegisterAttachStateChangeCallback(const sptr<IRemoteObject> callback)
87 {
88     // LCOV_EXCL_START
89     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
90     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
91     if (callback == nullptr) {
92         HILOGE("callback is nullptr");
93         return INVALID_REMOTE_OBJECT;
94     }
95 
96     sptr <MechControllerIpcDeathListener> diedListener = new MechControllerIpcDeathListener();
97     diedListener->tokenId_ = tokenId;
98     diedListener->objectType_ = RemoteObjectType::DEVICE_ATTACH_CALLBACK;
99     callback->AddDeathRecipient(diedListener);
100     {
101         std::lock_guard<std::mutex> lock(deviceAttachCallbackMutex);
102         deviceAttachCallback_[tokenId] = callback;
103         HILOGI("callback add success, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
104         if (listener_ == nullptr) {
105             listener_ = std::make_shared<MechConnectListenerImpl>();
106             int32_t registerListenerResult = MechConnectManager::GetInstance().AddDeviceChangeListener(listener_);
107             HILOGI("Register listener to MechConnectManager %{public}s, tokenId: %{public}s;",
108                    registerListenerResult == ERR_OK ? "success" : "failed", GetAnonymUint32(tokenId).c_str());
109             if (registerListenerResult != ERR_OK) {
110                 deviceAttachCallback_.erase(tokenId);
111                 return REGISTER_CALLBACK_FAILED;
112             }
113         } else {
114             HILOGI("DeviceChangeListener has registered");
115         }
116     }
117     HILOGI("end, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
118     return ERR_OK;
119     // LCOV_EXCL_STOP
120 }
121 
UnRegisterAttachStateChangeCallback()122 int32_t MechBodyControllerService::UnRegisterAttachStateChangeCallback()
123 {
124     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
125     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
126     std::lock_guard<std::mutex> lock(deviceAttachCallbackMutex);
127     if (deviceAttachCallback_.size() == 1 &&
128         deviceAttachCallback_.find(tokenId) != deviceAttachCallback_.end()) {
129         int32_t unRegisterResult = MechConnectManager::GetInstance().RemoveDeviceChangeListener(listener_);
130         HILOGI("Unregister listener from MechConnectManager %{public}s, tokenId: %{public}s;",
131                unRegisterResult == ERR_OK ? "success" : "failed", GetAnonymUint32(tokenId).c_str());
132         if (unRegisterResult != ERR_OK) {
133             return UNREGISTER_CALLBACK_FAILED;
134         }
135         listener_ = nullptr;
136         deviceAttachCallback_.clear();
137         HILOGI("Callback clean success, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
138     } else {
139         deviceAttachCallback_.erase(tokenId);
140         HILOGI("Callback remove success, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
141     }
142     HILOGI("end, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
143     return ERR_OK;
144 }
145 
OnAttachStateChange(const AttachmentState & attachmentState,const MechInfo & mechInfo)146 int32_t MechBodyControllerService::OnAttachStateChange(const AttachmentState &attachmentState,
147                                                        const MechInfo &mechInfo)
148 {
149     HILOGI("start");
150     std::lock_guard<std::mutex> lock(deviceAttachCallbackMutex);
151     for (const auto &item: deviceAttachCallback_) {
152         uint32_t tokenId = item.first;
153         HILOGI("start send callback data to tokenId: %{public}s; mech info: %{public}s",
154             GetAnonymUint32(tokenId).c_str(),
155                mechInfo.ToString().c_str());
156         sptr <IRemoteObject> callback = item.second;
157         MessageParcel data;
158         if (!data.WriteInterfaceToken(MECH_SERVICE_IPC_TOKEN)) {
159             HILOGE("Write interface token failed, tokenId: %{public}s, mechId: %{public}d, event: %{public}s",
160                 GetAnonymUint32(tokenId).c_str(),
161                 mechInfo.mechId, mechInfo.ToString().c_str());
162             continue;
163         }
164 
165         if (!data.WriteInt32(static_cast<int32_t>(attachmentState))) {
166             HILOGE("Write mechId failed, tokenId: %{public}s, mechId: %{public}d, attachmentState: %{public}d",
167                 GetAnonymUint32(tokenId).c_str(),
168                 mechInfo.mechId, static_cast<int32_t>(attachmentState));
169             return SEND_CALLBACK_INFO_FAILED;
170         }
171 
172         if (!data.WriteParcelable(&mechInfo)) {
173             HILOGE("Write state failed");
174             return SEND_CALLBACK_INFO_FAILED;
175         }
176 
177         if (callback == nullptr) {
178             HILOGE("Remote object is null");
179             return SEND_CALLBACK_INFO_FAILED;
180         }
181 
182         MessageParcel reply;
183         MessageOption option;
184         int32_t error =
185             callback->SendRequest(static_cast<uint32_t>(IMechBodyControllerCode::ATTACH_STATE_CHANGE_CALLBACK),
186             data, reply, option);
187         HILOGI("Send callback data %{public}s, result code: %{public}d",
188             error == ERR_NONE ? "success" : "failed", error);
189     }
190     HILOGI("end");
191     return ERR_OK;
192 }
193 
SetUserOperation(const std::shared_ptr<Operation> & operation,const std::string & mac,const std::string & param)194 int32_t MechBodyControllerService::SetUserOperation(const std::shared_ptr<Operation> &operation,
195                                                     const std::string &mac, const std::string &param)
196 {
197     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
198     HILOGI("start,tokenId: %{public}s; user operation: %{public}d; mac: %{public}s;",
199            GetAnonymUint32(tokenId).c_str(), static_cast<int32_t>(*operation),
200            GetAnonymStr(mac).c_str());
201     int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, PERMISSION_NAME);
202     if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
203         HILOGE("%{public}s: PERMISSION_DENIED", PERMISSION_NAME.c_str());
204         return PERMISSION_DENIED;
205     }
206     if (!IsSystemApp()) {
207         HILOGE("current app is not system app.");
208         return PERMISSION_DENIED;
209     }
210     cJSON *rootValue = cJSON_Parse(param.c_str());
211     if (rootValue == nullptr) {
212         HILOGE("Parse param json error.");
213         return INVALID_PARAMETERS_ERR;
214     }
215     cJSON *deviceNameJson = cJSON_GetObjectItemCaseSensitive(rootValue, "device_name");
216     if (deviceNameJson == nullptr || !cJSON_IsString(deviceNameJson) || (deviceNameJson->valuestring == nullptr)) {
217         cJSON_Delete(rootValue);
218         HILOGE("Parse deviceName error.");
219         return INVALID_PARAMETERS_ERR;
220     }
221     std::string deviceName = deviceNameJson->valuestring;
222     cJSON_Delete(rootValue);
223     BleSendManager::GetInstance().MechbodyConnect(mac, deviceName);
224     return ERR_OK;
225 }
226 
OnDeviceConnected(int32_t mechId)227 int32_t MechBodyControllerService::OnDeviceConnected(int32_t mechId)
228 {
229     HILOGI("enter. mechId %{public}d", mechId);
230     std::lock_guard<std::mutex> lock(motionManagersMutex);
231     if (motionManagers_.empty() || motionManagers_.find(mechId) == motionManagers_.end()) {
232         HILOGI("create new. mechId %{public}d", mechId);
233         if (sendAdapter_ == nullptr) {
234             sendAdapter_ = std::make_shared<TransportSendAdapter>();
235             sendAdapter_->RegisterBluetoothListener();
236         }
237         std::shared_ptr<MotionManager> manager = std::make_shared<MotionManager>(sendAdapter_, mechId);
238         manager->RegisterEventListener();
239         motionManagers_[mechId] = manager;
240     }
241     HILOGI("end");
242     return ERR_OK;
243 }
244 
OnDeviceDisconnected(int32_t mechId)245 int32_t MechBodyControllerService::OnDeviceDisconnected(int32_t mechId)
246 {
247     HILOGI("enter. mechId %{public}d", mechId);
248     std::lock_guard<std::mutex> lock(motionManagersMutex);
249     if (motionManagers_.empty()) {
250         HILOGD("motionManagers_ is empty.");
251         return ERR_OK;
252     }
253     auto it = motionManagers_.find(mechId);
254     if (it != motionManagers_.end()) {
255         HILOGD("find to erase.");
256         it->second->UnRegisterNotifyEvent();
257         it->second = nullptr;
258         motionManagers_.erase(it);
259     }
260     return ERR_OK;
261 }
262 
GetAttachedDevices(std::set<MechInfo> & mechInfo)263 int32_t MechBodyControllerService::GetAttachedDevices(std::set<MechInfo> &mechInfo)
264 {
265     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
266     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
267     if (!MechConnectManager::GetInstance().GetConnectMechList(mechInfo)) {
268         mechInfo.clear();
269         HILOGE("Get attached devices failed.");
270     }
271     HILOGI("end, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
272     return ERR_OK;
273 }
274 
SetTrackingEnabled(bool & isEnabled)275 int32_t MechBodyControllerService::SetTrackingEnabled(bool &isEnabled)
276 {
277     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
278     HILOGI("start, tokenId: %{public}s; isEnabled: %{public}s;",
279         GetAnonymUint32(tokenId).c_str(), isEnabled ? "true" : "false");
280     int32_t setResult = McControllerManager::GetInstance().SetTrackingEnabled(tokenId, isEnabled);
281     HILOGI("end. Set Tracking Enabled result: %{public}d.", setResult);
282     return setResult;
283 }
284 
GetTrackingEnabled(bool & isEnabled)285 int32_t MechBodyControllerService::GetTrackingEnabled(bool &isEnabled)
286 {
287     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
288     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
289     int32_t getResult = McControllerManager::GetInstance().GetTrackingEnabled(tokenId, isEnabled);
290     HILOGI("end. Get Tracking Enabled result: %{public}d.", getResult);
291     return getResult;
292 }
293 
RegisterTrackingEventCallback(sptr<IRemoteObject> callback)294 int32_t MechBodyControllerService::RegisterTrackingEventCallback(sptr <IRemoteObject> callback)
295 {
296     // LCOV_EXCL_START
297     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
298     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
299     if (callback == nullptr) {
300         HILOGE("callback is nullptr");
301         return INVALID_REMOTE_OBJECT;
302     }
303     int32_t registerResult = McControllerManager::GetInstance().RegisterTrackingEventCallback(tokenId,
304                                                                                               callback);
305     HILOGI("end. Register tracking event callback result: %{public}d.", registerResult);
306     return registerResult;
307     // LCOV_EXCL_STOP
308 }
309 
UnRegisterTrackingEventCallback()310 int32_t MechBodyControllerService::UnRegisterTrackingEventCallback()
311 {
312     // LCOV_EXCL_START
313     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
314     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
315     int32_t unregisterResult = McControllerManager::GetInstance().UnRegisterTrackingEventCallback(tokenId);
316     HILOGI("end. Unregister tracking event callback result: %{public}d.", unregisterResult);
317     return unregisterResult;
318     // LCOV_EXCL_STOP
319 }
320 
SetTrackingLayout(CameraTrackingLayout & cameraTrackingLayout)321 int32_t MechBodyControllerService::SetTrackingLayout(CameraTrackingLayout &cameraTrackingLayout)
322 {
323     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
324     HILOGI("start, tokenId: %{public}s; CameraTrackingLayout: %{public}d;", GetAnonymUint32(tokenId).c_str(),
325         static_cast<int32_t>(cameraTrackingLayout));
326     if (!IsSystemApp()) {
327         HILOGE("current app is not system app.");
328         return PERMISSION_DENIED;
329     }
330     int32_t setTrackingLayoutResult = McControllerManager::GetInstance()
331         .SetTrackingLayout(tokenId, cameraTrackingLayout);
332     HILOGI("end. Set tracking layout result: %{public}d.", setTrackingLayoutResult);
333     return setTrackingLayoutResult;
334 }
335 
GetTrackingLayout(CameraTrackingLayout & cameraTrackingLayout)336 int32_t MechBodyControllerService::GetTrackingLayout(CameraTrackingLayout &cameraTrackingLayout)
337 {
338     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
339     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
340     int32_t getTrackingLayoutResult =
341         McControllerManager::GetInstance().GetTrackingLayout(tokenId, cameraTrackingLayout);
342     HILOGI("end. Get tracking layout result: %{public}d.", getTrackingLayoutResult);
343     return getTrackingLayoutResult;
344 }
345 
RegisterCmdChannel(const sptr<IRemoteObject> callback)346 int32_t MechBodyControllerService::RegisterCmdChannel(const sptr<IRemoteObject> callback)
347 {
348     // LCOV_EXCL_START
349     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
350     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
351     sptr <MechControllerIpcDeathListener> diedListener = new MechControllerIpcDeathListener();
352     diedListener->tokenId_ = tokenId;
353     diedListener->objectType_ = RemoteObjectType::COMMAND_CHANNEL;
354     CHECK_POINTER_RETURN_VALUE(callback, INVALID_PARAMETERS_ERR, "callback");
355     callback->AddDeathRecipient(diedListener);
356     {
357         std::lock_guard<std::mutex> lock(cmdChannelMutex_);
358         cmdChannels_[tokenId] = callback;
359     }
360     HILOGI("command channel add success, tokenid: %{public}s;", GetAnonymUint32(tokenId).c_str());
361     return ERR_OK;
362     // LCOV_EXCL_STOP
363 }
364 
RotateByDegree(const int32_t & mechId,std::string & cmdId,const std::shared_ptr<RotateByDegreeParam> & rotateByDegreeParam)365 int32_t MechBodyControllerService::RotateByDegree(const int32_t &mechId, std::string &cmdId,
366     const std::shared_ptr<RotateByDegreeParam> &rotateByDegreeParam)
367 {
368     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
369     if (!IsSystemApp()) {
370         HILOGE("current app is not system app.");
371         return PERMISSION_DENIED;
372     }
373     if (mechId < 0) {
374         HILOGE("Invalid mech id");
375         return INVALID_MECH_ID;
376     }
377     if (!rotateByDegreeParam) {
378         HILOGE("Invalid rotateByDegreeParam");
379         return INVALID_ROTATE_PARAM;
380     }
381     if (rotateByDegreeParam->duration < 0) {
382         HILOGE("Invalid duration");
383         return INVALID_ROTATE_PARAM;
384     }
385     HILOGI("start, tokenId: %{public}s; mechId: %{public}d; rotate param: %{public}s",
386         GetAnonymUint32(tokenId).c_str(), mechId, rotateByDegreeParam->ToString().c_str());
387     if (rotateByDegreeParam->duration == 0) {
388         NotifyOperationResult(tokenId, cmdId, ExecResult::COMPLETED);
389         return ERR_OK;
390     }
391     std::shared_ptr<RotateParam> rotateParam = std::make_shared<RotateParam>();
392     rotateParam->degree.yaw = rotateByDegreeParam->degree.yaw;
393     rotateParam->degree.roll = rotateByDegreeParam->degree.roll;
394     rotateParam->degree.pitch = rotateByDegreeParam->degree.pitch;
395     rotateParam->duration = rotateByDegreeParam->duration;
396     rotateParam->isRelative = true;
397     HILOGI("RotateParam: %{public}s", rotateParam->ToString().c_str());
398 
399     std::lock_guard<std::mutex> lock(motionManagersMutex);
400     if (motionManagers_.empty()) {
401         return DEVICE_NOT_CONNECTED;
402     }
403     auto it = motionManagers_.find(mechId);
404     if (it == motionManagers_.end()) {
405         return DEVICE_NOT_CONNECTED;
406     }
407     std::shared_ptr<MotionManager> motionManager = it->second;
408     if (motionManager == nullptr) {
409         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
410             GetAnonymUint32(tokenId).c_str(), mechId);
411         return DEVICE_NOT_CONNECTED;
412     }
413     int32_t result = motionManager->Rotate(rotateParam, tokenId, cmdId);
414     HILOGI("end. Rotate By Degree execute result: %{public}d.", result);
415     return result;
416 }
417 
NotifyOperationResult(const uint32_t & tokenId,const std::string & cmdId,const ExecResult & result)418 int32_t MechBodyControllerService::NotifyOperationResult(const uint32_t &tokenId, const std::string &cmdId,
419     const ExecResult &result)
420 {
421     HILOGI("start, result: %{public}d;", result);
422     MessageParcel data;
423     if (!data.WriteInterfaceToken(MECH_SERVICE_IPC_TOKEN)) {
424         HILOGE("Write interface token failed");
425         return SEND_CALLBACK_INFO_FAILED;
426     }
427 
428     if (!data.WriteString(cmdId)) {
429         HILOGE("Write cmdId failed");
430         return SEND_CALLBACK_INFO_FAILED;
431     }
432     if (!data.WriteInt32(static_cast<int32_t>(result))) {
433         HILOGE("Write result failed");
434         return SEND_CALLBACK_INFO_FAILED;
435     }
436     MessageParcel reply;
437     MessageOption option;
438     {
439         std::lock_guard<std::mutex> lock(cmdChannelMutex_);
440         sptr<IRemoteObject> callback =  cmdChannels_[tokenId];
441         if (callback == nullptr) {
442             HILOGI("command channel is nullptr for tokenId: %{public}s", GetAnonymUint32(tokenId).c_str());
443             return NAPI_SEND_DATA_FAIL;
444         }
445         int32_t error =
446             callback->SendRequest(static_cast<uint32_t>(IMechBodyControllerCode::ROTATE_CALLBACK),
447             data, reply, option);
448         HILOGI("Send callback data %{public}s", error == ERR_NONE ? "success" : "failed");
449     }
450 
451     return ERR_OK;
452 }
453 
RotateToEulerAngles(const int32_t & mechId,std::string & cmdId,const std::shared_ptr<RotateToEulerAnglesParam> & rotateToEulerAnglesParam)454 int32_t MechBodyControllerService::RotateToEulerAngles(const int32_t &mechId, std::string &cmdId,
455     const std::shared_ptr<RotateToEulerAnglesParam> &rotateToEulerAnglesParam)
456 {
457     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
458     if (!IsSystemApp()) {
459         HILOGE("current app is not system app.");
460         return PERMISSION_DENIED;
461     }
462     if (mechId < 0) {
463         HILOGE("Invalid mech id");
464         return INVALID_MECH_ID;
465     }
466     if (!rotateToEulerAnglesParam) {
467         HILOGE("Invalid rotateToEulerAnglesParam");
468         return INVALID_ROTATE_PARAM;
469     }
470     if (rotateToEulerAnglesParam->duration < 0) {
471         HILOGE("Invalid duration");
472         return INVALID_ROTATE_PARAM;
473     }
474     HILOGI("start, tokenId: %{public}s; mechId: %{public}d; rotate param: %{public}s",
475         GetAnonymUint32(tokenId).c_str(), mechId, rotateToEulerAnglesParam->ToString().c_str());
476     if (rotateToEulerAnglesParam->duration == 0) {
477         NotifyOperationResult(tokenId, cmdId, ExecResult::COMPLETED);
478         return ERR_OK;
479     }
480     std::shared_ptr<RotateParam> rotateParam = std::make_shared<RotateParam>();
481     rotateParam->degree.yaw = rotateToEulerAnglesParam->angles.yaw;
482     rotateParam->degree.roll = rotateToEulerAnglesParam->angles.roll;
483     rotateParam->degree.pitch = rotateToEulerAnglesParam->angles.pitch;
484     rotateParam->duration = rotateToEulerAnglesParam->duration;
485     rotateParam->isRelative = false;
486     HILOGI("RotateParam: %{public}s", rotateParam->ToString().c_str());
487 
488     std::lock_guard<std::mutex> lock(motionManagersMutex);
489     if (motionManagers_.empty()) {
490         return DEVICE_NOT_CONNECTED;
491     }
492     auto it = motionManagers_.find(mechId);
493     if (it == motionManagers_.end()) {
494         return DEVICE_NOT_CONNECTED;
495     }
496     std::shared_ptr<MotionManager> motionManager = it->second;
497     if (motionManager == nullptr) {
498         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
499             GetAnonymUint32(tokenId).c_str(), mechId);
500         return DEVICE_NOT_CONNECTED;
501     }
502     int32_t result = motionManager->Rotate(rotateParam, tokenId, cmdId);
503     HILOGI("end. execute result: %{public}d.", result);
504     return result;
505 }
506 
GetMaxRotationTime(const int32_t & mechId,std::shared_ptr<TimeLimit> & timeLimit)507 int32_t MechBodyControllerService::GetMaxRotationTime(const int32_t &mechId,
508     std::shared_ptr<TimeLimit> &timeLimit)
509 {
510     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
511     if (!IsSystemApp()) {
512         HILOGE("current app is not system app.");
513         return PERMISSION_DENIED;
514     }
515     if (mechId < 0) {
516         HILOGE("Invalid mech id");
517         return INVALID_MECH_ID;
518     }
519     HILOGI("start, tokenId: %{public}s; mechId: %{public}d;",  GetAnonymUint32(tokenId).c_str(), mechId);
520 
521     std::lock_guard<std::mutex> lock(motionManagersMutex);
522     if (motionManagers_.empty()) {
523         return DEVICE_NOT_CONNECTED;
524     }
525     auto it = motionManagers_.find(mechId);
526     if (it == motionManagers_.end()) {
527         return DEVICE_NOT_CONNECTED;
528     }
529     std::shared_ptr<MotionManager> motionManager = it->second;
530     if (motionManager == nullptr) {
531         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
532             GetAnonymUint32(tokenId).c_str(), mechId);
533         return DEVICE_NOT_CONNECTED;
534     }
535     int32_t result = motionManager->GetSpeedControlTimeLimit(timeLimit);
536     HILOGI("end. result: %{public}d.", result);
537     return result;
538 }
539 
GetMaxRotationSpeed(const int32_t & mechId,RotateSpeedLimit & speedLimit)540 int32_t MechBodyControllerService::GetMaxRotationSpeed(const int32_t &mechId,
541     RotateSpeedLimit &speedLimit)
542 {
543     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
544     if (!IsSystemApp()) {
545         HILOGE("current app is not system app.");
546         return PERMISSION_DENIED;
547     }
548     if (mechId < 0) {
549         HILOGE("Invalid mech id");
550         return INVALID_MECH_ID;
551     }
552     HILOGI("start, tokenId: %{public}s; mechId: %{public}d;",  GetAnonymUint32(tokenId).c_str(), mechId);
553 
554     std::lock_guard<std::mutex> lock(motionManagersMutex);
555     if (motionManagers_.empty()) {
556         return DEVICE_NOT_CONNECTED;
557     }
558     auto it = motionManagers_.find(mechId);
559     if (it == motionManagers_.end()) {
560         return DEVICE_NOT_CONNECTED;
561     }
562     std::shared_ptr<MotionManager> motionManager = it->second;
563     if (motionManager == nullptr) {
564         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
565             GetAnonymUint32(tokenId).c_str(), mechId);
566         return DEVICE_NOT_CONNECTED;
567     }
568     int32_t result = motionManager->GetRotateSpeedLimit(speedLimit);
569     HILOGI("end. result: %{public}d.", result);
570     return result;
571 }
572 
RotateBySpeed(const int32_t & mechId,std::string & cmdId,const std::shared_ptr<RotateBySpeedParam> & rotateBySpeedParam)573 int32_t MechBodyControllerService::RotateBySpeed(const int32_t &mechId, std::string &cmdId,
574     const std::shared_ptr<RotateBySpeedParam> &rotateBySpeedParam)
575 {
576     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
577     if (!IsSystemApp()) {
578         HILOGE("current app is not system app.");
579         return PERMISSION_DENIED;
580     }
581     if (mechId < 0) {
582         HILOGE("Invalid mech id");
583         return INVALID_MECH_ID;
584     }
585     if (rotateBySpeedParam == nullptr) {
586         HILOGE("rotateBySpeedParam is nullptr.");
587         return INVALID_ROTATE_PARAM;
588     }
589     HILOGI("start, tokenId: %{public}s; mechId: %{public}d; rotate speed param: %{public}s",
590         GetAnonymUint32(tokenId).c_str(), mechId, rotateBySpeedParam->ToString().c_str());
591 
592     if (rotateBySpeedParam->duration == 0) {
593         NotifyOperationResult(tokenId, cmdId, ExecResult::COMPLETED);
594         return ERR_OK;
595     }
596     std::lock_guard<std::mutex> lock(motionManagersMutex);
597     if (motionManagers_.empty()) {
598         return DEVICE_NOT_CONNECTED;
599     }
600     auto it = motionManagers_.find(mechId);
601     if (it == motionManagers_.end()) {
602         return DEVICE_NOT_CONNECTED;
603     }
604     std::shared_ptr<MotionManager> motionManager = it->second;
605     if (motionManager == nullptr) {
606         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
607             GetAnonymUint32(tokenId).c_str(), mechId);
608         return DEVICE_NOT_CONNECTED;
609     }
610     int32_t result = motionManager->RotateBySpeed(rotateBySpeedParam, tokenId, cmdId);
611     HILOGI("end. execute result: %{public}d.", result);
612     return result;
613 }
614 
StopMoving(const int32_t & mechId,std::string & cmdId)615 int32_t MechBodyControllerService::StopMoving(const int32_t &mechId, std::string &cmdId)
616 {
617     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
618     if (!IsSystemApp()) {
619         HILOGE("current app is not system app.");
620         return PERMISSION_DENIED;
621     }
622     if (mechId < 0) {
623         HILOGE("Invalid mech id");
624         return INVALID_MECH_ID;
625     }
626     HILOGI("start, tokenId: %{public}s; mechId: %{public}d; cmdId: %{public}s",
627         GetAnonymUint32(tokenId).c_str(), mechId, cmdId.c_str());
628 
629     std::lock_guard<std::mutex> lock(motionManagersMutex);
630     if (motionManagers_.empty()) {
631         return DEVICE_NOT_CONNECTED;
632     }
633     auto it = motionManagers_.find(mechId);
634     if (it == motionManagers_.end()) {
635         return DEVICE_NOT_CONNECTED;
636     }
637     std::shared_ptr<MotionManager> motionManager = it->second;
638     if (motionManager == nullptr) {
639         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
640             GetAnonymUint32(tokenId).c_str(), mechId);
641         return DEVICE_NOT_CONNECTED;
642     }
643     int32_t result = motionManager->StopRotate(tokenId, cmdId);
644     HILOGI("end. execute result: %{public}d.", result);
645     return result;
646 }
647 
GetRotationAngles(const int32_t & mechId,std::shared_ptr<EulerAngles> & eulerAngles)648 int32_t MechBodyControllerService::GetRotationAngles(const int32_t &mechId,
649     std::shared_ptr<EulerAngles> &eulerAngles)
650 {
651     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
652     if (!IsSystemApp()) {
653         HILOGE("current app is not system app.");
654         return PERMISSION_DENIED;
655     }
656     if (mechId < 0) {
657         HILOGE("Invalid mech id");
658         return INVALID_MECH_ID;
659     }
660     HILOGI("start, tokenId: %{public}s; mechId: %{public}d;", GetAnonymUint32(tokenId).c_str(), mechId);
661     std::lock_guard<std::mutex> lock(motionManagersMutex);
662     if (motionManagers_.empty()) {
663         return DEVICE_NOT_CONNECTED;
664     }
665     auto it = motionManagers_.find(mechId);
666     if (it == motionManagers_.end()) {
667         return DEVICE_NOT_CONNECTED;
668     }
669     std::shared_ptr<MotionManager> motionManager = it->second;
670     if (motionManager == nullptr) {
671         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
672             GetAnonymUint32(tokenId).c_str(), mechId);
673         return DEVICE_NOT_CONNECTED;
674     }
675     int32_t result = motionManager->GetCurrentPosition(eulerAngles);
676     HILOGI("end. query result: %{public}d.", result);
677     return result;
678 }
679 
GetRotationDegreeLimits(const int32_t & mechId,RotateDegreeLimit & rotationLimit)680 int32_t MechBodyControllerService::GetRotationDegreeLimits(const int32_t &mechId,
681     RotateDegreeLimit &rotationLimit)
682 {
683     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
684     if (!IsSystemApp()) {
685         HILOGE("current app is not system app.");
686         return PERMISSION_DENIED;
687     }
688     if (mechId < 0) {
689         HILOGE("Invalid mech id");
690         return INVALID_MECH_ID;
691     }
692     HILOGI("start, tokenId: %{public}s; mechId: %{public}d;", GetAnonymUint32(tokenId).c_str(), mechId);
693     std::lock_guard<std::mutex> lock(motionManagersMutex);
694     if (motionManagers_.empty()) {
695         return DEVICE_NOT_CONNECTED;
696     }
697     auto it = motionManagers_.find(mechId);
698     if (it == motionManagers_.end()) {
699         return DEVICE_NOT_CONNECTED;
700     }
701     std::shared_ptr<MotionManager> motionManager = it->second;
702     if (motionManager == nullptr) {
703         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
704             GetAnonymUint32(tokenId).c_str(), mechId);
705         return DEVICE_NOT_CONNECTED;
706     }
707     int32_t result = motionManager->GetRotationLimit(rotationLimit);
708     HILOGI("end. query result: %{public}d.", result);
709     return result;
710 }
711 
GetRotationAxesStatus(const int32_t & mechId,RotationAxesStatus & axesStatus)712 int32_t MechBodyControllerService::GetRotationAxesStatus(const int32_t &mechId,
713     RotationAxesStatus &axesStatus)
714 {
715     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
716     if (!IsSystemApp()) {
717         HILOGE("current app is not system app.");
718         return PERMISSION_DENIED;
719     }
720     if (mechId < 0) {
721         HILOGE("Invalid mech id");
722         return INVALID_MECH_ID;
723     }
724     HILOGI("start, tokenId: %{public}s; mechId: %{public}d;", GetAnonymUint32(tokenId).c_str(), mechId);
725     std::lock_guard<std::mutex> lock(motionManagersMutex);
726     if (motionManagers_.empty()) {
727         return DEVICE_NOT_CONNECTED;
728     }
729     auto it = motionManagers_.find(mechId);
730     if (it == motionManagers_.end()) {
731         return DEVICE_NOT_CONNECTED;
732     }
733     std::shared_ptr<MotionManager> motionManager = it->second;
734     if (motionManager == nullptr) {
735         HILOGE("motionManager not exist. tokenId: %{public}s; mechId: %{public}d",
736             GetAnonymUint32(tokenId).c_str(), mechId);
737         return DEVICE_NOT_CONNECTED;
738     }
739     int32_t result = motionManager->GetRotationAxesStatus(mechId, axesStatus);
740     HILOGI("end. query result: %{public}d.", result);
741     return result;
742 }
743 
RegisterRotationAxesStatusChangeCallback(const sptr<IRemoteObject> callback)744 int32_t MechBodyControllerService::RegisterRotationAxesStatusChangeCallback(const sptr <IRemoteObject> callback)
745 {
746     // LCOV_EXCL_START
747     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
748     HILOGI("start tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
749     if (!IsSystemApp()) {
750         HILOGE("current app is not system app.");
751         return PERMISSION_DENIED;
752     }
753     if (callback == nullptr) {
754         HILOGE("callback is nullptr");
755         return INVALID_REMOTE_OBJECT;
756     }
757 
758     sptr <MechControllerIpcDeathListener> diedListener = new MechControllerIpcDeathListener();
759     diedListener->tokenId_ = tokenId;
760     diedListener->objectType_ = RemoteObjectType::ROTATION_AXES_STATUS_CALLBACK;
761     callback->AddDeathRecipient(diedListener);
762     {
763         std::lock_guard<std::mutex> lock(AxesStatusChangeCallbackMutex_);
764         rotationAxesStatusChangeCallback_[tokenId] = callback;
765     }
766     HILOGI("end, callback add success, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
767     return ERR_OK;
768     // LCOV_EXCL_STOP
769 }
770 
UnRegisterRotationAxesStatusChangeCallback()771 int32_t MechBodyControllerService::UnRegisterRotationAxesStatusChangeCallback()
772 {
773     // LCOV_EXCL_START
774     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
775     HILOGI("start, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
776     if (!IsSystemApp()) {
777         HILOGE("current app is not system app.");
778         return PERMISSION_DENIED;
779     }
780     std::lock_guard<std::mutex> lock(AxesStatusChangeCallbackMutex_);
781     rotationAxesStatusChangeCallback_.erase(tokenId);
782     HILOGI("end, callback remove success, tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
783     return ERR_OK;
784     // LCOV_EXCL_STOP
785 }
786 
OnRotationAxesStatusChange(const int32_t & mechId,const RotationAxesStatus & axesStatus)787 int32_t MechBodyControllerService::OnRotationAxesStatusChange(const int32_t &mechId,
788                                                               const RotationAxesStatus &axesStatus)
789 {
790     HILOGI("start notify Rotation Axes Status Change, mechId: %{public}d; axesStatus: %{public}s", mechId,
791            axesStatus.ToString().c_str());
792     std::lock_guard<std::mutex> lock(AxesStatusChangeCallbackMutex_);
793     for (const auto &item: rotationAxesStatusChangeCallback_) {
794         int32_t tokenId = item.first;
795         HILOGI("notify Rotation Axes Status to tokenId: %{public}s;", GetAnonymUint32(tokenId).c_str());
796         sptr <IRemoteObject> callback = item.second;
797         MessageParcel data;
798         if (!data.WriteInterfaceToken(MECH_SERVICE_IPC_TOKEN)) {
799             HILOGE("Write interface token failed");
800             continue;
801         }
802 
803         if (!data.WriteInt32(mechId)) {
804             HILOGE("Write mechId failed.");
805             continue;
806         }
807 
808         if (!data.WriteParcelable(&axesStatus)) {
809             HILOGE("Write axesStatus failed");
810             continue;
811         }
812         MessageParcel reply;
813         MessageOption option;
814         int32_t error =
815             callback->SendRequest(static_cast<uint32_t>(IMechBodyControllerCode::ROTATION_AXES_STATUS_CHANGE_CALLBACK),
816             data, reply, option);
817         HILOGI("notify tracking event to tokenId: %{public}s; axesStatus: %{public}s", GetAnonymUint32(tokenId).c_str(),
818             error == ERR_NONE ? "success" : "failed");
819     }
820     return ERR_OK;
821 }
822 
IsSystemApp()823 bool MechBodyControllerService::IsSystemApp()
824 {
825     uint64_t accessTokenIDEx = IPCSkeleton::GetCallingFullTokenID();
826     return OHOS::Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(accessTokenIDEx);
827 }
828 
829 } // namespace MechBodyController
830 } // namespace OHOS
831