1  /*
2   * Copyright (c) 2021-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 "brightness.h"
17  #include "napi/native_common.h"
18  #include "display_common.h"
19  #include "display_log.h"
20  #include "display_power_mgr_client.h"
21  
22  using namespace OHOS::PowerMgr;
23  
24  namespace OHOS {
25  namespace DisplayPowerMgr {
26  namespace {
27  const uint32_t MAX_ARGC = 2;
28  const uint32_t CALLBACK_ARGC = 1;
29  const uint32_t ARGV_BRIGHTNESS_INDEX = 0;
30  const uint32_t ARGV_CONTINUOUS_INDEX = 1;
31  const uint32_t ERR_DATA_INDEX = 0;
32  const uint32_t ERR_CODE_INDEX = 1;
33  const uint32_t MAX_FAIL_ARGC = 2;
34  const uint32_t MAX_BRIGHTNESS = DisplayPowerMgrClient::GetInstance().GetMaxBrightness();
35  const uint32_t MIN_BRIGHTNESS = DisplayPowerMgrClient::GetInstance().GetMinBrightness();
36  const uint32_t DEFAULT_BRIGHTNESS = DisplayPowerMgrClient::GetInstance().GetDefaultBrightness();
37  const uint32_t MAIN_DISPLAY_ID = DisplayPowerMgrClient::GetInstance().GetMainDisplayId();
38  
39  const std::string FUNC_SUCEESS_NAME = "success";
40  const std::string FUNC_FAIL_NAME = "fail";
41  const std::string FUNC_COMPLETE_NAME = "complete";
42  
43  const int32_t COMMON_ERROR_COED = 200;
44  const int32_t INPUT_ERROR_CODE = 202;
45  
46  const std::string SET_VALUE_ERROR_MGR = "value is not an available number";
47  const std::string GET_VALUE_ERROR_MGR = "get system screen brightness fail";
48  const std::string SET_MODE_ERROR_MGR = "value is not an available number";
49  const std::string SET_MODE_NOT_SUPPORTED_ERROR_MGR = "Auto adjusting brightness is not supported";
50  const std::string SET_KEEP_SCREENON_ERROR_MGR = "value is not an available boolean";
51  } // namespace
52  
53  std::map<DisplayErrors, std::string> Brightness::Result::errorTable_ = {
54      {DisplayErrors::ERR_CONNECTION_FAIL,   "Failed to connect to the service."},
55      {DisplayErrors::ERR_PERMISSION_DENIED, "Permission is denied"             },
56      {DisplayErrors::ERR_SYSTEM_API_DENIED, "System permission is denied"      },
57      {DisplayErrors::ERR_PARAM_INVALID,     "Invalid input parameter."         }
58  };
59  
Brightness(napi_env env,std::shared_ptr<RunningLock> runningLock)60  Brightness::Brightness(napi_env env, std::shared_ptr<RunningLock> runningLock) : env_(env), runningLock_(runningLock) {}
61  
~Brightness()62  Brightness::~Brightness()
63  {
64      ReleaseReference(successRef_);
65      ReleaseReference(failRef_);
66      ReleaseReference(completeRef_);
67      ReleaseReference(napiValRef_);
68  }
69  
GetValue()70  void Brightness::GetValue()
71  {
72      uint32_t brightness = brightnessInfo_.GetBrightness();
73      if (brightness < MIN_BRIGHTNESS || brightness > MAX_BRIGHTNESS) {
74          result_.Error(COMMON_ERROR_COED, GET_VALUE_ERROR_MGR);
75      } else {
76          result_.SetResult(BRIGHTNESS_VALUE, brightness);
77      }
78      ExecuteCallback();
79  }
80  
SetValue(napi_callback_info & info)81  void Brightness::SetValue(napi_callback_info& info)
82  {
83      DISPLAY_HILOGD(FEAT_BRIGHTNESS, "Brightness interface");
84      napi_value napiBrightness = GetCallbackInfo(info, ARGV_BRIGHTNESS_INDEX, napi_number);
85      napi_value napiUndefined = GetCallbackInfo(info, ARGV_BRIGHTNESS_INDEX, napi_undefined);
86      if (napiBrightness == nullptr && napiUndefined == nullptr) {
87          result_.ThrowError(env_, DisplayErrors::ERR_PARAM_INVALID);
88          return;
89      }
90  
91      int32_t value = MIN_BRIGHTNESS;
92      bool continuous = false;
93      if (napi_get_value_int32(env_, napiBrightness, &value) != napi_ok) {
94          if (napiUndefined != nullptr) {
95              return;
96          } else {
97              DISPLAY_HILOGW(COMP_FWK, "Failed to get the input number");
98              result_.ThrowError(env_, DisplayErrors::ERR_PARAM_INVALID);
99              return;
100          }
101      }
102      napi_value napiContinuous = GetCallbackInfo(info, ARGV_CONTINUOUS_INDEX, napi_boolean);
103      if (napiContinuous != nullptr) {
104          napi_get_value_bool(env_, napiContinuous, &continuous);
105      }
106  
107      if (!brightnessInfo_.SetBrightness(value, continuous)) {
108          DisplayErrors error = brightnessInfo_.GetServiceError();
109          if (error != DisplayErrors::ERR_OK) {
110              result_.ThrowError(env_, error);
111          }
112      }
113  }
114  
SystemSetValue()115  void Brightness::SystemSetValue()
116  {
117      DISPLAY_HILOGD(FEAT_BRIGHTNESS, "System brightness interface");
118      if (napiValRef_ == nullptr) {
119          result_.Error(INPUT_ERROR_CODE, SET_VALUE_ERROR_MGR);
120      } else {
121          int32_t brightness = MIN_BRIGHTNESS;
122          napi_value napiVal = nullptr;
123          napi_get_reference_value(env_, napiValRef_, &napiVal);
124          napi_get_value_int32(env_, napiVal, &brightness);
125          brightnessInfo_.SetBrightness(brightness, false);
126          ReleaseReference(napiValRef_);
127      }
128      ExecuteCallback();
129  }
130  
GetMode()131  void Brightness::GetMode()
132  {
133      int32_t isAuto = brightnessInfo_.GetAutoMode();
134      result_.SetResult(BRIGHTNESS_MODE, isAuto);
135      ExecuteCallback();
136  }
137  
SetMode()138  void Brightness::SetMode()
139  {
140      DISPLAY_HILOGD(COMP_FWK, "Set auto brightness");
141      if (napiValRef_ == nullptr) {
142          result_.Error(INPUT_ERROR_CODE, SET_MODE_ERROR_MGR);
143      } else {
144          int32_t mode = 0;
145          napi_value napiMode = nullptr;
146          napi_get_reference_value(env_, napiValRef_, &napiMode);
147          napi_get_value_int32(env_, napiMode, &mode);
148          if (!brightnessInfo_.SetAutoMode(static_cast<bool>(mode))) {
149              result_.Error(COMMON_ERROR_COED, SET_MODE_NOT_SUPPORTED_ERROR_MGR);
150          }
151          ReleaseReference(napiValRef_);
152      }
153      ExecuteCallback();
154  }
155  
SetKeepScreenOn()156  void Brightness::SetKeepScreenOn()
157  {
158      DISPLAY_HILOGD(COMP_FWK, "Set keep screen on");
159      if (napiValRef_ == nullptr) {
160          result_.Error(INPUT_ERROR_CODE, SET_KEEP_SCREENON_ERROR_MGR);
161      } else {
162          napi_value napiKeep = nullptr;
163          napi_get_reference_value(env_, napiValRef_, &napiKeep);
164          bool screenOn = false;
165          napi_get_value_bool(env_, napiKeep, &screenOn);
166          brightnessInfo_.ScreenOn(screenOn, runningLock_);
167          ReleaseReference(napiValRef_);
168      }
169      ExecuteCallback();
170  }
171  
GetCallbackInfo(napi_callback_info & info,uint32_t index,napi_valuetype checkType)172  napi_value Brightness::GetCallbackInfo(napi_callback_info& info, uint32_t index, napi_valuetype checkType)
173  {
174      size_t argc = MAX_ARGC;
175      napi_value argv[argc];
176      napi_value thisVar = nullptr;
177      void* data = nullptr;
178      if (napi_ok != napi_get_cb_info(env_, info, &argc, argv, &thisVar, &data)) {
179          DISPLAY_HILOGW(COMP_FWK, "Failed to get the input parameter");
180          return nullptr;
181      }
182  
183      if (argc > MAX_ARGC || index >= argc) {
184          DISPLAY_HILOGW(COMP_FWK, "parameter %{public}u is invalid", index);
185          return nullptr;
186      }
187  
188      napi_value options = argv[index];
189      RETURN_IF_WITH_RET(!CheckValueType(options, checkType), nullptr);
190      return options;
191  }
192  
CreateCallbackRef(napi_value & options)193  bool Brightness::CreateCallbackRef(napi_value& options)
194  {
195      RETURN_IF_WITH_RET(!CheckValueType(options, napi_object), false);
196  
197      napi_value succCallBack = GetOptions(options, FUNC_SUCEESS_NAME, napi_function);
198      if (succCallBack != nullptr) {
199          napi_create_reference(env_, succCallBack, 1, &successRef_);
200      }
201  
202      napi_value failCallBack = GetOptions(options, FUNC_FAIL_NAME, napi_function);
203      if (failCallBack != nullptr) {
204          napi_create_reference(env_, failCallBack, 1, &failRef_);
205      }
206  
207      napi_value completeCallBack = GetOptions(options, FUNC_COMPLETE_NAME, napi_function);
208      if (completeCallBack != nullptr) {
209          napi_create_reference(env_, completeCallBack, 1, &completeRef_);
210      }
211      return true;
212  }
213  
CreateValueRef(napi_value & options,const std::string & valName,napi_valuetype checkType)214  void Brightness::CreateValueRef(napi_value& options, const std::string& valName, napi_valuetype checkType)
215  {
216      napi_value value = GetOptions(options, valName, checkType);
217      if (value != nullptr) {
218          napi_create_reference(env_, value, 1, &napiValRef_);
219      }
220  }
221  
Error(int32_t code,const std::string & msg)222  void Brightness::Result::Error(int32_t code, const std::string& msg)
223  {
224      code_ = code;
225      msg_ = msg;
226      DISPLAY_HILOGW(COMP_FWK, "Error message, code: %{public}d, msg: %{public}s", code_, msg_.c_str());
227  }
228  
GetError(napi_env env,napi_value * error,size_t & size) const229  void Brightness::Result::GetError(napi_env env, napi_value* error, size_t& size) const
230  {
231      if (!error) {
232          DISPLAY_HILOGW(COMP_FWK, "error is null");
233          return;
234      }
235      napi_value data = nullptr;
236      napi_value code = nullptr;
237      napi_create_string_utf8(env, msg_.c_str(), msg_.size(), &data);
238      napi_create_int32(env, code_, &code);
239      size = MAX_FAIL_ARGC;
240      error[ERR_DATA_INDEX] = data;
241      error[ERR_CODE_INDEX] = code;
242  }
243  
GetError(napi_env & env)244  napi_value Brightness::Result::GetError(napi_env& env)
245  {
246      napi_value napiError = nullptr;
247      if (!IsError()) {
248          napi_get_undefined(env, &napiError);
249          return napiError;
250      }
251  
252      std::string msg;
253      auto item = errorTable_.find(static_cast<DisplayErrors>(code_));
254      if (item != errorTable_.end()) {
255          msg = item->second;
256      }
257      napi_value napiMsg;
258      NAPI_CALL(env, napi_create_string_utf8(env, msg.c_str(), msg.size(), &napiMsg));
259      NAPI_CALL(env, napi_create_error(env, nullptr, napiMsg, &napiError));
260  
261      napi_value napiCode;
262      NAPI_CALL(env, napi_create_int32(env, code_, &napiCode));
263  
264      napi_set_named_property(env, napiError, "code", napiCode);
265      napi_set_named_property(env, napiError, "message", napiMsg);
266  
267      DISPLAY_HILOGW(COMP_FWK, "throw error code: %{public}d, msg: %{public}s,", code_, msg.c_str());
268      return napiError;
269  }
270  
ThrowError(napi_env & env,DisplayErrors code)271  napi_value Brightness::Result::ThrowError(napi_env& env, DisplayErrors code)
272  {
273      Error(static_cast<int32_t>(code));
274      napi_value error = GetError(env);
275      RETURN_IF_WITH_RET(error == nullptr, nullptr);
276      napi_throw(env, error);
277      return nullptr;
278  }
279  
GetResult(napi_env env)280  napi_value Brightness::Result::GetResult(napi_env env)
281  {
282      napi_value result = nullptr;
283      NAPI_CALL(env, napi_create_object(env, &result));
284      for (const auto& it : mapResult_) {
285          napi_value napiValue = 0;
286          NAPI_CALL(env, napi_create_int32(env, it.second, &napiValue));
287          NAPI_CALL(env, napi_set_named_property(env, result, it.first.c_str(), napiValue));
288      }
289      return result;
290  }
291  
GetBrightness() const292  uint32_t Brightness::BrightnessInfo::GetBrightness() const
293  {
294      uint32_t brightness = DisplayPowerMgrClient::GetInstance().GetBrightness(MAIN_DISPLAY_ID);
295      DISPLAY_HILOGI(FEAT_BRIGHTNESS, "Get brightness: %{public}d", brightness);
296      return brightness;
297  }
298  
SetBrightness(int32_t value,bool continuous)299  bool Brightness::BrightnessInfo::SetBrightness(int32_t value, bool continuous)
300  {
301      DISPLAY_HILOGI(FEAT_BRIGHTNESS, "Set brightness: %{public}d, %{public}d", value, continuous);
302      value = value > static_cast<int32_t>(MAX_BRIGHTNESS) ? static_cast<int32_t>(MAX_BRIGHTNESS) : value;
303      value = value < static_cast<int32_t>(MIN_BRIGHTNESS) ? static_cast<int32_t>(MIN_BRIGHTNESS) : value;
304      bool isSucc = DisplayPowerMgrClient::GetInstance().SetBrightness(value, 0, continuous);
305      if (!isSucc) {
306          DISPLAY_HILOGW(FEAT_BRIGHTNESS, "Failed to set brightness: %{public}d", value);
307      }
308      return isSucc;
309  }
310  
GetAutoMode() const311  int32_t Brightness::BrightnessInfo::GetAutoMode() const
312  {
313      bool isAuto = DisplayPowerMgrClient::GetInstance().IsAutoAdjustBrightness();
314      DISPLAY_HILOGD(FEAT_BRIGHTNESS, "Automatic brightness adjustment: %{public}d", isAuto);
315      return static_cast<int32_t>(isAuto);
316  }
317  
SetAutoMode(bool mode)318  bool Brightness::BrightnessInfo::SetAutoMode(bool mode)
319  {
320      DISPLAY_HILOGD(FEAT_BRIGHTNESS, "AutoAdjustBrightness begin");
321      bool isSucc = DisplayPowerMgrClient::GetInstance().AutoAdjustBrightness(mode);
322      DISPLAY_HILOGD(FEAT_BRIGHTNESS, "set auto brightness mode: %{public}d, succ: %{public}d", mode, isSucc);
323      return isSucc;
324  }
325  
ScreenOn(bool keep,std::shared_ptr<RunningLock> & runningLock)326  void Brightness::BrightnessInfo::ScreenOn(bool keep, std::shared_ptr<RunningLock>& runningLock)
327  {
328      if (runningLock != nullptr) {
329          DISPLAY_HILOGD(COMP_FWK, "Keep screen on, keep: %{public}d, isUsed: %{public}d", keep, runningLock->IsUsed());
330          keep ? runningLock->Lock() : runningLock->UnLock();
331      }
332  }
333  
GetServiceError() const334  DisplayErrors Brightness::BrightnessInfo::GetServiceError() const
335  {
336      return DisplayPowerMgrClient::GetInstance().GetError();
337  }
338  
ExecuteCallback()339  void Brightness::ExecuteCallback()
340  {
341      bool error = result_.IsError();
342      if (!error) {
343          DISPLAY_HILOGD(COMP_FWK, "Call the js success method");
344          napi_value result = result_.GetResult(env_);
345          size_t argc = result ? CALLBACK_ARGC : 0;
346          CallFunction(successRef_, argc, result ? &result : nullptr);
347      }
348  
349      if (error) {
350          DISPLAY_HILOGD(COMP_FWK, "Call the js fail method");
351          size_t argc = MAX_FAIL_ARGC;
352          napi_value argv[argc];
353          result_.GetError(env_, argv, argc);
354          CallFunction(failRef_, argc, argv);
355      }
356      DISPLAY_HILOGD(COMP_FWK, "Call the js complete method");
357      CallFunction(completeRef_, 0, nullptr);
358  }
359  
CheckValueType(napi_value & value,napi_valuetype checkType)360  bool Brightness::CheckValueType(napi_value& value, napi_valuetype checkType)
361  {
362      napi_valuetype valueType = napi_undefined;
363      napi_typeof(env_, value, &valueType);
364      if (valueType != checkType) {
365          DISPLAY_HILOGD(COMP_FWK, "Check input parameter error");
366          return false;
367      }
368      return true;
369  }
370  
GetOptions(napi_value & options,const std::string & name,napi_valuetype checkType)371  napi_value Brightness::GetOptions(napi_value& options, const std::string& name, napi_valuetype checkType)
372  {
373      napi_value property = nullptr;
374      napi_status status = napi_get_named_property(env_, options, name.c_str(), &property);
375      if (status != napi_ok) {
376          DISPLAY_HILOGW(COMP_FWK, "Failed to get the %{public}s Options property", name.c_str());
377          return nullptr;
378      }
379      if (!CheckValueType(property, checkType)) {
380          DISPLAY_HILOGW(COMP_FWK, "Get %{public}s Options property type mismatch", name.c_str());
381          return nullptr;
382      }
383      return property;
384  }
385  
CallFunction(napi_ref & callbackRef,size_t argc,napi_value * response)386  void Brightness::CallFunction(napi_ref& callbackRef, size_t argc, napi_value* response)
387  {
388      RETURN_IF(callbackRef == nullptr);
389  
390      napi_value callResult = 0;
391      napi_value callback = nullptr;
392      napi_get_reference_value(env_, callbackRef, &callback);
393      napi_status status = napi_call_function(env_, nullptr, callback, argc, response, &callResult);
394      if (status != napi_ok) {
395          DISPLAY_HILOGW(COMP_FWK, "Failed to call the callback function");
396      }
397      ReleaseReference(callbackRef);
398  }
399  
ReleaseReference(napi_ref & ref)400  void Brightness::ReleaseReference(napi_ref& ref)
401  {
402      if (ref != nullptr) {
403          napi_delete_reference(env_, ref);
404          ref = nullptr;
405      }
406  }
407  } // namespace DisplayPowerMgr
408  } // namespace OHOS
409