1 /*
2 * Copyright (c) 2022 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 "light_client.h"
17
18 #include <securec.h>
19 #include <thread>
20
21 #include "death_recipient_template.h"
22 #include "hisysevent.h"
23 #include "iservice_registry.h"
24 #include "sensors_errors.h"
25 #include "system_ability_definition.h"
26
27 namespace OHOS {
28 namespace Sensors {
29
30 namespace {
31 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MISC_LOG_DOMAIN, "LightClient" };
32 constexpr int32_t GET_SERVICE_MAX_COUNT = 30;
33 constexpr uint32_t MAX_LIGHT_LIST_SIZE = 0X00ff;
34 constexpr uint32_t WAIT_MS = 200;
35 } // namespace
36
~LightClient()37 LightClient::~LightClient()
38 {
39 if (miscdeviceProxy_ != nullptr && serviceDeathObserver_ != nullptr) {
40 auto remoteObject = miscdeviceProxy_->AsObject();
41 if (remoteObject != nullptr) {
42 remoteObject->RemoveDeathRecipient(serviceDeathObserver_);
43 }
44 }
45 }
46
InitLightClient()47 int32_t LightClient::InitLightClient()
48 {
49 CALL_LOG_ENTER;
50 std::lock_guard<std::mutex> clientLock(clientMutex_);
51 if (miscdeviceProxy_ != nullptr) {
52 MISC_HILOGD("miscdeviceProxy_ already init");
53 return ERR_OK;
54 }
55 auto systemManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
56 CHKPR(systemManager, MISC_NATIVE_SAM_ERR);
57 int32_t retry = 0;
58 while (retry < GET_SERVICE_MAX_COUNT) {
59 miscdeviceProxy_ = iface_cast<IMiscdeviceService>(systemManager->GetSystemAbility(
60 MISCDEVICE_SERVICE_ABILITY_ID));
61 if (miscdeviceProxy_ != nullptr) {
62 MISC_HILOGD("miscdeviceProxy_ get service success, retry:%{public}d", retry);
63 serviceDeathObserver_ = new (std::nothrow) DeathRecipientTemplate(*const_cast<LightClient *>(this));
64 CHKPR(serviceDeathObserver_, MISC_NATIVE_GET_SERVICE_ERR);
65 auto remoteObject = miscdeviceProxy_->AsObject();
66 CHKPR(remoteObject, MISC_NATIVE_GET_SERVICE_ERR);
67 remoteObject->AddDeathRecipient(serviceDeathObserver_);
68 lightInfoList_ = miscdeviceProxy_->GetLightList();
69 return ERR_OK;
70 }
71 MISC_HILOGW("Get service failed, retry:%{public}d", retry);
72 std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_MS));
73 retry++;
74 }
75 HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::MISCDEVICE, "MISC_SERVICE_EXCEPTION",
76 HiviewDFX::HiSysEvent::EventType::FAULT, "PKG_NAME", "InitLightClient", "ERROR_CODE",
77 MISC_NATIVE_GET_SERVICE_ERR);
78 MISC_HILOGE("Get service failed");
79 return MISC_NATIVE_GET_SERVICE_ERR;
80 }
81
IsLightIdValid(int32_t lightId)82 bool LightClient::IsLightIdValid(int32_t lightId)
83 {
84 int32_t ret = InitLightClient();
85 if (ret != ERR_OK) {
86 MISC_HILOGE("InitLightClient failed, ret:%{public}d", ret);
87 return false;
88 }
89 for (const auto &item : lightInfoList_) {
90 if (lightId == item.lightId) {
91 return true;
92 }
93 }
94 return false;
95 }
96
GetLightList(LightInfo ** lightInfo,int32_t & count)97 int32_t LightClient::GetLightList(LightInfo **lightInfo, int32_t &count)
98 {
99 CALL_LOG_ENTER;
100 CHKPR(lightInfo, ERROR);
101 int32_t ret = InitLightClient();
102 if (ret != ERR_OK) {
103 MISC_HILOGE("InitLightClient failed");
104 return ERROR;
105 }
106 std::lock_guard<std::mutex> lightInfosLock(lightInfosMutex_);
107 if (lightInfos_ == nullptr) {
108 ret = ConvertLightInfos();
109 if (ret != ERR_OK) {
110 MISC_HILOGE("Convert light lists failed");
111 ClearLightInfos();
112 return ERROR;
113 }
114 }
115 *lightInfo = lightInfos_;
116 count = lightInfoCount_;
117 return ERR_OK;
118 }
119
IsLightAnimationValid(const LightAnimation & animation)120 bool LightClient::IsLightAnimationValid(const LightAnimation &animation)
121 {
122 if ((animation.mode < 0) || (animation.mode >= LIGHT_MODE_BUTT)) {
123 MISC_HILOGE("animation mode is invalid, mode:%{pubilc}d", animation.mode);
124 return false;
125 }
126 if ((animation.onTime < 0) || (animation.offTime < 0)) {
127 MISC_HILOGE("animation onTime or offTime is invalid, onTime:%{pubilc}d, offTime:%{pubilc}d",
128 animation.onTime, animation.offTime);
129 return false;
130 }
131 return true;
132 }
133
TurnOn(int32_t lightId,const LightColor & color,const LightAnimation & animation)134 int32_t LightClient::TurnOn(int32_t lightId, const LightColor &color, const LightAnimation &animation)
135 {
136 CALL_LOG_ENTER;
137 if (!IsLightIdValid(lightId)) {
138 MISC_HILOGE("lightId is invalid, lightId:%{pubilc}d", lightId);
139 return PARAMETER_ERROR;
140 }
141 if (!IsLightAnimationValid(animation)) {
142 MISC_HILOGE("animation is invalid");
143 return PARAMETER_ERROR;
144 }
145 CHKPR(miscdeviceProxy_, ERROR);
146 return miscdeviceProxy_->TurnOn(lightId, color, animation);
147 }
148
TurnOff(int32_t lightId)149 int32_t LightClient::TurnOff(int32_t lightId)
150 {
151 CALL_LOG_ENTER;
152 if (!IsLightIdValid(lightId)) {
153 MISC_HILOGE("lightId is invalid, lightId:%{pubilc}d", lightId);
154 return LIGHT_ID_NOT_SUPPORT;
155 }
156 CHKPR(miscdeviceProxy_, ERROR);
157 return miscdeviceProxy_->TurnOff(lightId);
158 }
159
ProcessDeathObserver(wptr<IRemoteObject> object)160 void LightClient::ProcessDeathObserver(wptr<IRemoteObject> object)
161 {
162 CALL_LOG_ENTER;
163 (void)object;
164 miscdeviceProxy_ = nullptr;
165 auto ret = InitLightClient();
166 if (ret != ERR_OK) {
167 MISC_HILOGE("InitLightClient failed, ret:%{public}d", ret);
168 return;
169 }
170 }
171
ClearLightInfos()172 void LightClient::ClearLightInfos()
173 {
174 CHKPV(lightInfos_);
175 free(lightInfos_);
176 lightInfos_ = nullptr;
177 }
178
ConvertLightInfos()179 int32_t LightClient::ConvertLightInfos()
180 {
181 CALL_LOG_ENTER;
182 if (lightInfoList_.empty()) {
183 MISC_HILOGE("Get light lists failed");
184 return ERROR;
185 }
186 size_t count = lightInfoList_.size();
187 if (count > MAX_LIGHT_LIST_SIZE) {
188 MISC_HILOGE("The number of lights exceed the maximum value");
189 return ERROR;
190 }
191 lightInfos_ = (LightInfo *)malloc(sizeof(LightInfo) * count);
192 CHKPR(lightInfos_, ERROR);
193 for (size_t i = 0; i < count; ++i) {
194 *(lightInfos_ + i) = lightInfoList_[i];
195 }
196 lightInfoCount_ = static_cast<int32_t>(count);
197 return SUCCESS;
198 }
199 } // namespace Sensors
200 } // namespace OHOS
201