1 /*
2 * Copyright (c) 2022 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 "sensor_connector.h"
17
18 #include <chrono>
19 #include <securec.h>
20
21 #include "display_manager_service_inner.h"
22
23 namespace OHOS {
24 namespace Rosen {
25 namespace {
26 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SensorConnector"};
27
28 #ifdef SENSOR_ENABLE
29 constexpr int64_t ORIENTATION_SENSOR_SAMPLING_RATE = 200000000; // 200ms
30 constexpr int64_t ORIENTATION_SENSOR_REPORTING_RATE = 0;
31 constexpr long ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL = 200; // 200ms
32 constexpr int VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT = 3;
33 #endif
34
35 #ifdef WM_SUBSCRIBE_MOTION_ENABLE
36 constexpr int32_t MOTION_ACTION_PORTRAIT = 0;
37 constexpr int32_t MOTION_ACTION_LEFT_LANDSCAPE = 1;
38 constexpr int32_t MOTION_ACTION_PORTRAIT_INVERTED = 2;
39 constexpr int32_t MOTION_ACTION_RIGHT_LANDSCAPE = 3;
40 #endif
41 }
42
43 #ifdef SENSOR_ENABLE
44 bool GravitySensorSubscriber::isGravitySensorSubscribed_ = false;
45 SensorUser GravitySensorSubscriber::user_;
46 long GravitySensorSubscriber::lastCallbackTime_ = 0;
47 #endif
48
49 #ifdef WM_SUBSCRIBE_MOTION_ENABLE
50 bool MotionSubscriber::isMotionSensorSubscribed_ = false;
51 sptr<RotationMotionEventCallback> MotionSubscriber::motionEventCallback_ = nullptr;
52 #endif
53
SubscribeRotationSensor()54 void SensorConnector::SubscribeRotationSensor()
55 {
56 WLOGFD("dms: subscribe rotation-related sensor");
57 ScreenRotationController::Init();
58 #ifdef WM_SUBSCRIBE_MOTION_ENABLE
59 MotionSubscriber::SubscribeMotionSensor();
60 if (MotionSubscriber::isMotionSensorSubscribed_) {
61 return;
62 }
63 #endif
64
65 #ifdef SENSOR_ENABLE
66 GravitySensorSubscriber::SubscribeGravitySensor();
67 #endif
68 }
69
UnsubscribeRotationSensor()70 void SensorConnector::UnsubscribeRotationSensor()
71 {
72 #ifdef WM_SUBSCRIBE_MOTION_ENABLE
73 MotionSubscriber::UnsubscribeMotionSensor();
74 #endif
75
76 #ifdef SENSOR_ENABLE
77 GravitySensorSubscriber::UnsubscribeGravitySensor();
78 #endif
79 }
80
81 // Gravity Sensor
82 #ifdef SENSOR_ENABLE
SubscribeGravitySensor()83 void GravitySensorSubscriber::SubscribeGravitySensor()
84 {
85 WLOGFI("dms: Subscribe gravity Sensor");
86 if (isGravitySensorSubscribed_) {
87 WLOGFE("dms: gravity sensor's already subscribed");
88 return;
89 }
90 if (strcpy_s(user_.name, sizeof(user_.name), "ScreenRotationController") != EOK) {
91 WLOGFE("dms strcpy_s error");
92 return;
93 }
94 user_.userData = nullptr;
95 user_.callback = &HandleGravitySensorEventCallback;
96 if (SubscribeSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
97 WLOGFE("dms: Subscribe gravity sensor failed");
98 return;
99 }
100 SetBatch(SENSOR_TYPE_ID_GRAVITY, &user_, ORIENTATION_SENSOR_SAMPLING_RATE, ORIENTATION_SENSOR_REPORTING_RATE);
101 SetMode(SENSOR_TYPE_ID_GRAVITY, &user_, SENSOR_ON_CHANGE);
102 if (ActivateSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
103 WLOGFE("dms: Activate gravity sensor failed");
104 return;
105 }
106 isGravitySensorSubscribed_ = true;
107 }
108
UnsubscribeGravitySensor()109 void GravitySensorSubscriber::UnsubscribeGravitySensor()
110 {
111 WLOGFI("dms: Unsubscribe gravity Sensor");
112 if (!isGravitySensorSubscribed_) {
113 WLOGFE("dms: Orientation Sensor is not subscribed");
114 return;
115 }
116 if (DeactivateSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
117 WLOGFE("dms: Deactivate gravity sensor failed");
118 return;
119 }
120 if (UnsubscribeSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
121 WLOGFE("dms: Unsubscribe gravity sensor failed");
122 return;
123 }
124 isGravitySensorSubscribed_ = false;
125 }
126
HandleGravitySensorEventCallback(SensorEvent * event)127 void GravitySensorSubscriber::HandleGravitySensorEventCallback(SensorEvent *event)
128 {
129 if (!CheckCallbackTimeInterval() || event == nullptr) {
130 return;
131 }
132 if (event->sensorTypeId != SENSOR_TYPE_ID_GRAVITY) {
133 WLOGE("dms: Orientation Sensor Callback is not SENSOR_TYPE_ID_GRAVITY");
134 return;
135 }
136 GravityData* gravityData = reinterpret_cast<GravityData*>(event->data);
137 int sensorDegree = CalcRotationDegree(gravityData);
138 DeviceRotation sensorRotationConverted = ScreenRotationController::ConvertSensorToDeviceRotation(
139 CalcSensorRotation(sensorDegree));
140 ScreenRotationController::HandleSensorEventInput(sensorRotationConverted);
141 }
142
CalcSensorRotation(int sensorDegree)143 SensorRotation GravitySensorSubscriber::CalcSensorRotation(int sensorDegree)
144 {
145 // Use ROTATION_0 when degree range is [0, 30]∪[330, 359]
146 if (sensorDegree >= 0 && (sensorDegree <= 30 || sensorDegree >= 330)) {
147 return SensorRotation::ROTATION_0;
148 } else if (sensorDegree >= 60 && sensorDegree <= 120) { // Use ROTATION_90 when degree range is [60, 120]
149 return SensorRotation::ROTATION_90;
150 } else if (sensorDegree >= 150 && sensorDegree <= 210) { // Use ROTATION_180 when degree range is [150, 210]
151 return SensorRotation::ROTATION_180;
152 } else if (sensorDegree >= 240 && sensorDegree <= 300) { // Use ROTATION_270 when degree range is [240, 300]
153 return SensorRotation::ROTATION_270;
154 } else {
155 return SensorRotation::INVALID;
156 }
157 }
158
CalcRotationDegree(GravityData * gravityData)159 int GravitySensorSubscriber::CalcRotationDegree(GravityData* gravityData)
160 {
161 if (gravityData == nullptr) {
162 return -1;
163 }
164 float x = gravityData->x;
165 float y = gravityData->y;
166 float z = gravityData->z;
167 int degree = -1;
168 if ((x * x + y * y) * VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT < z * z) {
169 return degree;
170 }
171 // arccotx = pi / 2 - arctanx, 90 is used to calculate acot(in degree); degree = rad / pi * 180
172 degree = 90 - static_cast<int>(round(atan2(y, -x) / M_PI * 180));
173 // Normalize the degree to the range of 0~360
174 return degree >= 0 ? degree % 360 : degree % 360 + 360;
175 }
176
CheckCallbackTimeInterval()177 bool GravitySensorSubscriber::CheckCallbackTimeInterval()
178 {
179 std::chrono::milliseconds ms = std::chrono::time_point_cast<std::chrono::milliseconds>(
180 std::chrono::steady_clock::now()).time_since_epoch();
181 long currentTimeInMillitm = ms.count();
182 if (currentTimeInMillitm - lastCallbackTime_ < ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL) {
183 return false;
184 }
185 lastCallbackTime_ = currentTimeInMillitm;
186 return true;
187 }
188 #endif
189
190 // Motion
191 #ifdef WM_SUBSCRIBE_MOTION_ENABLE
SubscribeMotionSensor()192 void MotionSubscriber::SubscribeMotionSensor()
193 {
194 WLOGFD("dms: Subscribe motion Sensor");
195 if (isMotionSensorSubscribed_) {
196 WLOGFE("dms: motion sensor's already subscribed");
197 return;
198 }
199 sptr<RotationMotionEventCallback> callback = new (std::nothrow) RotationMotionEventCallback();
200 if (callback == nullptr) {
201 return;
202 }
203 int32_t ret = OHOS::Msdp::SubscribeCallback(OHOS::Msdp::MOTION_TYPE_ROTATION, callback);
204 if (ret != 0) {
205 return;
206 }
207 motionEventCallback_ = callback;
208 isMotionSensorSubscribed_ = true;
209 }
210
UnsubscribeMotionSensor()211 void MotionSubscriber::UnsubscribeMotionSensor()
212 {
213 if (!isMotionSensorSubscribed_) {
214 WLOGFI("dms: Unsubscribe motion sensor");
215 return;
216 }
217 int32_t ret = OHOS::Msdp::UnsubscribeCallback(OHOS::Msdp::MOTION_TYPE_ROTATION, motionEventCallback_);
218 if (ret != 0) {
219 return;
220 }
221 isMotionSensorSubscribed_ = false;
222 }
223
OnMotionChanged(const MotionEvent & motionData)224 void RotationMotionEventCallback::OnMotionChanged(const MotionEvent& motionData)
225 {
226 DeviceRotation motionRotation = DeviceRotation::INVALID;
227 switch (motionData.status) {
228 case MOTION_ACTION_PORTRAIT: {
229 motionRotation = DeviceRotation::ROTATION_PORTRAIT;
230 break;
231 }
232 case MOTION_ACTION_LEFT_LANDSCAPE: {
233 motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ?
234 DeviceRotation::ROTATION_LANDSCAPE_INVERTED : DeviceRotation::ROTATION_LANDSCAPE;
235 break;
236 }
237 case MOTION_ACTION_PORTRAIT_INVERTED: {
238 motionRotation = DeviceRotation::ROTATION_PORTRAIT_INVERTED;
239 break;
240 }
241 case MOTION_ACTION_RIGHT_LANDSCAPE: {
242 motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ?
243 DeviceRotation::ROTATION_LANDSCAPE : DeviceRotation::ROTATION_LANDSCAPE_INVERTED;
244 break;
245 }
246 default: {
247 break;
248 }
249 }
250 ScreenRotationController::HandleSensorEventInput(motionRotation);
251 }
252 #endif
253 } // Rosen
254 } // OHOS