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