1/*
2 * Copyright (c) 2020 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 "nativeapi_deviceinfo.h"
17#include <string>
18#include <new>
19#include "global.h"
20#include "js_async_work.h"
21#include "nativeapi_common.h"
22#include "nativeapi_config.h"
23#include "parameter.h"
24#include "common/screen.h"
25
26namespace OHOS {
27namespace ACELite {
28namespace {
29JSIValue ExecuteAsyncWork(const JSIValue thisVal, const JSIValue* args,
30    uint8_t argsNum, AsyncWorkHandler ExecuteFunc, bool flag = false)
31{
32    JSIValue undefValue = JSI::CreateUndefined();
33    if (!NativeapiCommon::IsValidJSIValue(args, argsNum)) {
34        return undefValue;
35    }
36    FuncParams* params = new(std::nothrow) FuncParams();
37    if (params == nullptr) {
38        return undefValue;
39    }
40    params->thisVal = JSI::AcquireValue(thisVal);
41    params->args = JSI::AcquireValue(args[0]);
42    params->flag = flag;
43    JsAsyncWork::DispatchAsyncWork(ExecuteFunc, reinterpret_cast<void *>(params));
44    return undefValue;
45}
46
47void ExecuteGetInfo(void* data)
48{
49    FuncParams* params = reinterpret_cast<FuncParams *>(data);
50    if (params == nullptr) {
51        return;
52    }
53    JSIValue args = params->args;
54    JSIValue thisVal = params->thisVal;
55    JSIValue result = JSI::CreateObject();
56    if (!NativeapiDeviceInfo::GetProductInfo(result)) {
57        NativeapiCommon::FailCallBack(thisVal, args, ERROR_CODE_GENERAL);
58    } else {
59        NativeapiCommon::SuccessCallBack(thisVal, args, result);
60    }
61    JSI::ReleaseValueList(args, thisVal, result, ARGS_END);
62    delete params;
63    params = nullptr;
64}
65}
66
67void InitDeviceModule(JSIValue exports)
68{
69    JSI::SetModuleAPI(exports, "getInfo", NativeapiDeviceInfo::GetDeviceInfo);
70}
71
72bool NativeapiDeviceInfo::GetAPILevel(JSIValue result)
73{
74    int apiLevel = GetSdkApiVersion();
75    if (apiLevel < 1) {
76        return false;
77    }
78    JSI::SetStringProperty(result, "apiVersion", std::to_string(apiLevel).c_str());
79    return true;
80}
81
82JSIValue NativeapiDeviceInfo::GetDeviceInfo(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
83{
84    return ExecuteAsyncWork(thisVal, args, argsNum, ExecuteGetInfo);
85}
86
87bool NativeapiDeviceInfo::GetDeviceType(JSIValue result)
88{
89    const char* deviceType = ::GetDeviceType();
90    if (deviceType == nullptr) {
91        return false;
92    }
93    JSI::SetStringProperty(result, "deviceType", deviceType);
94    return true;
95}
96
97bool NativeapiDeviceInfo::GetLanguage(JSIValue result)
98{
99    // because of MAX_LANGUAGE_LENGTH is little,we use array instead of pointer
100    char langStr[MAX_LANGUAGE_LENGTH + 1] = {0};
101    if (GLOBAL_GetLanguage(langStr, MAX_LANGUAGE_LENGTH) != 0) {
102        JSI::SetStringProperty(result, "language", "");
103    } else {
104        JSI::SetStringProperty(result, "language", langStr);
105    }
106    return true;
107}
108
109bool NativeapiDeviceInfo::GetProductInfo(JSIValue result)
110{
111    bool isSuccess = true;
112    const char* brand =  GetBrand();
113    const char* manufacture = GetManufacture();
114    const char* model = GetProductModel();
115    if (brand == nullptr || manufacture == nullptr || model == nullptr) {
116        isSuccess = false;
117    } else {
118        JSI::SetStringProperty(result, "brand", brand);
119        JSI::SetStringProperty(result, "manufacturer", manufacture);
120        JSI::SetStringProperty(result, "model", model);
121        JSI::SetStringProperty(result, "product", model);
122    }
123    if (isSuccess) {
124        if (!NativeapiDeviceInfo::GetDeviceType(result) ||
125            !NativeapiDeviceInfo::GetLanguage(result) ||
126            !NativeapiDeviceInfo::GetAPILevel(result) ||
127            !NativeapiDeviceInfo::GetRegion(result)) {
128            isSuccess = false;
129        }
130    }
131
132    Screen &screen = Screen::GetInstance();
133    JSI::SetNumberProperty(result, "windowWidth", static_cast<double>(screen.GetWidth()));
134    JSI::SetNumberProperty(result, "windowHeight", static_cast<double>(screen.GetHeight()));
135    // set default value
136    const uint8_t defaultScreenDensity = 195;
137    const char * const defaultScreenShape = "rect";
138    JSI::SetNumberProperty(result, "screenDensity", static_cast<double>(defaultScreenDensity));
139    JSI::SetStringProperty(result, "screenShape", defaultScreenShape);
140    return isSuccess;
141}
142
143bool NativeapiDeviceInfo::GetRegion(JSIValue result)
144{
145    // because of MAX_REGION_LENGTH is little,we use array instead of pointer
146    char region[MAX_REGION_LENGTH + 1] = {0};
147    if (GLOBAL_GetRegion(region, MAX_REGION_LENGTH) != 0) {
148        JSI::SetStringProperty(result, "region", "");
149    } else {
150        JSI::SetStringProperty(result, "region", region);
151    }
152    return true;
153}
154} // ACELite
155} // OHOS
156