1 /*
2 * Copyright (c) 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 <cmath>
17 #include <hisysevent.h>
18 #include <parameters.h>
19 #include <vector>
20
21 #include "dm_common.h"
22
23 #include "fold_screen_controller/super_fold_sensor_manager.h"
24 #include "fold_screen_controller/super_fold_state_manager.h"
25 #include "window_manager_hilog.h"
26 #include "screen_session_manager.h"
27
28 namespace OHOS {
29
30 namespace Rosen {
31 namespace {
32 constexpr float ANGLE_MIN_VAL = 30.0F;
33 constexpr float ANGLE_MAX_VAL = 180.0F;
34 constexpr float ANGLE_FLAT_THRESHOLD = 160.0F;
35 constexpr float ANGLE_SENSOR_THRESHOLD = 160.0F;
36 constexpr float ANGLE_HALF_FOLD_THRESHOLD = 150.0F;
37 constexpr uint16_t HALL_HAVE_KEYBOARD_THRESHOLD = 0B0100;
38 constexpr uint16_t HALL_REMOVE_KEYBOARD_THRESHOLD = 0B0000;
39 constexpr uint16_t HALL_ACTIVE = 1 << 2;
40 constexpr int32_t SENSOR_SUCCESS = 0;
41 constexpr int32_t POSTURE_INTERVAL = 100000000; // 100ms
42 constexpr int32_t POSTURE_INTERVAL_FOR_WIDE_ANGLE = 10000000; // 10ms
43 constexpr float UNFOLD_ANGLE = 170.0F;
44 constexpr uint16_t SENSOR_EVENT_FIRST_DATA = 0;
45 constexpr float ACCURACY_ERROR_FOR_PC = 0.0001F;
46 } // namespace
47
GetInstance()48 SuperFoldSensorManager &SuperFoldSensorManager::GetInstance()
49 {
50 static SuperFoldSensorManager SuperFoldSensorManager;
51 return SuperFoldSensorManager;
52 }
53
SensorPostureDataCallback(SensorEvent * event)54 static void SensorPostureDataCallback(SensorEvent *event)
55 {
56 OHOS::Rosen::SuperFoldSensorManager::GetInstance().HandlePostureData(event);
57 }
58
SensorHallDataCallback(SensorEvent * event)59 static void SensorHallDataCallback(SensorEvent *event)
60 {
61 OHOS::Rosen::SuperFoldSensorManager::GetInstance().HandleHallData(event);
62 }
63
RegisterPostureCallback()64 void SuperFoldSensorManager::RegisterPostureCallback()
65 {
66 curInterval_ = POSTURE_INTERVAL;
67 postureUser.callback = SensorPostureDataCallback;
68 int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
69 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_POSTURE, &postureUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
70 int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
71 TLOGI(WmsLogTag::DMS,
72 "subscribeRet: %{public}d, setBatchRet: %{public}d, activateRet: %{public}d",
73 subscribeRet, setBatchRet, activateRet);
74 if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
75 TLOGI(WmsLogTag::DMS, "RegisterPostureCallback failed.");
76 } else {
77 TLOGI(WmsLogTag::DMS, "RegisterPostureCallback success.");
78 }
79 }
80
UnregisterPostureCallback()81 void SuperFoldSensorManager::UnregisterPostureCallback()
82 {
83 int32_t deactivateRet = DeactivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
84 int32_t unsubscribeRet = UnsubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
85 TLOGI(WmsLogTag::DMS, "deactivateRet: %{public}d, unsubscribeRet: %{public}d",
86 deactivateRet, unsubscribeRet);
87 if (deactivateRet == SENSOR_SUCCESS && unsubscribeRet == SENSOR_SUCCESS) {
88 TLOGI(WmsLogTag::DMS, "FoldScreenSensorManager.UnRegisterPostureCallback success.");
89 }
90 }
91
RegisterHallCallback()92 void SuperFoldSensorManager::RegisterHallCallback()
93 {
94 hallUser.callback = SensorHallDataCallback;
95 int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_HALL, &hallUser);
96 TLOGI(WmsLogTag::DMS, "subscribeRet: %{public}d", subscribeRet);
97 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_HALL, &hallUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
98 TLOGI(WmsLogTag::DMS, "setBatchRet: %{public}d", setBatchRet);
99 int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_HALL, &hallUser);
100 TLOGI(WmsLogTag::DMS, "activateRet: %{public}d", activateRet);
101 if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
102 TLOGI(WmsLogTag::DMS, "RegisterHallCallback failed.");
103 }
104 }
105
UnregisterHallCallback()106 void SuperFoldSensorManager::UnregisterHallCallback()
107 {
108 int32_t deactivateRet = DeactivateSensor(SENSOR_TYPE_ID_HALL, &hallUser);
109 int32_t unsubscribeRet = UnsubscribeSensor(SENSOR_TYPE_ID_HALL, &hallUser);
110 if (deactivateRet == SENSOR_SUCCESS && unsubscribeRet == SENSOR_SUCCESS) {
111 TLOGI(WmsLogTag::DMS, "UnRegisterHallCallback success.");
112 }
113 }
114
HandlePostureData(const SensorEvent * const event)115 void SuperFoldSensorManager::HandlePostureData(const SensorEvent * const event)
116 {
117 if (event == nullptr) {
118 TLOGI(WmsLogTag::DMS, "SensorEvent is nullptr.");
119 return;
120 }
121 if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
122 TLOGI(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
123 return;
124 }
125 if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(PostureData)) {
126 TLOGI(WmsLogTag::DMS, "SensorEvent dataLen less than posture data size.");
127 return;
128 }
129 PostureData *postureData = reinterpret_cast<PostureData *>(event[SENSOR_EVENT_FIRST_DATA].data);
130 curAngle_ = (*postureData).angle;
131 if (curAngle_ > UNFOLD_ANGLE && curInterval_ != POSTURE_INTERVAL_FOR_WIDE_ANGLE) {
132 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_POSTURE, &postureUser,
133 POSTURE_INTERVAL_FOR_WIDE_ANGLE, POSTURE_INTERVAL_FOR_WIDE_ANGLE);
134 int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
135 if (setBatchRet == 0 && activateRet == 0) {
136 curInterval_ = POSTURE_INTERVAL_FOR_WIDE_ANGLE;
137 }
138 } else if (curAngle_ < UNFOLD_ANGLE && curInterval_ != POSTURE_INTERVAL) {
139 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_POSTURE, &postureUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
140 int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
141 if (setBatchRet == 0 && activateRet == 0) {
142 curInterval_ = POSTURE_INTERVAL;
143 }
144 }
145 if (std::isgreater(curAngle_, ANGLE_MAX_VAL + ACCURACY_ERROR_FOR_PC)) {
146 TLOGI(WmsLogTag::DMS, "Invalid value, angle value is: %{public}f.", curAngle_);
147 return;
148 }
149 TLOGD(WmsLogTag::DMS, "angle value is: %{public}f.", curAngle_);
150 auto task = [this, curAngle = curAngle_] {
151 NotifyFoldAngleChanged(curAngle);
152 };
153 if (taskScheduler_) {
154 taskScheduler_->PostAsyncTask(task, "DMSHandlePosture");
155 }
156 }
157
NotifyFoldAngleChanged(float foldAngle)158 void SuperFoldSensorManager::NotifyFoldAngleChanged(float foldAngle)
159 {
160 SuperFoldStatusChangeEvents events = SuperFoldStatusChangeEvents::UNDEFINED;
161 if (std::isgreaterequal(foldAngle, ANGLE_FLAT_THRESHOLD)) {
162 TLOGD(WmsLogTag::DMS, "NotifyFoldAngleChanged is Expanded");
163 events = SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED;
164 } else if (std::isless(foldAngle, ANGLE_HALF_FOLD_THRESHOLD) &&
165 std::isgreater(foldAngle, ANGLE_MIN_VAL)) {
166 TLOGD(WmsLogTag::DMS, "NotifyFoldAngleChanged is Half Folded");
167 events = SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED;
168 } else if (std::islessequal(foldAngle, ANGLE_MIN_VAL)) {
169 TLOGD(WmsLogTag::DMS, "NotifyFoldAngleChanged is Folded");
170 events = SuperFoldStatusChangeEvents::ANGLE_CHANGE_FOLDED;
171 } else {
172 if (SuperFoldStateManager::GetInstance().GetCurrentStatus() == SuperFoldStatus::UNKNOWN ||
173 SuperFoldStateManager::GetInstance().GetCurrentStatus() == SuperFoldStatus::FOLDED) {
174 events = SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED;
175 }
176 TLOGD(WmsLogTag::DMS, "NotifyFoldAngleChanged is in BufferArea");
177 }
178 // notify
179 std::vector<float> foldAngles;
180 foldAngles.push_back(foldAngle);
181 ScreenSessionManager::GetInstance().NotifyFoldAngleChanged(foldAngles);
182 if (!ScreenRotationProperty::isDeviceHorizontal() ||
183 events == SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED) {
184 HandleSuperSensorChange(events);
185 }
186 }
187
HandleHallData(const SensorEvent * const event)188 void SuperFoldSensorManager::HandleHallData(const SensorEvent * const event)
189 {
190 if (event == nullptr) {
191 TLOGI(WmsLogTag::DMS, "SensorEvent is nullptr.");
192 return;
193 }
194 if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
195 TLOGI(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
196 return;
197 }
198 if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(HallData)) {
199 TLOGI(WmsLogTag::DMS, "SensorEvent[0].dataLen is nullptr.");
200 return;
201 }
202 auto data = reinterpret_cast<HallData*>(event->data);
203 auto status = static_cast<uint32_t>(data->status);
204 TLOGI(WmsLogTag::DMS, "HallData status is: %{public}u.", status);
205
206 if (curHall_ == (status & HALL_ACTIVE)) {
207 TLOGI(WmsLogTag::DMS, "Hall don't change, hall = %{public}u", curHall_);
208 return;
209 }
210 curHall_ = (status & HALL_ACTIVE);
211 TLOGI(WmsLogTag::DMS, "Hall change, hall = %{public}u", curHall_);
212 auto task = [this, curHall = curHall_] {
213 NotifyHallChanged(curHall);
214 };
215 if (taskScheduler_) {
216 taskScheduler_->PostAsyncTask(task, "DMSHandleHall");
217 }
218 }
219
NotifyHallChanged(uint16_t Hall)220 void SuperFoldSensorManager::NotifyHallChanged(uint16_t Hall)
221 {
222 SuperFoldStatusChangeEvents events;
223 if (Hall == HALL_REMOVE_KEYBOARD_THRESHOLD) {
224 TLOGI(WmsLogTag::DMS, "NotifyHallChanged: Keyboard off!");
225 events = SuperFoldStatusChangeEvents::KEYBOARD_OFF;
226 } else if (Hall == HALL_HAVE_KEYBOARD_THRESHOLD) {
227 TLOGI(WmsLogTag::DMS, "NotifyHallChanged: Keyboard on!");
228 events = SuperFoldStatusChangeEvents::KEYBOARD_ON;
229 HandleSuperSensorChange(SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED);
230 } else {
231 TLOGI(WmsLogTag::DMS, "NotifyHallChanged: Invalid Hall Value!");
232 return;
233 }
234 // notify
235 HandleSuperSensorChange(events);
236 if (std::isgreater(curAngle_, ANGLE_SENSOR_THRESHOLD)) {
237 HandleSuperSensorChange(SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED);
238 }
239 }
240
HandleSuperSensorChange(SuperFoldStatusChangeEvents events)241 void SuperFoldSensorManager::HandleSuperSensorChange(SuperFoldStatusChangeEvents events)
242 {
243 // trigger events
244 if (ScreenSessionManager::GetInstance().GetIsFoldStatusLocked() ||
245 ScreenSessionManager::GetInstance().GetIsLandscapeLockStatus()) {
246 return;
247 }
248 SuperFoldStateManager::GetInstance().HandleSuperFoldStatusChange(events);
249 }
250
HandleScreenConnectChange()251 void SuperFoldSensorManager::HandleScreenConnectChange()
252 {
253 TLOGW(WmsLogTag::DMS, "Screen connect to stop statemachine.");
254 SuperFoldStateManager::GetInstance().HandleScreenConnectChange();
255 }
256
HandleScreenDisconnectChange()257 void SuperFoldSensorManager::HandleScreenDisconnectChange()
258 {
259 if (ScreenSessionManager::GetInstance().GetIsFoldStatusLocked()) {
260 TLOGW(WmsLogTag::DMS, "Fold status is still locked.");
261 return;
262 }
263 if (ScreenSessionManager::GetInstance().GetIsLandscapeLockStatus()) {
264 TLOGW(WmsLogTag::DMS, "Landscape status is still locked.");
265 return;
266 }
267 TLOGW(WmsLogTag::DMS, "All locks have been unlocked to start statemachine.");
268 NotifyHallChanged(curHall_);
269 NotifyFoldAngleChanged(curAngle_);
270 }
271
HandleFoldStatusLockedToExpand()272 void SuperFoldSensorManager::HandleFoldStatusLockedToExpand()
273 {
274 TLOGI(WmsLogTag::DMS, "Fold status locked to expand and stop statemachine.");
275 SuperFoldStateManager::GetInstance().HandleScreenConnectChange();
276 }
277
HandleFoldStatusUnlocked()278 void SuperFoldSensorManager::HandleFoldStatusUnlocked()
279 {
280 if (ScreenSessionManager::GetInstance().GetIsLandscapeLockStatus()) {
281 TLOGI(WmsLogTag::DMS, "Landscape status is still locked.");
282 return;
283 }
284 TLOGI(WmsLogTag::DMS, "All locks have been unlocked to start statemachine.");
285 NotifyHallChanged(curHall_);
286 NotifyFoldAngleChanged(curAngle_);
287 }
288
GetCurAngle()289 float SuperFoldSensorManager::GetCurAngle()
290 {
291 return curAngle_;
292 }
293
SuperFoldSensorManager()294 SuperFoldSensorManager::SuperFoldSensorManager() {}
295
~SuperFoldSensorManager()296 SuperFoldSensorManager::~SuperFoldSensorManager() {}
297
SetTaskScheduler(std::shared_ptr<TaskScheduler> scheduler)298 void SuperFoldSensorManager::SetTaskScheduler(std::shared_ptr<TaskScheduler> scheduler)
299 {
300 TLOGI(WmsLogTag::DMS, "Set task scheduler.");
301 taskScheduler_ = scheduler;
302 }
303 } // Rosen
304 } // OHOS