• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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