1 /*
2 * Copyright (c) 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 #ifdef SENSOR_ENABLE
17 #include <cmath>
18 #include <hisysevent.h>
19 #include <parameters.h>
20
21 #include "fold_screen_controller/fold_screen_sensor_manager.h"
22 #include "fold_screen_state_internel.h"
23 #include "window_manager_hilog.h"
24 #include "screen_session_manager.h"
25
26 #ifdef POWER_MANAGER_ENABLE
27 #include <power_mgr_client.h>
28 #endif
29
SensorPostureDataCallback(SensorEvent * event)30 static void SensorPostureDataCallback(SensorEvent *event)
31 {
32 OHOS::Rosen::FoldScreenSensorManager::GetInstance().HandlePostureData(event);
33 }
34
SensorHallDataCallback(SensorEvent * event)35 static void SensorHallDataCallback(SensorEvent *event)
36 {
37 OHOS::Rosen::FoldScreenSensorManager::GetInstance().HandleHallData(event);
38 }
39
40 namespace OHOS {
41 namespace Rosen {
42 namespace {
43 constexpr float ANGLE_MIN_VAL = 0.0F;
44 constexpr float ANGLE_MAX_VAL = 180.0F;
45 constexpr int32_t SENSOR_SUCCESS = 0;
46 constexpr int32_t POSTURE_INTERVAL = 10000000;
47 constexpr uint16_t SENSOR_EVENT_FIRST_DATA = 0;
48 constexpr float ACCURACY_ERROR_FOR_ALTA = 0.0001F;
49 static float INWARD_HALF_FOLDED_MIN_THRESHOLD = static_cast<float>(system::GetIntParameter<int32_t>
50 ("const.fold.half_folded_min_threshold", 85));
51 static float LARGE_FOLD_HALF_FOLDED_MIN_THRESHOLD = static_cast<float>(system::GetIntParameter<int32_t>
52 ("const.large_fold.half_folded_min_threshold", 25));
53 constexpr float MINI_NOTIFY_FOLD_ANGLE = 0.5F;
54 float oldFoldAngle = 0.0F;
55 } // namespace
56 WM_IMPLEMENT_SINGLE_INSTANCE(FoldScreenSensorManager);
57
FoldScreenSensorManager()58 FoldScreenSensorManager::FoldScreenSensorManager()
59 {
60 }
61
SetFoldScreenPolicy(sptr<FoldScreenPolicy> foldScreenPolicy)62 void FoldScreenSensorManager::SetFoldScreenPolicy(sptr<FoldScreenPolicy> foldScreenPolicy)
63 {
64 foldScreenPolicy_ = foldScreenPolicy;
65 }
66
SetSensorFoldStateManager(sptr<SensorFoldStateManager> sensorFoldStateManager)67 void FoldScreenSensorManager::SetSensorFoldStateManager(sptr<SensorFoldStateManager> sensorFoldStateManager)
68 {
69 sensorFoldStateManager_ = sensorFoldStateManager;
70 }
71
RegisterPostureCallback()72 void FoldScreenSensorManager::RegisterPostureCallback()
73 {
74 postureUser.callback = SensorPostureDataCallback;
75 int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
76 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_POSTURE, &postureUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
77 int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
78 TLOGI(WmsLogTag::DMS,
79 "RegisterPostureCallback, subscribeRet: %{public}d, setBatchRet: %{public}d, activateRet: %{public}d",
80 subscribeRet, setBatchRet, activateRet);
81 if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
82 registerPosture_ = false;
83 TLOGE(WmsLogTag::DMS, "RegisterPostureCallback failed.");
84 } else {
85 registerPosture_ = true;
86 TLOGI(WmsLogTag::DMS, "RegisterPostureCallback success.");
87 }
88 }
89
UnRegisterPostureCallback()90 void FoldScreenSensorManager::UnRegisterPostureCallback()
91 {
92 int32_t deactivateRet = DeactivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
93 int32_t unsubscribeRet = UnsubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
94 TLOGI(WmsLogTag::DMS, "UnRegisterPostureCallback, deactivateRet: %{public}d, unsubscribeRet: %{public}d",
95 deactivateRet, unsubscribeRet);
96 if (deactivateRet == SENSOR_SUCCESS && unsubscribeRet == SENSOR_SUCCESS) {
97 registerPosture_ = false;
98 TLOGI(WmsLogTag::DMS, "UnRegisterPostureCallback success.");
99 }
100 }
101
RegisterHallCallback()102 void FoldScreenSensorManager::RegisterHallCallback()
103 {
104 hallUser.callback = SensorHallDataCallback;
105 int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
106 TLOGI(WmsLogTag::DMS, "RegisterHallCallback, subscribeRet: %{public}d", subscribeRet);
107 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_HALL_EXT, &hallUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
108 TLOGI(WmsLogTag::DMS, "RegisterHallCallback, setBatchRet: %{public}d", setBatchRet);
109 int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
110 TLOGI(WmsLogTag::DMS, "RegisterHallCallback, activateRet: %{public}d", activateRet);
111 if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
112 registerHall_ = false;
113 TLOGE(WmsLogTag::DMS, "RegisterHallCallback failed.");
114 } else {
115 registerHall_ = true;
116 TLOGI(WmsLogTag::DMS, "RegisterHallCallback success.");
117 }
118 }
119
UnRegisterHallCallback()120 void FoldScreenSensorManager::UnRegisterHallCallback()
121 {
122 int32_t deactivateRet1 = DeactivateSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
123 int32_t unsubscribeRet1 = UnsubscribeSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
124 if (deactivateRet1 == SENSOR_SUCCESS && unsubscribeRet1 == SENSOR_SUCCESS) {
125 TLOGI(WmsLogTag::DMS, "UnRegisterHallCallback success.");
126 registerHall_ = false;
127 }
128 }
129
HandlePostureData(const SensorEvent * const event)130 void FoldScreenSensorManager::HandlePostureData(const SensorEvent * const event)
131 {
132 if (event == nullptr) {
133 TLOGI(WmsLogTag::DMS, "SensorEvent is nullptr.");
134 return;
135 }
136 if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
137 TLOGI(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
138 return;
139 }
140 if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(PostureData)) {
141 TLOGI(WmsLogTag::DMS, "SensorEvent dataLen less than posture data size.");
142 return;
143 }
144 PostureData *postureData = reinterpret_cast<PostureData *>(event[SENSOR_EVENT_FIRST_DATA].data);
145 globalAngle = (*postureData).angle;
146 if (globalHall == USHRT_MAX || std::isless(globalAngle, ANGLE_MIN_VAL) ||
147 std::isgreater(globalAngle, ANGLE_MAX_VAL + ACCURACY_ERROR_FOR_ALTA)) {
148 TLOGE(WmsLogTag::DMS, "Invalid value, hall value is: %{public}u, angle value is: %{public}f.",
149 globalHall, globalAngle);
150 return;
151 }
152 TLOGD(WmsLogTag::DMS, "angle value in PostureData is: %{public}f.", globalAngle);
153 sensorFoldStateManager_->HandleAngleChange(globalAngle, globalHall, foldScreenPolicy_);
154 NotifyFoldAngleChanged(globalAngle);
155 }
156
NotifyFoldAngleChanged(float foldAngle)157 void FoldScreenSensorManager::NotifyFoldAngleChanged(float foldAngle)
158 {
159 if (fabs(foldAngle - oldFoldAngle) < MINI_NOTIFY_FOLD_ANGLE) {
160 return;
161 }
162 oldFoldAngle = foldAngle;
163 std::vector<float> foldAngles;
164 foldAngles.push_back(foldAngle);
165 ScreenSessionManager::GetInstance().NotifyFoldAngleChanged(foldAngles);
166 }
167
HandleHallData(const SensorEvent * const event)168 void FoldScreenSensorManager::HandleHallData(const SensorEvent * const event)
169 {
170 if (event == nullptr) {
171 TLOGI(WmsLogTag::DMS, "SensorEvent is nullptr.");
172 return;
173 }
174 if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
175 TLOGI(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
176 return;
177 }
178 if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(ExtHallData)) {
179 TLOGI(WmsLogTag::DMS, "SensorEvent dataLen less than hall data size.");
180 return;
181 }
182 ExtHallData *extHallData = reinterpret_cast<ExtHallData *>(event[SENSOR_EVENT_FIRST_DATA].data);
183 uint16_t flag = static_cast<uint16_t>((*extHallData).flag);
184 if (!(flag & (1 << 1))) {
185 TLOGI(WmsLogTag::DMS, "NOT Support Extend Hall.");
186 return;
187 }
188 if (globalHall == static_cast<uint16_t>((*extHallData).hall)) {
189 TLOGI(WmsLogTag::DMS, "Hall don't change, hall = %{public}u", globalHall);
190 return;
191 }
192 globalHall = static_cast<uint16_t>((*extHallData).hall);
193 if (globalHall == USHRT_MAX || std::isless(globalAngle, ANGLE_MIN_VAL) ||
194 std::isgreater(globalAngle, ANGLE_MAX_VAL + ACCURACY_ERROR_FOR_ALTA)) {
195 TLOGE(WmsLogTag::DMS, "Invalid value, hall value is: %{public}u, angle value is: %{public}f.",
196 globalHall, globalAngle);
197 return;
198 }
199 TLOGI(WmsLogTag::DMS, "hall value is: %{public}u, angle value is: %{public}f", globalHall, globalAngle);
200 if (!registerPosture_) {
201 globalAngle = ANGLE_MIN_VAL;
202 }
203 sensorFoldStateManager_->HandleHallChange(globalAngle, globalHall, foldScreenPolicy_);
204 }
205
RegisterApplicationStateObserver()206 void FoldScreenSensorManager::RegisterApplicationStateObserver()
207 {
208 sensorFoldStateManager_->RegisterApplicationStateObserver();
209 }
210
TriggerDisplaySwitch()211 void FoldScreenSensorManager::TriggerDisplaySwitch()
212 {
213 TLOGI(WmsLogTag::DMS, "TriggerDisplaySwitch hall value is: %{public}u, angle value is: %{public}f",
214 globalHall, globalAngle);
215 if (!registerPosture_) {
216 globalAngle = ANGLE_MIN_VAL;
217 } else {
218 if (FoldScreenStateInternel::IsDualDisplayFoldDevice()) {
219 globalAngle = INWARD_HALF_FOLDED_MIN_THRESHOLD;
220 } else if (FoldScreenStateInternel::IsSingleDisplayFoldDevice()) {
221 globalAngle = LARGE_FOLD_HALF_FOLDED_MIN_THRESHOLD;
222 }
223 }
224 sensorFoldStateManager_->HandleAngleChange(globalAngle, globalHall, foldScreenPolicy_);
225 }
226
GetSensorRegisterStatus()227 bool FoldScreenSensorManager::GetSensorRegisterStatus()
228 {
229 return registerHall_ || registerPosture_;
230 }
231
GetGlobalAngle() const232 float FoldScreenSensorManager::GetGlobalAngle() const
233 {
234 return globalAngle;
235 }
236
SetGlobalAngle(float angle)237 void FoldScreenSensorManager::SetGlobalAngle(float angle)
238 {
239 if (std::isless(angle, ANGLE_MIN_VAL) ||
240 std::isgreater(angle, ANGLE_MAX_VAL + ACCURACY_ERROR_FOR_ALTA)) {
241 TLOGI(WmsLogTag::DMS, "Invalid angle: %{public}f", angle);
242 return;
243 }
244 globalAngle = angle;
245 }
246
GetGlobalHall() const247 uint16_t FoldScreenSensorManager::GetGlobalHall() const
248 {
249 return globalHall;
250 }
251
SetGlobalHall(uint16_t hall)252 void FoldScreenSensorManager::SetGlobalHall(uint16_t hall)
253 {
254 if (hall == USHRT_MAX) {
255 TLOGI(WmsLogTag::DMS, "Invalid hall: %{public}u", hall);
256 return;
257 }
258 globalHall = hall;
259 }
260 } // Rosen
261 } // OHOS
262 #endif