• 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 std::map<Rotation, DisplayOrientation> ScreenRotationController::displayToDisplayOrientationMap_;
40 DeviceRotation ScreenRotationController::lastSensorRotationConverted_ = DeviceRotation::INVALID;
41 
Init()42 void ScreenRotationController::Init()
43 {
44     ProcessRotationMapping();
45     currentDisplayRotation_ = GetCurrentDisplayRotation();
46     defaultDisplayId_ = DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId();
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         WLOGFW("deviceRotation is invalid, return.");
86         return;
87     }
88     Orientation orientation = GetPreferredOrientation();
89     currentDisplayRotation_ = GetCurrentDisplayRotation();
90     lastSensorRotationConverted_ = deviceRotation;
91     if (!IsSensorRelatedOrientation(orientation)) {
92         WLOGFD("If the current preferred orientation is locked or sensor-independent, return.");
93         return;
94     }
95 
96     if (currentDisplayRotation_ == ConvertDeviceToDisplayRotation(deviceRotation)) {
97         WLOGFD("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         WLOGFE("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         WLOGFE("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     WLOGFI("dms: Set screen rotation: %{public}u withAnimation: %{public}u", targetRotation, withAnimation);
190 }
191 
CalcDeviceRotation(SensorRotation sensorRotation)192 DeviceRotation ScreenRotationController::CalcDeviceRotation(SensorRotation sensorRotation)
193 {
194     if (sensorRotation == SensorRotation::INVALID) {
195         return DeviceRotation::INVALID;
196     }
197     // offset(in degree) divided by 90 to get rotation bias
198     int32_t bias = static_cast<int32_t>(defaultDeviceRotationOffset_ / 90);
199     int32_t deviceRotationValue = static_cast<int32_t>(sensorRotation) - bias;
200     while (deviceRotationValue < 0) {
201         // +4 is used to normalize the values into the range 0~3, corresponding to the four rotations.
202         deviceRotationValue += 4;
203     }
204     if (defaultDeviceRotation_ == 1) {
205         deviceRotationValue += static_cast<int32_t>(defaultDeviceRotation_);
206         // %2 to determine whether the rotation is horizontal or vertical.
207         if (deviceRotationValue % 2 == 0) {
208             // if device's default rotation is landscape, use -2 to swap 0 and 90, 180 and 270.
209             deviceRotationValue -= 2;
210         }
211     }
212     return static_cast<DeviceRotation>(deviceRotationValue);
213 }
214 
IsSensorRelatedOrientation(Orientation orientation)215 bool ScreenRotationController::IsSensorRelatedOrientation(Orientation orientation)
216 {
217     if ((orientation >= Orientation::UNSPECIFIED && orientation <= Orientation::REVERSE_HORIZONTAL) ||
218         orientation == Orientation::LOCKED) {
219         return false;
220     }
221     return true;
222 }
223 
ProcessSwitchToSensorRelatedOrientation(Orientation orientation,DeviceRotation sensorRotationConverted)224 void ScreenRotationController::ProcessSwitchToSensorRelatedOrientation(
225     Orientation orientation, DeviceRotation sensorRotationConverted)
226 {
227     lastOrientationType_ = orientation;
228     switch (orientation) {
229         case Orientation::AUTO_ROTATION_RESTRICTED: {
230             if (isScreenRotationLocked_) {
231                 SetScreenRotation(rotationLockedRotation_);
232                 return;
233             }
234             [[fallthrough]];
235         }
236         case Orientation::SENSOR: {
237             ProcessSwitchToAutoRotation(sensorRotationConverted);
238             return;
239         }
240         case Orientation::AUTO_ROTATION_PORTRAIT_RESTRICTED: {
241             if (isScreenRotationLocked_) {
242                 ProcessSwitchToAutoRotationPortraitRestricted();
243                 return;
244             }
245             [[fallthrough]];
246         }
247         case Orientation::SENSOR_VERTICAL: {
248             ProcessSwitchToAutoRotationPortrait(sensorRotationConverted);
249             return;
250         }
251         case Orientation::AUTO_ROTATION_LANDSCAPE_RESTRICTED: {
252             if (isScreenRotationLocked_) {
253                 ProcessSwitchToAutoRotationLandscapeRestricted();
254                 return;
255             }
256             [[fallthrough]];
257         }
258         case Orientation::SENSOR_HORIZONTAL: {
259             ProcessSwitchToAutoRotationLandscape(sensorRotationConverted);
260             return;
261         }
262         default: {
263             return;
264         }
265     }
266 }
267 
ProcessSwitchToAutoRotation(DeviceRotation rotation)268 void ScreenRotationController::ProcessSwitchToAutoRotation(DeviceRotation rotation)
269 {
270     if (rotation != DeviceRotation::INVALID) {
271         SetScreenRotation(ConvertDeviceToDisplayRotation(rotation));
272     }
273 }
274 
ProcessSwitchToAutoRotationPortrait(DeviceRotation rotation)275 void ScreenRotationController::ProcessSwitchToAutoRotationPortrait(DeviceRotation rotation)
276 {
277     if (IsDeviceRotationVertical(rotation)) {
278         SetScreenRotation(ConvertDeviceToDisplayRotation(rotation));
279         return;
280     }
281     SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT));
282 }
283 
ProcessSwitchToAutoRotationLandscape(DeviceRotation rotation)284 void ScreenRotationController::ProcessSwitchToAutoRotationLandscape(DeviceRotation rotation)
285 {
286     if (IsDeviceRotationHorizontal(rotation)) {
287         SetScreenRotation(ConvertDeviceToDisplayRotation(rotation));
288         return;
289     }
290     SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE));
291 }
292 
ProcessSwitchToAutoRotationPortraitRestricted()293 void ScreenRotationController::ProcessSwitchToAutoRotationPortraitRestricted()
294 {
295     if (IsCurrentDisplayVertical()) {
296         return;
297     }
298     if (IsDisplayRotationVertical(rotationLockedRotation_)) {
299         SetScreenRotation(rotationLockedRotation_);
300         return;
301     }
302     SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT));
303 }
304 
ProcessSwitchToAutoRotationLandscapeRestricted()305 void ScreenRotationController::ProcessSwitchToAutoRotationLandscapeRestricted()
306 {
307     if (IsCurrentDisplayHorizontal()) {
308         return;
309     }
310     if (IsDisplayRotationHorizontal(rotationLockedRotation_)) {
311         SetScreenRotation(rotationLockedRotation_);
312         return;
313     }
314     SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE));
315 }
316 
ConvertSensorToDeviceRotation(SensorRotation sensorRotation)317 DeviceRotation ScreenRotationController::ConvertSensorToDeviceRotation(SensorRotation sensorRotation)
318 {
319     if (sensorToDeviceRotationMap_.empty()) {
320         ProcessRotationMapping();
321     }
322     return sensorToDeviceRotationMap_.at(sensorRotation);
323 }
324 
ConvertRotationToDisplayOrientation(Rotation rotation)325 DisplayOrientation ScreenRotationController::ConvertRotationToDisplayOrientation(Rotation rotation)
326 {
327     if (displayToDisplayOrientationMap_.empty()) {
328         ProcessRotationMapping();
329     }
330     return displayToDisplayOrientationMap_.at(rotation);
331 }
332 
ConvertDeviceToDisplayRotation(DeviceRotation deviceRotation)333 Rotation ScreenRotationController::ConvertDeviceToDisplayRotation(DeviceRotation deviceRotation)
334 {
335     if (deviceRotation == DeviceRotation::INVALID) {
336         return GetCurrentDisplayRotation();
337     }
338     if (deviceToDisplayRotationMap_.empty()) {
339         ProcessRotationMapping();
340     }
341     return deviceToDisplayRotationMap_.at(deviceRotation);
342 }
343 
ProcessRotationMapping()344 void ScreenRotationController::ProcessRotationMapping()
345 {
346     sptr<SupportedScreenModes> modes =
347         DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(defaultDisplayId_);
348 
349     // 0 means PORTRAIT, 1 means LANDSCAPE.
350     defaultDeviceRotation_ = (modes == nullptr || modes->width_ < modes->height_) ? 0 : 1;
351 
352     if (deviceToDisplayRotationMap_.empty()) {
353         deviceToDisplayRotationMap_ = {
354             {DeviceRotation::ROTATION_PORTRAIT,
355                 defaultDeviceRotation_ == 0 ? Rotation::ROTATION_0 : Rotation::ROTATION_90},
356             {DeviceRotation::ROTATION_LANDSCAPE,
357                 defaultDeviceRotation_ == 1 ? Rotation::ROTATION_0 : Rotation::ROTATION_90},
358             {DeviceRotation::ROTATION_PORTRAIT_INVERTED,
359                 defaultDeviceRotation_ == 0 ? Rotation::ROTATION_180 : Rotation::ROTATION_270},
360             {DeviceRotation::ROTATION_LANDSCAPE_INVERTED,
361                 defaultDeviceRotation_ == 1 ? Rotation::ROTATION_180 : Rotation::ROTATION_270},
362         };
363     }
364     if (displayToDisplayOrientationMap_.empty()) {
365         displayToDisplayOrientationMap_ = {
366             {defaultDeviceRotation_ == 0 ? Rotation::ROTATION_0 : Rotation::ROTATION_90,
367                 DisplayOrientation::PORTRAIT},
368             {defaultDeviceRotation_ == 1 ? Rotation::ROTATION_0 : Rotation::ROTATION_90,
369                 DisplayOrientation::LANDSCAPE},
370             {defaultDeviceRotation_ == 0 ? Rotation::ROTATION_180 : Rotation::ROTATION_270,
371                 DisplayOrientation::PORTRAIT_INVERTED},
372             {defaultDeviceRotation_ == 1 ? Rotation::ROTATION_180 : Rotation::ROTATION_270,
373                 DisplayOrientation::LANDSCAPE_INVERTED},
374         };
375     }
376     if (sensorToDeviceRotationMap_.empty()) {
377         sensorToDeviceRotationMap_ = {
378             {SensorRotation::ROTATION_0, CalcDeviceRotation(SensorRotation::ROTATION_0)},
379             {SensorRotation::ROTATION_90, CalcDeviceRotation(SensorRotation::ROTATION_90)},
380             {SensorRotation::ROTATION_180, CalcDeviceRotation(SensorRotation::ROTATION_180)},
381             {SensorRotation::ROTATION_270, CalcDeviceRotation(SensorRotation::ROTATION_270)},
382             {SensorRotation::INVALID, DeviceRotation::INVALID},
383         };
384     }
385 }
386 
IsDeviceRotationVertical(DeviceRotation deviceRotation)387 bool ScreenRotationController::IsDeviceRotationVertical(DeviceRotation deviceRotation)
388 {
389     return (deviceRotation == DeviceRotation::ROTATION_PORTRAIT) ||
390         (deviceRotation == DeviceRotation::ROTATION_PORTRAIT_INVERTED);
391 }
392 
IsDeviceRotationHorizontal(DeviceRotation deviceRotation)393 bool ScreenRotationController::IsDeviceRotationHorizontal(DeviceRotation deviceRotation)
394 {
395     return (deviceRotation == DeviceRotation::ROTATION_LANDSCAPE) ||
396         (deviceRotation == DeviceRotation::ROTATION_LANDSCAPE_INVERTED);
397 }
398 
IsCurrentDisplayVertical()399 bool ScreenRotationController::IsCurrentDisplayVertical()
400 {
401     return IsDisplayRotationVertical(GetCurrentDisplayRotation());
402 }
403 
IsCurrentDisplayHorizontal()404 bool ScreenRotationController::IsCurrentDisplayHorizontal()
405 {
406     return IsDisplayRotationHorizontal(GetCurrentDisplayRotation());
407 }
408 
IsDefaultDisplayRotationPortrait()409 bool ScreenRotationController::IsDefaultDisplayRotationPortrait()
410 {
411     return Rotation::ROTATION_0 == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT);
412 }
413 
IsDisplayRotationVertical(Rotation rotation)414 bool ScreenRotationController::IsDisplayRotationVertical(Rotation rotation)
415 {
416     return (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT)) ||
417         (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT_INVERTED));
418 }
419 
IsDisplayRotationHorizontal(Rotation rotation)420 bool ScreenRotationController::IsDisplayRotationHorizontal(Rotation rotation)
421 {
422     return (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE)) ||
423         (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE_INVERTED));
424 }
425 
ProcessSwitchToSensorUnrelatedOrientation(Orientation orientation,bool withAnimation)426 void ScreenRotationController::ProcessSwitchToSensorUnrelatedOrientation(Orientation orientation, bool withAnimation)
427 {
428     if (lastOrientationType_ == orientation) {
429         return;
430     }
431     lastOrientationType_ = orientation;
432     switch (orientation) {
433         case Orientation::UNSPECIFIED: {
434             SetScreenRotation(Rotation::ROTATION_0, withAnimation);
435             break;
436         }
437         case Orientation::VERTICAL: {
438             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT), withAnimation);
439             break;
440         }
441         case Orientation::REVERSE_VERTICAL: {
442             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT_INVERTED),
443                 withAnimation);
444             break;
445         }
446         case Orientation::HORIZONTAL: {
447             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE), withAnimation);
448             break;
449         }
450         case Orientation::REVERSE_HORIZONTAL: {
451             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE_INVERTED),
452                 withAnimation);
453             break;
454         }
455         default: {
456             return;
457         }
458     }
459 }
460 
ProcessOrientationSwitch(Orientation orientation,bool withAnimation)461 void ScreenRotationController::ProcessOrientationSwitch(Orientation orientation, bool withAnimation)
462 {
463     if (!IsSensorRelatedOrientation(orientation)) {
464         ProcessSwitchToSensorUnrelatedOrientation(orientation, withAnimation);
465     } else {
466         ProcessSwitchToSensorRelatedOrientation(orientation, lastSensorRotationConverted_);
467     }
468 }
469 } // Rosen
470 } // OHOS