配置ro.sf.hwrotation为竖屏
ro.sf.hwrotation=270
ro.sf.hwrotation=0
表示不旋转 ro.sf.hwrotation=90
表示旋转90°
ro.sf.hwrotation=180
表示旋转180°
ro.sf.hwrotation=270
表示旋转270°
首先强制进入桌面后竖屏
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java里面修改WindowManagerService
boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
long ident = Binder.clearCallingIdentity();
try {
// int req = getOrientationLocked();
/*SCREEN_ORIENTATION_LANDSCAPE :横屏显示,SCREEN_ORIENTATION_PORTRAIT : 竖屏显示*/
int req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
if (req != mLastOrientation) {
mLastOrientation = req;
但是这样会有个问题,就是如果机器默认是横屏,你强制进入桌面是竖屏的话,会在进入桌面前,自动旋转,而这个旋转会导致开机动画旋转错乱
解决开机动画旋转:
frameworks/base/cmds/bootanimation/BootAnimation.cpp
BootAnimation::BootAnimation(bool shutdown) : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
mTimeFormat12Hour(false), mTimeCheckThread(NULL) {
mSession = new SurfaceComposerClient();
// If the system has already booted, the animation is not being used for a boot.
mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
mShutdown = shutdown;
mReverseAxis = false;
mVideoFile = NULL;
mVideoAnimation = false;
//注释mShotdown判断, 启动时, 方向有可能设置为0以外的数值
//if(mShutdown){
sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain)); // primary_display_token
DisplayInfo dinfo;
status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
if (status == OK) {
ALOGD("DISPLAY,W-H: %d-%d, ori: %d", dinfo.w, dinfo.h, dinfo.orientation);
//解决启动时方向错误, 其中, 变量 rot根据需要的方向设置[0, 3];
int rot = 1;//90度
if (rot >= 0) {
int w = dinfo.w;
int h = dinfo.h;
if(rot == 1 || rot == 3){//竖屏时, xy轴需要对调
mReverseAxis=true;
h = dinfo.w;
w = dinfo.h;
}else{
mReverseAxis=false;
}
Rect layerStackRect(w, h);
Rect displayRect(0, 0, w, h);
SurfaceComposerClient::setDisplayProjection(dtoken, rot, layerStackRect, displayRect);
}
}
//}
}
status_t BootAnimation::readyToRun() {
mAssets.addDefaultAssets();
sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
ISurfaceComposer::eDisplayIdMain));
DisplayInfo dinfo;
status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
if (status)
return -1;
// create the native surface
int curWidth = dinfo.w;
int curHeight = dinfo.h;
//注释 mShutdown, 屏幕旋转不只发生在关机动画时.
if(/*mShutdown && */mReverseAxis){
curWidth = dinfo.h;
curHeight = dinfo.w;
}
//...省略代码
}
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
private WindowManagerService(Context context, InputManagerService inputManager,
boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
//... 省略代码
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
//设置默认旋转方向, 与动画的默认方向保持一致
mRotation = Surface.ROTATION_90;
SurfaceControl.openTransaction();
try {
createWatermarkInTransaction();
} finally {
SurfaceControl.closeTransaction();
}
showEmulatorDisplayOverlayIfNeeded();
}
/**
* Updates the current rotation.
*
* Returns true if the rotation has been changed. In this case YOU
* MUST CALL sendNewConfiguration() TO UNFREEZE THE SCREEN.
*/
public boolean updateRotationUncheckedLocked(boolean inTransaction) {
//省略大量代码
if (DEBUG_ORIENTATION) {
Slog.v(TAG_WM, "Selected orientation "
+ mLastOrientation + ", got rotation " + rotation
+ " which has " + (altOrientation ? "incompatible" : "compatible")
+ " metrics");
}
//保持默认方向
/*if (mRotateOnBoot) {
mRotation = Surface.ROTATION_0;
rotation = Surface.ROTATION_90;
}*/
if (mRotation == rotation && mAltOrientation == altOrientation) {
// No change.
return false;
}
//省略大量代码
}
最终更新屏幕显示:
frameworks/base/services/core/java/com/android/server/display/DisplayDevice.java
/**
* Sets the display projection while in a transaction.
*
* @param orientation defines the display's orientation
* @param layerStackRect defines which area of the window manager coordinate
* space will be used
* @param displayRect defines where on the display will layerStackRect be
* mapped to. displayRect is specified post-orientation, that is
* it uses the orientation seen by the end-user
*/
public final void setProjectionInTransactionLocked(int orientation,
Rect layerStackRect, Rect displayRect) {
if (mCurrentOrientation != orientation
|| mCurrentLayerStackRect == null
|| !mCurrentLayerStackRect.equals(layerStackRect)
|| mCurrentDisplayRect == null
|| !mCurrentDisplayRect.equals(displayRect)) {
mCurrentOrientation = orientation;
if (mCurrentLayerStackRect == null) {
mCurrentLayerStackRect = new Rect();
}
mCurrentLayerStackRect.set(layerStackRect);
if (mCurrentDisplayRect == null) {
mCurrentDisplayRect = new Rect();
}
mCurrentDisplayRect.set(displayRect);
//与Bootanimation中的函数类似
SurfaceControl.setDisplayProjection(mDisplayToken,
orientation, layerStackRect, displayRect);
}
}