android 系统定制之多屏幕尺寸
背景是我们的系统支持多luncher,然后希望每个luncher都有一个分辨率。这两天追了一下代码发现修改的东西主要集中在 WindowManagerService 。
我们知道,android提供了很便利的修改屏幕分辨率的方法
adb shell wm size 1080x1920
adb shell wm density 360
adb shell wm size reset
adb shell wm density reset
在android 应用中是这样拿屏幕尺寸的:
WindowManager wm = (WindowManager) activity
.getSystemService(Context.WINDOW_SERVICE);
Point point = new Point();
wm.getDefaultDisplay().getRealSize(point);
StringBuilder sb = new StringBuilder();
sb.append("width:").append(wm.getDefaultDisplay().getWidth()
).append(",height:").append(wm.getDefaultDisplay().getHeight());
sb.append("\nx:").append(point.x).append(",y:").append(point.y);
WindowManager wm1 = activity.getWindowManager();
sb.append("\nwidth:").append(wm1.getDefaultDisplay().getWidth()
).append(",height:").append(wm1.getDefaultDisplay().getHeight());
WindowManager manager = activity.getWindowManager();
DisplayMetrics outMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(outMetrics);
sb.append("\nwidth:").append(outMetrics.widthPixels
).append(",height:").append(outMetrics.heightPixels);
Resources resources = activity.getResources();
DisplayMetrics dm = resources.getDisplayMetrics();
sb.append("\nwidth:").append(dm.widthPixels
).append(",height:").append(dm.heightPixels
).append(",density").append(dm.density);
Rect rect = new Rect();
rootView.getWindowVisibleDisplayFrame(rect);
sb.append("\nwidth:").append(rect.width()
).append(",height:").append(rect.height());
sb.append(hasNavBar(activity) ? "\nhas" : "\nno").append(" virtual keyboard");
Log.e("ScreenUtil", sb.toString());
调用栈很长,不列出来了,从wm到app,跨进程调用的是:
/frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
@Override
public void setDisplayInfoOverrideFromWindowManager(int displayId, DisplayInfo info) {
setDisplayInfoOverrideFromWindowManagerInternal(displayId, info);
}
private void setDisplayInfoOverrideFromWindowManagerInternal(
int displayId, DisplayInfo info) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
if (display != null) {
if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) {
sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_CHANGED);
scheduleTraversalLocked(false);
}
}
}
}
./frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
/** Do not call if mDisplayReady == false */
DisplayInfo updateDisplayAndOrientationLocked() {
...
mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
displayContent.getDisplayId(), displayInfo);
...
}
private DisplayContent newDisplayContentLocked(final Display display) {
DisplayContent displayContent = new DisplayContent(display, this);
final int displayId = display.getDisplayId();
if (DEBUG_DISPLAY) Slog.v(TAG, "Adding display=" + display);
mDisplayContents.put(displayId, displayContent);
DisplayInfo displayInfo = displayContent.getDisplayInfo();
final Rect rect = new Rect();
mDisplaySettings.getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
synchronized (displayContent.mDisplaySizeLock) {
displayInfo.overscanLeft = rect.left;
displayInfo.overscanTop = rect.top;
displayInfo.overscanRight = rect.right;
displayInfo.overscanBottom = rect.bottom;
mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
displayId, displayInfo);
}
configureDisplayPolicyLocked(displayContent);
// TODO: Create an input channel for each display with touch capability.
if (displayId == Display.DEFAULT_DISPLAY) {
displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent);
registerPointerEventListener(displayContent.mTapDetector);
}
return displayContent;
}
那么就是修改下 setDisplayInfoOverrideFromWindowManager 的方法就可以了。但是修改了之后,目测事件的分法会乱掉。
点击事件的映射,回头弄完再说吧。
查了一下api,发现android8完整的实现了这个功能