SpriteController: Reparent pointer surfaces under DisplayContent
When using MediaProjection to mirror a display, only surfaces that are inside the mirrored DisplayContent's hierarcy show up in the mirror surface. Previously, since pointer icons created by SpriteController were not part of SF's hierarcy under the DisplayContent's SurfaceControl, they did not show up in the mirror surface. In this CL, we reparent pointer sprite surfaces to the the DisplayContent's SurfaceControl whenever there are surface changes, ensuring that they show up in screen recordings. Bug: 202258016 Test: manual: Start screen recording from quick settings tile Change-Id: Ib404ed36bd13b0fc8cc4a6fb593dc54b3e35dd1a
This commit is contained in:
@@ -27,10 +27,12 @@ namespace android {
|
||||
|
||||
// --- SpriteController ---
|
||||
|
||||
SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
|
||||
mLooper(looper), mOverlayLayer(overlayLayer) {
|
||||
SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer,
|
||||
ParentSurfaceProvider parentSurfaceProvider)
|
||||
: mLooper(looper),
|
||||
mOverlayLayer(overlayLayer),
|
||||
mParentSurfaceProvider(std::move(parentSurfaceProvider)) {
|
||||
mHandler = new WeakMessageHandler(this);
|
||||
|
||||
mLocked.transactionNestingCount = 0;
|
||||
mLocked.deferredSpriteUpdate = false;
|
||||
}
|
||||
@@ -168,8 +170,7 @@ void SpriteController::doUpdateSprites() {
|
||||
|
||||
// If surface is a new one, we have to set right layer stack.
|
||||
if (update.surfaceChanged || update.state.dirty & DIRTY_DISPLAY_ID) {
|
||||
t.setLayerStack(update.state.surfaceControl,
|
||||
ui::LayerStack::fromValue(update.state.displayId));
|
||||
t.reparent(update.state.surfaceControl, mParentSurfaceProvider(update.state.displayId));
|
||||
needApplyTransaction = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,8 @@ protected:
|
||||
virtual ~SpriteController();
|
||||
|
||||
public:
|
||||
SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
|
||||
using ParentSurfaceProvider = std::function<sp<SurfaceControl>(int /*displayId*/)>;
|
||||
SpriteController(const sp<Looper>& looper, int32_t overlayLayer, ParentSurfaceProvider parent);
|
||||
|
||||
/* Creates a new sprite, initially invisible. */
|
||||
virtual sp<Sprite> createSprite();
|
||||
@@ -245,6 +246,7 @@ private:
|
||||
sp<Looper> mLooper;
|
||||
const int32_t mOverlayLayer;
|
||||
sp<WeakMessageHandler> mHandler;
|
||||
ParentSurfaceProvider mParentSurfaceProvider;
|
||||
|
||||
sp<SurfaceComposerClient> mSurfaceComposerClient;
|
||||
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace android {
|
||||
class MockSpriteController : public SpriteController {
|
||||
|
||||
public:
|
||||
MockSpriteController(sp<Looper> looper) : SpriteController(looper, 0) {}
|
||||
MockSpriteController(sp<Looper> looper)
|
||||
: SpriteController(looper, 0, [](int) { return nullptr; }) {}
|
||||
~MockSpriteController() {}
|
||||
|
||||
MOCK_METHOD(sp<Sprite>, createSprite, (), (override));
|
||||
|
||||
@@ -98,6 +98,7 @@ import android.view.InputMonitor;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.PointerIcon;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.VerifiedInputEvent;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.widget.Toast;
|
||||
@@ -2906,6 +2907,15 @@ public class InputManagerService extends IInputManager.Stub
|
||||
return PointerIcon.getDefaultIcon(getContextForPointerIcon(displayId));
|
||||
}
|
||||
|
||||
// Native callback.
|
||||
private long getParentSurfaceForPointers(int displayId) {
|
||||
final SurfaceControl sc = mWindowManagerCallbacks.getParentSurfaceForPointers(displayId);
|
||||
if (sc == null) {
|
||||
return 0;
|
||||
}
|
||||
return sc.mNativeObject;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Context getContextForPointerIcon(int displayId) {
|
||||
if (mPointerIconDisplayContext != null
|
||||
@@ -3105,6 +3115,12 @@ public class InputManagerService extends IInputManager.Stub
|
||||
* Called when the drag over window has changed.
|
||||
*/
|
||||
void notifyDropWindow(IBinder token, float x, float y);
|
||||
|
||||
/**
|
||||
* Get the {@link SurfaceControl} that should be the parent for the surfaces created for
|
||||
* pointers such as the mouse cursor and touch spots for the given display.
|
||||
*/
|
||||
SurfaceControl getParentSurfaceForPointers(int displayId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.os.IBinder;
|
||||
import android.util.Slog;
|
||||
import android.view.InputApplicationHandle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
|
||||
@@ -234,6 +235,19 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
|
||||
mService.mDragDropController::reportDropWindow, token, x, y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceControl getParentSurfaceForPointers(int displayId) {
|
||||
synchronized (mService.mGlobalLock) {
|
||||
final DisplayContent dc = mService.mRoot.getDisplayContent(displayId);
|
||||
if (dc == null) {
|
||||
Slog.e(TAG, "Failed to get parent surface for pointers on display " + displayId
|
||||
+ " - DisplayContent not found.");
|
||||
return null;
|
||||
}
|
||||
return dc.getOverlayLayer();
|
||||
}
|
||||
}
|
||||
|
||||
/** Waits until the built-in input devices have been configured. */
|
||||
public boolean waitForInputDevicesReady(long timeoutMillis) {
|
||||
synchronized (mInputDevicesReadyMonitor) {
|
||||
|
||||
@@ -129,6 +129,7 @@ static struct {
|
||||
jmethodID getTouchCalibrationForInputDevice;
|
||||
jmethodID getContextForDisplay;
|
||||
jmethodID notifyDropWindow;
|
||||
jmethodID getParentSurfaceForPointers;
|
||||
} gServiceClassInfo;
|
||||
|
||||
static struct {
|
||||
@@ -390,7 +391,7 @@ private:
|
||||
void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
|
||||
void ensureSpriteControllerLocked();
|
||||
int32_t getPointerDisplayId();
|
||||
void updatePointerDisplayLocked();
|
||||
sp<SurfaceControl> getParentSurfaceForPointers(int displayId);
|
||||
static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
|
||||
|
||||
static inline JNIEnv* jniEnv() {
|
||||
@@ -669,6 +670,18 @@ int32_t NativeInputManager::getPointerDisplayId() {
|
||||
return pointerDisplayId;
|
||||
}
|
||||
|
||||
sp<SurfaceControl> NativeInputManager::getParentSurfaceForPointers(int displayId) {
|
||||
JNIEnv* env = jniEnv();
|
||||
jlong nativeSurfaceControlPtr =
|
||||
env->CallLongMethod(mServiceObj, gServiceClassInfo.getParentSurfaceForPointers,
|
||||
displayId);
|
||||
if (checkAndClearExceptionFromCallback(env, "getParentSurfaceForPointers")) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<SurfaceControl*>(nativeSurfaceControlPtr);
|
||||
}
|
||||
|
||||
void NativeInputManager::ensureSpriteControllerLocked() REQUIRES(mLock) {
|
||||
if (mLocked.spriteController == nullptr) {
|
||||
JNIEnv* env = jniEnv();
|
||||
@@ -676,7 +689,9 @@ void NativeInputManager::ensureSpriteControllerLocked() REQUIRES(mLock) {
|
||||
if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) {
|
||||
layer = -1;
|
||||
}
|
||||
mLocked.spriteController = new SpriteController(mLooper, layer);
|
||||
mLocked.spriteController = new SpriteController(mLooper, layer, [this](int displayId) {
|
||||
return getParentSurfaceForPointers(displayId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2504,9 +2519,11 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
"getTouchCalibrationForInputDevice",
|
||||
"(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.getContextForDisplay, clazz,
|
||||
"getContextForDisplay",
|
||||
"(I)Landroid/content/Context;")
|
||||
GET_METHOD_ID(gServiceClassInfo.getContextForDisplay, clazz, "getContextForDisplay",
|
||||
"(I)Landroid/content/Context;");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.getParentSurfaceForPointers, clazz,
|
||||
"getParentSurfaceForPointers", "(I)J");
|
||||
|
||||
// InputDevice
|
||||
|
||||
|
||||
Reference in New Issue
Block a user