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