1 /*
2  * Copyright (c) 2022-2024 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 "cj_environment_callback.h"
17 
18 #include "hilog_tag_wrapper.h"
19 
20 namespace OHOS {
21 namespace AbilityRuntime {
CjEnvironmentCallback()22 CjEnvironmentCallback::CjEnvironmentCallback()
23 {
24 }
25 
26 int32_t CjEnvironmentCallback::serialNumber_ = 0;
27 
ConvertColorMode(std::string colormode)28 int32_t ConvertColorMode(std::string colormode)
29 {
30     auto resolution = -1;
31     static const std::vector<std::pair<std::string, int32_t>> resolutions = {
32         { "dark", 0 },
33         { "light", 1 },
34     };
35     for (const auto& [tempColorMode, value] : resolutions) {
36         if (tempColorMode == colormode) {
37             resolution = value;
38             break;
39         }
40     }
41     return resolution;
42 }
43 
ConvertDirection(std::string direction)44 int32_t ConvertDirection(std::string direction)
45 {
46     auto resolution = -1;
47     static const std::vector<std::pair<std::string, int32_t>> resolutions = {
48         { "vertical", 0 },
49         { "horizontal", 1 },
50     };
51     for (const auto& [tempDirection, value] : resolutions) {
52         if (tempDirection == direction) {
53             resolution = value;
54             break;
55         }
56     }
57     return resolution;
58 }
59 
ConvertDensity(std::string density)60 int32_t ConvertDensity(std::string density)
61 {
62     auto resolution = 0;
63     static const std::vector<std::pair<std::string, int32_t>> resolutions = {
64         { "sdpi", 120 },
65         { "mdpi", 160 },
66         { "ldpi", 240 },
67         { "xldpi", 320 },
68         { "xxldpi", 480 },
69         { "xxxldpi", 640 },
70     };
71     for (const auto& [tempdensity, value] : resolutions) {
72         if (tempdensity == density) {
73             resolution = value;
74             break;
75         }
76     }
77     return resolution;
78 }
79 
ConvertDisplayId(std::string displayId)80 int32_t ConvertDisplayId(std::string displayId)
81 {
82     if (displayId == AppExecFwk::ConfigurationInner::EMPTY_STRING) {
83         return -1;
84     }
85     return std::stoi(displayId);
86 }
87 
CreateCConfiguration(const AppExecFwk::Configuration &configuration)88 CConfiguration CreateCConfiguration(const AppExecFwk::Configuration &configuration)
89 {
90     CConfiguration cfg;
91     cfg.language = CreateCStringFromString(configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_LANGUAGE));
92     cfg.colorMode = ConvertColorMode(configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE));
93     std::string direction = configuration.GetItem(AppExecFwk::ConfigurationInner::APPLICATION_DIRECTION);
94     cfg.direction = ConvertDirection(direction);
95     std::string density = configuration.GetItem(AppExecFwk::ConfigurationInner::APPLICATION_DENSITYDPI);
96     cfg.screenDensity = ConvertDensity(density);
97     cfg.displayId = ConvertDisplayId(configuration.GetItem(AppExecFwk::ConfigurationInner::APPLICATION_DISPLAYID));
98     std::string hasPointerDevice = configuration.GetItem(AAFwk::GlobalConfigurationKey::INPUT_POINTER_DEVICE);
99     cfg.hasPointerDevice = hasPointerDevice == "true" ? true : false;
100     std::string fontSizeScale = configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_SIZE_SCALE);
101     cfg.fontSizeScale = fontSizeScale == "" ? 1.0 : std::stod(fontSizeScale);
102     std::string fontWeightScale = configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_FONT_WEIGHT_SCALE);
103     cfg.fontWeightScale = fontWeightScale == "" ? 1.0 : std::stod(fontWeightScale);
104     cfg.mcc = CreateCStringFromString(configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_MCC));
105     cfg.mnc = CreateCStringFromString(configuration.GetItem(AAFwk::GlobalConfigurationKey::SYSTEM_MNC));
106     return cfg;
107 }
108 
CallConfigurationUpdatedInner(const AppExecFwk::Configuration &config, const std::map<int32_t, std::function<void(CConfiguration)>> &callbacks)109 void CjEnvironmentCallback::CallConfigurationUpdatedInner(const AppExecFwk::Configuration &config,
110     const std::map<int32_t, std::function<void(CConfiguration)>> &callbacks)
111 {
112     TAG_LOGD(AAFwkTag::APPKIT, "methodName = onConfiguration");
113     for (auto &callback : callbacks) {
114         if (!callback.second) {
115             TAG_LOGE(AAFwkTag::APPKIT, " Invalid cjCallback");
116             return;
117         }
118         auto cfg = CreateCConfiguration(config);
119         callback.second(cfg);
120     }
121 }
122 
OnConfigurationUpdated(const AppExecFwk::Configuration &config)123 void CjEnvironmentCallback::OnConfigurationUpdated(const AppExecFwk::Configuration &config)
124 {
125     std::weak_ptr<CjEnvironmentCallback> thisWeakPtr(shared_from_this());
126     std::shared_ptr<CjEnvironmentCallback> cjEnvCallback = thisWeakPtr.lock();
127     if (cjEnvCallback) {
128         cjEnvCallback->CallConfigurationUpdatedInner(config, onConfigurationUpdatedCallbacks_);
129     }
130 }
131 
CallMemoryLevelInner(const int level, const std::map<int32_t, std::function<void(int32_t)>> &callbacks)132 void CjEnvironmentCallback::CallMemoryLevelInner(const int level,
133     const std::map<int32_t, std::function<void(int32_t)>> &callbacks)
134 {
135     TAG_LOGD(AAFwkTag::APPKIT, "onMemoryLevel");
136     for (auto &callback : callbacks) {
137         if (!callback.second) {
138             TAG_LOGE(AAFwkTag::APPKIT, "Invalid jsCallback");
139             return;
140         }
141         callback.second(static_cast<int32_t>(level));
142     }
143 }
144 
OnMemoryLevel(const int level)145 void CjEnvironmentCallback::OnMemoryLevel(const int level)
146 {
147     std::weak_ptr<CjEnvironmentCallback> thisWeakPtr(shared_from_this());
148     std::shared_ptr<CjEnvironmentCallback> cjEnvCallback = thisWeakPtr.lock();
149     if (cjEnvCallback) {
150         cjEnvCallback->CallMemoryLevelInner(level, onMemoryLevelCallbacks_);
151     }
152 }
153 
Register(std::function<void(CConfiguration)> cfgCallback, std::function<void(int32_t)> memCallback, bool isSync)154 int32_t CjEnvironmentCallback::Register(std::function<void(CConfiguration)> cfgCallback,
155     std::function<void(int32_t)> memCallback, bool isSync)
156 {
157     int32_t callbackId = serialNumber_;
158     if (serialNumber_ < INT32_MAX) {
159         serialNumber_++;
160     } else {
161         serialNumber_ = 0;
162     }
163     if (isSync) {
164         return -1;
165     } else {
166         onConfigurationUpdatedCallbacks_.emplace(callbackId, cfgCallback);
167         onMemoryLevelCallbacks_.emplace(callbackId, memCallback);
168     }
169     return callbackId;
170 }
171 
UnRegister(int32_t callbackId, bool isSync)172 bool CjEnvironmentCallback::UnRegister(int32_t callbackId, bool isSync)
173 {
174     TAG_LOGD(AAFwkTag::APPKIT, "callbackId : %{public}d", callbackId);
175     if (isSync) {
176         return false;
177     }
178     auto itCfg = onConfigurationUpdatedCallbacks_.find(callbackId);
179     if (itCfg == onConfigurationUpdatedCallbacks_.end()) {
180         TAG_LOGE(AAFwkTag::APPKIT, "callbackId: %{public}d is not in callbacks_", callbackId);
181         return false;
182     }
183     TAG_LOGD(AAFwkTag::APPKIT, "callbacks_.callbackId : %{public}d", itCfg->first);
184     auto itMem = onMemoryLevelCallbacks_.find(callbackId);
185     if (itMem == onMemoryLevelCallbacks_.end()) {
186         TAG_LOGE(AAFwkTag::APPKIT, "callbackId: %{public}d is not in callbacks_", callbackId);
187         return false;
188     }
189     TAG_LOGD(AAFwkTag::APPKIT, "callbacks_.callbackId : %{public}d", itMem->first);
190     return onConfigurationUpdatedCallbacks_.erase(callbackId) == 1 && onMemoryLevelCallbacks_.erase(callbackId) == 1;
191 }
192 
IsEmpty() const193 bool CjEnvironmentCallback::IsEmpty() const
194 {
195     return onConfigurationUpdatedCallbacks_.empty() && onMemoryLevelCallbacks_.empty();
196 }
197 }  // namespace AbilityRuntime
198 }  // namespace OHOS