背景:
针对READ_FRAME_BUFFER的权限原理剖析前面文章已经进行了详细讲解,具体文章如下:
但是文章也给大家留下了一个疑问,那就是具有READ_FRAME_BUFFER权限到底是否可以截图到手机上secure画面,比如银行等密码手势画面。
针对这个疑问也进行了直播讲解和验证,答案就是READ_FRAME_BUFFER权限确实可以实现对这些敏感隐私画面进行截图。
下面给大家展示相关的源码,大家也可以自行用下面源码进行验证你的设备是否可以截图成果。
直播代码分享:
要进行截图secure layer的接口分享:
frameworks/base/core/java/android/window/ScreenCapture.java
cpp
/**
* Whether to allow the screenshot of secure layers. Warning: This should only be done
* if the content will be placed in a secure SurfaceControl.
*
* @see ScreenshotHardwareBuffer#containsSecureLayers()
*/
public T setCaptureSecureLayers(boolean captureSecureLayers) {
mCaptureSecureLayers = captureSecureLayers;
return getThis();
}
注释可以看出是可以截图安全的layer到sc。
不使用setCaptureSecureLayers截图代码如下:
cpp
public static Bitmap captureScreenshot() {
try {
final ScreenCapture.CaptureArgs captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
.setSourceCrop(new Rect(0,0,2960,1440))
.build();
ScreenCapture.SynchronousScreenCaptureListener syncScreenCapture =
ScreenCapture.createSyncCaptureListener();
try {
WindowManagerGlobal.getWindowManagerService().captureDisplay(0,
captureArgs, syncScreenCapture);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
final ScreenCapture.ScreenshotHardwareBuffer screenshotHardwareBuffer =
syncScreenCapture.getBuffer();
return screenshotHardwareBuffer.asBitmap();
} finally {
}
}
保存图片到sdcard私有目录方法:
cpp
public static String saveBitmap(Context context, Bitmap bitmap,
String subDir, String fileName) {
File baseDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
if (baseDir == null) return null;
File targetDir = new File(baseDir, subDir);
if (!targetDir.exists()) targetDir.mkdirs();
File imageFile = new File(targetDir, fileName + ".jpg");
try (FileOutputStream fos = new FileOutputStream(imageFile)) {
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
return imageFile.getAbsolutePath();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
调用方式:
cpp
CaptureScreenshotUtil.saveBitmap(MainActivity.this, CaptureScreenshotUtil.captureScreenshot(),"aaa","test");
权限声明:
bash
<uses-permission android:name="android.permission.READ_FRAME_BUFFER"></uses-permission>
注意需要基于源码编译apk,系统签名安装。
验证得到的结果
原设备画面展示:

截图到图片展示如下

明显看到手势密码部分的Activity是无法被截图到的,这块与豆包官方声明基本上一致。
但是真的是这样吗?
使用setCaptureSecureLayers后截图情况
代码上只是在原来基础上加入setCaptureSecureLayers(true)
cpp
try {
final ScreenCapture.CaptureArgs captureArgs = new ScreenCapture.CaptureArgs.Builder<>()
.setSourceCrop(new Rect(0,0,2960,1440))
//重点差异
.setCaptureSecureLayers(true)
.build();
ScreenCapture.SynchronousScreenCaptureListener syncScreenCapture =
ScreenCapture.createSyncCaptureListener();
try {
WindowManagerGlobal.getWindowManagerService().captureDisplay(0,
captureArgs, syncScreenCapture);
} catch (RemoteException e) {
Log.e("lsm666888", "Failed to request screencapture for display");
e.rethrowAsRuntimeException();
}
final ScreenCapture.ScreenshotHardwareBuffer screenshotHardwareBuffer =
syncScreenCapture.getBuffer();
return screenshotHardwareBuffer.asBitmap();
} finally {
}
运行后进行截图,效果如下:

可以看出明显这次截图是可以截图到手势密码的画面了,所以最后的结论就是如下:
READ_FRAME_BUFFER权限确实是需要系统签名才可以使用的,默认不设置setCaptureSecureLayers(true)那确实无法截图到手势密码等secure画面,但是如果设置了setCaptureSecureLayers(true)就可以截图到各个secure的内容。
所以READ_FRAME_BUFFER权限是可以截图到各个手势密码等高度隐私的画面。