diff options
3 files changed, 74 insertions, 14 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 c460465bfb11..fce008c23350 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -175,7 +175,7 @@ public final class MediaProjectionManagerService extends SystemService private void maybeStopMediaProjection(int reason) { synchronized (mLock) { - if (!mMediaProjectionStopController.isExemptFromStopping(mProjectionGrant)) { + if (!mMediaProjectionStopController.isExemptFromStopping(mProjectionGrant, reason)) { Slog.d(TAG, "Content Recording: Stopping MediaProjection due to " + MediaProjectionStopController.stopReasonToString(reason)); mProjectionGrant.stop(); @@ -1272,6 +1272,10 @@ public final class MediaProjectionManagerService extends SystemService return mDisplayId; } + long getCreateTimeMillis() { + return mCreateTimeMs; + } + @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_MEDIA_PROJECTION) @Override public boolean isValid() { diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java b/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java index f5b26c41015e..c018e6bc1dc7 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java @@ -27,6 +27,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; +import android.os.SystemClock; import android.provider.Settings; import android.telecom.TelecomManager; import android.telephony.TelephonyCallback; @@ -46,6 +47,8 @@ public class MediaProjectionStopController { private static final String TAG = "MediaProjectionStopController"; @VisibleForTesting + static final int STOP_REASON_UNKNOWN = 0; + @VisibleForTesting static final int STOP_REASON_KEYGUARD = 1; @VisibleForTesting static final int STOP_REASON_CALL_END = 2; @@ -61,6 +64,7 @@ public class MediaProjectionStopController { private final ContentResolver mContentResolver; private boolean mIsInCall; + private long mLastCallStartTimeMillis; public MediaProjectionStopController(Context context, Consumer<Integer> stopReasonConsumer) { mStopReasonConsumer = stopReasonConsumer; @@ -95,8 +99,8 @@ public class MediaProjectionStopController { * Checks whether the given projection grant is exempt from stopping restrictions. */ public boolean isExemptFromStopping( - MediaProjectionManagerService.MediaProjection projectionGrant) { - return isExempt(projectionGrant, false); + MediaProjectionManagerService.MediaProjection projectionGrant, int stopReason) { + return isExempt(projectionGrant, stopReason, false); } /** @@ -110,7 +114,8 @@ public class MediaProjectionStopController { * MediaProjection session */ private boolean isExempt( - MediaProjectionManagerService.MediaProjection projectionGrant, boolean forStart) { + MediaProjectionManagerService.MediaProjection projectionGrant, int stopReason, + boolean forStart) { if (projectionGrant == null || projectionGrant.packageName == null) { return true; } @@ -151,6 +156,14 @@ public class MediaProjectionStopController { return true; } + if (stopReason == STOP_REASON_CALL_END + && projectionGrant.getCreateTimeMillis() < mLastCallStartTimeMillis) { + Slog.v(TAG, + "Continuing MediaProjection as (phone) call started after MediaProjection was" + + " created."); + return true; + } + return false; } @@ -167,7 +180,7 @@ public class MediaProjectionStopController { return false; } - if (isExempt(projectionGrant, true)) { + if (isExempt(projectionGrant, STOP_REASON_UNKNOWN, true)) { return false; } return true; @@ -188,9 +201,13 @@ public class MediaProjectionStopController { return; } boolean isInCall = mTelecomManager.isInCall(); + if (isInCall) { + mLastCallStartTimeMillis = SystemClock.uptimeMillis(); + } if (isInCall == mIsInCall) { return; } + if (mIsInCall && !isInCall) { mStopReasonConsumer.accept(STOP_REASON_CALL_END); } diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java index 89d2d2847007..affcfc14034e 100644 --- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java @@ -194,12 +194,14 @@ public class MediaProjectionStopControllerTest { @Test public void testExemptFromStoppingNullProjection() throws Exception { - assertThat(mStopController.isExemptFromStopping(null)).isTrue(); + assertThat(mStopController.isExemptFromStopping(null, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } @Test public void testExemptFromStoppingInvalidProjection() throws Exception { - assertThat(mStopController.isExemptFromStopping(createMediaProjection(null))).isTrue(); + assertThat(mStopController.isExemptFromStopping(createMediaProjection(null), + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } @Test @@ -213,7 +215,8 @@ public class MediaProjectionStopControllerTest { Settings.Global.putInt(mContext.getContentResolver(), DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, 1); - assertThat(mStopController.isExemptFromStopping(mediaProjection)).isTrue(); + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } finally { Settings.Global.putInt(mContext.getContentResolver(), DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS, value); @@ -230,7 +233,8 @@ public class MediaProjectionStopControllerTest { eq(mediaProjection.uid), eq(mediaProjection.packageName), nullable(String.class), nullable(String.class)); - assertThat(mStopController.isExemptFromStopping(mediaProjection)).isTrue(); + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } @Test @@ -244,7 +248,8 @@ public class MediaProjectionStopControllerTest { doReturn(PackageManager.PERMISSION_DENIED).when( mPackageManager).checkPermission( RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); - assertThat(mStopController.isExemptFromStopping(mediaProjection)).isTrue(); + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } catch (Exception e) { throw new RuntimeException(e); } @@ -261,7 +266,8 @@ public class MediaProjectionStopControllerTest { packages.valueAt(0)); doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); - assertThat(mStopController.isExemptFromStopping(mediaProjection)).isTrue(); + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } @Test @@ -270,7 +276,8 @@ public class MediaProjectionStopControllerTest { PACKAGE_NAME); doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); - assertThat(mStopController.isExemptFromStopping(mediaProjection)).isTrue(); + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } @Test @@ -278,7 +285,8 @@ public class MediaProjectionStopControllerTest { MediaProjectionManagerService.MediaProjection mediaProjection = createMediaProjection(); doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); - assertThat(mStopController.isExemptFromStopping(mediaProjection)).isTrue(); + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } @Test @@ -287,7 +295,8 @@ public class MediaProjectionStopControllerTest { mediaProjection.notifyVirtualDisplayCreated(1); doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); - assertThat(mStopController.isExemptFromStopping(mediaProjection)).isFalse(); + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isFalse(); } @Test @@ -368,6 +377,36 @@ public class MediaProjectionStopControllerTest { verify(mStopConsumer).accept(MediaProjectionStopController.STOP_REASON_CALL_END); } + @Test + @EnableFlags(com.android.media.projection.flags.Flags.FLAG_STOP_MEDIA_PROJECTION_ON_CALL_END) + public void testExemptFromStopping_callEnd_callBeforeMediaProjection() throws Exception { + when(mTelecomManager.isInCall()).thenReturn(true); + mStopController.callStateChanged(); + + MediaProjectionManagerService.MediaProjection mediaProjection = createMediaProjection(); + mediaProjection.notifyVirtualDisplayCreated(1); + doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( + RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); + + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_CALL_END)).isFalse(); + } + + @Test + @EnableFlags(com.android.media.projection.flags.Flags.FLAG_STOP_MEDIA_PROJECTION_ON_CALL_END) + public void testExemptFromStopping_callEnd_callAfterMediaProjection() throws Exception { + MediaProjectionManagerService.MediaProjection mediaProjection = createMediaProjection(); + mediaProjection.notifyVirtualDisplayCreated(1); + doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( + RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); + + when(mTelecomManager.isInCall()).thenReturn(true); + mStopController.callStateChanged(); + + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_CALL_END)).isTrue(); + } + private MediaProjectionManagerService.MediaProjection createMediaProjection() throws NameNotFoundException { return createMediaProjection(PACKAGE_NAME); |