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 "screen_session_manager/include/screen_rotation_property.h"
28 #include "screen_session_manager.h"
29 #include "sensor_agent.h"
30 #include "sensor_agent_type.h"
31
32 #ifdef POWER_MANAGER_ENABLE
33 #include <power_mgr_client.h>
34 #endif
35
36 namespace OHOS::Rosen {
37 using OHOS::AppExecFwk::AppStateData;
38 using OHOS::AppExecFwk::ApplicationState;
39 namespace {
40 const std::string CAMERA_NAME = "camera";
41 constexpr float ANGLE_MIN_VAL = 0.0F;
42 constexpr float ALTA_HALF_FOLDED_MAX_THRESHOLD = 140.0F;
43 constexpr float CLOSE_ALTA_HALF_FOLDED_MIN_THRESHOLD = 70.0F;
44 constexpr float OPEN_ALTA_HALF_FOLDED_MIN_THRESHOLD = 25.0F;
45 constexpr float ALTA_HALF_FOLDED_BUFFER = 10.0F;
46 constexpr float LARGER_BOUNDARY_FOR_ALTA_THRESHOLD = 90.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 int32_t TENT_MODE_OFF = 0;
54 constexpr int32_t TENT_MODE_ON = 1;
55 constexpr int32_t TENT_MODE_HOVER_ON = 2;
56 } // namespace
57
SingleDisplaySensorPocketFoldStateManager()58 SingleDisplaySensorPocketFoldStateManager::SingleDisplaySensorPocketFoldStateManager()
59 {
60 auto stringListConfig = ScreenSceneConfig::GetStringListConfig();
61 if (stringListConfig.count("hallSwitchApp") != 0) {
62 hallSwitchPackageNameList_ = stringListConfig["hallSwitchApp"];
63 }
64 }
~SingleDisplaySensorPocketFoldStateManager()65 SingleDisplaySensorPocketFoldStateManager::~SingleDisplaySensorPocketFoldStateManager() {}
66
HandleAngleChange(float angle,int hall,sptr<FoldScreenPolicy> foldScreenPolicy)67 void SingleDisplaySensorPocketFoldStateManager::HandleAngleChange(float angle, int hall,
68 sptr<FoldScreenPolicy> foldScreenPolicy)
69 {
70 currentAngle = angle;
71 if (IsTentMode()) {
72 return TentModeHandleSensorChange(angle, hall, foldScreenPolicy);
73 }
74 FoldStatus nextState = GetNextFoldState(angle, hall);
75 HandleSensorChange(nextState, angle, foldScreenPolicy);
76 }
77
HandleHallChange(float angle,int hall,sptr<FoldScreenPolicy> foldScreenPolicy)78 void SingleDisplaySensorPocketFoldStateManager::HandleHallChange(float angle, int hall,
79 sptr<FoldScreenPolicy> foldScreenPolicy)
80 {
81 currentHall = hall;
82 if (IsTentMode()) {
83 return TentModeHandleSensorChange(angle, hall, foldScreenPolicy);
84 }
85 FoldStatus nextState = GetNextFoldState(angle, hall);
86 HandleSensorChange(nextState, angle, foldScreenPolicy);
87 }
88
UpdateSwitchScreenBoundaryForLargeFoldDevice(float angle,int hall)89 void SingleDisplaySensorPocketFoldStateManager::UpdateSwitchScreenBoundaryForLargeFoldDevice(float angle, int hall)
90 {
91 if (hall == HALL_FOLDED_THRESHOLD) {
92 allowUserSensorForLargeFoldDevice = SMALLER_BOUNDARY_FLAG;
93 } else if (angle >= LARGER_BOUNDARY_FOR_ALTA_THRESHOLD) {
94 allowUserSensorForLargeFoldDevice = LARGER_BOUNDARY_FLAG;
95 }
96 }
97
GetNextFoldState(float angle,int hall)98 FoldStatus SingleDisplaySensorPocketFoldStateManager::GetNextFoldState(float angle, int hall)
99 {
100 UpdateSwitchScreenBoundaryForLargeFoldDevice(angle, hall);
101 FoldStatus currentState = GetCurrentState();
102 if (std::isless(angle, ANGLE_MIN_VAL)) {
103 return currentState;
104 }
105 FoldStatus state;
106
107 if (allowUserSensorForLargeFoldDevice == SMALLER_BOUNDARY_FLAG) {
108 if (std::islessequal(angle, OPEN_ALTA_HALF_FOLDED_MIN_THRESHOLD) && hall == HALL_FOLDED_THRESHOLD) {
109 state = FoldStatus::FOLDED;
110 } else if (std::isgreaterequal(angle, OPEN_ALTA_HALF_FOLDED_MIN_THRESHOLD + ALTA_HALF_FOLDED_BUFFER) &&
111 hall == HALL_FOLDED_THRESHOLD) {
112 state = FoldStatus::HALF_FOLD;
113 } else if (std::islessequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD - ALTA_HALF_FOLDED_BUFFER) &&
114 hall == HALL_THRESHOLD) {
115 state = FoldStatus::HALF_FOLD;
116 } else if (std::isgreaterequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD)) {
117 state = FoldStatus::EXPAND;
118 } else {
119 state = currentState;
120 if (state == FoldStatus::UNKNOWN) {
121 state = FoldStatus::HALF_FOLD;
122 }
123 }
124 return state;
125 }
126
127 if (hall == HALL_THRESHOLD && angle == OPEN_ALTA_HALF_FOLDED_MIN_THRESHOLD) {
128 state = currentState;
129 } else if (std::islessequal(angle, CLOSE_ALTA_HALF_FOLDED_MIN_THRESHOLD)) {
130 state = FoldStatus::FOLDED;
131 } else if (std::islessequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD - ALTA_HALF_FOLDED_BUFFER) &&
132 std::isgreater(angle, CLOSE_ALTA_HALF_FOLDED_MIN_THRESHOLD + ALTA_HALF_FOLDED_BUFFER)) {
133 state = FoldStatus::HALF_FOLD;
134 } else if (std::isgreaterequal(angle, ALTA_HALF_FOLDED_MAX_THRESHOLD)) {
135 state = FoldStatus::EXPAND;
136 } else {
137 state = currentState;
138 if (state == FoldStatus::UNKNOWN) {
139 state = FoldStatus::HALF_FOLD;
140 }
141 }
142 return state;
143 }
144
RegisterApplicationStateObserver()145 void SingleDisplaySensorPocketFoldStateManager::RegisterApplicationStateObserver()
146 {
147 applicationStateObserver_ = new (std::nothrow) ApplicationStatePocketObserver();
148 auto appMgrClient_ = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
149 if (applicationStateObserver_ == nullptr) {
150 TLOGI(WmsLogTag::DMS, "applicationStateObserver_ is nullptr.");
151 return;
152 }
153 if (appMgrClient_ == nullptr) {
154 TLOGE(WmsLogTag::DMS, "appMgrClient_ is nullptr.");
155 } else {
156 auto flag = static_cast<int32_t>(
157 appMgrClient_->RegisterApplicationStateObserver(applicationStateObserver_, hallSwitchPackageNameList_));
158 if (flag != ERR_OK) {
159 TLOGE(WmsLogTag::DMS, "Register app debug listener failed.");
160 } else {
161 TLOGI(WmsLogTag::DMS, "Register app debug listener success.");
162 }
163 }
164 }
165
HandleTentChange(int tentType,sptr<FoldScreenPolicy> foldScreenPolicy,int32_t hall)166 void SingleDisplaySensorPocketFoldStateManager::HandleTentChange(int tentType,
167 sptr<FoldScreenPolicy> foldScreenPolicy, int32_t hall)
168 {
169 if (tentType == tentModeType_) {
170 TLOGI(WmsLogTag::DMS, "Repeat reporting tent mode:%{public}d, no processing", tentModeType_);
171 return;
172 }
173
174 SetTentMode(tentType);
175 if (foldScreenPolicy == nullptr) {
176 TLOGE(WmsLogTag::DMS, "foldScreenPolicy is nullptr");
177 return;
178 }
179 if (tentType != TENT_MODE_OFF) {
180 ReportTentStatusChange(ReportTentModeStatus::NORMAL_ENTER_TENT_MODE);
181 HandleSensorChange(FoldStatus::FOLDED, currentAngle, foldScreenPolicy);
182 foldScreenPolicy->ChangeOnTentMode(FoldStatus::FOLDED);
183 if (tentType == TENT_MODE_ON) {
184 SetDeviceStatusAndParam(static_cast<uint32_t>(DMDeviceStatus::STATUS_TENT));
185 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::TENT_STATUS);
186 } else if (tentType == TENT_MODE_HOVER_ON) {
187 SetDeviceStatusAndParam(static_cast<uint32_t>(DMDeviceStatus::STATUS_TENT_HOVER));
188 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::TENT_STATUS_HOVER);
189 }
190 } else {
191 if (hall == HALL_FOLDED_THRESHOLD) {
192 currentAngle = ANGLE_MIN_VAL;
193 }
194 FoldStatus nextState = FoldStatus::UNKNOWN;
195 if (hall == -1) {
196 nextState = GetNextFoldState(currentAngle, currentHall);
197 } else {
198 nextState = GetNextFoldState(currentAngle, hall);
199 }
200 if (nextState == FoldStatus::FOLDED) {
201 SetDeviceStatusAndParam(static_cast<uint32_t>(DMDeviceStatus::STATUS_FOLDED));
202 } else {
203 SetDeviceStatusAndParam(static_cast<uint32_t>(DMDeviceStatus::UNKNOWN));
204 }
205 HandleSensorChange(nextState, currentAngle, foldScreenPolicy);
206 ReportTentStatusChange(ReportTentModeStatus::NORMAL_EXIT_TENT_MODE);
207 foldScreenPolicy->ChangeOffTentMode();
208 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::TENT_STATUS_CANCEL);
209 }
210 }
211
TriggerTentExit(float angle,int hall)212 bool SingleDisplaySensorPocketFoldStateManager::TriggerTentExit(float angle, int hall)
213 {
214 if (hall == HALL_FOLDED_THRESHOLD) {
215 ReportTentStatusChange(ReportTentModeStatus::ABNORMAL_EXIT_TENT_MODE_DUE_TO_HALL);
216 TLOGI(WmsLogTag::DMS, "Exit tent mode due to hall sensor report folded");
217 return true;
218 }
219
220 if (std::isless(angle, TENT_MODE_EXIT_MIN_THRESHOLD) || std::isgreater(angle, TENT_MODE_EXIT_MAX_THRESHOLD)) {
221 ReportTentStatusChange(ReportTentModeStatus::ABNORMAL_EXIT_TENT_MODE_DUE_TO_ANGLE);
222 TLOGI(WmsLogTag::DMS, "Exit tent mode due to angle sensor report angle:%{public}f", angle);
223 return true;
224 }
225
226 return false;
227 }
228
TentModeHandleSensorChange(float angle,int hall,sptr<FoldScreenPolicy> foldScreenPolicy)229 void SingleDisplaySensorPocketFoldStateManager::TentModeHandleSensorChange(float angle, int hall,
230 sptr<FoldScreenPolicy> foldScreenPolicy)
231 {
232 if (TriggerTentExit(angle, hall)) {
233 FoldStatus nextState = GetNextFoldState(angle, hall);
234 HandleSensorChange(nextState, angle, foldScreenPolicy);
235 TLOGI(WmsLogTag::DMS, "exit tent mode. angle: %{public}f, hall: %{public}d", angle, hall);
236 SetTentMode(TENT_MODE_OFF);
237 if (nextState == FoldStatus::FOLDED) {
238 SetDeviceStatusAndParam(static_cast<uint32_t>(DMDeviceStatus::STATUS_FOLDED));
239 } else {
240 SetDeviceStatusAndParam(static_cast<uint32_t>(DMDeviceStatus::UNKNOWN));
241 }
242 ScreenRotationProperty::HandleHoverStatusEventInput(DeviceHoverStatus::TENT_STATUS_CANCEL);
243 }
244 }
245
ReportTentStatusChange(ReportTentModeStatus tentStatus)246 void SingleDisplaySensorPocketFoldStateManager::ReportTentStatusChange(ReportTentModeStatus tentStatus)
247 {
248 int32_t status = static_cast<int32_t>(tentStatus);
249 TLOGI(WmsLogTag::DMS, "report tentStatus: %{public}d", status);
250 int32_t ret = HiSysEventWrite(
251 OHOS::HiviewDFX::HiSysEvent::Domain::WINDOW_MANAGER,
252 "FOLD_TENT_MODE",
253 OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
254 "FOLD_TENT_STATUS", status);
255 if (ret != 0) {
256 TLOGE(WmsLogTag::DMS, "Write HiSysEvent error, ret: %{public}d", ret);
257 }
258 }
259
ApplicationStatePocketObserver()260 ApplicationStatePocketObserver::ApplicationStatePocketObserver() {}
261
RegisterCameraForegroundChanged(std::function<void ()> callback)262 void ApplicationStatePocketObserver::RegisterCameraForegroundChanged(std::function<void()> callback)
263 {
264 onCameraForegroundChanged_ = callback;
265 }
266
OnForegroundApplicationChanged(const AppStateData & appStateData)267 void ApplicationStatePocketObserver::OnForegroundApplicationChanged(const AppStateData &appStateData)
268 {
269 if (appStateData.state == static_cast<int32_t>(ApplicationState::APP_STATE_FOREGROUND)) {
270 if (appStateData.bundleName.find(CAMERA_NAME) != std::string::npos) {
271 isCameraForeground_ = true;
272 }
273 foregroundBundleName_ = appStateData.bundleName;
274 }
275 if (appStateData.state == static_cast<int32_t>(ApplicationState::APP_STATE_BACKGROUND)) {
276 if (appStateData.bundleName.find(CAMERA_NAME) != std::string::npos) {
277 isCameraForeground_ = false;
278 }
279 if (foregroundBundleName_.compare(appStateData.bundleName) == 0) {
280 foregroundBundleName_ = "" ;
281 }
282 }
283 if (appStateData.bundleName.find(CAMERA_NAME) != std::string::npos) {
284 if (onCameraForegroundChanged_ == nullptr) {
285 TLOGE(WmsLogTag::DMS, "onCameraForegroundChanged_ not register");
286 return;
287 }
288 }
289 }
290
IsCameraForeground()291 bool ApplicationStatePocketObserver::IsCameraForeground()
292 {
293 return isCameraForeground_;
294 }
295
GetForegroundApp()296 std::string ApplicationStatePocketObserver::GetForegroundApp()
297 {
298 return foregroundBundleName_;
299 }
300
SetDeviceStatusAndParam(uint32_t deviceStatus)301 void SingleDisplaySensorPocketFoldStateManager::SetDeviceStatusAndParam(uint32_t deviceStatus)
302 {
303 TLOGI(WmsLogTag::DMS, "Set device status to: %{public}u", deviceStatus);
304 SetDeviceStatus(deviceStatus);
305 system::SetParameter("persist.dms.device.status", std::to_string(deviceStatus));
306 }
307 } // namespace OHOS::Rosen