众所周知,android为了保护用户隐私,有一个属性可以防止截屏,不过这个属性只能在应用中使用,如果直接攻击系统,还是可以获取截屏的。
两种截屏方式:
一、通过目前应用市场中的截屏软件(截屏大师),获取到了其调用的截屏接口MediaProjection类
二、系统截屏:开机键+音量下
屏蔽方法:
针对一:必走applyVirtualDisplayFlags(),添加flag,使之截屏为空白或者一片黑,ADT的monitor工具也无法截屏咯!
@Override // Binder call
public int applyVirtualDisplayFlags(int flags) {
if (mType == MediaProjectionManager.TYPE_SCREEN_CAPTURE) {
flags &= ~DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
| DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION;
// + {
if (!SystemProperties.getBoolean("ro.allow.screenshot", true)) {
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
}
// + }
return flags;
}
...
}
针对二:
具体截屏流程参考
最后会调用到:
ISurfaceComposer.cpp(/frameworks/native/libs/gui)
virtual status_t captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ,
bool useIdentityTransform,
ISurfaceComposer::Rotation rotation)
{
// + {
char value[PROPERTY_VALUE_MAX];
property_get("ro.allow.screenshot", value, "true");
if (strncmp(value, "true", 4) != 0) {
return NULL;
}
// + }
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
data.writeStrongBinder(IInterface::asBinder(producer));
data.write(sourceCrop);
data.writeUint32(reqWidth);
data.writeUint32(reqHeight);
data.writeUint32(minLayerZ);
data.writeUint32(maxLayerZ);
data.writeInt32(static_cast<int32_t>(useIdentityTransform));
data.writeInt32(static_cast<int32_t>(rotation));
remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
return reply.readInt32();
}