为了能够更动感的去学习WMS窗口概念,这里我们从应用的图像画面获取来认识WindowState,作为WMS学习的一个突破口,现在暂时记住下面这句话,
WindowState是WMS中的一个对象,保存了APP窗口相关信息。
保存了窗口相关信息?图像信息也包含么?答案是包含了的,我们可以从WindowState里获取到应用的GrahpicBuffer,进而保存期图像画面。(使用SurfaceControl相关方法)
在【Android】使用SurfaceControl.captureLayers获取应用图像Layer试验 里面
试验了调用WallPaperControll的方法Bitmap screenshotWallpaperLocked()方法来保存WapllPaper图像,
这个方法里通过SurfaceControl.captureLayers调用,传入wallpaperWindowState.getSurfaceControl().getHandle(),得到了相应的GraphicBuffer,
SurfaceControl.captureLayers( wallpaperWindowState.getSurfaceControl().getHandle(), bounds, 1 /* frameScale */);
695 /**
696 * Take a screenshot of the wallpaper if it's visible.
697 *
698 * @return Bitmap of the wallpaper
699 */
700 Bitmap screenshotWallpaperLocked() {
701 if (!mService.mPolicy.isScreenOn()) {
702 if (DEBUG_SCREENSHOT) {
703 Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
704 }
705 return null;
706 }
707
708 final WindowState wallpaperWindowState = getTopVisibleWallpaper();
709 if (wallpaperWindowState == null) {
710 if (DEBUG_SCREENSHOT) {
711 Slog.i(TAG_WM, "No visible wallpaper to screenshot");
712 }
713 return null;
714 }
715
716 final Rect bounds = wallpaperWindowState.getBounds();
717 bounds.offsetTo(0, 0);
718
719 GraphicBuffer wallpaperBuffer = SurfaceControl.captureLayers(
720 wallpaperWindowState.getSurfaceControl().getHandle(), bounds, 1 /* frameScale */);
721
722 if (wallpaperBuffer == null) {
723 Slog.w(TAG_WM, "Failed to screenshot wallpaper");
724 return null;
725 }
726 return Bitmap.createHardwareBitmap(wallpaperBuffer);
727 }
这里给了我们启发,WindowState.getSurfaceControl()方法可以获取到应用SurfaceControl相关内容,进而获取到应用图像。
命令dumpsys window windows可以查看到WIndowState的信息,如
WINDOW MANAGER WINDOWS (dumpsys window windows)
Window #0 Window{bb28569 u0 ScreenDecorOverlayBottom}:
mDisplayId=0 rootTaskId=1 mSession=Session{d35f7c7 3452:u0a10142} mClient=android.os.BinderProxy@1b679d8
mOwnerUid=10142 showForAllUsers=true package=com.android.systemui appop=NONE
mAttrs={(0,0)(fillxwrap) gr=BOTTOM CENTER_VERTICAL sim={adjust=pan} layoutInDisplayCutoutMode=always ty=NAVIGATION_BAR_PANEL fmt=TRANSLUCENT
fl=NOT_FOCUSABLE NOT_TOUCHABLE NOT_TOUCH_MODAL LAYOUT_IN_SCREEN SPLIT_TOUCH FLAG_SLIPPERY
pfl=SHOW_FOR_ALL_USERS NO_MOVE_ANIMATION IS_ROUNDED_CORNERS_OVERLAY COLOR_SPACE_AGNOSTIC USE_BLAST FIT_INSETS_CONTROLLED TRUSTED_OVERLAY
vsysui=LAYOUT_STABLE
bhv=DEFAULT}
Requested w=1080 h=66 mLayoutSeq=125
一个比较朴素的试验,可以在WindowState的dump方法里,添加SurfaceControl.captureLayers方法,获取到相应的GraphicBuffer,再仿照 Bitmap screenshotWallpaperLocked()里的处理,调用
Bitmap.createHardwareBitmap方法,转换为Bitmap对象,再调用Bitmap的compress方法,就可以保存图像了。
3305 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3306 final TaskStack stack = getStack();
3307 pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId());
3308 if (stack != null) {
3309 pw.print(" stackId="); pw.print(stack.mStackId);
3310 }
3311 pw.print(" mSession="); pw.print(mSession);
3312 pw.print(" mClient="); pw.println(mClient.asBinder());
3313 pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
3314 pw.print(" mShowToOwnerOnly="); pw.print(mShowToOwnerOnly);
3315 pw.print(" package="); pw.print(mAttrs.packageName);
3316 pw.print(" appop="); pw.println(AppOpsManager.opToName(mAppOp));
3317 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs.toString(prefix));
3318 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
3319 pw.print(" h="); pw.print(mRequestedHeight);
这个就很直观的展现了WindowState和应用surface相关联系。也说明,WMS有能力获取到应用图像。
WMS在创建窗口的时候创建WIndowState,并且告诉SurfaceFlinger去创建Surface对象,提供给App去绘图。
Surface联系如下:
参考资料:
https://blog.csdn.net/yangwen123/article/details/80674965?spm=1001.2014.3001.5502