• 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 
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