• 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     if (deviceToDisplayRotationMap_.empty()) {
352         deviceToDisplayRotationMap_ = {
353             {DeviceRotation::ROTATION_PORTRAIT,
354                 defaultDeviceRotation_ == 0 ? Rotation::ROTATION_0 : Rotation::ROTATION_90},
355             {DeviceRotation::ROTATION_LANDSCAPE,
356                 defaultDeviceRotation_ == 1 ? Rotation::ROTATION_0 : Rotation::ROTATION_90},
357             {DeviceRotation::ROTATION_PORTRAIT_INVERTED,
358                 defaultDeviceRotation_ == 0 ? Rotation::ROTATION_180 : Rotation::ROTATION_270},
359             {DeviceRotation::ROTATION_LANDSCAPE_INVERTED,
360                 defaultDeviceRotation_ == 1 ? Rotation::ROTATION_180 : Rotation::ROTATION_270},
361         };
362     }
363     if (displayToDisplayOrientationMap_.empty()) {
364         displayToDisplayOrientationMap_ = {
365             {defaultDeviceRotation_ == 0 ? Rotation::ROTATION_0 : Rotation::ROTATION_90,
366                 DisplayOrientation::PORTRAIT},
367             {defaultDeviceRotation_ == 1 ? Rotation::ROTATION_0 : Rotation::ROTATION_90,
368                 DisplayOrientation::LANDSCAPE},
369             {defaultDeviceRotation_ == 0 ? Rotation::ROTATION_180 : Rotation::ROTATION_270,
370                 DisplayOrientation::PORTRAIT_INVERTED},
371             {defaultDeviceRotation_ == 1 ? Rotation::ROTATION_180 : Rotation::ROTATION_270,
372                 DisplayOrientation::LANDSCAPE_INVERTED},
373         };
374     }
375     if (sensorToDeviceRotationMap_.empty()) {
376         sensorToDeviceRotationMap_ = {
377             {SensorRotation::ROTATION_0, CalcDeviceRotation(SensorRotation::ROTATION_0)},
378             {SensorRotation::ROTATION_90, CalcDeviceRotation(SensorRotation::ROTATION_90)},
379             {SensorRotation::ROTATION_180, CalcDeviceRotation(SensorRotation::ROTATION_180)},
380             {SensorRotation::ROTATION_270, CalcDeviceRotation(SensorRotation::ROTATION_270)},
381             {SensorRotation::INVALID, DeviceRotation::INVALID},
382         };
383     }
384 }
385 
IsDeviceRotationVertical(DeviceRotation deviceRotation)386 bool ScreenRotationController::IsDeviceRotationVertical(DeviceRotation deviceRotation)
387 {
388     return (deviceRotation == DeviceRotation::ROTATION_PORTRAIT) ||
389         (deviceRotation == DeviceRotation::ROTATION_PORTRAIT_INVERTED);
390 }
391 
IsDeviceRotationHorizontal(DeviceRotation deviceRotation)392 bool ScreenRotationController::IsDeviceRotationHorizontal(DeviceRotation deviceRotation)
393 {
394     return (deviceRotation == DeviceRotation::ROTATION_LANDSCAPE) ||
395         (deviceRotation == DeviceRotation::ROTATION_LANDSCAPE_INVERTED);
396 }
397 
IsCurrentDisplayVertical()398 bool ScreenRotationController::IsCurrentDisplayVertical()
399 {
400     return IsDisplayRotationVertical(GetCurrentDisplayRotation());
401 }
402 
IsCurrentDisplayHorizontal()403 bool ScreenRotationController::IsCurrentDisplayHorizontal()
404 {
405     return IsDisplayRotationHorizontal(GetCurrentDisplayRotation());
406 }
407 
IsDefaultDisplayRotationPortrait()408 bool ScreenRotationController::IsDefaultDisplayRotationPortrait()
409 {
410     return Rotation::ROTATION_0 == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT);
411 }
412 
IsDisplayRotationVertical(Rotation rotation)413 bool ScreenRotationController::IsDisplayRotationVertical(Rotation rotation)
414 {
415     return (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT)) ||
416         (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT_INVERTED));
417 }
418 
IsDisplayRotationHorizontal(Rotation rotation)419 bool ScreenRotationController::IsDisplayRotationHorizontal(Rotation rotation)
420 {
421     return (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE)) ||
422         (rotation == ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE_INVERTED));
423 }
424 
ProcessSwitchToSensorUnrelatedOrientation(Orientation orientation,bool withAnimation)425 void ScreenRotationController::ProcessSwitchToSensorUnrelatedOrientation(Orientation orientation, bool withAnimation)
426 {
427     if (lastOrientationType_ == orientation) {
428         return;
429     }
430     lastOrientationType_ = orientation;
431     switch (orientation) {
432         case Orientation::UNSPECIFIED: {
433             SetScreenRotation(Rotation::ROTATION_0, withAnimation);
434             break;
435         }
436         case Orientation::VERTICAL: {
437             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT), withAnimation);
438             break;
439         }
440         case Orientation::REVERSE_VERTICAL: {
441             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_PORTRAIT_INVERTED),
442                 withAnimation);
443             break;
444         }
445         case Orientation::HORIZONTAL: {
446             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE), withAnimation);
447             break;
448         }
449         case Orientation::REVERSE_HORIZONTAL: {
450             SetScreenRotation(ConvertDeviceToDisplayRotation(DeviceRotation::ROTATION_LANDSCAPE_INVERTED),
451                 withAnimation);
452             break;
453         }
454         default: {
455             return;
456         }
457     }
458 }
459 
ProcessOrientationSwitch(Orientation orientation,bool withAnimation)460 void ScreenRotationController::ProcessOrientationSwitch(Orientation orientation, bool withAnimation)
461 {
462     if (!IsSensorRelatedOrientation(orientation)) {
463         ProcessSwitchToSensorUnrelatedOrientation(orientation, withAnimation);
464     } else {
465         ProcessSwitchToSensorRelatedOrientation(orientation, lastSensorRotationConverted_);
466     }
467 }
468 } // Rosen
469 } // OHOS