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