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