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 #ifdef SENSOR_ENABLE
17 #include <cmath>
18 #include <hisysevent.h>
19 #include <parameters.h>
20
21 #include "fold_screen_controller/secondary_fold_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
30 namespace OHOS {
31 namespace Rosen {
32 namespace {
33 constexpr float ANGLE_MIN_VAL = 0.0F;
34 constexpr float ANGLE_MAX_VAL = 180.0F;
35 constexpr int32_t SENSOR_SUCCESS = 0;
36 // 10ms = 1000 * 1000 * 10 ns
37 constexpr int32_t POSTURE_INTERVAL = 10000000;
38 constexpr uint16_t SENSOR_EVENT_FIRST_DATA = 0;
39 constexpr uint16_t HALL_B_C_COLUMN_ORDER = 1;
40 constexpr uint16_t HALL_A_B_COLUMN_ORDER = 4;
41 constexpr float ACCURACY_ERROR_FOR_ALTA = 0.0001F;
42 constexpr float MINI_NOTIFY_FOLD_ANGLE = 0.5F;
43 std::vector<float> oldFoldAngle = {0.0F, 0.0F};
44 constexpr size_t SECONDARY_POSTURE_SIZE = 3;
45 constexpr size_t SECONDARY_HALL_SIZE = 2;
46 constexpr uint16_t FIRST_DATA = 0;
47 constexpr uint16_t SECOND_DATA = 1;
48 constexpr uint16_t THIRD_DATA = 2;
49 const int32_t MAIN_STATUS_WIDTH = 0;
50 const int32_t FULL_STATUS_WIDTH = 1;
51 const int32_t GLOBAL_FULL_STATUS_WIDTH = 2;
52 const int32_t SCREEN_HEIGHT = 3;
53 const int32_t FULL_STATUS_OFFSET_X = 4;
54 const int32_t PARAMS_VECTOR_SIZE = 5;
55 } // namespace
56 WM_IMPLEMENT_SINGLE_INSTANCE(SecondaryFoldSensorManager);
57
SecondarySensorPostureDataCallback(SensorEvent * event)58 static void SecondarySensorPostureDataCallback(SensorEvent *event)
59 {
60 SecondaryFoldSensorManager::GetInstance().HandlePostureData(event);
61 }
62
SecondarySensorHallDataCallbackExt(SensorEvent * event)63 static void SecondarySensorHallDataCallbackExt(SensorEvent *event)
64 {
65 SecondaryFoldSensorManager::GetInstance().HandleHallDataExt(event);
66 }
67
SetFoldScreenPolicy(sptr<FoldScreenPolicy> foldScreenPolicy)68 void SecondaryFoldSensorManager::SetFoldScreenPolicy(sptr<FoldScreenPolicy> foldScreenPolicy)
69 {
70 foldScreenPolicy_ = foldScreenPolicy;
71 }
72
SetSensorFoldStateManager(sptr<SensorFoldStateManager> sensorFoldStateManager)73 void SecondaryFoldSensorManager::SetSensorFoldStateManager(sptr<SensorFoldStateManager> sensorFoldStateManager)
74 {
75 sensorFoldStateManager_ = sensorFoldStateManager;
76 }
77
RegisterPostureCallback()78 void SecondaryFoldSensorManager::RegisterPostureCallback()
79 {
80 postureUser.callback = SecondarySensorPostureDataCallback;
81 int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
82 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_POSTURE, &postureUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
83 int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
84 TLOGI(WmsLogTag::DMS,
85 "subscribeRet: %{public}d, setBatchRet: %{public}d, activateRet: %{public}d",
86 subscribeRet, setBatchRet, activateRet);
87 if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
88 TLOGE(WmsLogTag::DMS, "failed.");
89 } else {
90 registerPosture_ = true;
91 TLOGI(WmsLogTag::DMS, "success.");
92 }
93 }
94
UnRegisterPostureCallback()95 void SecondaryFoldSensorManager::UnRegisterPostureCallback()
96 {
97 int32_t deactivateRet = DeactivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
98 int32_t unsubscribeRet = UnsubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
99 TLOGI(WmsLogTag::DMS, "deactivateRet: %{public}d, unsubscribeRet: %{public}d",
100 deactivateRet, unsubscribeRet);
101 if (deactivateRet == SENSOR_SUCCESS && unsubscribeRet == SENSOR_SUCCESS) {
102 registerPosture_ = false;
103 TLOGI(WmsLogTag::DMS, "success.");
104 }
105 }
106
RegisterHallCallback()107 void SecondaryFoldSensorManager::RegisterHallCallback()
108 {
109 hallUser.callback = SecondarySensorHallDataCallbackExt;
110 int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
111 TLOGI(WmsLogTag::DMS, "subscribeRet: %{public}d", subscribeRet);
112 int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_HALL_EXT, &hallUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
113 TLOGI(WmsLogTag::DMS, "setBatchRet: %{public}d", setBatchRet);
114 int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
115 TLOGI(WmsLogTag::DMS, "activateRet: %{public}d", activateRet);
116 if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
117 TLOGE(WmsLogTag::DMS, "failed.");
118 } else {
119 TLOGI(WmsLogTag::DMS, "success.");
120 }
121 }
122
UnRegisterHallCallback()123 void SecondaryFoldSensorManager::UnRegisterHallCallback()
124 {
125 int32_t deactivateRet = DeactivateSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
126 int32_t unsubscribeRet = UnsubscribeSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
127 if (deactivateRet == SENSOR_SUCCESS && unsubscribeRet == SENSOR_SUCCESS) {
128 TLOGW(WmsLogTag::DMS, "success.");
129 }
130 }
131
HandlePostureData(const SensorEvent * const event)132 void SecondaryFoldSensorManager::HandlePostureData(const SensorEvent * const event)
133 {
134 float postureBc = 0.0F;
135 float postureAb = 0.0F;
136 float postureAbAnti = 0.0F;
137 if (!GetPostureInner(event, postureBc, postureAb, postureAbAnti)) {
138 return;
139 }
140 globalAngle_[FIRST_DATA] = postureBc;
141 globalAngle_[SECOND_DATA] = postureAb;
142 globalAngle_[THIRD_DATA] = postureAbAnti;
143 if (IsDataBeyondBoundary()) {
144 return;
145 }
146 TLOGD(WmsLogTag::DMS, "%{public}s, %{public}s",
147 FoldScreenStateInternel::TransVec2Str(globalAngle_, "angle").c_str(),
148 FoldScreenStateInternel::TransVec2Str(globalHall_, "hall").c_str());
149 if (sensorFoldStateManager_ == nullptr) {
150 return;
151 }
152 sensorFoldStateManager_->HandleAngleOrHallChange(globalAngle_, globalHall_, foldScreenPolicy_, true);
153 NotifyFoldAngleChanged(globalAngle_);
154 }
155
NotifyFoldAngleChanged(const std::vector<float> & angles)156 void SecondaryFoldSensorManager::NotifyFoldAngleChanged(const std::vector<float> &angles)
157 {
158 if (angles.size() < SECONDARY_HALL_SIZE) {
159 return;
160 }
161 bool bcFlag = fabs(angles[0] - oldFoldAngle[0]) < MINI_NOTIFY_FOLD_ANGLE;
162 bool abFlag = fabs(angles[1] - oldFoldAngle[1]) < MINI_NOTIFY_FOLD_ANGLE;
163 if (bcFlag && abFlag) {
164 return;
165 }
166 oldFoldAngle[0] = angles[0];
167 oldFoldAngle[1] = angles[1];
168 std::vector<float> notifyAngles = {angles[0], angles[1]};
169 ScreenSessionManager::GetInstance().NotifyFoldAngleChanged(notifyAngles);
170 }
171
HandleHallDataExt(const SensorEvent * const event)172 void SecondaryFoldSensorManager::HandleHallDataExt(const SensorEvent * const event)
173 {
174 uint16_t hallBc = 0;
175 uint16_t hallAb = 0;
176 if (!GetHallInner(event, hallBc, hallAb)) {
177 return;
178 }
179 globalHall_[FIRST_DATA] = hallBc;
180 globalHall_[SECOND_DATA] = hallAb;
181 if (IsDataBeyondBoundary()) {
182 return;
183 }
184 TLOGI(WmsLogTag::DMS, "%{public}s, %{public}s",
185 FoldScreenStateInternel::TransVec2Str(globalAngle_, "angle").c_str(),
186 FoldScreenStateInternel::TransVec2Str(globalHall_, "hall").c_str());
187 if (!registerPosture_) {
188 globalAngle_[FIRST_DATA] = ANGLE_MIN_VAL;
189 globalAngle_[SECOND_DATA] = ANGLE_MIN_VAL;
190 globalAngle_[THIRD_DATA] = ANGLE_MIN_VAL;
191 }
192 if (sensorFoldStateManager_ == nullptr) {
193 return;
194 }
195 sensorFoldStateManager_->HandleAngleOrHallChange(globalAngle_, globalHall_, foldScreenPolicy_, registerPosture_);
196 return;
197 }
198
IsDataBeyondBoundary()199 bool SecondaryFoldSensorManager::IsDataBeyondBoundary()
200 {
201 if (globalAngle_.size() < SECONDARY_POSTURE_SIZE || globalHall_.size() < SECONDARY_HALL_SIZE) {
202 TLOGE(WmsLogTag::DMS, "oversize, global angles: %{public}zu, halls size: %{public}zu.",
203 globalAngle_.size(), globalHall_.size());
204 return true;
205 }
206 for (size_t i = 0; i < SECONDARY_POSTURE_SIZE - 1; i++) {
207 float angle = globalAngle_[i];
208 if (std::isless(angle, ANGLE_MIN_VAL) ||
209 std::isgreater(angle, ANGLE_MAX_VAL + ACCURACY_ERROR_FOR_ALTA)) {
210 TLOGE(WmsLogTag::DMS, "i = %{public}zu, angle = %{public}f", i, angle);
211 return true;
212 }
213 }
214 for (size_t i = 0; i < SECONDARY_HALL_SIZE; i++) {
215 uint16_t hall = globalHall_[i];
216 if (hall != 0 && hall != 1) {
217 TLOGE(WmsLogTag::DMS, "i = %{public}zu, hall = %{public}u", i, hall);
218 return true;
219 }
220 }
221 return false;
222 }
223
GetPostureInner(const SensorEvent * const event,float & valueBc,float & valueAb,float & valueAbAnti)224 bool SecondaryFoldSensorManager::GetPostureInner(const SensorEvent * const event, float &valueBc, float &valueAb,
225 float &valueAbAnti)
226 {
227 if (event == nullptr) {
228 TLOGW(WmsLogTag::DMS, "SensorEvent is nullptr.");
229 return false;
230 }
231 if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
232 TLOGW(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
233 return false;
234 }
235 if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(FoldScreenSensorManager::PostureDataSecondary)) {
236 TLOGW(WmsLogTag::DMS, "SensorEvent dataLen less than posture data size.");
237 return false;
238 }
239 FoldScreenSensorManager::PostureDataSecondary *postureData =
240 reinterpret_cast<FoldScreenSensorManager::PostureDataSecondary *>(event[SENSOR_EVENT_FIRST_DATA].data);
241 valueBc = (*postureData).postureBc;
242 valueAb = (*postureData).postureAb;
243 valueAbAnti = (*postureData).postureAbAnti;
244 TLOGD(WmsLogTag::DMS, "postureBc: %{public}f, postureAb: %{public}f, postureAbAnti: %{public}f.",
245 valueBc, valueAb, valueAbAnti);
246 return true;
247 }
248
GetHallInner(const SensorEvent * const event,uint16_t & valueBc,uint16_t & valueAb)249 bool SecondaryFoldSensorManager::GetHallInner(const SensorEvent * const event, uint16_t &valueBc, uint16_t &valueAb)
250 {
251 if (event == nullptr) {
252 TLOGW(WmsLogTag::DMS, "SensorEvent is nullptr.");
253 return false;
254 }
255 if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
256 TLOGW(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
257 return false;
258 }
259 if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(FoldScreenSensorManager::ExtHallData)) {
260 TLOGW(WmsLogTag::DMS, "SensorEvent dataLen less than hall data size.");
261 return false;
262 }
263 FoldScreenSensorManager::ExtHallData *extHallData =
264 reinterpret_cast<FoldScreenSensorManager::ExtHallData *>(event[SENSOR_EVENT_FIRST_DATA].data);
265 uint16_t flag = static_cast<uint16_t>((*extHallData).flag);
266 if (!(flag & (1 << HALL_B_C_COLUMN_ORDER)) || !(flag & (1 << HALL_A_B_COLUMN_ORDER))) {
267 TLOGW(WmsLogTag::DMS, "not support Extend Hall.");
268 return false;
269 }
270 valueBc = static_cast<uint16_t>((*extHallData).hall); // axis of bc screen. 0: hall closed, 1: hall expaned
271 valueAb = static_cast<uint16_t>((*extHallData).hallAb);
272 TLOGI(WmsLogTag::DMS, "hallBc: %{public}u, hallAb: %{public}u.", valueBc, valueAb);
273 return true;
274 }
275
PowerKeySetScreenActiveRect()276 void SecondaryFoldSensorManager::PowerKeySetScreenActiveRect()
277 {
278 if (foldScreenPolicy_ == nullptr) {
279 TLOGE(WmsLogTag::DMS, "fold screen policy is not initialized.");
280 return;
281 }
282 if (foldScreenPolicy_->GetScreenParams().size() != PARAMS_VECTOR_SIZE) {
283 return;
284 }
285 uint32_t x = 0;
286 uint32_t y = 0;
287 uint32_t width = foldScreenPolicy_->GetScreenParams()[SCREEN_HEIGHT];
288 uint32_t height = 0;
289 {
290 std::lock_guard<std::recursive_mutex> lock_mode(foldScreenPolicy_->displayModeMutex_);
291 if (foldScreenPolicy_->lastDisplayMode_ == FoldDisplayMode::FULL) {
292 y = foldScreenPolicy_->GetScreenParams()[FULL_STATUS_OFFSET_X];
293 height = foldScreenPolicy_->GetScreenParams()[FULL_STATUS_WIDTH];
294 } else if (foldScreenPolicy_->lastDisplayMode_ == FoldDisplayMode::MAIN) {
295 height = foldScreenPolicy_->GetScreenParams()[MAIN_STATUS_WIDTH];
296 } else if (foldScreenPolicy_->lastDisplayMode_ == FoldDisplayMode::GLOBAL_FULL) {
297 height = foldScreenPolicy_->GetScreenParams()[GLOBAL_FULL_STATUS_WIDTH];
298 } else {
299 TLOGW(WmsLogTag::DMS, "displayMode[%{public}u] unknown.", foldScreenPolicy_->lastDisplayMode_);
300 return;
301 }
302 }
303 OHOS::Rect rectCur {
304 .x = x,
305 .y = y,
306 .w = width,
307 .h = height,
308 };
309 RSInterfaces::GetInstance().SetScreenActiveRect(0, rectCur);
310 isPowerRectExe_ = true;
311 }
312
IsPostureUserCallbackInvalid() const313 bool SecondaryFoldSensorManager::IsPostureUserCallbackInvalid() const
314 {
315 return postureUser.callback == nullptr;
316 }
317
IsHallUserCallbackInvalid() const318 bool SecondaryFoldSensorManager::IsHallUserCallbackInvalid() const
319 {
320 return hallUser.callback == nullptr;
321 }
322
GetGlobalAngle() const323 std::vector<float> SecondaryFoldSensorManager::GetGlobalAngle() const
324 {
325 return globalAngle_;
326 }
327
GetGlobalHall() const328 std::vector<uint16_t> SecondaryFoldSensorManager::GetGlobalHall() const
329 {
330 return globalHall_;
331 }
332 } // Rosen
333 } // OHOS
334 #endif