diff options
4 files changed, 32 insertions, 200 deletions
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig index 6da2a073ec19..1cf42820f356 100644 --- a/core/java/android/companion/virtual/flags/flags.aconfig +++ b/core/java/android/companion/virtual/flags/flags.aconfig @@ -18,13 +18,6 @@ flag { } flag { - namespace: "virtual_devices" - name: "media_projection_keyguard_restrictions" - description: "Auto-stop MP when the device locks" - bug: "348335290" -} - -flag { namespace: "virtual_devices" name: "virtual_display_insets" description: "APIs for specifying virtual display insets (via cutout)" 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 2e0bb4f88485..18f2f48b80a3 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionStopController.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.pm.PackageManager; import android.os.Binder; import android.os.SystemClock; +import android.os.UserHandle; import android.provider.Settings; import android.telecom.TelecomManager; import android.telephony.TelephonyCallback; @@ -38,6 +39,7 @@ import android.view.Display; import com.android.internal.annotations.VisibleForTesting; import com.android.server.SystemConfig; +import java.util.List; import java.util.function.Consumer; /** @@ -60,21 +62,35 @@ public class MediaProjectionStopController { private final TelephonyManager mTelephonyManager; private final AppOpsManager mAppOpsManager; private final PackageManager mPackageManager; - private final RoleManager mRoleManager; + private final RoleHolderProvider mRoleHolderProvider; private final ContentResolver mContentResolver; private boolean mIsInCall; private long mLastCallStartTimeMillis; + + @VisibleForTesting + interface RoleHolderProvider { + List<String> getRoleHoldersAsUser(String roleName, UserHandle user); + } + public MediaProjectionStopController(Context context, Consumer<Integer> stopReasonConsumer) { + this(context, stopReasonConsumer, + (roleName, user) -> context.getSystemService(RoleManager.class) + .getRoleHoldersAsUser(roleName, user)); + } + + @VisibleForTesting + MediaProjectionStopController(Context context, Consumer<Integer> stopReasonConsumer, + RoleHolderProvider roleHolderProvider) { mStopReasonConsumer = stopReasonConsumer; mKeyguardManager = context.getSystemService(KeyguardManager.class); mTelecomManager = context.getSystemService(TelecomManager.class); mTelephonyManager = context.getSystemService(TelephonyManager.class); mAppOpsManager = context.getSystemService(AppOpsManager.class); mPackageManager = context.getPackageManager(); - mRoleManager = context.getSystemService(RoleManager.class); mContentResolver = context.getContentResolver(); + mRoleHolderProvider = roleHolderProvider; } /** @@ -146,8 +162,9 @@ public class MediaProjectionStopController { Slog.v(TAG, "Continuing MediaProjection for package with OP_PROJECT_MEDIA AppOp "); return true; } - if (mRoleManager.getRoleHoldersAsUser(AssociationRequest.DEVICE_PROFILE_APP_STREAMING, - projectionGrant.userHandle).contains(projectionGrant.packageName)) { + if (mRoleHolderProvider.getRoleHoldersAsUser( + AssociationRequest.DEVICE_PROFILE_APP_STREAMING, projectionGrant.userHandle) + .contains(projectionGrant.packageName)) { Slog.v(TAG, "Continuing MediaProjection for package holding app streaming role."); return true; } @@ -177,10 +194,6 @@ public class MediaProjectionStopController { */ public boolean isStartForbidden( MediaProjectionManagerService.MediaProjection projectionGrant) { - if (!android.companion.virtualdevice.flags.Flags.mediaProjectionKeyguardRestrictions()) { - return false; - } - if (!mKeyguardManager.isKeyguardLocked()) { return false; } @@ -194,9 +207,6 @@ public class MediaProjectionStopController { @VisibleForTesting void onKeyguardLockedStateChanged(boolean isKeyguardLocked) { if (!isKeyguardLocked) return; - if (!android.companion.virtualdevice.flags.Flags.mediaProjectionKeyguardRestrictions()) { - return; - } mStopReasonConsumer.accept(STOP_REASON_KEYGUARD); } 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 3ced56a04138..a58a9cd2a28f 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 @@ -34,7 +34,6 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -53,15 +52,11 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.testng.Assert.assertThrows; -import android.Manifest; import android.annotation.SuppressLint; import android.app.ActivityManagerInternal; import android.app.ActivityOptions.LaunchCookie; import android.app.AppOpsManager; -import android.app.Instrumentation; import android.app.KeyguardManager; -import android.app.role.RoleManager; -import android.companion.AssociationRequest; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -76,11 +71,9 @@ import android.media.projection.StopReason; import android.os.Binder; import android.os.IBinder; import android.os.Looper; -import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.os.test.TestLooper; -import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; @@ -99,7 +92,6 @@ import com.android.server.testutils.OffsettableClock; import com.android.server.wm.WindowManagerInternal; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -110,7 +102,6 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import java.util.Objects; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -292,8 +283,6 @@ public class MediaProjectionManagerServiceTest { assertThat(stoppedCallback2).isFalse(); } - @EnableFlags(android.companion.virtualdevice.flags - .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) @Test public void testCreateProjection_keyguardLocked() throws Exception { MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(); @@ -308,8 +297,6 @@ public class MediaProjectionManagerServiceTest { assertThat(mIMediaProjectionCallback.mLatch.await(5, TimeUnit.SECONDS)).isTrue(); } - @EnableFlags(android.companion.virtualdevice.flags - .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) @Test public void testCreateProjection_keyguardLocked_packageAllowlisted() throws NameNotFoundException { @@ -325,8 +312,6 @@ public class MediaProjectionManagerServiceTest { assertThat(mService.getActiveProjectionInfo()).isNotNull(); } - @EnableFlags(android.companion.virtualdevice.flags - .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) @Test public void testCreateProjection_keyguardLocked_AppOpMediaProjection() throws NameNotFoundException { @@ -347,50 +332,6 @@ public class MediaProjectionManagerServiceTest { assertThat(mService.getActiveProjectionInfo()).isNotNull(); } - @EnableFlags(android.companion.virtualdevice.flags - .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) - @Test - public void testCreateProjection_keyguardLocked_RoleHeld() { - runWithRole( - AssociationRequest.DEVICE_PROFILE_APP_STREAMING, - () -> { - try { - mAppInfo.privateFlags |= PRIVATE_FLAG_PRIVILEGED; - doReturn(mAppInfo) - .when(mPackageManager) - .getApplicationInfoAsUser( - anyString(), - any(ApplicationInfoFlags.class), - any(UserHandle.class)); - MediaProjectionManagerService.MediaProjection projection = - mService.createProjectionInternal( - Process.myUid(), - mContext.getPackageName(), - TYPE_MIRRORING, - /* isPermanentGrant= */ false, - UserHandle.CURRENT, - DEFAULT_DISPLAY); - doReturn(true).when(mKeyguardManager).isKeyguardLocked(); - doReturn(PackageManager.PERMISSION_DENIED) - .when(mPackageManager) - .checkPermission(RECORD_SENSITIVE_CONTENT, projection.packageName); - - projection.start(mIMediaProjectionCallback); - projection.notifyVirtualDisplayCreated(10); - - // The projection was started because it was allowed to capture the - // keyguard. - assertWithMessage("Failed to run projection") - .that(mService.getActiveProjectionInfo()) - .isNotNull(); - } catch (NameNotFoundException e) { - throw new RuntimeException(e); - } - }); - } - - @EnableFlags(android.companion.virtualdevice.flags - .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) @Test public void testCreateProjection_keyguardLocked_screenshareProtectionsDisabled() throws NameNotFoundException { @@ -416,8 +357,6 @@ public class MediaProjectionManagerServiceTest { } } - @EnableFlags(android.companion.virtualdevice.flags - .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) @Test public void testCreateProjection_keyguardLocked_noDisplayCreated() throws NameNotFoundException { @@ -509,8 +448,6 @@ public class MediaProjectionManagerServiceTest { assertThat(secondProjection).isNotEqualTo(projection); } - @EnableFlags(android.companion.virtualdevice.flags - .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) @Test public void testReuseProjection_keyguardNotLocked_startConsentDialog() throws NameNotFoundException { @@ -527,8 +464,6 @@ public class MediaProjectionManagerServiceTest { verify(mContext).startActivityAsUser(any(), any()); } - @EnableFlags(android.companion.virtualdevice.flags - .Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) @Test public void testReuseProjection_keyguardLocked_noConsentDialog() throws NameNotFoundException { MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions(); @@ -1302,48 +1237,6 @@ public class MediaProjectionManagerServiceTest { return mService.getProjectionInternal(UID, PACKAGE_NAME); } - /** - * Run the provided block giving the current context's package the provided role. - */ - @SuppressWarnings("SameParameterValue") - private void runWithRole(String role, Runnable block) { - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - String packageName = mContext.getPackageName(); - UserHandle user = instrumentation.getTargetContext().getUser(); - RoleManager roleManager = Objects.requireNonNull( - mContext.getSystemService(RoleManager.class)); - try { - CountDownLatch latch = new CountDownLatch(1); - instrumentation.getUiAutomation().adoptShellPermissionIdentity( - Manifest.permission.MANAGE_ROLE_HOLDERS, - Manifest.permission.BYPASS_ROLE_QUALIFICATION); - - roleManager.setBypassingRoleQualification(true); - roleManager.addRoleHolderAsUser(role, packageName, - /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, - mContext.getMainExecutor(), success -> { - if (success) { - latch.countDown(); - } else { - Assert.fail("Couldn't set role for test (failure) " + role); - } - }); - assertWithMessage("Couldn't set role for test (timeout) : " + role) - .that(latch.await(1, TimeUnit.SECONDS)).isTrue(); - block.run(); - - } catch (InterruptedException e) { - throw new RuntimeException(e); - } finally { - roleManager.removeRoleHolderAsUser(role, packageName, - /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, - mContext.getMainExecutor(), (aBool) -> {}); - roleManager.setBypassingRoleQualification(false); - instrumentation.getUiAutomation() - .dropShellPermissionIdentity(); - } - } - private static class FakeIMediaProjectionCallback extends IMediaProjectionCallback.Stub { CountDownLatch mLatch = new CountDownLatch(1); @Override 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 379079a0018c..10ac0495d69a 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 @@ -22,7 +22,6 @@ import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_ import static android.view.Display.INVALID_DISPLAY; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -37,13 +36,10 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.Manifest; import android.annotation.SuppressLint; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; -import android.app.Instrumentation; import android.app.KeyguardManager; -import android.app.role.RoleManager; import android.companion.AssociationRequest; import android.content.Context; import android.content.pm.ApplicationInfo; @@ -69,7 +65,6 @@ import com.android.server.SystemConfig; import com.android.server.wm.WindowManagerInternal; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -79,9 +74,7 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import java.util.Objects; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import java.util.List; import java.util.function.Consumer; /** @@ -123,6 +116,8 @@ public class MediaProjectionStopControllerTest { private KeyguardManager mKeyguardManager; @Mock private TelecomManager mTelecomManager; + @Mock + private MediaProjectionStopController.RoleHolderProvider mRoleManager; private AppOpsManager mAppOpsManager; @Mock @@ -145,7 +140,7 @@ public class MediaProjectionStopControllerTest { mContext.addMockSystemService(TelecomManager.class, mTelecomManager); mContext.setMockPackageManager(mPackageManager); - mStopController = new MediaProjectionStopController(mContext, mStopConsumer); + mStopController = new MediaProjectionStopController(mContext, mStopConsumer, mRoleManager); mService = new MediaProjectionManagerService(mContext, mMediaProjectionMetricsLoggerInjector); @@ -170,8 +165,6 @@ public class MediaProjectionStopControllerTest { } @Test - @EnableFlags( - android.companion.virtualdevice.flags.Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) public void testMediaProjectionNotRestricted() throws Exception { when(mKeyguardManager.isKeyguardLocked()).thenReturn(false); @@ -180,8 +173,6 @@ public class MediaProjectionStopControllerTest { } @Test - @EnableFlags( - android.companion.virtualdevice.flags.Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) public void testMediaProjectionRestricted() throws Exception { MediaProjectionManagerService.MediaProjection mediaProjection = createMediaProjection(); mediaProjection.notifyVirtualDisplayCreated(1); @@ -239,21 +230,13 @@ public class MediaProjectionStopControllerTest { @Test public void testExemptFromStoppingHasAppStreamingRole() throws Exception { - runWithRole( - AssociationRequest.DEVICE_PROFILE_APP_STREAMING, - () -> { - try { - MediaProjectionManagerService.MediaProjection mediaProjection = - createMediaProjection(); - doReturn(PackageManager.PERMISSION_DENIED).when( - mPackageManager).checkPermission( - RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); - assertThat(mStopController.isExemptFromStopping(mediaProjection, - MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); + MediaProjectionManagerService.MediaProjection mediaProjection = createMediaProjection(); + doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( + RECORD_SENSITIVE_CONTENT, mediaProjection.packageName); + doReturn(List.of(mediaProjection.packageName)).when(mRoleManager).getRoleHoldersAsUser( + eq(AssociationRequest.DEVICE_PROFILE_APP_STREAMING), any(UserHandle.class)); + assertThat(mStopController.isExemptFromStopping(mediaProjection, + MediaProjectionStopController.STOP_REASON_UNKNOWN)).isTrue(); } @Test @@ -316,8 +299,6 @@ public class MediaProjectionStopControllerTest { } @Test - @EnableFlags( - android.companion.virtualdevice.flags.Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) public void testKeyguardLockedStateChanged_unlocked() { mStopController.onKeyguardLockedStateChanged(false); @@ -325,8 +306,6 @@ public class MediaProjectionStopControllerTest { } @Test - @EnableFlags( - android.companion.virtualdevice.flags.Flags.FLAG_MEDIA_PROJECTION_KEYGUARD_RESTRICTIONS) public void testKeyguardLockedStateChanged_locked() { mStopController.onKeyguardLockedStateChanged(true); @@ -438,47 +417,4 @@ public class MediaProjectionStopControllerTest { MediaProjectionManager.TYPE_SCREEN_CAPTURE, false, mContext.getUser(), INVALID_DISPLAY); } - - /** - * Run the provided block giving the current context's package the provided role. - */ - @SuppressWarnings("SameParameterValue") - private void runWithRole(String role, Runnable block) { - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - String packageName = mContext.getPackageName(); - UserHandle user = instrumentation.getTargetContext().getUser(); - RoleManager roleManager = Objects.requireNonNull( - mContext.getSystemService(RoleManager.class)); - try { - CountDownLatch latch = new CountDownLatch(1); - instrumentation.getUiAutomation().adoptShellPermissionIdentity( - Manifest.permission.MANAGE_ROLE_HOLDERS, - Manifest.permission.BYPASS_ROLE_QUALIFICATION); - - roleManager.setBypassingRoleQualification(true); - roleManager.addRoleHolderAsUser(role, packageName, - /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, - mContext.getMainExecutor(), success -> { - if (success) { - latch.countDown(); - } else { - Assert.fail("Couldn't set role for test (failure) " + role); - } - }); - assertWithMessage("Couldn't set role for test (timeout) : " + role) - .that(latch.await(1, TimeUnit.SECONDS)).isTrue(); - block.run(); - - } catch (InterruptedException e) { - throw new RuntimeException(e); - } finally { - roleManager.removeRoleHolderAsUser(role, packageName, - /* flags= */ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, user, - mContext.getMainExecutor(), (aBool) -> { - }); - roleManager.setBypassingRoleQualification(false); - instrumentation.getUiAutomation() - .dropShellPermissionIdentity(); - } - } } |