• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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