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