MediaProjectionHolder
Holds the MediaProjection token obtained by the host Activity, plus the single VirtualDisplay + ImageReader pair mirroring the screen for it.
The host app must call set after the user grants screen-capture consent (e.g. via MediaProjectionManager.createScreenCaptureIntent()). CaptureScreenTool reads the token from here.
set registers a per-projection MediaProjection.Callback, required for two reasons: the platform requires a callback to be registered before createVirtualDisplay() can be called at all — without one, CaptureScreenTool throws IllegalStateException on every call; and onStop lets this holder clear itself when the user revokes consent via the system's screen-capture notification, instead of holding a dead token that looks valid but isn't. The callback only clears state if the stopping projection is still the current one, so a late onStop from a replaced projection can't wipe out its successor.
One virtual display per projection. On Android 14+ (targetSdk 34+) a MediaProjection may call createVirtualDisplay only once. The holder therefore creates the virtual display lazily on the first capture and keeps it (and its reader) alive for the projection's lifetime; each capture reads the most recent frame. Everything is released when the projection stops, on clear, or when set replaces it.
Properties
Functions
Stores mediaProjection as the active projection token and registers its callback. Any previous projection is unregistered, its virtual display released, and it is stopped. Calling again with the current projection is a no-op.