【Android】使用SurfaceControl.captureLayers获取应用图像Layer试验

https://blog.csdn.net/aaajj/article/details/93653074

https://blog.csdn.net/aaajj/article/details/102537628

https://blog.csdn.net/aaajj/article/details/113076275

 

里面讨论了从SurfaceFlinger中获取layer图像的一个试验

采用的方法是直接获取GraphicBuffer,进而找到数据地址来获取图片进行保存,

这样的操作可以加深对GrapicBuffer的理解,其实获取layer,系统里已经提供了相应的方法,在查看截图程序screencap关注SurfaceFlinger程序的时候,注意到里面有方法


4727 status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder

 

在里SurfaceControl.java也有方法

1323 public static GraphicBuffer captureLayers(IBinder layerHandleToken, Rect sourceCrop,

 

 

我们来找一下系统中有没有调用,

 

找到了2个调用的地方

/frameworks/base/services/core/java/com/android/server/wm/

H A D

TaskSnapshotController.java

268 final GraphicBuffer buffer = SurfaceControl.captureLayers(

H A D

WallpaperController.java

719 GraphicBuffer wallpaperBuffer = SurfaceControl.captureLayers(

 

WallpaperController.java为例

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
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    }

 

 

这个方法里获取到了wallpaper的layer的GraphicBuffer对象,Bitmap里面竟然还有方法可以把GraphicBuffer转换为Bitmap对象,看起来很强大。

 

我们再看看哪里调用的screenshotWallpaperLocked方法

如果我们调用这个方法,就可以获取这个Bitmap对象来保存图片,这样就可以查看这个方法的实际效果。

 

WindowManagerService.java里有调用

3689    public Bitmap screenshotWallpaper() {
3690        if (!checkCallingPermission(READ_FRAME_BUFFER, "screenshotWallpaper()")) {
3691            throw new SecurityException("Requires READ_FRAME_BUFFER permission");
3692        }
3693        try {
3694            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "screenshotWallpaper");
3695            synchronized (mWindowMap) {
3696                return mRoot.mWallpaperController.screenshotWallpaperLocked();
3697            }
3698        } finally {
3699            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
3700        }
3701    }

 

 

这个方法没有提供对外的接口,我们不方便在app里调用这个方法,

我们可以在WMS的dump方法里来进行调用测试,

 

获取到Bitmap对象后,调用其compress方法来保存图片,注意,由于wms所在的进程system_server的用户名是 system,不能写/sdcard目录,我们需要保存文件到/data/anr 这样user是system的路径下,当然,手机最好root下,便于我们查看/data里各目录的信息

 

通过dumpsys window命令来进行调用触发

我们可以看到,图片被获取保存了,pull到电脑上查看,就是wallpaper图片

 

通过这个试验,我们可以了解到cartureLaryers方法的使用,其参数IBinder handle,看起来是对应的surfaceControl对象,这个需要我们继续探索了解。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值