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