1 /*
2 * Copyright (c) 2025 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 #include <system_ability_definition.h>
16 #include "setting_datashare.h"
17 #include "touchpad_settings_handler.h"
18 #include "mmi_log.h"
19 #include "account_manager.h"
20
21 #undef MMI_LOG_TAG
22 #define MMI_LOG_TAG "TouchpadSettingsObserver"
23
24 #define TP_CHECK_FALSE_RETURN(cond, ret, fmt, ...) \
25 if (!(cond)) { \
26 MMI_HILOGE(fmt, ##__VA_ARGS__); \
27 return ret; \
28 }
29
30 namespace OHOS {
31 namespace MMI {
32 namespace {
33 const std::string g_volumeSwitchesKey {"settings.trackpad.right_volume_switches"};
34 const std::string g_brightnessSwitchesKey {"settings.trackpad.left_brightness_switches"};
35 const std::string g_pressureKey {"settings.trackpad.press_level"};
36 const std::string g_vibrationKey {"settings.trackpad.shock_level"};
37 const std::string g_touchpadSwitchesKey {"settings.trackpad.touchpad_switches"};
38 const std::string g_knuckleSwitchesKey {"settings.trackpad.touchpad_switches"};
39 const std::string g_datashareBaseUri =
40 "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_";
41 const std::string g_libthpPath {"/system/lib64/libthp_extra_innerapi.z.so"};
42 const std::map<std::string, int> g_keyToCmd = {
43 {g_volumeSwitchesKey, 111}, // right volume gesture cmd 111
44 {g_brightnessSwitchesKey, 110}, // left brightness gesture cmd 110
45 {g_pressureKey, 103}, // pressure cmd 103
46 {g_vibrationKey, 104}, // vibration cmd 104
47 {g_touchpadSwitchesKey, 108}, // touchpad switches cmd 108
48 {g_knuckleSwitchesKey, 109} // knuckle switches cmd 109
49 };
50 const std::map<std::string, std::string> g_defaultValue = {
51 {g_volumeSwitchesKey, "1"}, // default gesture on
52 {g_brightnessSwitchesKey, "1"}, // default gesture on
53 {g_pressureKey, "2"}, // default pressure value 2
54 {g_vibrationKey, "2"}, // default vibration value 2
55 {g_touchpadSwitchesKey, "1"}, // tdefault touchpad on
56 {g_knuckleSwitchesKey, "0"} // default knuckle off
57 };
58 } // namespace
59
60 std::mutex TouchpadSettingsObserver::mutex_;
61 std::shared_ptr<TouchpadSettingsObserver> TouchpadSettingsObserver::instance_ = nullptr;
62
TouchpadSettingsObserver()63 TouchpadSettingsObserver::TouchpadSettingsObserver() {}
64
~TouchpadSettingsObserver()65 TouchpadSettingsObserver::~TouchpadSettingsObserver() {}
66
GetInstance()67 std::shared_ptr<TouchpadSettingsObserver> TouchpadSettingsObserver::GetInstance()
68 {
69 if (instance_ == nullptr) {
70 std::lock_guard<std::mutex> lock(mutex_);
71 if (instance_ == nullptr) {
72 instance_ = std::make_shared<TouchpadSettingsObserver>();
73 }
74 }
75 return instance_;
76 }
77
RegisterUpdateFunc()78 void TouchpadSettingsObserver::RegisterUpdateFunc()
79 {
80 updateFunc_ = nullptr;
81 const std::string datashareUri = datashareUri_;
82 const std::string libthpPath = g_libthpPath;
83 const std::map<std::string, int> keyToCmd = g_keyToCmd;
84 const std::map<std::string, std::string> defaultValue = g_defaultValue;
85
86 SettingObserver::UpdateFunc UpdateFunc =
87 [datashareUri, libthpPath, keyToCmd, defaultValue](const std::string& key) {
88 MMI_HILOGI("Touchpad settings change: %{public}s", key.c_str());
89 typedef const char* (*ThpExtraRunCommandFunc)(const char* command, const char* parameters);
90 const char* (*ThpExtraRunCommand)(const char* command, const char* parameters) {};
91 std::string value;
92
93 auto ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID).GetStringValue(key, value, datashareUri);
94 if (ret != 0) {
95 auto valueIter = defaultValue.find(key);
96 if (valueIter == defaultValue.end()) {
97 MMI_HILOGE("Invalid value key");
98 return;
99 }
100 value = valueIter->second;
101 }
102 MMI_HILOGI("Get value: %{public}s", value.c_str());
103
104 auto cmdIter = keyToCmd.find(key);
105 if (cmdIter == keyToCmd.end()) {
106 MMI_HILOGE("Invalid command key");
107 return;
108 }
109
110 void *handle = nullptr;
111 handle = dlopen(libthpPath.c_str(), RTLD_LAZY);
112 if (handle == nullptr) {
113 MMI_HILOGE("Handle is null");
114 return;
115 }
116
117 ThpExtraRunCommand = reinterpret_cast<ThpExtraRunCommandFunc>(dlsym(handle, "ThpExtraRunCommand"));
118 if (ThpExtraRunCommand == nullptr) {
119 MMI_HILOGE("ThpExtraRunCommand is null");
120 dlclose(handle);
121 return;
122 }
123 const std::string param = std::string("#").append(std::to_string(cmdIter->second)).append("#").append(value);
124 ThpExtraRunCommand("THP_TouchpadStatusChange", param.c_str());
125 dlclose(handle);
126 };
127 MMI_HILOGI("Update function register end");
128 updateFunc_ = UpdateFunc;
129 return;
130 }
131
RegisterDatashareObserver(const std::string key,SettingObserver::UpdateFunc onUpdate)132 sptr<SettingObserver> TouchpadSettingsObserver::RegisterDatashareObserver(
133 const std::string key, SettingObserver::UpdateFunc onUpdate)
134 {
135 ErrCode ret = 0;
136 if (key.empty() || datashareUri_.empty() || onUpdate == nullptr) {
137 MMI_HILOGE("Invalid input parameter");
138 return nullptr;
139 }
140
141 auto &settingHelper = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID);
142 sptr<SettingObserver> settingObserver = settingHelper.CreateObserver(key, onUpdate);
143 if (settingObserver == nullptr) {
144 MMI_HILOGE("CreateObserver fail");
145 return nullptr;
146 }
147
148 ret = settingHelper.RegisterObserver(settingObserver, datashareUri_);
149 if (ret != ERR_OK) {
150 MMI_HILOGE("RegisterObserver failed");
151 return nullptr;
152 }
153 return settingObserver;
154 }
155
RegisterTpObserver(const int32_t accountId)156 bool TouchpadSettingsObserver::RegisterTpObserver(const int32_t accountId)
157 {
158 if (!isCommonEventReady_.load() || hasRegistered_) { return false; }
159 std::lock_guard<std::mutex> lock(lock_);
160 ErrCode ret = 0;
161
162 currentAccountId_ = accountId;
163 TP_CHECK_FALSE_RETURN(currentAccountId_ >= 0, false, "Get account info fail");
164
165 datashareUri_ = g_datashareBaseUri + std::to_string(currentAccountId_) + "?Proxy=true";
166 RegisterUpdateFunc();
167 TP_CHECK_FALSE_RETURN(updateFunc_ != nullptr, false, "Update function is null");
168
169 if (volumeSwitchesObserver_ == nullptr) {
170 volumeSwitchesObserver_ = RegisterDatashareObserver(g_volumeSwitchesKey, updateFunc_);
171 }
172 if (brightnessSwitchesObserver_ == nullptr) {
173 brightnessSwitchesObserver_ = RegisterDatashareObserver(g_brightnessSwitchesKey, updateFunc_);
174 }
175 if (pressureObserver_ == nullptr) {
176 pressureObserver_ = RegisterDatashareObserver(g_pressureKey, updateFunc_);
177 }
178 if (vibrationObserver_ == nullptr) {
179 vibrationObserver_ = RegisterDatashareObserver(g_vibrationKey, updateFunc_);
180 }
181 if (touchpadSwitchesObserver_ == nullptr) {
182 touchpadSwitchesObserver_ = RegisterDatashareObserver(g_touchpadSwitchesKey, updateFunc_);
183 }
184 if (knuckleSwitchesObserver_ == nullptr) {
185 knuckleSwitchesObserver_ = RegisterDatashareObserver(g_knuckleSwitchesKey, updateFunc_);
186 }
187 if (volumeSwitchesObserver_ == nullptr || brightnessSwitchesObserver_ == nullptr || pressureObserver_ == nullptr ||
188 vibrationObserver_ == nullptr ||touchpadSwitchesObserver_ == nullptr || knuckleSwitchesObserver_ == nullptr) {
189 MMI_HILOGE("Register setting observer fail");
190 return false;
191 }
192 MMI_HILOGI("Register touchpad observer");
193 hasRegistered_ = true;
194 return true;
195 }
196
UnregisterTpObserver(const int32_t accountId)197 bool TouchpadSettingsObserver::UnregisterTpObserver(const int32_t accountId)
198 {
199 if (!hasRegistered_ || accountId == currentAccountId_) {
200 return false;
201 }
202 std::lock_guard<std::mutex> lock { lock_ };
203 ErrCode ret = 0;
204
205 auto &settingHelper = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID);
206 if (volumeSwitchesObserver_ != nullptr) {
207 ret = settingHelper.UnregisterObserver(volumeSwitchesObserver_, datashareUri_);
208 TP_CHECK_FALSE_RETURN(ret == 0, false, "Unregister volumeSwitchesObserver fail");
209 volumeSwitchesObserver_ = nullptr;
210 }
211 if (brightnessSwitchesObserver_ != nullptr) {
212 ret = settingHelper.UnregisterObserver(brightnessSwitchesObserver_, datashareUri_);
213 TP_CHECK_FALSE_RETURN(ret == 0, false, "Unregister brightnessSwitchesObserver fail");
214 brightnessSwitchesObserver_ = nullptr;
215 }
216 if (pressureObserver_ != nullptr) {
217 ret = settingHelper.UnregisterObserver(pressureObserver_, datashareUri_);
218 TP_CHECK_FALSE_RETURN(ret == 0, false, "Unregister pressureObserver fail");
219 pressureObserver_ = nullptr;
220 }
221 if (vibrationObserver_ != nullptr) {
222 ret = settingHelper.UnregisterObserver(vibrationObserver_, datashareUri_);
223 TP_CHECK_FALSE_RETURN(ret == 0, false, "Unregister vibrationObserver fail");
224 vibrationObserver_ = nullptr;
225 }
226 if (touchpadSwitchesObserver_ != nullptr) {
227 ret = settingHelper.UnregisterObserver(touchpadSwitchesObserver_, datashareUri_);
228 TP_CHECK_FALSE_RETURN(ret == 0, false, "Unregister touchpadSwitchesObserver fail");
229 touchpadSwitchesObserver_ = nullptr;
230 }
231 if (knuckleSwitchesObserver_ != nullptr) {
232 ret = settingHelper.UnregisterObserver(knuckleSwitchesObserver_, datashareUri_);
233 TP_CHECK_FALSE_RETURN(ret == 0, false, "Unregister knuckleSwitchesObserver fail");
234 knuckleSwitchesObserver_ = nullptr;
235 }
236
237 hasRegistered_ = false;
238 MMI_HILOGI("Unregister touchpad observer");
239 return true;
240 }
241
SyncTouchpadSettingsData()242 void TouchpadSettingsObserver::SyncTouchpadSettingsData()
243 {
244 if (!isCommonEventReady_.load()) {
245 return;
246 }
247 if (!hasRegistered_) {
248 RegisterTpObserver(ACCOUNT_MGR->GetCurrentAccountSetting().GetAccountId());
249 return;
250 }
251 std::lock_guard<std::mutex> lock { lock_ };
252 if (updateFunc_ == nullptr) {
253 return;
254 }
255 updateFunc_(g_volumeSwitchesKey);
256 updateFunc_(g_brightnessSwitchesKey);
257 updateFunc_(g_pressureKey);
258 updateFunc_(g_vibrationKey);
259 updateFunc_(g_touchpadSwitchesKey);
260 updateFunc_(g_knuckleSwitchesKey);
261 MMI_HILOGI("Sync touchpad settings end");
262 }
263
SetCommonEventReady()264 void TouchpadSettingsObserver::SetCommonEventReady()
265 {
266 isCommonEventReady_.store(true);
267 }
268
GetCommonEventStatus()269 bool TouchpadSettingsObserver::GetCommonEventStatus()
270 {
271 return isCommonEventReady_.load();
272 }
273 } // namespace MMI
274 } // namespace OHOS
275