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 <parameters.h>
17 #include <hisysevent.h>
18
19 #include "fold_screen_controller/fold_screen_policy.h"
20 #include "fold_screen_controller/sensor_fold_state_manager/single_display_sensor_pocket_fold_state_manager.h"
21 #include "fold_screen_controller/sensor_fold_state_manager/sensor_fold_state_manager.h"
22 #include "session/screen/include/screen_session.h"
23 #include "screen_scene_config.h"
24
25 #include "window_manager_hilog.h"
26 #include "app_mgr_client.h"
27 #include "session_manager/include/screen_rotation_property.h"
28 #include "screen_session_manager.h"
29
30 #ifdef POWER_MANAGER_ENABLE
31 #include <power_mgr_client.h>
32 #endif
33
34 namespace OHOS::Rosen {
35 using OHOS::AppExecFwk::AppStateData;
36 using OHOS::AppExecFwk::ApplicationState;
37 namespace {
38 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SingleDisplaySensorPocketFoldStateManager"};
39 const std::string CAMERA_NAME = "camera";
40 constexpr float ANGLE_MIN_VAL = 0.0F;
41 constexpr float ALTA_HALF_FOLDED_MAX_THRESHOLD = 140.0F;
42 constexpr float CLOSE_ALTA_HALF_FOLDED_MIN_THRESHOLD = 70.0F;
43 constexpr float OPEN_ALTA_HALF_FOLDED_MIN_THRESHOLD = 25.0F;
44 constexpr float ALTA_HALF_FOLDED_BUFFER = 10.0F;
45 constexpr float LARGER_BOUNDARY_FOR_ALTA_THRESHOLD = 90.0F;
46 constexpr float CAMERA_MAX_VAL = 100.0F;
47 constexpr int32_t LARGER_BOUNDARY_FLAG = 1;
48 constexpr int32_t SMALLER_BOUNDARY_FLAG = 0;
49 constexpr int32_t HALL_THRESHOLD = 1;
50 constexpr int32_t HALL_FOLDED_THRESHOLD = 0;
51 constexpr float TENT_MODE_EXIT_MIN_THRESHOLD = 5.0F;
52 constexpr float TENT_MODE_EXIT_MAX_THRESHOLD = 175.0F;
53 constexpr float HOVER_STATUS_EXIT_MIN_THRESHOLD = 5.0F;
54 constexpr float HOVER_STATUS_EXIT_MAX_THRESHOLD = 175.0F;
55 } // namespace
56
SingleDisplaySensorPocketFoldStateManager()57 SingleDisplaySensorPocketFoldStateManager::SingleDisplaySensorPocketFoldStateManager()
58 {
59 auto stringListConfig = ScreenSceneConfig::GetStringListConfig();
60 if (stringListConfig.count("hallSwitchApp") != 0) {
61 hallSwitchPackageNameList_ = stringListConfig["hallSwitchApp"];
62 }
63 }
~SingleDisplaySensorPocketFoldStateManager()64 SingleDisplaySensorPocketFoldStateManager::~SingleDisplaySensorPocketFoldStateManager() {}
65
HandleAngleChange(float angle,int hall,sptr<FoldScreenPolicy> foldScreenPolicy)66 void SingleDisplaySensorPocketFoldStateManager::HandleAngleChange(float angle, int hall,
67 sptr<FoldScreenPolicy> foldScreenPolicy)
68 {
69 currentAngle_ = angle;
70 SetCameraFoldStrategy(angle);
71 if (isInCameraFoldStrategy_) {
72 HandleSensorChange(FoldStatus::FOLDED, angle, foldScreenPolicy);
73 SetCameraRotationStatusChange(angle, hall);
74 return;
75 }
76 SetCameraRotationStatusChange(angle, hall);
77 if (IsTentMode()) {
78 return TentModeHandleSensorChange(angle, hall, foldScreenPolicy);
79 }
80 FoldStatus nextState = GetNextFoldState(angle, hall);
81 HandleSensorChange(nextState, angle, foldScreenPolicy);
82 }
83
HandleHallChange(float angle,int hall,sptr<FoldScreenPolicy> foldScreenPolicy)84 void SingleDisplaySensorPocketFoldStateManager::HandleHallChange(float angle, int hall,
85 sptr<FoldScreenPolicy> foldScreenPolicy)
86 {
87 currentHall_ = hall;
88 TLOGI(WmsLogTag::DMS, "isInCameraFoldStrategy_:%{public}d", isInCameraFoldStrategy_);
89 SetCameraFoldStrategy(angle);
90 if (isInCameraFoldStrategy_) {
91 HandleSensorChange(FoldStatus::FOLDED, angle, foldScreenPolicy);
92 SetCameraRotationStatusChange(angle, hall);
93 if (hall == HALL_THRESHOLD) {
94 PowerMgr::PowerMgrClient::GetInstance().WakeupDeviceAsync();
95 }
96 return;
97 }
98 SetCameraRotationStatusChange(angle, hall);
99 if (IsTentMode()) {
100 return TentModeHandleSensorChange(angle, hall, foldScreenPolicy);
101 }
102 FoldStatus nextState = GetNextFoldState(angle, hall);
103 HandleSensorChange(nextState, angle, foldScreenPolicy);
104 }
105
UpdateSwitchScreenBoundaryForLargeFoldDevice(float angle,int hall)106 void SingleDisplaySensorPocketFoldStateManager::UpdateSwitchScreenBoundaryForLargeFoldDevice(float angle, int hall)
107 {
108 if (hall == HALL_FOLDED_THRESHOLD) {
109 allowUserSensorForLargeFoldDevice = SMALLER_BOUNDARY_FLAG;
110 } else if (angle >= LARGER_BOUNDARY_FOR_ALTA_THRESHOLD) {
111 allowUserSensorForLargeFoldDevice = LARGER_BOUNDARY_FLAG;
112 }
113 }
114
SetCameraFoldStrategy(float angle)115 void SingleDisplaySensorPocketFoldStateManager::SetCameraFoldStrategy(float angle)
116 {
117 FoldStatus currentState = GetCurrentState();
118
119 if (angle >= CAMERA_MAX_VAL) {
120 if (isInCameraFoldStrategy_ != false) {
121 isInCameraFoldStrategy_ = false;
122 TLOGI(WmsLogTag::DMS, "Disable CameraFoldStrategy, angle: %{public}f, currentFoldState: %{public}d. ",
123 angle, currentState);
124 }
125 return;
126 }
127 if (applicationStateObserver_ == nullptr) {
128 return;
129 }
130 if (applicationStateObserver_->GetForegroundApp().empty()) {
131 return;
132 }
133 if (applicationStateObserver_->GetForegroundApp().find(CAMERA_NAME) != std::string::npos &&
134 currentState == FoldStatus::FOLDED) {
135 if (isInCameraFoldStrategy_ != true) {
136 isInCameraFoldStrategy_ = true;
137 TLOGI(WmsLogTag::DMS, "Enable CameraFoldStrategy, angle: %{public}f, currentFoldState: %{public}d, ",
138 angle, currentState);
139 }
140 }
141 }
142
SetCameraRotationStatusChange(float angle,int hall)143 void SingleDisplaySensorPocketFoldStateManager::SetCameraRotationStatusChange(float angle, int hall)
144 {
145 if (hall == HALL_FOLDED_THRESHOLD) {
146 if (isCameraRotationStrategy_) {
147 TLOGI(WmsLogTag::DMS, "hall is %{public}d, exit cemera status", hall);
148 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::CAMERA_STATUS_CANCEL);
149 isCameraRotationStrategy_ = false;
150 }
151 return;
152 }
153
154 if ((std::isless(angle, HOVER_STATUS_EXIT_MIN_THRESHOLD)) ||
155 (std::isgreater(angle, HOVER_STATUS_EXIT_MAX_THRESHOLD))) {
156 if (isCameraRotationStrategy_) {
157 TLOGI(WmsLogTag::DMS, "angle is:%{public}f, exit camera status", angle);
158 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::CAMERA_STATUS_CANCEL);
159 isCameraRotationStrategy_ = false;
160 }
161 return;
162 }
163
164 if (applicationStateObserver_ == nullptr) {
165 return;
166 }
167 if ((angle > ANGLE_MIN_VAL) && (angle < CAMERA_MAX_VAL) &&
168 (applicationStateObserver_->GetForegroundApp().find(CAMERA_NAME) != std::string::npos)) {
169 // "< 1e-6" means validSensorRotation is 0.
170 if (fabsf(ScreenSessionManager::GetInstance().GetScreenSession(0)->GetValidSensorRotation() - 0.f) < 1e-6) {
171 TLOGI(WmsLogTag::DMS, "angle is:%{public}f and is camera app, but SensorRotation is 0,"
172 "not into camera status", angle);
173 } else {
174 if (!isCameraRotationStrategy_) {
175 TLOGI(WmsLogTag::DMS, "angle is:%{public}f and is camera app, into camera status", angle);
176 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::CAMERA_STATUS);
177 isCameraRotationStrategy_ = true;
178 }
179 }
180 } else {
181 if (isCameraRotationStrategy_) {
182 TLOGI(WmsLogTag::DMS, "angle is:%{public}f or is not camera app, exit camera status", angle);
183 if (std::isgreater(angle, CAMERA_MAX_VAL)) {
184 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::CAMERA_STATUS_CANCEL, false);
185 } else {
186 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::CAMERA_STATUS_CANCEL);
187 }
188 isCameraRotationStrategy_ = false;
189 }
190 }
191 }
192
GetNextFoldState(float angle,int hall)193 FoldStatus SingleDisplaySensorPocketFoldStateManager::GetNextFoldState(float angle, int hall)
194 {
195 UpdateSwitchScreenBoundaryForLargeFoldDevice(angle, hall);
196 FoldStatus currentState = GetCurrentState();
197 if (std::isless(angle, ANGLE_MIN_VAL)) {
198 return currentState;
199 }
200 FoldStatus state;
201
202 if (allowUserSensorForLargeFoldDevice == SMALLER_BOUNDARY_FLAG) {
203 if (hall == HALL_FOLDED_THRESHOLD) {
204 state = FoldStatus::FOLDED;
205 } else if (std::islessequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD - ALTA_HALF_FOLDED_BUFFER) &&
206 hall == HALL_THRESHOLD) {
207 state = FoldStatus::HALF_FOLD;
208 } else if (std::isgreaterequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD)) {
209 state = FoldStatus::EXPAND;
210 } else {
211 state = currentState;
212 if (state == FoldStatus::UNKNOWN) {
213 state = FoldStatus::HALF_FOLD;
214 }
215 }
216 return state;
217 }
218
219 if (hall == HALL_THRESHOLD && angle == OPEN_ALTA_HALF_FOLDED_MIN_THRESHOLD) {
220 state = currentState;
221 } else if (std::islessequal(angle, CLOSE_ALTA_HALF_FOLDED_MIN_THRESHOLD)) {
222 state = FoldStatus::FOLDED;
223 } else if (std::islessequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD - ALTA_HALF_FOLDED_BUFFER) &&
224 std::isgreater(angle, CLOSE_ALTA_HALF_FOLDED_MIN_THRESHOLD + ALTA_HALF_FOLDED_BUFFER)) {
225 state = FoldStatus::HALF_FOLD;
226 } else if (std::isgreaterequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD)) {
227 state = FoldStatus::EXPAND;
228 } else {
229 state = currentState;
230 if (state == FoldStatus::UNKNOWN) {
231 state = FoldStatus::HALF_FOLD;
232 }
233 }
234 return state;
235 }
236
RegisterApplicationStateObserver()237 void SingleDisplaySensorPocketFoldStateManager::RegisterApplicationStateObserver()
238 {
239 applicationStateObserver_ = new (std::nothrow) ApplicationStatePocketObserver();
240 auto appMgrClient_ = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
241 if (applicationStateObserver_ == nullptr) {
242 TLOGI(WmsLogTag::DMS, "applicationStateObserver_ is nullptr.");
243 return;
244 }
245 if (appMgrClient_ == nullptr) {
246 TLOGE(WmsLogTag::DMS, "appMgrClient_ is nullptr.");
247 } else {
248 auto flag = static_cast<int32_t>(
249 appMgrClient_->RegisterApplicationStateObserver(applicationStateObserver_, hallSwitchPackageNameList_));
250 if (flag != ERR_OK) {
251 TLOGE(WmsLogTag::DMS, "Register app debug listener failed.");
252 } else {
253 TLOGI(WmsLogTag::DMS, "Register app debug listener success.");
254 }
255 }
256 applicationStateObserver_->RegisterCameraForegroundChanged([&]() {
257 TLOGI(WmsLogTag::DMS, "onCameraForeground, angle: %{public}f, hall: %{public}d", currentAngle_, currentHall_);
258 if (GetCurrentState() == FoldStatus::FOLDED) {
259 SetCameraFoldStrategy(currentAngle_);
260 SetCameraRotationStatusChange(currentAngle_, currentHall_);
261 }
262 });
263 }
264
HandleTentChange(bool isTent,sptr<FoldScreenPolicy> foldScreenPolicy,int32_t hall)265 void SingleDisplaySensorPocketFoldStateManager::HandleTentChange(bool isTent,
266 sptr<FoldScreenPolicy> foldScreenPolicy, int32_t hall)
267 {
268 bool isNotRepeated = isTent ^ IsTentMode();
269 if (!isNotRepeated) {
270 WLOGI("Repeat reporting tent mode:%{public}s, no processing", (isTent == true) ? "on" : "off");
271 return;
272 }
273
274 SetTentMode(isTent);
275 if (foldScreenPolicy == nullptr) {
276 WLOGE("foldScreenPolicy is nullptr");
277 return;
278 }
279
280 if (isTent) {
281 ReportTentStatusChange(ReportTentModeStatus::NORMAL_ENTER_TENT_MODE);
282 HandleSensorChange(FoldStatus::FOLDED, currentAngle_, foldScreenPolicy);
283 foldScreenPolicy->ChangeOnTentMode(FoldStatus::FOLDED);
284 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::TENT_STATUS);
285 } else {
286 FoldStatus nextState = FoldStatus::UNKNOWN;
287 if (hall == -1) {
288 nextState = GetNextFoldState(currentAngle_, currentHall_);
289 } else {
290 nextState = GetNextFoldState(currentAngle_, hall);
291 }
292 HandleSensorChange(nextState, currentAngle_, foldScreenPolicy);
293 ReportTentStatusChange(ReportTentModeStatus::NORMAL_EXIT_TENT_MODE);
294 foldScreenPolicy->ChangeOffTentMode();
295 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::TENT_STATUS_CANCEL);
296 }
297 }
298
TriggerTentExit(float angle,int hall)299 bool SingleDisplaySensorPocketFoldStateManager::TriggerTentExit(float angle, int hall)
300 {
301 if (hall == HALL_FOLDED_THRESHOLD) {
302 ReportTentStatusChange(ReportTentModeStatus::ABNORMAL_EXIT_TENT_MODE_DUE_TO_HALL);
303 WLOGI("Exit tent mode due to hall sensor report folded");
304 return true;
305 }
306
307 if (std::isless(angle, TENT_MODE_EXIT_MIN_THRESHOLD) || std::isgreater(angle, TENT_MODE_EXIT_MAX_THRESHOLD)) {
308 ReportTentStatusChange(ReportTentModeStatus::ABNORMAL_EXIT_TENT_MODE_DUE_TO_ANGLE);
309 WLOGI("Exit tent mode due to angle sensor report angle:%{public}f", angle);
310 return true;
311 }
312
313 return false;
314 }
315
TentModeHandleSensorChange(float angle,int hall,sptr<FoldScreenPolicy> foldScreenPolicy)316 void SingleDisplaySensorPocketFoldStateManager::TentModeHandleSensorChange(float angle, int hall,
317 sptr<FoldScreenPolicy> foldScreenPolicy)
318 {
319 if (TriggerTentExit(angle, hall)) {
320 FoldStatus nextState = GetNextFoldState(angle, hall);
321 HandleSensorChange(nextState, angle, foldScreenPolicy);
322 TLOGI(WmsLogTag::DMS, "exit tent mode. angle: %{public}f, hall: %{public}d", angle, hall);
323 SetTentMode(false);
324 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::TENT_STATUS_CANCEL);
325 }
326 }
327
ReportTentStatusChange(ReportTentModeStatus tentStatus)328 void SingleDisplaySensorPocketFoldStateManager::ReportTentStatusChange(ReportTentModeStatus tentStatus)
329 {
330 int32_t status = static_cast<int32_t>(tentStatus);
331 TLOGI(WmsLogTag::DMS, "report tentStatus: %{public}d", status);
332 int32_t ret = HiSysEventWrite(
333 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
334 "FOLD_TENT_MODE",
335 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
336 "FOLD_TENT_STATUS", status);
337 if (ret != 0) {
338 TLOGE(WmsLogTag::DMS, "Write HiSysEvent error, ret: %{public}d", ret);
339 }
340 }
341
ApplicationStatePocketObserver()342 ApplicationStatePocketObserver::ApplicationStatePocketObserver() {}
343
RegisterCameraForegroundChanged(std::function<void ()> callback)344 void ApplicationStatePocketObserver::RegisterCameraForegroundChanged(std::function<void()> callback)
345 {
346 onCameraForegroundChanged_ = callback;
347 }
348
OnForegroundApplicationChanged(const AppStateData & appStateData)349 void ApplicationStatePocketObserver::OnForegroundApplicationChanged(const AppStateData &appStateData)
350 {
351 if (appStateData.state == static_cast<int32_t>(ApplicationState::APP_STATE_FOREGROUND)) {
352 foregroundBundleName_ = appStateData.bundleName;
353 }
354 if (appStateData.state == static_cast<int32_t>(ApplicationState::APP_STATE_BACKGROUND)
355 && foregroundBundleName_.compare(appStateData.bundleName) == 0) {
356 foregroundBundleName_ = "" ;
357 }
358 if (appStateData.bundleName.find(CAMERA_NAME) != std::string::npos) {
359 if (onCameraForegroundChanged_ == nullptr) {
360 TLOGE(WmsLogTag::DMS, "onCameraForegroundChanged_ not register");
361 return;
362 }
363 onCameraForegroundChanged_();
364 }
365 }
366
GetForegroundApp()367 std::string ApplicationStatePocketObserver::GetForegroundApp()
368 {
369 return foregroundBundleName_;
370 }
371 } // namespace OHOS::Rosen