• 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 "screen_rotation_controller.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 
26 DisplayId ScreenRotationController::defaultDisplayId_ = 0;
27 Rotation ScreenRotationController::currentDisplayRotation_;
28 bool ScreenRotationController::isScreenRotationLocked_ = true;
29 uint32_t ScreenRotationController::defaultDeviceRotationOffset_ = 0;
30 Orientation ScreenRotationController::lastOrientationType_ = Orientation::UNSPECIFIED;
31 Rotation ScreenRotationController::lastSensorDecidedRotation_;
32 Rotation ScreenRotationController::rotationLockedRotation_;
33 uint32_t ScreenRotationController::defaultDeviceRotation_ = 0;
34 std::map<SensorRotation, DeviceRotation> ScreenRotationController::sensorToDeviceRotationMap_;
35 std::map<DeviceRotation, Rotation> ScreenRotationController::deviceToDisplayRotationMap_;
36 std::map<Rotation, DisplayOrientation> ScreenRotationController::displayToDisplayOrientationMap_;
37 DeviceRotation ScreenRotationController::lastSensorRotationConverted_ = DeviceRotation::INVALID;
38 
Init()39 void ScreenRotationController::Init()
40 {
41     ProcessRotationMapping();
42     currentDisplayRotation_ = GetCurrentDisplayRotation();
43     defaultDisplayId_ = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId();
44     if (defaultDisplayId_  == DISPLAY_ID_INVALID) {
45         TLOGE(WmsLogTag::DMS, "defaultDisplayId_ is invalid");
46     }
47     lastSensorDecidedRotation_ = currentDisplayRotation_;
48     rotationLockedRotation_ = currentDisplayRotation_;
49 }
50 
IsScreenRotationLocked()51 bool ScreenRotationController::IsScreenRotationLocked()
52 {
53     return isScreenRotationLocked_;
54 }
55 
SetScreenRotationLocked(bool isLocked)56 DMError ScreenRotationController::SetScreenRotationLocked(bool isLocked)
57 {
58     isScreenRotationLocked_ = isLocked;
59     if (isLocked) {
60         rotationLockedRotation_ = GetCurrentDisplayRotation();
61         return DMError::DM_OK;
62     }
63     if (GetCurrentDisplayRotation() == ConvertDeviceToDisplayRotation(lastSensorRotationConverted_)) {
64         return DMError::DM_OK;
65     }
66     Orientation currentOrientation = GetPreferredOrientation();
67     if (IsSensorRelatedOrientation(currentOrientation)) {
68         ProcessSwitchToSensorRelatedOrientation(currentOrientation, lastSensorRotationConverted_);
69     }
70     return DMError::DM_OK;
71 }
72 
SetDefaultDeviceRotationOffset(uint32_t defaultDeviceRotationOffset)73 void ScreenRotationController::SetDefaultDeviceRotationOffset(uint32_t defaultDeviceRotationOffset)
74 {
75     // Available options for defaultDeviceRotationOffset: {0, 90, 180, 270}
76     if (defaultDeviceRotationOffset < 0 || defaultDeviceRotationOffset > 270 || defaultDeviceRotationOffset % 90 != 0) {
77         return;
78     }
79     defaultDeviceRotationOffset_ = defaultDeviceRotationOffset;
80 }
81 
HandleSensorEventInput(DeviceRotation deviceRotation)82 void ScreenRotationController::HandleSensorEventInput(DeviceRotation deviceRotation)
83 {
84     if (deviceRotation == DeviceRotation::INVALID) {
85         TLOGW(WmsLogTag::DMS, "deviceRotation is invalid, return.");
86         return;
87     }
88     Orientation orientation = GetPreferredOrientation();
89     currentDisplayRotation_ = GetCurrentDisplayRotation();
90     lastSensorRotationConverted_ = deviceRotation;
91     if (!IsSensorRelatedOrientation(orientation)) {
92         TLOGD(WmsLogTag::DMS, "If the current preferred orientation is locked or sensor-independent, return.");
93         return;
94     }
95 
96     if (currentDisplayRotation_ == ConvertDeviceToDisplayRotation(deviceRotation)) {
97         TLOGD(WmsLogTag::DMS, "If the current display rotation is same to sensor rotation, return.");
98         return;
99     }
100     Rotation targetDisplayRotation = CalcTargetDisplayRotation(orientation, deviceRotation);
101     SetScreenRotation(targetDisplayRotation);
102 }
103 
GetCurrentDisplayRotation()104 Rotation ScreenRotationController::GetCurrentDisplayRotation()
105 {
106     sptr<DisplayInfo> defaultDisplayInfo = DisplayManagerServiceInner::GetInstance().GetDefaultDisplay();
107     if (defaultDisplayInfo == nullptr) {
108         TLOGE(WmsLogTag::DMS, "Cannot get default display info");
109         return defaultDeviceRotation_ == 0 ? ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT) :
110             ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE);
111     }
112     return defaultDisplayInfo->GetRotation();
113 }
114 
GetPreferredOrientation()115 Orientation ScreenRotationController::GetPreferredOrientation()
116 {
117     sptr<ScreenInfo> screenInfo = DisplayManagerServiceInner::GetInstance().GetScreenInfoByDisplayId(defaultDisplayId_);
118     if (screenInfo == nullptr) {
119         TLOGE(WmsLogTag::DMS, "Cannot get default screen info");
120         return Orientation::UNSPECIFIED;
121     }
122     return screenInfo->GetOrientation();
123 }
124 
CalcTargetDisplayRotation(Orientation requestedOrientation,DeviceRotation sensorRotationConverted)125 Rotation ScreenRotationController::CalcTargetDisplayRotation(
126     Orientation requestedOrientation, DeviceRotation sensorRotationConverted)
127 {
128     switch (requestedOrientation) {
129         case Orientation::SENSOR: {
130             lastSensorDecidedRotation_ = ConvertDeviceToDisplayRotation(sensorRotationConverted);
131             return lastSensorDecidedRotation_;
132         }
133         case Orientation::SENSOR_VERTICAL: {
134             return ProcessAutoRotationPortraitOrientation(sensorRotationConverted);
135         }
136         case Orientation::SENSOR_HORIZONTAL: {
137             return ProcessAutoRotationLandscapeOrientation(sensorRotationConverted);
138         }
139         case Orientation::AUTO_ROTATION_RESTRICTED: {
140             if (isScreenRotationLocked_) {
141                 return currentDisplayRotation_;
142             }
143             lastSensorDecidedRotation_ = ConvertDeviceToDisplayRotation(sensorRotationConverted);
144             return lastSensorDecidedRotation_;
145         }
146         case Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED: {
147             if (isScreenRotationLocked_) {
148                 return currentDisplayRotation_;
149             }
150             return ProcessAutoRotationPortraitOrientation(sensorRotationConverted);
151         }
152         case Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED: {
153             if (isScreenRotationLocked_) {
154                 return currentDisplayRotation_;
155             }
156             return ProcessAutoRotationLandscapeOrientation(sensorRotationConverted);
157         }
158         default: {
159             return currentDisplayRotation_;
160         }
161     }
162 }
163 
ProcessAutoRotationPortraitOrientation(DeviceRotation sensorRotationConverted)164 Rotation ScreenRotationController::ProcessAutoRotationPortraitOrientation(DeviceRotation sensorRotationConverted)
165 {
166     if (IsDeviceRotationHorizontal(sensorRotationConverted)) {
167         return currentDisplayRotation_;
168     }
169     lastSensorDecidedRotation_ = ConvertDeviceToDisplayRotation(sensorRotationConverted);
170     return lastSensorDecidedRotation_;
171 }
172 
ProcessAutoRotationLandscapeOrientation(DeviceRotation sensorRotationConverted)173 Rotation ScreenRotationController::ProcessAutoRotationLandscapeOrientation(DeviceRotation sensorRotationConverted)
174 {
175     if (IsDeviceRotationVertical(sensorRotationConverted)) {
176         return currentDisplayRotation_;
177     }
178     lastSensorDecidedRotation_ = ConvertDeviceToDisplayRotation(sensorRotationConverted);
179     return lastSensorDecidedRotation_;
180 }
181 
SetScreenRotation(Rotation targetRotation,bool withAnimation)182 void ScreenRotationController::SetScreenRotation(Rotation targetRotation, bool withAnimation)
183 {
184     if (targetRotation == GetCurrentDisplayRotation()) {
185         return;
186     }
187     DisplayManagerServiceInner::GetInstance().GetDefaultDisplay()->SetRotation(targetRotation);
188     DisplayManagerServiceInner::GetInstance().SetRotationFromWindow(defaultDisplayId_, targetRotation, withAnimation);
189     TLOGI(WmsLogTag::DMS, "dms: Set screen rotation: %{public}u withAnimation: %{public}u", targetRotation,
190         withAnimation);
191 }
192 
CalcDeviceRotation(SensorRotation sensorRotation)193 DeviceRotation ScreenRotationController::CalcDeviceRotation(SensorRotation sensorRotation)
194 {
195     if (sensorRotation == SensorRotation::INVALID) {
196         return DeviceRotation::INVALID;
197     }
198     // offset(in degree) divided by 90 to get rotation bias
199     int32_t bias = static_cast<int32_t>(defaultDeviceRotationOffset_ / 90);
200     int32_t deviceRotationValue = static_cast<int32_t>(sensorRotation) - bias;
201     while (deviceRotationValue < 0) {
202         // +4 is used to normalize the values into the range 0~3, corresponding to the four rotations.
203         deviceRotationValue += 4;
204     }
205     if (defaultDeviceRotation_ == 1) {
206         deviceRotationValue += static_cast<int32_t>(defaultDeviceRotation_);
207         // %2 to determine whether the rotation is horizontal or vertical.
208         if (deviceRotationValue % 2 == 0) {
209             // if device's default rotation is landscape, use -2 to swap 0 and 90, 180 and 270.
210             deviceRotationValue -= 2;
211         }
212     }
213     return static_cast<DeviceRotation>(deviceRotationValue);
214 }
215 
IsSensorRelatedOrientation(Orientation orientation)216 bool ScreenRotationController::IsSensorRelatedOrientation(Orientation orientation)
217 {
218     if ((orientation >= Orientation::UNSPECIFIED && orientation <= Orientation::REVERSE_HORIZONTAL) ||
219         orientation == Orientation::LOCKED) {
220         return false;
221     }
222     return true;
223 }
224 
ProcessSwitchToSensorRelatedOrientation(Orientation orientation,DeviceRotation sensorRotationConverted)225 void ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(
226     Orientation orientation, DeviceRotation sensorRotationConverted)
227 {
228     lastOrientationType_ = orientation;
229     switch (orientation) {
230         case Orientation::AUTO_ROTATION_RESTRICTED: {
231             if (isScreenRotationLocked_) {
232                 SetScreenRotation(rotationLockedRotation_);
233                 return;
234             }
235             [[fallthrough]];
236         }
237         case Orientation::SENSOR: {
238             ProcessSwitchToAutoRotation(sensorRotationConverted);
239             return;
240         }
241         case Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED: {
242             if (isScreenRotationLocked_) {
243                 ProcessSwitchToAutoRotationPortraitRestricted();
244                 return;
245             }
246             [[fallthrough]];
247         }
248         case Orientation::SENSOR_VERTICAL: {
249             ProcessSwitchToAutoRotationPortrait(sensorRotationConverted);
250             return;
251         }
252         case Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED: {
253             if (isScreenRotationLocked_) {
254                 ProcessSwitchToAutoRotationLandscapeRestricted();
255                 return;
256             }
257             [[fallthrough]];
258         }
259         case Orientation::SENSOR_HORIZONTAL: {
260             ProcessSwitchToAutoRotationLandscape(sensorRotationConverted);
261             return;
262         }
263         default: {
264             return;
265         }
266     }
267 }
268 
ProcessSwitchToAutoRotation(DeviceRotation rotation)269 void ScreenRotationController::ProcessSwitchToAutoRotation(DeviceRotation rotation)
270 {
271     if (rotation != DeviceRotation::INVALID) {
272         SetScreenRotation(ConvertDeviceToDisplayRotation(rotation));
273     }
274 }
275 
ProcessSwitchToAutoRotationPortrait(DeviceRotation rotation)276 void ScreenRotationController::ProcessSwitchToAutoRotationPortrait(DeviceRotation rotation)
277 {
278     if (IsDeviceRotationVertical(rotation)) {
279         SetScreenRotation(ConvertDeviceToDisplayRotation(rotation));
280         return;
281     }
282     SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT));
283 }
284 
ProcessSwitchToAutoRotationLandscape(DeviceRotation rotation)285 void ScreenRotationController::ProcessSwitchToAutoRotationLandscape(DeviceRotation rotation)
286 {
287     if (IsDeviceRotationHorizontal(rotation)) {
288         SetScreenRotation(ConvertDeviceToDisplayRotation(rotation));
289         return;
290     }
291     SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE));
292 }
293 
ProcessSwitchToAutoRotationPortraitRestricted()294 void ScreenRotationController::ProcessSwitchToAutoRotationPortraitRestricted()
295 {
296     if (IsCurrentDisplayVertical()) {
297         return;
298     }
299     if (IsDisplayRotationVertical(rotationLockedRotation_)) {
300         SetScreenRotation(rotationLockedRotation_);
301         return;
302     }
303     SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT));
304 }
305 
ProcessSwitchToAutoRotationLandscapeRestricted()306 void ScreenRotationController::ProcessSwitchToAutoRotationLandscapeRestricted()
307 {
308     if (IsCurrentDisplayHorizontal()) {
309         return;
310     }
311     if (IsDisplayRotationHorizontal(rotationLockedRotation_)) {
312         SetScreenRotation(rotationLockedRotation_);
313         return;
314     }
315     SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE));
316 }
317 
ConvertSensorToDeviceRotation(SensorRotation sensorRotation)318 DeviceRotation ScreenRotationController::ConvertSensorToDeviceRotation(SensorRotation sensorRotation)
319 {
320     if (sensorToDeviceRotationMap_.empty()) {
321         ProcessRotationMapping();
322     }
323     return sensorToDeviceRotationMap_.at(sensorRotation);
324 }
325 
ConvertRotationToDisplayOrientation(Rotation rotation)326 DisplayOrientation ScreenRotationController::ConvertRotationToDisplayOrientation(Rotation rotation)
327 {
328     if (displayToDisplayOrientationMap_.empty()) {
329         ProcessRotationMapping();
330     }
331     return displayToDisplayOrientationMap_.at(rotation);
332 }
333 
ConvertDeviceToDisplayRotation(DeviceRotation deviceRotation)334 Rotation ScreenRotationController::ConvertDeviceToDisplayRotation(DeviceRotation deviceRotation)
335 {
336     if (deviceRotation == DeviceRotation::INVALID) {
337         return GetCurrentDisplayRotation();
338     }
339     if (deviceToDisplayRotationMap_.empty()) {
340         ProcessRotationMapping();
341     }
342     return deviceToDisplayRotationMap_.at(deviceRotation);
343 }
344 
ProcessRotationMapping()345 void ScreenRotationController::ProcessRotationMapping()
346 {
347     sptr<SupportedScreenModes> modes =
348         DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(defaultDisplayId_);
349 
350     // 0 means PORTRAIT, 1 means LANDSCAPE.
351     defaultDeviceRotation_ = (modes == nullptr || modes->width_ < modes->height_) ? 0 : 1;
352 
353     if (deviceToDisplayRotationMap_.empty()) {
354         deviceToDisplayRotationMap_ = {
355             {DeviceRotation::ROTATION_PORTRAIT,
356                 defaultDeviceRotation_ == 0 ? Rotation::ROTATION_0 : Rotation::ROTATION_90},
357             {DeviceRotation::ROTATION_LANDSCAPE,
358                 defaultDeviceRotation_ == 1 ? Rotation::ROTATION_0 : Rotation::ROTATION_90},
359             {DeviceRotation::ROTATION_PORTRAIT_INVERTED,
360                 defaultDeviceRotation_ == 0 ? Rotation::ROTATION_180 : Rotation::ROTATION_270},
361             {DeviceRotation::ROTATION_LANDSCAPE_INVERTED,
362                 defaultDeviceRotation_ == 1 ? Rotation::ROTATION_180 : Rotation::ROTATION_270},
363         };
364     }
365     if (displayToDisplayOrientationMap_.empty()) {
366         displayToDisplayOrientationMap_ = {
367             {defaultDeviceRotation_ == 0 ? Rotation::ROTATION_0 : Rotation::ROTATION_90,
368                 DisplayOrientation::PORTRAIT},
369             {defaultDeviceRotation_ == 1 ? Rotation::ROTATION_0 : Rotation::ROTATION_90,
370                 DisplayOrientation::LANDSCAPE},
371             {defaultDeviceRotation_ == 0 ? Rotation::ROTATION_180 : Rotation::ROTATION_270,
372                 DisplayOrientation::PORTRAIT_INVERTED},
373             {defaultDeviceRotation_ == 1 ? Rotation::ROTATION_180 : Rotation::ROTATION_270,
374                 DisplayOrientation::LANDSCAPE_INVERTED},
375         };
376     }
377     if (sensorToDeviceRotationMap_.empty()) {
378         sensorToDeviceRotationMap_ = {
379             {SensorRotation::ROTATION_0, CalcDeviceRotation(SensorRotation::ROTATION_0)},
380             {SensorRotation::ROTATION_90, CalcDeviceRotation(SensorRotation::ROTATION_90)},
381             {SensorRotation::ROTATION_180, CalcDeviceRotation(SensorRotation::ROTATION_180)},
382             {SensorRotation::ROTATION_270, CalcDeviceRotation(SensorRotation::ROTATION_270)},
383             {SensorRotation::INVALID, DeviceRotation::INVALID},
384         };
385     }
386 }
387 
IsDeviceRotationVertical(DeviceRotation deviceRotation)388 bool ScreenRotationController::IsDeviceRotationVertical(DeviceRotation deviceRotation)
389 {
390     return (deviceRotation == DeviceRotation::ROTATION_PORTRAIT) ||
391         (deviceRotation == DeviceRotation::ROTATION_PORTRAIT_INVERTED);
392 }
393 
IsDeviceRotationHorizontal(DeviceRotation deviceRotation)394 bool ScreenRotationController::IsDeviceRotationHorizontal(DeviceRotation deviceRotation)
395 {
396     return (deviceRotation == DeviceRotation::ROTATION_LANDSCAPE) ||
397         (deviceRotation == DeviceRotation::ROTATION_LANDSCAPE_INVERTED);
398 }
399 
IsCurrentDisplayVertical()400 bool ScreenRotationController::IsCurrentDisplayVertical()
401 {
402     return IsDisplayRotationVertical(GetCurrentDisplayRotation());
403 }
404 
IsCurrentDisplayHorizontal()405 bool ScreenRotationController::IsCurrentDisplayHorizontal()
406 {
407     return IsDisplayRotationHorizontal(GetCurrentDisplayRotation());
408 }
409 
IsDefaultDisplayRotationPortrait()410 bool ScreenRotationController::IsDefaultDisplayRotationPortrait()
411 {
412     return Rotation::ROTATION_0 == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT);
413 }
414 
IsDisplayRotationVertical(Rotation rotation)415 bool ScreenRotationController::IsDisplayRotationVertical(Rotation rotation)
416 {
417     return (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT)) ||
418         (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT_INVERTED));
419 }
420 
IsDisplayRotationHorizontal(Rotation rotation)421 bool ScreenRotationController::IsDisplayRotationHorizontal(Rotation rotation)
422 {
423     return (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE)) ||
424         (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE_INVERTED));
425 }
426 
ProcessSwitchToSensorUnrelatedOrientation(Orientation orientation,bool withAnimation)427 void ScreenRotationController::ProcessSwitchToSensorUnrelatedOrientation(Orientation orientation, bool withAnimation)
428 {
429     if (lastOrientationType_ == orientation) {
430         return;
431     }
432     lastOrientationType_ = orientation;
433     switch (orientation) {
434         case Orientation::UNSPECIFIED: {
435             SetScreenRotation(Rotation::ROTATION_0, withAnimation);
436             break;
437         }
438         case Orientation::VERTICAL: {
439             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT), withAnimation);
440             break;
441         }
442         case Orientation::REVERSE_VERTICAL: {
443             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT_INVERTED),
444                 withAnimation);
445             break;
446         }
447         case Orientation::HORIZONTAL: {
448             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE), withAnimation);
449             break;
450         }
451         case Orientation::REVERSE_HORIZONTAL: {
452             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE_INVERTED),
453                 withAnimation);
454             break;
455         }
456         default: {
457             return;
458         }
459     }
460 }
461 
ProcessOrientationSwitch(Orientation orientation,bool withAnimation)462 void ScreenRotationController::ProcessOrientationSwitch(Orientation orientation, bool withAnimation)
463 {
464     if (!IsSensorRelatedOrientation(orientation)) {
465         ProcessSwitchToSensorUnrelatedOrientation(orientation, withAnimation);
466     } else {
467         ProcessSwitchToSensorRelatedOrientation(orientation, lastSensorRotationConverted_);
468     }
469 }
470 } // Rosen
471 } // OHOS