• 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() || event == nullptr) {
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     if (gravityData == nullptr) {
149         return -1;
150     }
151     float x = gravityData->x;
152     float y = gravityData->y;
153     float z = gravityData->z;
154     int degree = -1;
155     if ((x * x + y * y) * VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT < z * z) {
156         return degree;
157     }
158     // arccotx = pi / 2 - arctanx, 90 is used to calculate acot(in degree); degree = rad / pi * 180
159     degree = 90 - static_cast<int>(round(atan2(y, -x) / M_PI * 180));
160     // Normalize the degree to the range of 0~360
161     return degree >= 0 ? degree % 360 : degree % 360 + 360;
162 }
163 
CheckCallbackTimeInterval()164 bool GravitySensorSubscriber::CheckCallbackTimeInterval()
165 {
166     std::chrono::milliseconds ms = std::chrono::time_point_cast<std::chrono::milliseconds>(
167         std::chrono::steady_clock::now()).time_since_epoch();
168     long currentTimeInMillitm = ms.count();
169     if (currentTimeInMillitm - lastCallbackTime_ < ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL) {
170         return false;
171     }
172     lastCallbackTime_ = currentTimeInMillitm;
173     return true;
174 }
175 
176 // Motion
177 #ifdef WM_SUBSCRIBE_MOTION_ENABLE
SubscribeMotionSensor()178 void MotionSubscriber::SubscribeMotionSensor()
179 {
180     WLOGFI("dms: Subscribe motion Sensor");
181     if (isMotionSensorSubscribed_) {
182         WLOGFE("dms: motion sensor's already subscribed");
183         return;
184     }
185     sptr<RotationMotionEventCallback> callback = new (std::nothrow) RotationMotionEventCallback();
186     if (callback == nullptr) {
187         return;
188     }
189     int32_t ret = OHOS::Msdp::SubscribeCallback(OHOS::Msdp::MOTION_TYPE_ROTATION, callback);
190     if (ret != 0) {
191         return;
192     }
193     motionEventCallback_ = callback;
194     isMotionSensorSubscribed_ = true;
195 }
196 
UnsubscribeMotionSensor()197 void MotionSubscriber::UnsubscribeMotionSensor()
198 {
199     if (!isMotionSensorSubscribed_) {
200         WLOGFI("dms: Unsubscribe motion sensor");
201         return;
202     }
203     int32_t ret = OHOS::Msdp::UnsubscribeCallback(OHOS::Msdp::MOTION_TYPE_ROTATION, motionEventCallback_);
204     if (ret != 0) {
205         return;
206     }
207     isMotionSensorSubscribed_ = false;
208 }
209 
OnMotionChanged(const MotionEvent & motionData)210 void RotationMotionEventCallback::OnMotionChanged(const MotionEvent& motionData)
211 {
212     DeviceRotation motionRotation = DeviceRotation::INVALID;
213     switch (motionData.status) {
214         case MOTION_ACTION_PORTRAIT: {
215             motionRotation = DeviceRotation::ROTATION_PORTRAIT;
216             break;
217         }
218         case MOTION_ACTION_LEFT_LANDSCAPE: {
219             motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ?
220                 DeviceRotation::ROTATION_LANDSCAPE_INVERTED : DeviceRotation::ROTATION_LANDSCAPE;
221             break;
222         }
223         case MOTION_ACTION_PORTRAIT_INVERTED: {
224             motionRotation = DeviceRotation::ROTATION_PORTRAIT_INVERTED;
225             break;
226         }
227         case MOTION_ACTION_RIGHT_LANDSCAPE: {
228             motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ?
229                 DeviceRotation::ROTATION_LANDSCAPE : DeviceRotation::ROTATION_LANDSCAPE_INVERTED;
230             break;
231         }
232         default: {
233             break;
234         }
235     }
236     ScreenRotationController::HandleSensorEventInput(motionRotation);
237 }
238 #endif
239 } // Rosen
240 } // OHOS