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