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