• 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 = 135.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;
42 constexpr uint16_t SENSOR_EVENT_FIRST_DATA = 0;
43 constexpr float ACCURACY_ERROR_FOR_PC = 0.0001F;
44 } // namespace
45 
GetInstance()46 SuperFoldSensorManager &SuperFoldSensorManager::GetInstance()
47 {
48     static SuperFoldSensorManager SuperFoldSensorManager;
49     return SuperFoldSensorManager;
50 }
51 
SensorPostureDataCallback(SensorEvent * event)52 static void SensorPostureDataCallback(SensorEvent *event)
53 {
54     OHOS::Rosen::SuperFoldSensorManager::GetInstance().HandlePostureData(event);
55 }
56 
SensorHallDataCallback(SensorEvent * event)57 static void SensorHallDataCallback(SensorEvent *event)
58 {
59     OHOS::Rosen::SuperFoldSensorManager::GetInstance().HandleHallData(event);
60 }
61 
RegisterPostureCallback()62 void SuperFoldSensorManager::RegisterPostureCallback()
63 {
64     postureUser.callback = SensorPostureDataCallback;
65     int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
66     int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_POSTURE, &postureUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
67     int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
68     TLOGI(WmsLogTag::DMS,
69         "subscribeRet: %{public}d, setBatchRet: %{public}d, activateRet: %{public}d",
70         subscribeRet, setBatchRet, activateRet);
71     if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
72         TLOGI(WmsLogTag::DMS, "RegisterPostureCallback failed.");
73     } else {
74         TLOGI(WmsLogTag::DMS, "RegisterPostureCallback success.");
75     }
76 }
77 
UnregisterPostureCallback()78 void SuperFoldSensorManager::UnregisterPostureCallback()
79 {
80     int32_t deactivateRet = DeactivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
81     int32_t unsubscribeRet = UnsubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
82     TLOGI(WmsLogTag::DMS, "deactivateRet: %{public}d, unsubscribeRet: %{public}d",
83         deactivateRet, unsubscribeRet);
84     if (deactivateRet == SENSOR_SUCCESS && unsubscribeRet == SENSOR_SUCCESS) {
85         TLOGI(WmsLogTag::DMS, "FoldScreenSensorManager.UnRegisterPostureCallback success.");
86     }
87 }
88 
RegisterHallCallback()89 void SuperFoldSensorManager::RegisterHallCallback()
90 {
91     hallUser.callback = SensorHallDataCallback;
92     int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_HALL, &hallUser);
93     TLOGI(WmsLogTag::DMS, "subscribeRet: %{public}d", subscribeRet);
94     int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_HALL, &hallUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
95     TLOGI(WmsLogTag::DMS, "setBatchRet: %{public}d", setBatchRet);
96     int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_HALL, &hallUser);
97     TLOGI(WmsLogTag::DMS, "activateRet: %{public}d", activateRet);
98     if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
99         TLOGI(WmsLogTag::DMS, "RegisterHallCallback failed.");
100     }
101 }
102 
UnregisterHallCallback()103 void SuperFoldSensorManager::UnregisterHallCallback()
104 {
105     int32_t deactivateRet = DeactivateSensor(SENSOR_TYPE_ID_HALL, &hallUser);
106     int32_t unsubscribeRet = UnsubscribeSensor(SENSOR_TYPE_ID_HALL, &hallUser);
107     if (deactivateRet == SENSOR_SUCCESS && unsubscribeRet == SENSOR_SUCCESS) {
108         TLOGI(WmsLogTag::DMS, "UnRegisterHallCallback success.");
109     }
110 }
111 
HandlePostureData(const SensorEvent * const event)112 void SuperFoldSensorManager::HandlePostureData(const SensorEvent * const event)
113 {
114     if (event == nullptr) {
115         TLOGI(WmsLogTag::DMS, "SensorEvent is nullptr.");
116         return;
117     }
118     if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
119         TLOGI(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
120         return;
121     }
122     if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(PostureData)) {
123         TLOGI(WmsLogTag::DMS, "SensorEvent dataLen less than posture data size.");
124         return;
125     }
126     PostureData *postureData = reinterpret_cast<PostureData *>(event[SENSOR_EVENT_FIRST_DATA].data);
127     curAngle_ = (*postureData).angle;
128     if (std::isgreater(curAngle_, ANGLE_MAX_VAL + ACCURACY_ERROR_FOR_PC)) {
129         TLOGI(WmsLogTag::DMS, "Invalid value, angle value is: %{public}f.", curAngle_);
130         return;
131     }
132     TLOGD(WmsLogTag::DMS, "angle value is: %{public}f.", curAngle_);
133     NotifyFoldAngleChanged(curAngle_);
134 }
135 
NotifyFoldAngleChanged(float foldAngle)136 void SuperFoldSensorManager::NotifyFoldAngleChanged(float foldAngle)
137 {
138     SuperFoldStatusChangeEvents events = SuperFoldStatusChangeEvents::UNDEFINED;
139     if (std::isgreaterequal(foldAngle, ANGLE_FLAT_THRESHOLD)) {
140         TLOGD(WmsLogTag::DMS, "NotifyFoldAngleChanged is Expanded");
141         events = SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED;
142     } else if (std::isless(foldAngle, ANGLE_HALF_FOLD_THRESHOLD) &&
143         std::isgreater(foldAngle, ANGLE_MIN_VAL)) {
144         TLOGD(WmsLogTag::DMS, "NotifyFoldAngleChanged is Half Folded");
145         events = SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED;
146     } else if (std::islessequal(foldAngle, ANGLE_MIN_VAL)) {
147         TLOGD(WmsLogTag::DMS, "NotifyFoldAngleChanged is Folded");
148         events = SuperFoldStatusChangeEvents::ANGLE_CHANGE_FOLDED;
149     } else {
150         if (SuperFoldStateManager::GetInstance().GetCurrentStatus() == SuperFoldStatus::UNKNOWN) {
151             events = SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED;
152         }
153         TLOGD(WmsLogTag::DMS, "NotifyFoldAngleChanged is in BufferArea");
154     }
155     // notify
156     std::vector<float> foldAngles;
157     foldAngles.push_back(foldAngle);
158     ScreenSessionManager::GetInstance().NotifyFoldAngleChanged(foldAngles);
159     if (!ScreenRotationProperty::isDeviceHorizontal() ||
160         events == SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED) {
161         HandleSuperSensorChange(events);
162     }
163 }
164 
HandleHallData(const SensorEvent * const event)165 void SuperFoldSensorManager::HandleHallData(const SensorEvent * const event)
166 {
167     if (event == nullptr) {
168         TLOGI(WmsLogTag::DMS, "SensorEvent is nullptr.");
169         return;
170     }
171     if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
172         TLOGI(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
173         return;
174     }
175     if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(HallData)) {
176         TLOGI(WmsLogTag::DMS, "SensorEvent[0].dataLen is nullptr.");
177         return;
178     }
179     auto data = reinterpret_cast<HallData*>(event->data);
180     auto status = static_cast<uint32_t>(data->status);
181     TLOGI(WmsLogTag::DMS, "HallData status is: %{public}u.", status);
182 
183     if (curHall_ == (status & HALL_ACTIVE)) {
184         TLOGI(WmsLogTag::DMS, "Hall don't change, hall = %{public}u", curHall_);
185         return;
186     }
187     curHall_ = (status & HALL_ACTIVE);
188     TLOGI(WmsLogTag::DMS, "Hall change, hall = %{public}u", curHall_);
189     NotifyHallChanged(curHall_);
190 }
191 
NotifyHallChanged(uint16_t Hall)192 void SuperFoldSensorManager::NotifyHallChanged(uint16_t Hall)
193 {
194     SuperFoldStatusChangeEvents events;
195     if (Hall == HALL_REMOVE_KEYBOARD_THRESHOLD) {
196         TLOGI(WmsLogTag::DMS, "NotifyHallChanged: Keyboard off!");
197         events = SuperFoldStatusChangeEvents::KEYBOARD_OFF;
198     } else if (Hall == HALL_HAVE_KEYBOARD_THRESHOLD) {
199         TLOGI(WmsLogTag::DMS, "NotifyHallChanged: Keyboard on!");
200         events = SuperFoldStatusChangeEvents::KEYBOARD_ON;
201         HandleSuperSensorChange(SuperFoldStatusChangeEvents::ANGLE_CHANGE_HALF_FOLDED);
202     } else {
203         TLOGI(WmsLogTag::DMS, "NotifyHallChanged: Invalid Hall Value!");
204         return;
205     }
206     // notify
207     HandleSuperSensorChange(events);
208     if (std::isgreater(curAngle_, ANGLE_SENSOR_THRESHOLD)) {
209         HandleSuperSensorChange(SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED);
210     }
211 }
212 
HandleSuperSensorChange(SuperFoldStatusChangeEvents events)213 void SuperFoldSensorManager::HandleSuperSensorChange(SuperFoldStatusChangeEvents events)
214 {
215     // trigger events
216     if (ScreenSessionManager::GetInstance().GetIsExtendScreenConnected()) {
217         return;
218     }
219     SuperFoldStateManager::GetInstance().HandleSuperFoldStatusChange(events);
220 }
221 
HandleScreenConnectChange()222 void SuperFoldSensorManager::HandleScreenConnectChange()
223 {
224     TLOGI(WmsLogTag::DMS, "Screen connect to stop statemachine.");
225     if (SuperFoldStateManager::GetInstance().GetCurrentStatus() == SuperFoldStatus::KEYBOARD) {
226         SuperFoldStateManager::GetInstance().HandleSuperFoldStatusChange(
227             SuperFoldStatusChangeEvents::KEYBOARD_OFF);
228         SuperFoldStateManager::GetInstance().HandleSuperFoldStatusChange(
229             SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED);
230     } else {
231         SuperFoldStateManager::GetInstance().HandleSuperFoldStatusChange(
232             SuperFoldStatusChangeEvents::ANGLE_CHANGE_EXPANDED);
233     }
234 }
235 
HandleScreenDisconnectChange()236 void SuperFoldSensorManager::HandleScreenDisconnectChange()
237 {
238     TLOGI(WmsLogTag::DMS, "Screen disconnect to stop statemachine.");
239     NotifyHallChanged(curHall_);
240     NotifyFoldAngleChanged(curAngle_);
241 }
242 
GetCurAngle()243 float SuperFoldSensorManager::GetCurAngle()
244 {
245     return curAngle_;
246 }
247 
SuperFoldSensorManager()248 SuperFoldSensorManager::SuperFoldSensorManager() {}
249 
~SuperFoldSensorManager()250 SuperFoldSensorManager::~SuperFoldSensorManager() {}
251 } // Rosen
252 } // OHOS