1e0dac50fSopenharmony_ci/*
2e0dac50fSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3e0dac50fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e0dac50fSopenharmony_ci * you may not use this file except in compliance with the License.
5e0dac50fSopenharmony_ci * You may obtain a copy of the License at
6e0dac50fSopenharmony_ci *
7e0dac50fSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e0dac50fSopenharmony_ci *
9e0dac50fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e0dac50fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e0dac50fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0dac50fSopenharmony_ci * See the License for the specific language governing permissions and
13e0dac50fSopenharmony_ci * limitations under the License.
14e0dac50fSopenharmony_ci */
15e0dac50fSopenharmony_ci
16e0dac50fSopenharmony_ci#include "sensor_connector.h"
17e0dac50fSopenharmony_ci
18e0dac50fSopenharmony_ci#include <chrono>
19e0dac50fSopenharmony_ci#include <securec.h>
20e0dac50fSopenharmony_ci
21e0dac50fSopenharmony_ci#include "display_manager_service_inner.h"
22e0dac50fSopenharmony_ci
23e0dac50fSopenharmony_cinamespace OHOS {
24e0dac50fSopenharmony_cinamespace Rosen {
25e0dac50fSopenharmony_cinamespace {
26e0dac50fSopenharmony_ciconstexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SensorConnector"};
27e0dac50fSopenharmony_ci
28e0dac50fSopenharmony_ci#ifdef SENSOR_ENABLE
29e0dac50fSopenharmony_ci    constexpr int64_t ORIENTATION_SENSOR_SAMPLING_RATE = 200000000; // 200ms
30e0dac50fSopenharmony_ci    constexpr int64_t ORIENTATION_SENSOR_REPORTING_RATE = 0;
31e0dac50fSopenharmony_ci    constexpr long ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL = 200; // 200ms
32e0dac50fSopenharmony_ci    constexpr int VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT = 3;
33e0dac50fSopenharmony_ci#endif
34e0dac50fSopenharmony_ci
35e0dac50fSopenharmony_ci#ifdef WM_SUBSCRIBE_MOTION_ENABLE
36e0dac50fSopenharmony_ci    constexpr int32_t MOTION_ACTION_PORTRAIT = 0;
37e0dac50fSopenharmony_ci    constexpr int32_t MOTION_ACTION_LEFT_LANDSCAPE = 1;
38e0dac50fSopenharmony_ci    constexpr int32_t MOTION_ACTION_PORTRAIT_INVERTED = 2;
39e0dac50fSopenharmony_ci    constexpr int32_t MOTION_ACTION_RIGHT_LANDSCAPE = 3;
40e0dac50fSopenharmony_ci#endif
41e0dac50fSopenharmony_ci}
42e0dac50fSopenharmony_ci
43e0dac50fSopenharmony_ci#ifdef SENSOR_ENABLE
44e0dac50fSopenharmony_cibool GravitySensorSubscriber::isGravitySensorSubscribed_ = false;
45e0dac50fSopenharmony_ciSensorUser GravitySensorSubscriber::user_;
46e0dac50fSopenharmony_cilong GravitySensorSubscriber::lastCallbackTime_ = 0;
47e0dac50fSopenharmony_ci#endif
48e0dac50fSopenharmony_ci
49e0dac50fSopenharmony_ci#ifdef WM_SUBSCRIBE_MOTION_ENABLE
50e0dac50fSopenharmony_cibool MotionSubscriber::isMotionSensorSubscribed_ = false;
51e0dac50fSopenharmony_cisptr<RotationMotionEventCallback> MotionSubscriber::motionEventCallback_ = nullptr;
52e0dac50fSopenharmony_ci#endif
53e0dac50fSopenharmony_ci
54e0dac50fSopenharmony_civoid SensorConnector::SubscribeRotationSensor()
55e0dac50fSopenharmony_ci{
56e0dac50fSopenharmony_ci    WLOGFD("dms: subscribe rotation-related sensor");
57e0dac50fSopenharmony_ci    ScreenRotationController::Init();
58e0dac50fSopenharmony_ci#ifdef WM_SUBSCRIBE_MOTION_ENABLE
59e0dac50fSopenharmony_ci    MotionSubscriber::SubscribeMotionSensor();
60e0dac50fSopenharmony_ci    if (MotionSubscriber::isMotionSensorSubscribed_) {
61e0dac50fSopenharmony_ci        return;
62e0dac50fSopenharmony_ci    }
63e0dac50fSopenharmony_ci#endif
64e0dac50fSopenharmony_ci
65e0dac50fSopenharmony_ci#ifdef SENSOR_ENABLE
66e0dac50fSopenharmony_ci    GravitySensorSubscriber::SubscribeGravitySensor();
67e0dac50fSopenharmony_ci#endif
68e0dac50fSopenharmony_ci}
69e0dac50fSopenharmony_ci
70e0dac50fSopenharmony_civoid SensorConnector::UnsubscribeRotationSensor()
71e0dac50fSopenharmony_ci{
72e0dac50fSopenharmony_ci#ifdef WM_SUBSCRIBE_MOTION_ENABLE
73e0dac50fSopenharmony_ci    MotionSubscriber::UnsubscribeMotionSensor();
74e0dac50fSopenharmony_ci#endif
75e0dac50fSopenharmony_ci
76e0dac50fSopenharmony_ci#ifdef SENSOR_ENABLE
77e0dac50fSopenharmony_ci    GravitySensorSubscriber::UnsubscribeGravitySensor();
78e0dac50fSopenharmony_ci#endif
79e0dac50fSopenharmony_ci}
80e0dac50fSopenharmony_ci
81e0dac50fSopenharmony_ci// Gravity Sensor
82e0dac50fSopenharmony_ci#ifdef SENSOR_ENABLE
83e0dac50fSopenharmony_civoid GravitySensorSubscriber::SubscribeGravitySensor()
84e0dac50fSopenharmony_ci{
85e0dac50fSopenharmony_ci    WLOGFI("dms: Subscribe gravity Sensor");
86e0dac50fSopenharmony_ci    if (isGravitySensorSubscribed_) {
87e0dac50fSopenharmony_ci        WLOGFE("dms: gravity sensor's already subscribed");
88e0dac50fSopenharmony_ci        return;
89e0dac50fSopenharmony_ci    }
90e0dac50fSopenharmony_ci    if (strcpy_s(user_.name, sizeof(user_.name), "ScreenRotationController") != EOK) {
91e0dac50fSopenharmony_ci        WLOGFE("dms strcpy_s error");
92e0dac50fSopenharmony_ci        return;
93e0dac50fSopenharmony_ci    }
94e0dac50fSopenharmony_ci    user_.userData = nullptr;
95e0dac50fSopenharmony_ci    user_.callback = &HandleGravitySensorEventCallback;
96e0dac50fSopenharmony_ci    if (SubscribeSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
97e0dac50fSopenharmony_ci        WLOGFE("dms: Subscribe gravity sensor failed");
98e0dac50fSopenharmony_ci        return;
99e0dac50fSopenharmony_ci    }
100e0dac50fSopenharmony_ci    SetBatch(SENSOR_TYPE_ID_GRAVITY, &user_, ORIENTATION_SENSOR_SAMPLING_RATE, ORIENTATION_SENSOR_REPORTING_RATE);
101e0dac50fSopenharmony_ci    SetMode(SENSOR_TYPE_ID_GRAVITY, &user_, SENSOR_ON_CHANGE);
102e0dac50fSopenharmony_ci    if (ActivateSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
103e0dac50fSopenharmony_ci        WLOGFE("dms: Activate gravity sensor failed");
104e0dac50fSopenharmony_ci        return;
105e0dac50fSopenharmony_ci    }
106e0dac50fSopenharmony_ci    isGravitySensorSubscribed_ = true;
107e0dac50fSopenharmony_ci}
108e0dac50fSopenharmony_ci
109e0dac50fSopenharmony_civoid GravitySensorSubscriber::UnsubscribeGravitySensor()
110e0dac50fSopenharmony_ci{
111e0dac50fSopenharmony_ci    WLOGFI("dms: Unsubscribe gravity Sensor");
112e0dac50fSopenharmony_ci    if (!isGravitySensorSubscribed_) {
113e0dac50fSopenharmony_ci        WLOGFE("dms: Orientation Sensor is not subscribed");
114e0dac50fSopenharmony_ci        return;
115e0dac50fSopenharmony_ci    }
116e0dac50fSopenharmony_ci    if (DeactivateSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
117e0dac50fSopenharmony_ci        WLOGFE("dms: Deactivate gravity sensor failed");
118e0dac50fSopenharmony_ci        return;
119e0dac50fSopenharmony_ci    }
120e0dac50fSopenharmony_ci    if (UnsubscribeSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) {
121e0dac50fSopenharmony_ci        WLOGFE("dms: Unsubscribe gravity sensor failed");
122e0dac50fSopenharmony_ci        return;
123e0dac50fSopenharmony_ci    }
124e0dac50fSopenharmony_ci    isGravitySensorSubscribed_ = false;
125e0dac50fSopenharmony_ci}
126e0dac50fSopenharmony_ci
127e0dac50fSopenharmony_civoid GravitySensorSubscriber::HandleGravitySensorEventCallback(SensorEvent *event)
128e0dac50fSopenharmony_ci{
129e0dac50fSopenharmony_ci    if (!CheckCallbackTimeInterval() || event == nullptr) {
130e0dac50fSopenharmony_ci        return;
131e0dac50fSopenharmony_ci    }
132e0dac50fSopenharmony_ci    if (event->sensorTypeId != SENSOR_TYPE_ID_GRAVITY) {
133e0dac50fSopenharmony_ci        WLOGE("dms: Orientation Sensor Callback is not SENSOR_TYPE_ID_GRAVITY");
134e0dac50fSopenharmony_ci        return;
135e0dac50fSopenharmony_ci    }
136e0dac50fSopenharmony_ci    GravityData* gravityData = reinterpret_cast<GravityData*>(event->data);
137e0dac50fSopenharmony_ci    int sensorDegree = CalcRotationDegree(gravityData);
138e0dac50fSopenharmony_ci    DeviceRotation sensorRotationConverted = ScreenRotationController::ConvertSensorToDeviceRotation(
139e0dac50fSopenharmony_ci        CalcSensorRotation(sensorDegree));
140e0dac50fSopenharmony_ci    ScreenRotationController::HandleSensorEventInput(sensorRotationConverted);
141e0dac50fSopenharmony_ci}
142e0dac50fSopenharmony_ci
143e0dac50fSopenharmony_ciSensorRotation GravitySensorSubscriber::CalcSensorRotation(int sensorDegree)
144e0dac50fSopenharmony_ci{
145e0dac50fSopenharmony_ci    // Use ROTATION_0 when degree range is [0, 30]∪[330, 359]
146e0dac50fSopenharmony_ci    if (sensorDegree >= 0 && (sensorDegree <= 30 || sensorDegree >= 330)) {
147e0dac50fSopenharmony_ci        return SensorRotation::ROTATION_0;
148e0dac50fSopenharmony_ci    } else if (sensorDegree >= 60 && sensorDegree <= 120) { // Use ROTATION_90 when degree range is [60, 120]
149e0dac50fSopenharmony_ci        return SensorRotation::ROTATION_90;
150e0dac50fSopenharmony_ci    } else if (sensorDegree >= 150 && sensorDegree <= 210) { // Use ROTATION_180 when degree range is [150, 210]
151e0dac50fSopenharmony_ci        return SensorRotation::ROTATION_180;
152e0dac50fSopenharmony_ci    } else if (sensorDegree >= 240 && sensorDegree <= 300) { // Use ROTATION_270 when degree range is [240, 300]
153e0dac50fSopenharmony_ci        return SensorRotation::ROTATION_270;
154e0dac50fSopenharmony_ci    } else {
155e0dac50fSopenharmony_ci        return SensorRotation::INVALID;
156e0dac50fSopenharmony_ci    }
157e0dac50fSopenharmony_ci}
158e0dac50fSopenharmony_ci
159e0dac50fSopenharmony_ciint GravitySensorSubscriber::CalcRotationDegree(GravityData* gravityData)
160e0dac50fSopenharmony_ci{
161e0dac50fSopenharmony_ci    if (gravityData == nullptr) {
162e0dac50fSopenharmony_ci        return -1;
163e0dac50fSopenharmony_ci    }
164e0dac50fSopenharmony_ci    float x = gravityData->x;
165e0dac50fSopenharmony_ci    float y = gravityData->y;
166e0dac50fSopenharmony_ci    float z = gravityData->z;
167e0dac50fSopenharmony_ci    int degree = -1;
168e0dac50fSopenharmony_ci    if ((x * x + y * y) * VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT < z * z) {
169e0dac50fSopenharmony_ci        return degree;
170e0dac50fSopenharmony_ci    }
171e0dac50fSopenharmony_ci    // arccotx = pi / 2 - arctanx, 90 is used to calculate acot(in degree); degree = rad / pi * 180
172e0dac50fSopenharmony_ci    degree = 90 - static_cast<int>(round(atan2(y, -x) / M_PI * 180));
173e0dac50fSopenharmony_ci    // Normalize the degree to the range of 0~360
174e0dac50fSopenharmony_ci    return degree >= 0 ? degree % 360 : degree % 360 + 360;
175e0dac50fSopenharmony_ci}
176e0dac50fSopenharmony_ci
177e0dac50fSopenharmony_cibool GravitySensorSubscriber::CheckCallbackTimeInterval()
178e0dac50fSopenharmony_ci{
179e0dac50fSopenharmony_ci    std::chrono::milliseconds ms = std::chrono::time_point_cast<std::chrono::milliseconds>(
180e0dac50fSopenharmony_ci        std::chrono::steady_clock::now()).time_since_epoch();
181e0dac50fSopenharmony_ci    long currentTimeInMillitm = ms.count();
182e0dac50fSopenharmony_ci    if (currentTimeInMillitm - lastCallbackTime_ < ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL) {
183e0dac50fSopenharmony_ci        return false;
184e0dac50fSopenharmony_ci    }
185e0dac50fSopenharmony_ci    lastCallbackTime_ = currentTimeInMillitm;
186e0dac50fSopenharmony_ci    return true;
187e0dac50fSopenharmony_ci}
188e0dac50fSopenharmony_ci#endif
189e0dac50fSopenharmony_ci
190e0dac50fSopenharmony_ci// Motion
191e0dac50fSopenharmony_ci#ifdef WM_SUBSCRIBE_MOTION_ENABLE
192e0dac50fSopenharmony_civoid MotionSubscriber::SubscribeMotionSensor()
193e0dac50fSopenharmony_ci{
194e0dac50fSopenharmony_ci    WLOGFD("dms: Subscribe motion Sensor");
195e0dac50fSopenharmony_ci    if (isMotionSensorSubscribed_) {
196e0dac50fSopenharmony_ci        WLOGFE("dms: motion sensor's already subscribed");
197e0dac50fSopenharmony_ci        return;
198e0dac50fSopenharmony_ci    }
199e0dac50fSopenharmony_ci    sptr<RotationMotionEventCallback> callback = new (std::nothrow) RotationMotionEventCallback();
200e0dac50fSopenharmony_ci    if (callback == nullptr) {
201e0dac50fSopenharmony_ci        return;
202e0dac50fSopenharmony_ci    }
203e0dac50fSopenharmony_ci    int32_t ret = OHOS::Msdp::SubscribeCallback(OHOS::Msdp::MOTION_TYPE_ROTATION, callback);
204e0dac50fSopenharmony_ci    if (ret != 0) {
205e0dac50fSopenharmony_ci        return;
206e0dac50fSopenharmony_ci    }
207e0dac50fSopenharmony_ci    motionEventCallback_ = callback;
208e0dac50fSopenharmony_ci    isMotionSensorSubscribed_ = true;
209e0dac50fSopenharmony_ci}
210e0dac50fSopenharmony_ci
211e0dac50fSopenharmony_civoid MotionSubscriber::UnsubscribeMotionSensor()
212e0dac50fSopenharmony_ci{
213e0dac50fSopenharmony_ci    if (!isMotionSensorSubscribed_) {
214e0dac50fSopenharmony_ci        WLOGFI("dms: Unsubscribe motion sensor");
215e0dac50fSopenharmony_ci        return;
216e0dac50fSopenharmony_ci    }
217e0dac50fSopenharmony_ci    int32_t ret = OHOS::Msdp::UnsubscribeCallback(OHOS::Msdp::MOTION_TYPE_ROTATION, motionEventCallback_);
218e0dac50fSopenharmony_ci    if (ret != 0) {
219e0dac50fSopenharmony_ci        return;
220e0dac50fSopenharmony_ci    }
221e0dac50fSopenharmony_ci    isMotionSensorSubscribed_ = false;
222e0dac50fSopenharmony_ci}
223e0dac50fSopenharmony_ci
224e0dac50fSopenharmony_civoid RotationMotionEventCallback::OnMotionChanged(const MotionEvent& motionData)
225e0dac50fSopenharmony_ci{
226e0dac50fSopenharmony_ci    DeviceRotation motionRotation = DeviceRotation::INVALID;
227e0dac50fSopenharmony_ci    switch (motionData.status) {
228e0dac50fSopenharmony_ci        case MOTION_ACTION_PORTRAIT: {
229e0dac50fSopenharmony_ci            motionRotation = DeviceRotation::ROTATION_PORTRAIT;
230e0dac50fSopenharmony_ci            break;
231e0dac50fSopenharmony_ci        }
232e0dac50fSopenharmony_ci        case MOTION_ACTION_LEFT_LANDSCAPE: {
233e0dac50fSopenharmony_ci            motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ?
234e0dac50fSopenharmony_ci                DeviceRotation::ROTATION_LANDSCAPE_INVERTED : DeviceRotation::ROTATION_LANDSCAPE;
235e0dac50fSopenharmony_ci            break;
236e0dac50fSopenharmony_ci        }
237e0dac50fSopenharmony_ci        case MOTION_ACTION_PORTRAIT_INVERTED: {
238e0dac50fSopenharmony_ci            motionRotation = DeviceRotation::ROTATION_PORTRAIT_INVERTED;
239e0dac50fSopenharmony_ci            break;
240e0dac50fSopenharmony_ci        }
241e0dac50fSopenharmony_ci        case MOTION_ACTION_RIGHT_LANDSCAPE: {
242e0dac50fSopenharmony_ci            motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ?
243e0dac50fSopenharmony_ci                DeviceRotation::ROTATION_LANDSCAPE : DeviceRotation::ROTATION_LANDSCAPE_INVERTED;
244e0dac50fSopenharmony_ci            break;
245e0dac50fSopenharmony_ci        }
246e0dac50fSopenharmony_ci        default: {
247e0dac50fSopenharmony_ci            break;
248e0dac50fSopenharmony_ci        }
249e0dac50fSopenharmony_ci    }
250e0dac50fSopenharmony_ci    ScreenRotationController::HandleSensorEventInput(motionRotation);
251e0dac50fSopenharmony_ci}
252e0dac50fSopenharmony_ci#endif
253e0dac50fSopenharmony_ci} // Rosen
254e0dac50fSopenharmony_ci} // OHOS