1 /*
2  * Copyright (c) 2023 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 #ifdef SENSOR_ENABLE
17 #include <cmath>
18 #include <hisysevent.h>
19 #include <parameters.h>
20 
21 #include "fold_screen_controller/fold_screen_sensor_manager.h"
22 #include "fold_screen_state_internel.h"
23 #include "window_manager_hilog.h"
24 #include "screen_session_manager.h"
25 
26 #ifdef POWER_MANAGER_ENABLE
27 #include <power_mgr_client.h>
28 #endif
29 
SensorPostureDataCallback(SensorEvent * event)30 static void SensorPostureDataCallback(SensorEvent *event)
31 {
32     OHOS::Rosen::FoldScreenSensorManager::GetInstance().HandlePostureData(event);
33 }
34 
SensorHallDataCallback(SensorEvent * event)35 static void SensorHallDataCallback(SensorEvent *event)
36 {
37     OHOS::Rosen::FoldScreenSensorManager::GetInstance().HandleHallData(event);
38 }
39 
40 namespace OHOS {
41 namespace Rosen {
42 namespace {
43 constexpr float ANGLE_MIN_VAL = 0.0F;
44 constexpr float ANGLE_MAX_VAL = 180.0F;
45 constexpr int32_t SENSOR_SUCCESS = 0;
46 constexpr int32_t POSTURE_INTERVAL = 100000000;
47 constexpr uint16_t SENSOR_EVENT_FIRST_DATA = 0;
48 constexpr float ACCURACY_ERROR_FOR_ALTA = 0.0001F;
49 static const float INWARD_HALF_FOLDED_MIN_THRESHOLD = static_cast<float>(system::GetIntParameter<int32_t>
50     ("const.fold.half_folded_min_threshold", 85));
51 static const float LARGE_FOLD_HALF_FOLDED_MIN_THRESHOLD = static_cast<float>(system::GetIntParameter<int32_t>
52     ("const.large_fold.half_folded_min_threshold", 25));
53 constexpr float MINI_NOTIFY_FOLD_ANGLE = 0.5F;
54 float oldFoldAngle = 0.0F;
55 } // namespace
56 WM_IMPLEMENT_SINGLE_INSTANCE(FoldScreenSensorManager);
57 
FoldScreenSensorManager()58 FoldScreenSensorManager::FoldScreenSensorManager()
59 {
60 }
61 
SetFoldScreenPolicy(sptr<FoldScreenPolicy> foldScreenPolicy)62 void FoldScreenSensorManager::SetFoldScreenPolicy(sptr<FoldScreenPolicy> foldScreenPolicy)
63 {
64     foldScreenPolicy_ = foldScreenPolicy;
65 }
66 
SetSensorFoldStateManager(sptr<SensorFoldStateManager> sensorFoldStateManager)67 void FoldScreenSensorManager::SetSensorFoldStateManager(sptr<SensorFoldStateManager> sensorFoldStateManager)
68 {
69     sensorFoldStateManager_ = sensorFoldStateManager;
70 }
71 
RegisterPostureCallback()72 void FoldScreenSensorManager::RegisterPostureCallback()
73 {
74     postureUser.callback = SensorPostureDataCallback;
75     int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
76     int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_POSTURE, &postureUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
77     int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
78     TLOGI(WmsLogTag::DMS,
79         "RegisterPostureCallback, subscribeRet: %{public}d, setBatchRet: %{public}d, activateRet: %{public}d",
80         subscribeRet, setBatchRet, activateRet);
81     if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
82         TLOGE(WmsLogTag::DMS, "RegisterPostureCallback failed.");
83     } else {
84         registerPosture_ = true;
85         TLOGI(WmsLogTag::DMS, "FoldScreenSensorManager.RegisterPostureCallback success.");
86     }
87 }
88 
UnRegisterPostureCallback()89 void FoldScreenSensorManager::UnRegisterPostureCallback()
90 {
91     int32_t deactivateRet = DeactivateSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
92     int32_t unsubscribeRet = UnsubscribeSensor(SENSOR_TYPE_ID_POSTURE, &postureUser);
93     TLOGI(WmsLogTag::DMS, "UnRegisterPostureCallback, deactivateRet: %{public}d, unsubscribeRet: %{public}d",
94         deactivateRet, unsubscribeRet);
95     if (deactivateRet == SENSOR_SUCCESS && unsubscribeRet == SENSOR_SUCCESS) {
96         registerPosture_ = false;
97         TLOGI(WmsLogTag::DMS, "FoldScreenSensorManager.UnRegisterPostureCallback success.");
98     }
99 }
100 
RegisterHallCallback()101 void FoldScreenSensorManager::RegisterHallCallback()
102 {
103     hallUser.callback = SensorHallDataCallback;
104     int32_t subscribeRet = SubscribeSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
105     TLOGI(WmsLogTag::DMS, "RegisterHallCallback, subscribeRet: %{public}d", subscribeRet);
106     int32_t setBatchRet = SetBatch(SENSOR_TYPE_ID_HALL_EXT, &hallUser, POSTURE_INTERVAL, POSTURE_INTERVAL);
107     TLOGI(WmsLogTag::DMS, "RegisterHallCallback, setBatchRet: %{public}d", setBatchRet);
108     int32_t activateRet = ActivateSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
109     TLOGI(WmsLogTag::DMS, "RegisterHallCallback, activateRet: %{public}d", activateRet);
110     if (subscribeRet != SENSOR_SUCCESS || setBatchRet != SENSOR_SUCCESS || activateRet != SENSOR_SUCCESS) {
111         TLOGE(WmsLogTag::DMS, "RegisterHallCallback failed.");
112     }
113 }
114 
UnRegisterHallCallback()115 void FoldScreenSensorManager::UnRegisterHallCallback()
116 {
117     int32_t deactivateRet1 = DeactivateSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
118     int32_t unsubscribeRet1 = UnsubscribeSensor(SENSOR_TYPE_ID_HALL_EXT, &hallUser);
119     if (deactivateRet1 == SENSOR_SUCCESS && unsubscribeRet1 == SENSOR_SUCCESS) {
120         TLOGI(WmsLogTag::DMS, "FoldScreenSensorManager.UnRegisterHallCallback success.");
121     }
122 }
123 
HandlePostureData(const SensorEvent * const event)124 void FoldScreenSensorManager::HandlePostureData(const SensorEvent * const event)
125 {
126     if (event == nullptr) {
127         TLOGI(WmsLogTag::DMS, "SensorEvent is nullptr.");
128         return;
129     }
130     if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
131         TLOGI(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
132         return;
133     }
134     if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(PostureData)) {
135         TLOGI(WmsLogTag::DMS, "SensorEvent dataLen less than posture data size.");
136         return;
137     }
138     PostureData *postureData = reinterpret_cast<PostureData *>(event[SENSOR_EVENT_FIRST_DATA].data);
139     globalAngle = (*postureData).angle;
140     if (globalHall == USHRT_MAX || std::isless(globalAngle, ANGLE_MIN_VAL) ||
141         std::isgreater(globalAngle, ANGLE_MAX_VAL + ACCURACY_ERROR_FOR_ALTA)) {
142         TLOGE(WmsLogTag::DMS, "Invalid value, hall value is: %{public}u, angle value is: %{public}f.",
143             globalHall, globalAngle);
144         return;
145     }
146     TLOGD(WmsLogTag::DMS, "angle value in PostureData is: %{public}f.", globalAngle);
147     sensorFoldStateManager_->HandleAngleChange(globalAngle, globalHall, foldScreenPolicy_);
148     notifyFoldAngleChanged(globalAngle);
149 }
150 
notifyFoldAngleChanged(float foldAngle)151 void FoldScreenSensorManager::notifyFoldAngleChanged(float foldAngle)
152 {
153     if (fabs(foldAngle - oldFoldAngle) < MINI_NOTIFY_FOLD_ANGLE) {
154         return;
155     }
156     oldFoldAngle = foldAngle;
157     std::vector<float> foldAngles;
158     foldAngles.push_back(foldAngle);
159     ScreenSessionManager::GetInstance().NotifyFoldAngleChanged(foldAngles);
160 }
161 
HandleHallData(const SensorEvent * const event)162 void FoldScreenSensorManager::HandleHallData(const SensorEvent * const event)
163 {
164     if (event == nullptr) {
165         TLOGI(WmsLogTag::DMS, "SensorEvent is nullptr.");
166         return;
167     }
168     if (event[SENSOR_EVENT_FIRST_DATA].data == nullptr) {
169         TLOGI(WmsLogTag::DMS, "SensorEvent[0].data is nullptr.");
170         return;
171     }
172     if (event[SENSOR_EVENT_FIRST_DATA].dataLen < sizeof(ExtHallData)) {
173         TLOGI(WmsLogTag::DMS, "SensorEvent dataLen less than hall data size.");
174         return;
175     }
176     ExtHallData *extHallData = reinterpret_cast<ExtHallData *>(event[SENSOR_EVENT_FIRST_DATA].data);
177     uint16_t flag = (uint16_t)(*extHallData).flag;
178     if (!(flag & (1 << 1))) {
179         TLOGI(WmsLogTag::DMS, "NOT Support Extend Hall.");
180         return;
181     }
182     if (globalHall == (uint16_t)(*extHallData).hall) {
183         TLOGI(WmsLogTag::DMS, "Hall don't change, hall = %{public}u", globalHall);
184         return;
185     }
186     globalHall = (uint16_t)(*extHallData).hall;
187     if (globalHall == USHRT_MAX || std::isless(globalAngle, ANGLE_MIN_VAL) ||
188         std::isgreater(globalAngle, ANGLE_MAX_VAL + ACCURACY_ERROR_FOR_ALTA)) {
189         TLOGE(WmsLogTag::DMS, "Invalid value, hall value is: %{public}u, angle value is: %{public}f.",
190             globalHall, globalAngle);
191         return;
192     }
193     TLOGI(WmsLogTag::DMS, "hall value is: %{public}u, angle value is: %{public}f", globalHall, globalAngle);
194     if (!registerPosture_) {
195         globalAngle = ANGLE_MIN_VAL;
196     }
197     sensorFoldStateManager_->HandleHallChange(globalAngle, globalHall, foldScreenPolicy_);
198 }
199 
RegisterApplicationStateObserver()200 void FoldScreenSensorManager::RegisterApplicationStateObserver()
201 {
202     sensorFoldStateManager_->RegisterApplicationStateObserver();
203 }
204 
TriggerDisplaySwitch()205 void FoldScreenSensorManager::TriggerDisplaySwitch()
206 {
207     TLOGI(WmsLogTag::DMS, "TriggerDisplaySwitch hall value is: %{public}u, angle value is: %{public}f",
208         globalHall, globalAngle);
209     if (!registerPosture_) {
210         globalAngle = ANGLE_MIN_VAL;
211     } else {
212         if (FoldScreenStateInternel::IsDualDisplayFoldDevice()) {
213             globalAngle = INWARD_HALF_FOLDED_MIN_THRESHOLD;
214         } else if (FoldScreenStateInternel::IsSingleDisplayFoldDevice()) {
215             globalAngle = LARGE_FOLD_HALF_FOLDED_MIN_THRESHOLD;
216         }
217     }
218     sensorFoldStateManager_->HandleAngleChange(globalAngle, globalHall, foldScreenPolicy_);
219 }
220 } // Rosen
221 } // OHOS
222 #endif