Loading services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +5 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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() { Loading services/core/java/com/android/server/media/projection/MediaProjectionStopController.java +21 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } /** Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -167,7 +180,7 @@ public class MediaProjectionStopController { return false; } if (isExempt(projectionGrant, true)) { if (isExempt(projectionGrant, STOP_REASON_UNKNOWN, true)) { return false; } return true; Loading @@ -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); } Loading services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java +48 −9 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); Loading @@ -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 Loading @@ -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); } Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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); Loading Loading
services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +5 −1 Original line number Diff line number Diff line Loading @@ -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(); Loading Loading @@ -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() { Loading
services/core/java/com/android/server/media/projection/MediaProjectionStopController.java +21 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } /** Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -167,7 +180,7 @@ public class MediaProjectionStopController { return false; } if (isExempt(projectionGrant, true)) { if (isExempt(projectionGrant, STOP_REASON_UNKNOWN, true)) { return false; } return true; Loading @@ -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); } Loading
services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java +48 −9 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); Loading @@ -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 Loading @@ -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); } Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading @@ -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 Loading Loading @@ -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); Loading