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
27 #ifdef SENSOR_ENABLE
28 constexpr int64_t ORIENTATION_SENSOR_SAMPLING_RATE = 200000000; // 200ms
29 constexpr int64_t ORIENTATION_SENSOR_REPORTING_RATE = 0;
30 constexpr long ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL = 200; // 200ms
31 constexpr int VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT = 3;
32 #endif
33
34 #ifdef WM_SUBSCRIBE_MOTION_ENABLE
35 constexpr int32_t MOTION_ACTION_PORTRAIT = 0;
36 constexpr int32_t MOTION_ACTION_LEFT_LANDSCAPE = 1;
37 constexpr int32_t MOTION_ACTION_PORTRAIT_INVERTED = 2;
38 constexpr int32_t MOTION_ACTION_RIGHT_LANDSCAPE = 3;
39 const int32_t MOTION_TYPE_ROTATION = 700;
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 static void RotationMotionEventCallback(const MotionSensorEvent& motionData);
52 #endif
53
SubscribeRotationSensor()54 void SensorConnector::SubscribeRotationSensor()
55 {
56 TLOGD(WmsLogTag::DMS, "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 TLOGI(WmsLogTag::DMS, "dms: Subscribe gravity Sensor");
86 if (isGravitySensorSubscribed_) {
87 TLOGE(WmsLogTag::DMS, "dms: gravity sensor's already subscribed");
88 return;
89 }
90 if (strcpy_s(user_.name, sizeof(user_.name), "ScreenRotationController") != EOK) {
91 TLOGE(WmsLogTag::DMS, "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 TLOGE(WmsLogTag::DMS, "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 TLOGE(WmsLogTag::DMS, "dms: Activate gravity sensor failed");
104 return;
105 }
106 isGravitySensorSubscribed_ = true;
107 }
108
UnsubscribeGravitySensor()109 void GravitySensorSubscriber::UnsubscribeGravitySensor()
110 {
111 TLOGI(WmsLogTag::DMS, "dms: Unsubscribe gravity Sensor");
112 if (!isGravitySensorSubscribed_) {
113 TLOGE(WmsLogTag::DMS, "dms: Orientation Sensor is not subscribed");
114 return;
115 }
116 if (DeactivateSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
117 TLOGE(WmsLogTag::DMS, "dms: Deactivate gravity sensor failed");
118 return;
119 }
120 if (UnsubscribeSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
121 TLOGE(WmsLogTag::DMS, "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 TLOGE(WmsLogTag::DMS, "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 TLOGD(WmsLogTag::DMS, "dms: Subscribe motion Sensor");
195 if (isMotionSensorSubscribed_) {
196 TLOGE(WmsLogTag::DMS, "dms: motion sensor's already subscribed");
197 return;
198 }
199 if (!SubscribeCallback(MOTION_TYPE_ROTATION, RotationMotionEventCallback)) {
200 TLOGE(WmsLogTag::DMS, "dms: motion sensor subscribe failed");
201 return;
202 }
203 isMotionSensorSubscribed_ = true;
204 }
205
UnsubscribeMotionSensor()206 void MotionSubscriber::UnsubscribeMotionSensor()
207 {
208 if (!isMotionSensorSubscribed_) {
209 TLOGI(WmsLogTag::DMS, "dms: Unsubscribe motion sensor");
210 return;
211 }
212 if (!UnsubscribeCallback(MOTION_TYPE_ROTATION, RotationMotionEventCallback)) {
213 TLOGE(WmsLogTag::DMS, "dms: motion sensor unsubscribe failed");
214 return;
215 }
216 isMotionSensorSubscribed_ = false;
217 }
218
RotationMotionEventCallback(const MotionSensorEvent & motionData)219 void RotationMotionEventCallback(const MotionSensorEvent& motionData)
220 {
221 DeviceRotation motionRotation = DeviceRotation::INVALID;
222 switch (motionData.status) {
223 case MOTION_ACTION_PORTRAIT: {
224 motionRotation = DeviceRotation::ROTATION_PORTRAIT;
225 break;
226 }
227 case MOTION_ACTION_LEFT_LANDSCAPE: {
228 motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ?
229 DeviceRotation::ROTATION_LANDSCAPE_INVERTED : DeviceRotation::ROTATION_LANDSCAPE;
230 break;
231 }
232 case MOTION_ACTION_PORTRAIT_INVERTED: {
233 motionRotation = DeviceRotation::ROTATION_PORTRAIT_INVERTED;
234 break;
235 }
236 case MOTION_ACTION_RIGHT_LANDSCAPE: {
237 motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ?
238 DeviceRotation::ROTATION_LANDSCAPE : DeviceRotation::ROTATION_LANDSCAPE_INVERTED;
239 break;
240 }
241 default: {
242 break;
243 }
244 }
245 ScreenRotationController::HandleSensorEventInput(motionRotation);
246 }
247 #endif
248 } // Rosen
249 } // OHOS