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 23namespace OHOS { 24namespace Rosen { 25namespace { 26constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "SensorConnector"}; 27 28#ifdef SENSOR_ENABLE 29 constexpr int64_t ORIENTATION_SENSOR_SAMPLING_RATE = 200000000; // 200ms 30 constexpr int64_t ORIENTATION_SENSOR_REPORTING_RATE = 0; 31 constexpr long ORIENTATION_SENSOR_CALLBACK_TIME_INTERVAL = 200; // 200ms 32 constexpr int VALID_INCLINATION_ANGLE_THRESHOLD_COEFFICIENT = 3; 33#endif 34 35#ifdef WM_SUBSCRIBE_MOTION_ENABLE 36 constexpr int32_t MOTION_ACTION_PORTRAIT = 0; 37 constexpr int32_t MOTION_ACTION_LEFT_LANDSCAPE = 1; 38 constexpr int32_t MOTION_ACTION_PORTRAIT_INVERTED = 2; 39 constexpr int32_t MOTION_ACTION_RIGHT_LANDSCAPE = 3; 40#endif 41} 42 43#ifdef SENSOR_ENABLE 44bool GravitySensorSubscriber::isGravitySensorSubscribed_ = false; 45SensorUser GravitySensorSubscriber::user_; 46long GravitySensorSubscriber::lastCallbackTime_ = 0; 47#endif 48 49#ifdef WM_SUBSCRIBE_MOTION_ENABLE 50bool MotionSubscriber::isMotionSensorSubscribed_ = false; 51sptr<RotationMotionEventCallback> MotionSubscriber::motionEventCallback_ = nullptr; 52#endif 53 54void SensorConnector::SubscribeRotationSensor() 55{ 56 WLOGFD("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 70void 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 83void GravitySensorSubscriber::SubscribeGravitySensor() 84{ 85 WLOGFI("dms: Subscribe gravity Sensor"); 86 if (isGravitySensorSubscribed_) { 87 WLOGFE("dms: gravity sensor's already subscribed"); 88 return; 89 } 90 if (strcpy_s(user_.name, sizeof(user_.name), "ScreenRotationController") != EOK) { 91 WLOGFE("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 WLOGFE("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 WLOGFE("dms: Activate gravity sensor failed"); 104 return; 105 } 106 isGravitySensorSubscribed_ = true; 107} 108 109void GravitySensorSubscriber::UnsubscribeGravitySensor() 110{ 111 WLOGFI("dms: Unsubscribe gravity Sensor"); 112 if (!isGravitySensorSubscribed_) { 113 WLOGFE("dms: Orientation Sensor is not subscribed"); 114 return; 115 } 116 if (DeactivateSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) { 117 WLOGFE("dms: Deactivate gravity sensor failed"); 118 return; 119 } 120 if (UnsubscribeSensor(SENSOR_TYPE_ID_GRAVITY, &user_) != 0) { 121 WLOGFE("dms: Unsubscribe gravity sensor failed"); 122 return; 123 } 124 isGravitySensorSubscribed_ = false; 125} 126 127void GravitySensorSubscriber::HandleGravitySensorEventCallback(SensorEvent *event) 128{ 129 if (!CheckCallbackTimeInterval() || event == nullptr) { 130 return; 131 } 132 if (event->sensorTypeId != SENSOR_TYPE_ID_GRAVITY) { 133 WLOGE("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 143SensorRotation 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 159int 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 177bool 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 192void MotionSubscriber::SubscribeMotionSensor() 193{ 194 WLOGFD("dms: Subscribe motion Sensor"); 195 if (isMotionSensorSubscribed_) { 196 WLOGFE("dms: motion sensor's already subscribed"); 197 return; 198 } 199 sptr<RotationMotionEventCallback> callback = new (std::nothrow) RotationMotionEventCallback(); 200 if (callback == nullptr) { 201 return; 202 } 203 int32_t ret = OHOS::Msdp::SubscribeCallback(OHOS::Msdp::MOTION_TYPE_ROTATION, callback); 204 if (ret != 0) { 205 return; 206 } 207 motionEventCallback_ = callback; 208 isMotionSensorSubscribed_ = true; 209} 210 211void MotionSubscriber::UnsubscribeMotionSensor() 212{ 213 if (!isMotionSensorSubscribed_) { 214 WLOGFI("dms: Unsubscribe motion sensor"); 215 return; 216 } 217 int32_t ret = OHOS::Msdp::UnsubscribeCallback(OHOS::Msdp::MOTION_TYPE_ROTATION, motionEventCallback_); 218 if (ret != 0) { 219 return; 220 } 221 isMotionSensorSubscribed_ = false; 222} 223 224void RotationMotionEventCallback::OnMotionChanged(const MotionEvent& motionData) 225{ 226 DeviceRotation motionRotation = DeviceRotation::INVALID; 227 switch (motionData.status) { 228 case MOTION_ACTION_PORTRAIT: { 229 motionRotation = DeviceRotation::ROTATION_PORTRAIT; 230 break; 231 } 232 case MOTION_ACTION_LEFT_LANDSCAPE: { 233 motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ? 234 DeviceRotation::ROTATION_LANDSCAPE_INVERTED : DeviceRotation::ROTATION_LANDSCAPE; 235 break; 236 } 237 case MOTION_ACTION_PORTRAIT_INVERTED: { 238 motionRotation = DeviceRotation::ROTATION_PORTRAIT_INVERTED; 239 break; 240 } 241 case MOTION_ACTION_RIGHT_LANDSCAPE: { 242 motionRotation = ScreenRotationController::IsDefaultDisplayRotationPortrait() ? 243 DeviceRotation::ROTATION_LANDSCAPE : DeviceRotation::ROTATION_LANDSCAPE_INVERTED; 244 break; 245 } 246 default: { 247 break; 248 } 249 } 250 ScreenRotationController::HandleSensorEventInput(motionRotation); 251} 252#endif 253} // Rosen 254} // OHOS