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