RK3288 6.0 双屏异显,横屏+竖屏由于是横屏+竖屏的组合,目前考虑两种实现方案。1.副屏存在黑边 2.对副屏内容进行拉伸。
默认情况下,我们设置的双屏初始rotation都为Surface.ROTATION_0,因此需将WSM中的updateRotationUncheckedLocked方法的该语句进行屏蔽。
if (mRotateOnBoot) {
mRotation = Surface.ROTATION_0;
rotation = Surface.ROTATION_90;
}
/* display portrait, force android rotation according to 90 */
if("true".equals(SystemProperties.get("persist.display.portrait","false"))){
rotation = Surface.ROTATION_90;
}
//LQH
// rotation = Surface.ROTATION_0;
/* display portrait end */
// if("vr".equals(SystemProperties.get("ro.target.product","tablet")))
// rotation = Surface.ROTATION_0;
if (mRotation == rotation && mAltOrientation == altOrientation) {
// No change.
return false;
}
ro.sf.hwrotation=0 主屏初始方向 (在./native/services/surfaceflinger/SurfaceFlinger.cpp进行赋值)
ro.orientation.einit=90 副屏初始方向
ro.same.orientation=false 主副屏orientaion是否相同
ro.rotation.external=false 副屏是否随主屏旋转
参考http://blog.csdn.net/ljp1205/article/details/53405641,了解Display框架及其初始化过程,主要对Display初始化时的参数进行调整。
该部分的代码在base/services/core/java/com/android/server/display/LocalDisplayAdapter.java的getDisplayDeviceInfoLocked()方法下完成:
@Override
public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
if (mInfo == null) {
SurfaceControl.PhysicalDisplayInfo phys = mDisplayInfos[mActivePhysIndex];
mInfo = new DisplayDeviceInfo();
mInfo.width = phys.width;
mInfo.height = phys.height;
mInfo.modeId = mActiveModeId;
mInfo.defaultModeId = mDefaultModeId;
mInfo.supportedModes = new Display.Mode[mSupportedModes.size()];
for (int i = 0; i < mSupportedModes.size(); i++) {
DisplayModeRecord record = mSupportedModes.valueAt(i);
mInfo.supportedModes[i] = record.mMode;
}
mInfo.colorTransformId = mActiveColorTransformId;
mInfo.defaultColorTransformId = mDefaultColorTransformId;
mInfo.supportedColorTransforms =
new Display.ColorTransform[mSupportedColorTransforms.size()];
for (int i = 0; i < mSupportedColorTransforms.size(); i++) {
mInfo.supportedColorTransforms[i] = mSupportedColorTransforms.valueAt(i);
}
mInfo.appVsyncOffsetNanos = phys.appVsyncOffsetNanos;
mInfo.presentationDeadlineNanos = phys.presentationDeadlineNanos;
mInfo.state = mState;
mInfo.uniqueId = getUniqueId();
// Assume that all built-in displays that have secure output (eg. HDCP) also
// support compositing from gralloc protected buffers.
if (phys.secure) {
mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
| DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
}
if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
final Resources res = getContext().getResources();
mInfo.name = res.getString(
com.android.internal.R.string.display_manager_built_in_display_name);
mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
| DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
if (res.getBoolean(com.android.internal.R.bool.config_mainBuiltInDisplayIsRound)
|| (Build.HARDWARE.contains("goldfish")
&& SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
}
mInfo.type = Display.TYPE_BUILT_IN;
mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
mInfo.xDpi = phys.xDpi;
mInfo.yDpi = phys.yDpi;
mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
} else {
mInfo.type = Display.TYPE_HDMI;
mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
boolean noRotate = "0".equals(SystemProperties.get("ro.sf.hwrotation"));
if(noRotate && mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI){
if (SystemProperties.getBoolean("ro.rotation.external", false)) {
mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
}
String value = SystemProperties.get("ro.orientation.einit");
if ("0".equals(value)) {
mInfo.rotation = Surface.ROTATION_0;
} else if ("90".equals(value)) {
mInfo.rotation = Surface.ROTATION_90;
} else if ("180".equals(value)) {
mInfo.rotation = Surface.ROTATION_180;
} else if ("270".equals(value)) {
mInfo.rotation = Surface.ROTATION_270;
}
}
mInfo.name = getContext().getResources().getString(
com.android.internal.R.string.display_manager_hdmi_display_name);
mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
mInfo.setAssumedDensityForExternalDisplay(phys.width, phys.height);
// For demonstration purposes, allow rotation of the external display.
// In the future we might allow the user to configure this directly.
if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
mInfo.rotation = Surface.ROTATION_270;
}
// For demonstration purposes, allow rotation of the external display
// to follow the built-in display.
if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {
mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
}
}
}
return mInfo;
}
最终显示的frame大小确定,在framework/native/service/surfaceflinger/DisplayDevice.cpp中
bool isHdmiScreen = mType == DisplayDevice::DISPLAY_EXTERNAL;
if (isHdmiScreen) {
int eInitOrientation = 0;
bool isSfHwrotated = false;
bool isSupportRotation = false;
bool isPrimaryExternalSameOrientation = false;
Rect newFrame = Rect(0,0,getWidth(),getHeight());
Rect newFrameRotated = Rect(0,0,getHeight(),getWidth());
float frameRatio = (float)frame.getWidth() / frame.getHeight();
char value[PROPERTY_VALUE_MAX];
property_get("ro.sf.hwrotation", value, "0");
isSfHwrotated = atoi(value) != 0;
property_get("ro.same.orientation", value, "false");
isPrimaryExternalSameOrientation = !strcmp(value,"true");
if(!isSfHwrotated) {
property_get("ro.orientation.einit", value, "0");
eInitOrientation = atoi(value) / 90;
property_get("ro.rotation.external", value, "false");
isSupportRotation = !strcmp(value,"true");
}
if (isSupportRotation && !isPrimaryExternalSameOrientation) {
mClientOrientation = orientation;
if (eInitOrientation % 2 == 1) {
frame = frameRatio > 1.0 ? frame : newFrameRotated;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
} else {
frame = frameRatio > 1.0 ? newFrame : frame;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
} else if (isSupportRotation) {
mClientOrientation = orientation;
if (eInitOrientation % 2 == 1) {
//frame = frameRatio > 1.0 ? frame : frame;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
} else {
frame = frameRatio > 1.0 ? newFrame : newFrameRotated;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
} else if (eInitOrientation % 2 != 0) {
if (isPrimaryExternalSameOrientation) {
//frame = frameRatio > 1.0 ? frame : frame;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
} else {
//应该走的这里
frame = frameRatio > 1.0 ? frame : newFrameRotated;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
} else if (eInitOrientation % 2 == 0) {
if (isPrimaryExternalSameOrientation) {
frame = frameRatio > 1.0 ? newFrame : frame;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
} else {
frame = frameRatio > 1.0 ? newFrame : frame;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
} else {
frame = frameRatio > 1.0 ? newFrame : frame;
ALOGE("%d,[%d,%d]",__LINE__,frame.getWidth(),frame.getHeight());
}
ALOGE("update frame [%d,%d]",frame.getWidth(),frame.getHeight());
}
根据具体情况进行配置,即可实现 双屏异显,横屏+竖屏,竖屏存在黑边的效果。在上面的补丁中,可对frame进行强制定义为副屏大小,则可以实现拉伸效果,填充黑边。
frame=Rect(0,0,getHeight(),getWidth());
但两块屏幕比例相差较大的情况下,拉伸显示的效果较差。
注:在设置中将g-sensor的旋转功能关闭,旋转对上述实现存在一定影响。