summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/companion/virtual/flags/flags.aconfig7
-rw-r--r--services/core/java/com/android/server/media/projection/MediaProjectionStopController.java32
-rw-r--r--services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java107
-rw-r--r--services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionStopControllerTest.java86
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();
- }
- }
}