diff options
5 files changed, 99 insertions, 7 deletions
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp index 3f6046f01f11..53a84bd1b21e 100644 --- a/cmds/bootanimation/BootAnimation.cpp +++ b/cmds/bootanimation/BootAnimation.cpp @@ -583,6 +583,15 @@ status_t BootAnimation::readyToRun() { mFlingerSurface = s; mTargetInset = -1; + // Rotate the boot animation according to the value specified in the sysprop + // ro.bootanim.set_orientation_<display_id>. Four values are supported: ORIENTATION_0, + // ORIENTATION_90, ORIENTATION_180 and ORIENTATION_270. + // If the value isn't specified or is ORIENTATION_0, nothing will be changed. + // This is needed to support having boot animation in orientations different from the natural + // device orientation. For example, on tablets that may want to keep natural orientation + // portrait for applications compatibility and to have the boot animation in landscape. + rotateAwayFromNaturalOrientationIfNeeded(); + projectSceneToWindow(); // Register a display event receiver @@ -596,6 +605,50 @@ status_t BootAnimation::readyToRun() { return NO_ERROR; } +void BootAnimation::rotateAwayFromNaturalOrientationIfNeeded() { + const auto orientation = parseOrientationProperty(); + + if (orientation == ui::ROTATION_0) { + // Do nothing if the sysprop isn't set or is set to ROTATION_0. + return; + } + + if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) { + std::swap(mWidth, mHeight); + std::swap(mInitWidth, mInitHeight); + mFlingerSurfaceControl->updateDefaultBufferSize(mWidth, mHeight); + } + + Rect displayRect(0, 0, mWidth, mHeight); + Rect layerStackRect(0, 0, mWidth, mHeight); + + SurfaceComposerClient::Transaction t; + t.setDisplayProjection(mDisplayToken, orientation, layerStackRect, displayRect); + t.apply(); +} + +ui::Rotation BootAnimation::parseOrientationProperty() { + const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds(); + if (displayIds.size() == 0) { + return ui::ROTATION_0; + } + const auto displayId = displayIds[0]; + const auto syspropName = [displayId] { + std::stringstream ss; + ss << "ro.bootanim.set_orientation_" << displayId.value; + return ss.str(); + }(); + const auto syspropValue = android::base::GetProperty(syspropName, "ORIENTATION_0"); + if (syspropValue == "ORIENTATION_90") { + return ui::ROTATION_90; + } else if (syspropValue == "ORIENTATION_180") { + return ui::ROTATION_180; + } else if (syspropValue == "ORIENTATION_270") { + return ui::ROTATION_270; + } + return ui::ROTATION_0; +} + void BootAnimation::projectSceneToWindow() { glViewport(0, 0, mWidth, mHeight); glScissor(0, 0, mWidth, mHeight); diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h index 86582053b4e1..8683b71a3762 100644 --- a/cmds/bootanimation/BootAnimation.h +++ b/cmds/bootanimation/BootAnimation.h @@ -30,6 +30,8 @@ #include <utils/Thread.h> #include <binder/IBinder.h> +#include <ui/Rotation.h> + #include <EGL/egl.h> #include <GLES2/gl2.h> @@ -200,6 +202,8 @@ private: ui::Size limitSurfaceSize(int width, int height) const; void resizeSurface(int newWidth, int newHeight); void projectSceneToWindow(); + void rotateAwayFromNaturalOrientationIfNeeded(); + ui::Rotation parseOrientationProperty(); bool shouldStopPlayingPart(const Animation::Part& part, int fadedFramesCount, int lastDisplayedProgress); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 4c499861cb9a..4c19322a9790 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -1125,7 +1125,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } mDisplayPolicy = new DisplayPolicy(mWmService, this); - mDisplayRotation = new DisplayRotation(mWmService, this); + mDisplayRotation = new DisplayRotation(mWmService, this, mDisplayInfo.address); mDeviceStateController = new DeviceStateController(mWmService.mContext, mWmService.mH, newFoldState -> { diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 185e06eecabb..4fb137b847b0 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -58,6 +58,7 @@ import android.provider.Settings; import android.util.Slog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; +import android.view.DisplayAddress; import android.view.IWindowManager; import android.view.Surface; import android.window.TransitionRequestInfo; @@ -211,15 +212,16 @@ public class DisplayRotation { private boolean mDemoHdmiRotationLock; private boolean mDemoRotationLock; - DisplayRotation(WindowManagerService service, DisplayContent displayContent) { - this(service, displayContent, displayContent.getDisplayPolicy(), + DisplayRotation(WindowManagerService service, DisplayContent displayContent, + DisplayAddress displayAddress) { + this(service, displayContent, displayAddress, displayContent.getDisplayPolicy(), service.mDisplayWindowSettings, service.mContext, service.getWindowManagerLock()); } @VisibleForTesting DisplayRotation(WindowManagerService service, DisplayContent displayContent, - DisplayPolicy displayPolicy, DisplayWindowSettings displayWindowSettings, - Context context, Object lock) { + DisplayAddress displayAddress, DisplayPolicy displayPolicy, + DisplayWindowSettings displayWindowSettings, Context context, Object lock) { mService = service; mDisplayContent = displayContent; mDisplayPolicy = displayPolicy; @@ -235,6 +237,8 @@ public class DisplayRotation { mDeskDockRotation = readRotation(R.integer.config_deskDockRotation); mUndockedHdmiRotation = readRotation(R.integer.config_undockedHdmiRotation); + mRotation = readDefaultDisplayRotation(displayAddress); + if (isDefaultDisplay) { final Handler uiHandler = UiThread.getHandler(); mOrientationListener = new OrientationListener(mContext, uiHandler); @@ -248,6 +252,33 @@ public class DisplayRotation { } } + // Change the default value to the value specified in the sysprop + // ro.bootanim.set_orientation_<display_id>. Four values are supported: ORIENTATION_0, + // ORIENTATION_90, ORIENTATION_180 and ORIENTATION_270. + // If the value isn't specified or is ORIENTATION_0, nothing will be changed. + // This is needed to support having default orientation different from the natural + // device orientation. For example, on tablets that may want to keep natural orientation + // portrait for applications compatibility but have landscape orientation as a default choice + // from the UX perspective. + @Surface.Rotation + private int readDefaultDisplayRotation(DisplayAddress displayAddress) { + if (!(displayAddress instanceof DisplayAddress.Physical)) { + return Surface.ROTATION_0; + } + final DisplayAddress.Physical physicalAddress = (DisplayAddress.Physical) displayAddress; + String syspropValue = SystemProperties.get( + "ro.bootanim.set_orientation_" + physicalAddress.getPhysicalDisplayId(), + "ORIENTATION_0"); + if (syspropValue.equals("ORIENTATION_90")) { + return Surface.ROTATION_90; + } else if (syspropValue.equals("ORIENTATION_180")) { + return Surface.ROTATION_180; + } else if (syspropValue.equals("ORIENTATION_270")) { + return Surface.ROTATION_270; + } + return Surface.ROTATION_0; + } + private int readRotation(int resID) { try { final int rotation = mContext.getResources().getInteger(resID); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java index b45c37f9da0c..491f876dceed 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java @@ -60,6 +60,7 @@ import android.os.PowerManagerInternal; import android.os.SystemClock; import android.platform.test.annotations.Presubmit; import android.provider.Settings; +import android.view.DisplayAddress; import android.view.Surface; import android.view.WindowManager; @@ -101,6 +102,7 @@ public class DisplayRotationTests { private static WindowManagerService sMockWm; private DisplayContent mMockDisplayContent; private DisplayPolicy mMockDisplayPolicy; + private DisplayAddress mMockDisplayAddress; private Context mMockContext; private Resources mMockRes; private SensorManager mMockSensorManager; @@ -1091,9 +1093,11 @@ public class DisplayRotationTests { when(mMockResolver.acquireProvider(Settings.AUTHORITY)) .thenReturn(mFakeSettingsProvider.getIContentProvider()); + mMockDisplayAddress = mock(DisplayAddress.class); + mMockDisplayWindowSettings = mock(DisplayWindowSettings.class); - mTarget = new DisplayRotation(sMockWm, mMockDisplayContent, mMockDisplayPolicy, - mMockDisplayWindowSettings, mMockContext, new Object()); + mTarget = new DisplayRotation(sMockWm, mMockDisplayContent, mMockDisplayAddress, + mMockDisplayPolicy, mMockDisplayWindowSettings, mMockContext, new Object()); reset(sMockWm); captureObservers(); |