diff options
| author | 2023-09-07 12:44:48 +0000 | |
|---|---|---|
| committer | 2023-09-13 13:45:40 +0000 | |
| commit | 1bc7a32560e8b1485de98289fd35d6a3388c29e6 (patch) | |
| tree | 6aa7e46c59242da7670093cfd0ba4cea96641cf1 | |
| parent | dead0f9ca81872e3a1ccd3e28b4cbea980f3b33c (diff) | |
Stop active MediaProjection callbacks before registering new callbacks
A race condition when starting a new mediaprojection session during an active one was caused by new callbacks being registered then immediately stopped when cleaning up callbacks from the previous session. Instead, existing callbacks should be stopped before new callbacks are registered.
Bug: 279417791
Test: atest FrameworksServicesTests:MediaProjectionManagerServiceTest#testCreateProjection_priorProjectionGrant
Test: smoke test on Felix & Tangor
Change-Id: I7c61f0da14f9be5c5a49792c9b336070b9a40e6e
2 files changed, 26 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index 802a7f2954af..9954a903be5c 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -975,9 +975,6 @@ public final class MediaProjectionManagerService extends SystemService throw new SecurityException("Media projections require a foreground service" + " of type ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION"); } - - mCallback = callback; - registerCallback(mCallback); try { mToken = callback.asBinder(); mDeathEater = () -> { @@ -1022,6 +1019,11 @@ public final class MediaProjectionManagerService extends SystemService } } startProjectionLocked(this); + + // Register new callbacks after stop has been dispatched to previous session. + mCallback = callback; + registerCallback(mCallback); + // Mark this token as used when the app gets the MediaProjection instance. mCountStarts++; } diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java index ddd1221e4c91..b0fd60672853 100644 --- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java @@ -202,6 +202,24 @@ public class MediaProjectionManagerServiceTest { } @Test + public void testCreateProjection_priorProjectionGrant() throws NameNotFoundException { + // Create a first projection. + MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(); + FakeIMediaProjectionCallback callback1 = new FakeIMediaProjectionCallback(); + projection.start(callback1); + + // Create a second projection. + MediaProjectionManagerService.MediaProjection secondProjection = + startProjectionPreconditions(); + FakeIMediaProjectionCallback callback2 = new FakeIMediaProjectionCallback(); + secondProjection.start(callback2); + + // Check that the second projection's callback hasn't been stopped. + assertThat(callback1.mStopped).isTrue(); + assertThat(callback2.mStopped).isFalse(); + } + + @Test public void testCreateProjection_attemptReuse_noPriorProjectionGrant() throws NameNotFoundException { // Create a first projection. @@ -785,8 +803,11 @@ public class MediaProjectionManagerServiceTest { } private static class FakeIMediaProjectionCallback extends IMediaProjectionCallback.Stub { + boolean mStopped = false; + @Override public void onStop() throws RemoteException { + mStopped = true; } @Override |