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 if (!isCameraRotationStrategy_) {
170 TLOGI(WmsLogTag::DMS, "angle is:%{public}f and is camera app, into camera status", angle);
171 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::CAMERA_STATUS);
172 isCameraRotationStrategy_ = true;
173 }
174 } else {
175 if (isCameraRotationStrategy_) {
176 TLOGI(WmsLogTag::DMS, "angle is:%{public}f or is not camera app, exit camera status", angle);
177 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::CAMERA_STATUS_CANCEL);
178 isCameraRotationStrategy_ = false;
179 }
180 }
181 }
182
GetNextFoldState(float angle,int hall)183 FoldStatus SingleDisplaySensorPocketFoldStateManager::GetNextFoldState(float angle, int hall)
184 {
185 UpdateSwitchScreenBoundaryForLargeFoldDevice(angle, hall);
186 FoldStatus currentState = GetCurrentState();
187 if (std::isless(angle, ANGLE_MIN_VAL)) {
188 return currentState;
189 }
190 FoldStatus state;
191
192 if (allowUserSensorForLargeFoldDevice == SMALLER_BOUNDARY_FLAG) {
193 if (hall == HALL_FOLDED_THRESHOLD) {
194 state = FoldStatus::FOLDED;
195 } else if (std::islessequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD - ALTA_HALF_FOLDED_BUFFER) &&
196 hall == HALL_THRESHOLD) {
197 state = FoldStatus::HALF_FOLD;
198 } else if (std::isgreaterequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD)) {
199 state = FoldStatus::EXPAND;
200 } else {
201 state = currentState;
202 if (state == FoldStatus::UNKNOWN) {
203 state = FoldStatus::HALF_FOLD;
204 }
205 }
206 return state;
207 }
208
209 if (hall == HALL_THRESHOLD && angle == OPEN_ALTA_HALF_FOLDED_MIN_THRESHOLD) {
210 state = currentState;
211 } else if (std::islessequal(angle, CLOSE_ALTA_HALF_FOLDED_MIN_THRESHOLD)) {
212 state = FoldStatus::FOLDED;
213 } else if (std::islessequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD - ALTA_HALF_FOLDED_BUFFER) &&
214 std::isgreater(angle, CLOSE_ALTA_HALF_FOLDED_MIN_THRESHOLD + ALTA_HALF_FOLDED_BUFFER)) {
215 state = FoldStatus::HALF_FOLD;
216 } else if (std::isgreaterequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD)) {
217 state = FoldStatus::EXPAND;
218 } else {
219 state = currentState;
220 if (state == FoldStatus::UNKNOWN) {
221 state = FoldStatus::HALF_FOLD;
222 }
223 }
224 return state;
225 }
226
RegisterApplicationStateObserver()227 void SingleDisplaySensorPocketFoldStateManager::RegisterApplicationStateObserver()
228 {
229 applicationStateObserver_ = new (std::nothrow) ApplicationStatePocketObserver();
230 auto appMgrClient_ = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
231 if (applicationStateObserver_ == nullptr) {
232 TLOGI(WmsLogTag::DMS, "applicationStateObserver_ is nullptr.");
233 return;
234 }
235 if (appMgrClient_ == nullptr) {
236 TLOGE(WmsLogTag::DMS, "appMgrClient_ is nullptr.");
237 } else {
238 auto flag = static_cast<int32_t>(
239 appMgrClient_->RegisterApplicationStateObserver(applicationStateObserver_, hallSwitchPackageNameList_));
240 if (flag != ERR_OK) {
241 TLOGE(WmsLogTag::DMS, "Register app debug listener failed.");
242 } else {
243 TLOGI(WmsLogTag::DMS, "Register app debug listener success.");
244 }
245 }
246 }
247
HandleTentChange(bool isTent,sptr<FoldScreenPolicy> foldScreenPolicy)248 void SingleDisplaySensorPocketFoldStateManager::HandleTentChange(bool isTent, sptr<FoldScreenPolicy> foldScreenPolicy)
249 {
250 bool isNotRepeated = isTent ^ IsTentMode();
251 if (!isNotRepeated) {
252 WLOGI("Repeat reporting tent mode:%{public}s, no processing", (isTent == true) ? "on" : "off");
253 return;
254 }
255
256 SetTentMode(isTent);
257 if (foldScreenPolicy == nullptr) {
258 WLOGE("foldScreenPolicy is nullptr");
259 return;
260 }
261
262 if (isTent) {
263 ReportTentStatusChange(ReportTentModeStatus::NORMAL_ENTER_TENT_MODE);
264 HandleSensorChange(FoldStatus::FOLDED, currentAngle_, foldScreenPolicy);
265 foldScreenPolicy->ChangeOnTentMode(FoldStatus::FOLDED);
266 } else {
267 FoldStatus nextState = GetNextFoldState(currentAngle_, currentHall_);
268 HandleSensorChange(nextState, currentAngle_, foldScreenPolicy);
269 ReportTentStatusChange(ReportTentModeStatus::NORMAL_EXIT_TENT_MODE);
270 foldScreenPolicy->ChangeOffTentMode();
271 }
272 }
273
TriggerTentExit(float angle,int hall)274 bool SingleDisplaySensorPocketFoldStateManager::TriggerTentExit(float angle, int hall)
275 {
276 if (hall == HALL_FOLDED_THRESHOLD) {
277 ReportTentStatusChange(ReportTentModeStatus::ABNORMAL_EXIT_TENT_MODE_DUE_TO_HALL);
278 WLOGI("Exit tent mode due to hall sensor report folded");
279 return true;
280 }
281
282 if (std::isless(angle, TENT_MODE_EXIT_MIN_THRESHOLD) || std::isgreater(angle, TENT_MODE_EXIT_MAX_THRESHOLD)) {
283 ReportTentStatusChange(ReportTentModeStatus::ABNORMAL_EXIT_TENT_MODE_DUE_TO_ANGLE);
284 WLOGI("Exit tent mode due to angle sensor report angle:%{public}f", angle);
285 return true;
286 }
287
288 return false;
289 }
290
TentModeHandleSensorChange(float angle,int hall,sptr<FoldScreenPolicy> foldScreenPolicy)291 void SingleDisplaySensorPocketFoldStateManager::TentModeHandleSensorChange(float angle, int hall,
292 sptr<FoldScreenPolicy> foldScreenPolicy)
293 {
294 if (TriggerTentExit(angle, hall)) {
295 FoldStatus nextState = GetNextFoldState(angle, hall);
296 HandleSensorChange(nextState, angle, foldScreenPolicy);
297 TLOGI(WmsLogTag::DMS, "exit tent mode. angle: %{public}f, hall: %{public}d", angle, hall);
298 SetTentMode(false);
299 }
300 }
301
ReportTentStatusChange(ReportTentModeStatus tentStatus)302 void SingleDisplaySensorPocketFoldStateManager::ReportTentStatusChange(ReportTentModeStatus tentStatus)
303 {
304 int32_t status = static_cast<int32_t>(tentStatus);
305 TLOGI(WmsLogTag::DMS, "report tentStatus: %{public}d", status);
306 int32_t ret = HiSysEventWrite(
307 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
308 "FOLD_TENT_MODE",
309 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
310 "FOLD_TENT_STATUS", status);
311 if (ret != 0) {
312 TLOGE(WmsLogTag::DMS, "Write HiSysEvent error, ret: %{public}d", ret);
313 }
314 }
315
ApplicationStatePocketObserver()316 ApplicationStatePocketObserver::ApplicationStatePocketObserver() {}
317
OnForegroundApplicationChanged(const AppStateData & appStateData)318 void ApplicationStatePocketObserver::OnForegroundApplicationChanged(const AppStateData &appStateData)
319 {
320 if (appStateData.state == static_cast<int32_t>(ApplicationState::APP_STATE_FOREGROUND)) {
321 foregroundBundleName_ = appStateData.bundleName;
322 }
323 if (appStateData.state == static_cast<int32_t>(ApplicationState::APP_STATE_BACKGROUND)
324 && foregroundBundleName_.compare(appStateData.bundleName) == 0) {
325 foregroundBundleName_ = "" ;
326 }
327 }
328
GetForegroundApp()329 std::string ApplicationStatePocketObserver::GetForegroundApp()
330 {
331 return foregroundBundleName_;
332 }
333 } // namespace OHOS::Rosen