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