diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 5034ef1dfec5a..73961ff373dd1 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -864,7 +864,8 @@ public final class DisplayManager { if (surface != null) { builder.setSurface(surface); } - return createVirtualDisplay(null /* projection */, builder.build(), callback, handler); + return createVirtualDisplay(null /* projection */, builder.build(), callback, handler, + null /* windowContext */); } // TODO : Remove this hidden API after remove all callers. (Refer to MultiDisplayService) @@ -882,15 +883,17 @@ public final class DisplayManager { if (surface != null) { builder.setSurface(surface); } - return createVirtualDisplay(projection, builder.build(), callback, handler); + return createVirtualDisplay(projection, builder.build(), callback, handler, + null /* windowContext */); } /** @hide */ public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection, @NonNull VirtualDisplayConfig virtualDisplayConfig, - @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { + @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler, + @Nullable Context windowContext) { return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback, - handler); + handler, windowContext); } /** diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java index 2025f40ed20a8..1fec3c9ff50a7 100644 --- a/core/java/android/hardware/display/DisplayManagerGlobal.java +++ b/core/java/android/hardware/display/DisplayManagerGlobal.java @@ -583,7 +583,7 @@ public final class DisplayManagerGlobal { public VirtualDisplay createVirtualDisplay(@NonNull Context context, MediaProjection projection, @NonNull VirtualDisplayConfig virtualDisplayConfig, VirtualDisplay.Callback callback, - Handler handler) { + Handler handler, @Nullable Context windowContext) { VirtualDisplayCallback callbackWrapper = new VirtualDisplayCallback(callback, handler); IMediaProjection projectionToken = projection != null ? projection.getProjection() : null; int displayId; @@ -609,7 +609,7 @@ public final class DisplayManagerGlobal { return null; } return new VirtualDisplay(this, display, callbackWrapper, - virtualDisplayConfig.getSurface()); + virtualDisplayConfig.getSurface(), windowContext); } public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) { diff --git a/core/java/android/hardware/display/VirtualDisplay.java b/core/java/android/hardware/display/VirtualDisplay.java index bf62c95cf6db5..71cbd20e80053 100644 --- a/core/java/android/hardware/display/VirtualDisplay.java +++ b/core/java/android/hardware/display/VirtualDisplay.java @@ -15,6 +15,8 @@ */ package android.hardware.display; +import android.annotation.Nullable; +import android.content.Context; import android.view.Display; import android.view.Surface; @@ -36,13 +38,19 @@ public final class VirtualDisplay { private final Display mDisplay; private IVirtualDisplayCallback mToken; private Surface mSurface; + /** + * Store the WindowContext in a field. If it is a local variable, and it is garbage collected + * during a MediaProjection session, the WindowContainer listener no longer exists. + */ + @Nullable private final Context mWindowContext; VirtualDisplay(DisplayManagerGlobal global, Display display, - IVirtualDisplayCallback token, Surface surface) { + IVirtualDisplayCallback token, Surface surface, Context windowContext) { mGlobal = global; mDisplay = display; mToken = token; mSurface = surface; + mWindowContext = windowContext; } /** diff --git a/media/java/android/media/projection/MediaProjection.java b/media/java/android/media/projection/MediaProjection.java index 353556d70a198..5259c4f07639e 100644 --- a/media/java/android/media/projection/MediaProjection.java +++ b/media/java/android/media/projection/MediaProjection.java @@ -25,6 +25,7 @@ import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.hardware.display.VirtualDisplayConfig; import android.os.Handler; +import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; import android.util.Log; @@ -50,13 +51,6 @@ public final class MediaProjection { private final Context mContext; private final Map mCallbacks; - /** - * Store the WindowContext in a field. If it is a local variable, and it is garbage collected - * during a MediaProjection session, the WindowContainer listener no longer exists. - */ - @Nullable - private Context mWindowContext; - /** @hide */ public MediaProjection(Context context, IMediaProjection impl) { mCallbacks = new ArrayMap(); @@ -107,19 +101,22 @@ public final class MediaProjection { public VirtualDisplay createVirtualDisplay(@NonNull String name, int width, int height, int dpi, boolean isSecure, @Nullable Surface surface, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { - DisplayManager dm = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE); int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR | DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; if (isSecure) { flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; } + Context windowContext = mContext.createWindowContext(mContext.getDisplayNoVerify(), + TYPE_APPLICATION, null /* options */); final VirtualDisplayConfig.Builder builder = buildMirroredVirtualDisplay(name, width, - height, dpi); + height, dpi, windowContext.getWindowContextToken()); builder.setFlags(flags); if (surface != null) { builder.setSurface(surface); } - return dm.createVirtualDisplay(this, builder.build(), callback, handler); + VirtualDisplay virtualDisplay = createVirtualDisplay(builder.build(), callback, handler, + windowContext); + return virtualDisplay; } /** @@ -148,13 +145,17 @@ public final class MediaProjection { public VirtualDisplay createVirtualDisplay(@NonNull String name, int width, int height, int dpi, int flags, @Nullable Surface surface, @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { + Context windowContext = mContext.createWindowContext(mContext.getDisplayNoVerify(), + TYPE_APPLICATION, null /* options */); final VirtualDisplayConfig.Builder builder = buildMirroredVirtualDisplay(name, width, - height, dpi); + height, dpi, windowContext.getWindowContextToken()); builder.setFlags(flags); if (surface != null) { builder.setSurface(surface); } - return createVirtualDisplay(builder.build(), callback, handler); + VirtualDisplay virtualDisplay = createVirtualDisplay(builder.build(), callback, handler, + windowContext); + return virtualDisplay; } /** @@ -168,12 +169,10 @@ public final class MediaProjection { * @return a config representing a VirtualDisplay */ private VirtualDisplayConfig.Builder buildMirroredVirtualDisplay(@NonNull String name, - int width, int height, int dpi) { - mWindowContext = mContext.createWindowContext(mContext.getDisplayNoVerify(), - TYPE_APPLICATION, null /* options */); + int width, int height, int dpi, IBinder windowContextToken) { final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width, height, dpi); - builder.setWindowTokenClientToMirror(mWindowContext.getWindowContextToken()); + builder.setWindowTokenClientToMirror(windowContextToken); return builder; } @@ -183,20 +182,22 @@ public final class MediaProjection { * * @param virtualDisplayConfig The arguments for the virtual display configuration. See * {@link VirtualDisplayConfig} for using it. - * @param callback Callback to call when the virtual display's state - * changes, or null if none. - * @param handler The {@link android.os.Handler} on which the callback should be - * invoked, or null if the callback should be invoked on the calling - * thread's main {@link android.os.Looper}. + * @param callback Callback to call when the virtual display's state changes, or null if none. + * @param handler The {@link android.os.Handler} on which the callback should be invoked, or + * null if the callback should be invoked on the calling thread's main + * {@link android.os.Looper}. + * @param windowContext the WindowContext associated with the caller. * * @see android.hardware.display.VirtualDisplay * @hide */ @Nullable public VirtualDisplay createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig, - @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler) { + @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler, + Context windowContext) { DisplayManager dm = mContext.getSystemService(DisplayManager.class); - return dm.createVirtualDisplay(this, virtualDisplayConfig, callback, handler); + return dm.createVirtualDisplay(this, virtualDisplayConfig, callback, handler, + windowContext); } /** diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java index a713e5b13667d..39d7a1555dfce 100644 --- a/services/core/java/com/android/server/vr/Vr2dDisplay.java +++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java @@ -302,7 +302,8 @@ class Vr2dDisplay { builder.setUniqueId(UNIQUE_DISPLAY_ID); builder.setFlags(flags); mVirtualDisplay = mDisplayManager.createVirtualDisplay(null /* projection */, - builder.build(), null /* callback */, null /* handler */); + builder.build(), null /* callback */, null /* handler */, + null /* windowContext */); if (mVirtualDisplay != null) { updateDisplayId(mVirtualDisplay.getDisplay().getDisplayId());