• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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