旋转屏幕的办法有两个
1.旋转FB,改framebuffer驱动
2.改Framwork
因为想做到动态旋转,其实看到很多平台也实现了这个功能,如rockchip的修改为,旋转这样就搞定了:
IWindowManager wm = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
wm.freezeRotation(OrientationValue);
不过我试了一下并不奏效,不知道还改了什么地方,就没有深究下去了,看到网上有博友的改法,索性试了一下最好磕磕碰碰的还是弄好了,就是不太优雅。
我imx6平台的代码保留着ro.sf.hwrotation 这参数,需要静态旋转直接改这个参数就可以了,就是路径是 system/build.prop
改完了需要重启。
动态修改的办法:
1.frameworks/native/services/surfaceflinger/DisplayDevice.cpp
uint32_t DisplayDevice::getOrientationTransform() const {
uint32_t transform = 0;
char property[PROPERTY_VALUE_MAX];
if (property_get("persist.sf.hwrotation", property, NULL) > 0) {
switch (atoi(property)) {
case 0:
transform = Transform::ROT_0;
break;
case 90:
transform = Transform::ROT_90;
break;
case 180:
transform = Transform::ROT_180;
break;
case 270:
transform = Transform::ROT_270;
break;
}
}
return transform;
}
uint32_t DisplayDevice::getOrientationTransform() const {
uint32_t transform = 0;
char property[PROPERTY_VALUE_MAX];
if (property_get("persist.sf.hwrotation", property, NULL) > 0) {
switch (atoi(property)) {
case 0:
transform = Transform::ROT_0;
break;
case 90:
transform = Transform::ROT_90;
break;
case 180:
transform = Transform::ROT_180;
break;
case 270:
transform = Transform::ROT_270;
break;
}
return transform;
}
void DisplayDevice::setProjection(int orientation,
const Rect& newViewport, const Rect& newFrame) {
Rect viewport(newViewport);
Rect frame(newFrame);
int displayOrientation = DisplayState::eOrientationDefault;
char property[PROPERTY_VALUE_MAX];
if (mType == DISPLAY_PRIMARY) {
// if (property_get("ro.sf.hwrotation", property, NULL) > 0) {
if (property_get("persist.sf.hwrotation", property, NULL) > 0) {
switch (atoi(property)) {
case 90:
displayOrientation = DisplayState::eOrientation90;
break;
case 180:
displayOrientation = DisplayState::eOrientation180;
break;
case 270:
displayOrientation = DisplayState::eOrientation270;
break;
}
}
}
orientation = (orientation + displayOrientation) % 4;
const int w = mDisplayWidth;
const int h = mDisplayHeight;
..........
}
2.
frameworks/base/services/java/com/android/server/wm/WindowManagerService.java
boolean updateOrientationFromAppTokensLocked(boolean inTransaction)
int req = getOrientationFromWindowsLocked();
if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
req = getOrientationFromAppTokensLocked();
}
if (req != mForcedAppOrientation) {
String str_rotation =SystemProperties.get("persist.sf.hwrotation", "0");
if ("90".equals(str_rotation))
req = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
else if ("180".equals(str_rotation))
req = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
else if ("270".equals(str_rotation))
req = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
else if ("0".equals(str_rotation))
req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
else
req = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
mForcedAppOrientation = req;
这样就修改好了重新编译烧录后 setporp persist.sf.hwrotation 270 点新窗口就发现串口旋转了。
然后再集成到Settng中,为了及时生效点完之后,弹一个Dialog然后再立刻关闭掉,就旋转了,比较简单不演示了。
后面还发现了一个问题,开机动画转了,但是显示的情况不对,后面分析发现在横屏竖屏切换的时候x,y坐标获取我们没有修改,开机动画并不知道这一个情况。
为了方便起见直接改:
frameworks/base/cmds/bootanimation/BootAnimation.cpp
status_t BootAnimation::readyToRun() 里
char value[PROPERTY_VALUE_MAX];
property_get(ROTATION_DIR, value, "0");
uint32_t ortation = atoi(value);
if(ortation/90%2){
uint32_t tmp = dinfo.h;
dinfo.h = dinfo.w;
dinfo.w = tmp;
}
// create the native surface
**sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);**
在createSurface 之前切换 dinfo.w和dinfo.h。
最后发现: DisplayInfo这个结构是记录屏幕x,y和旋转的关键结构,如果需要优雅的改变屏幕旋转的方向应该从这个结构下手,分析framwork才是。懒癌发作,等哪天有时间分析再改吧。