From 3733ec3be4259c2473cd9e8816b6b54e70c084f4 Mon Sep 17 00:00:00 2001 From: Nick Chameyev Date: Thu, 26 Jan 2023 17:11:06 +0000 Subject: [PATCH] [Partial Screensharing] Handle enterprise policies Adds a logic that shows/hides work profile or personal profile tabs in partial screen sharing when it is not allowed to capture the screen. Adds a logic that shows screen capture disabled dialog when we can't even start the app picker dialog (when we can't capture the screen completely). Bug: 233348916 Test: manual testing using TestDPC with various device policies (disabled screen capture on work profile, on fully managed device, disallow sharing into managed profile policy), starting screen sharing from work or personal profile host app Test: com.android.systemui.screenrecord.RecordingControllerTest Test: com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolverTest Change-Id: Ib732826a977c560318ff147d630d426c0828b3bd --- .../MediaProjectionAppSelectorActivity.kt | 14 ++- .../MediaProjectionPermissionActivity.java | 68 ++++++++++++--- .../MediaProjectionAppSelectorComponent.kt | 11 ++- .../systemui/qs/tiles/ScreenRecordTile.java | 3 +- .../screenrecord/RecordingController.java | 36 +++++++- .../ScreenRecordPermissionDialog.kt | 5 +- .../screenrecord/RecordingControllerTest.java | 85 ++++++++++++++++++- .../ScreenRecordPermissionDialogTest.kt | 2 + 8 files changed, 197 insertions(+), 27 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt index a692ad74615fc..52d417140e04b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt @@ -28,12 +28,15 @@ import android.os.ResultReceiver import android.os.UserHandle import android.view.ViewGroup import com.android.internal.annotations.VisibleForTesting +import com.android.internal.app.AbstractMultiProfilePagerAdapter.EmptyStateProvider import com.android.internal.app.AbstractMultiProfilePagerAdapter.MyUserIdProvider import com.android.internal.app.ChooserActivity import com.android.internal.app.ResolverListController import com.android.internal.app.chooser.NotSelectableTargetInfo import com.android.internal.app.chooser.TargetInfo import com.android.systemui.R +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorComponent import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorController import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler @@ -47,6 +50,7 @@ import javax.inject.Inject class MediaProjectionAppSelectorActivity( private val componentFactory: MediaProjectionAppSelectorComponent.Factory, private val activityLauncher: AsyncActivityLauncher, + private val featureFlags: FeatureFlags, /** This is used to override the dependency in a screenshot test */ @VisibleForTesting private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)? @@ -56,7 +60,8 @@ class MediaProjectionAppSelectorActivity( constructor( componentFactory: MediaProjectionAppSelectorComponent.Factory, activityLauncher: AsyncActivityLauncher, - ) : this(componentFactory, activityLauncher, null) + featureFlags: FeatureFlags + ) : this(componentFactory, activityLauncher, featureFlags, listControllerFactory = null) private lateinit var configurationController: ConfigurationController private lateinit var controller: MediaProjectionAppSelectorController @@ -91,6 +96,13 @@ class MediaProjectionAppSelectorActivity( override fun appliedThemeResId(): Int = R.style.Theme_SystemUI_MediaProjectionAppSelector + override fun createBlockerEmptyStateProvider(): EmptyStateProvider = + if (featureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) { + component.emptyStateProvider + } else { + super.createBlockerEmptyStateProvider() + } + override fun createListController(userHandle: UserHandle): ResolverListController = listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java index d830fc4a5fb5d..c4e76b203f195 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java @@ -45,33 +45,46 @@ import android.text.style.StyleSpan; import android.util.Log; import android.view.Window; -import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; +import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver; +import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog; import com.android.systemui.screenrecord.MediaProjectionPermissionDialog; import com.android.systemui.screenrecord.ScreenShareOption; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.util.Utils; +import javax.inject.Inject; + +import dagger.Lazy; + public class MediaProjectionPermissionActivity extends Activity implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener { private static final String TAG = "MediaProjectionPermissionActivity"; private static final float MAX_APP_NAME_SIZE_PX = 500f; private static final String ELLIPSIS = "\u2026"; + private final FeatureFlags mFeatureFlags; + private final Lazy mScreenCaptureDevicePolicyResolver; + private String mPackageName; private int mUid; private IMediaProjectionManager mService; - private FeatureFlags mFeatureFlags; private AlertDialog mDialog; + @Inject + public MediaProjectionPermissionActivity(FeatureFlags featureFlags, + Lazy screenCaptureDevicePolicyResolver) { + mFeatureFlags = featureFlags; + mScreenCaptureDevicePolicyResolver = screenCaptureDevicePolicyResolver; + } + @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); - mFeatureFlags = Dependency.get(FeatureFlags.class); mPackageName = getCallingPackage(); IBinder b = ServiceManager.getService(MEDIA_PROJECTION_SERVICE); mService = IMediaProjectionManager.Stub.asInterface(b); @@ -104,6 +117,12 @@ public class MediaProjectionPermissionActivity extends Activity return; } + if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) { + if (showScreenCaptureDisabledDialogIfNeeded()) { + return; + } + } + TextPaint paint = new TextPaint(); paint.setTextSize(42); @@ -171,16 +190,7 @@ public class MediaProjectionPermissionActivity extends Activity mDialog = dialogBuilder.create(); } - SystemUIDialog.registerDismissListener(mDialog); - SystemUIDialog.applyFlags(mDialog); - SystemUIDialog.setDialogSize(mDialog); - - mDialog.setOnCancelListener(this); - mDialog.create(); - mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true); - - final Window w = mDialog.getWindow(); - w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + setUpDialog(mDialog); mDialog.show(); } @@ -200,6 +210,32 @@ public class MediaProjectionPermissionActivity extends Activity } } + private void setUpDialog(AlertDialog dialog) { + SystemUIDialog.registerDismissListener(dialog); + SystemUIDialog.applyFlags(dialog); + SystemUIDialog.setDialogSize(dialog); + + dialog.setOnCancelListener(this); + dialog.create(); + dialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true); + + final Window w = dialog.getWindow(); + w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + } + + private boolean showScreenCaptureDisabledDialogIfNeeded() { + final UserHandle hostUserHandle = getHostUserHandle(); + if (mScreenCaptureDevicePolicyResolver.get() + .isScreenCaptureCompletelyDisabled(hostUserHandle)) { + AlertDialog dialog = new ScreenCaptureDisabledDialog(this); + setUpDialog(dialog); + dialog.show(); + return true; + } + + return false; + } + private void grantMediaProjectionPermission(int screenShareMode) { try { if (screenShareMode == ENTIRE_SCREEN) { @@ -211,7 +247,7 @@ public class MediaProjectionPermissionActivity extends Activity intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION, projection.asBinder()); intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE, - UserHandle.getUserHandleForUid(getLaunchedFromUid())); + getHostUserHandle()); intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); // Start activity from the current foreground user to avoid creating a separate @@ -230,6 +266,10 @@ public class MediaProjectionPermissionActivity extends Activity } } + private UserHandle getHostUserHandle() { + return UserHandle.getUserHandleForUid(getLaunchedFromUid()); + } + private IMediaProjection createProjection(int uid, String packageName) throws RemoteException { return mService.createProjection(uid, packageName, MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */); diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt index e665d832a5687..1678c6e6b7a9e 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt @@ -24,6 +24,7 @@ import com.android.launcher3.icons.IconFactory import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.media.MediaProjectionAppSelectorActivity import com.android.systemui.media.MediaProjectionAppSelectorActivity.Companion.EXTRA_HOST_APP_USER_HANDLE +import com.android.systemui.media.MediaProjectionPermissionActivity import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerLabelLoader import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader import com.android.systemui.mediaprojection.appselector.data.AppIconLoader @@ -45,10 +46,10 @@ import dagger.Provides import dagger.Subcomponent import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap -import javax.inject.Qualifier -import javax.inject.Scope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob +import javax.inject.Qualifier +import javax.inject.Scope @Qualifier @Retention(AnnotationRetention.BINARY) annotation class MediaProjectionAppSelector @@ -67,6 +68,11 @@ interface MediaProjectionModule { fun provideMediaProjectionAppSelectorActivity( activity: MediaProjectionAppSelectorActivity ): Activity + + @Binds + @IntoMap + @ClassKey(MediaProjectionPermissionActivity::class) + fun bindsMediaProjectionPermissionActivity(impl: MediaProjectionPermissionActivity): Activity } /** @@ -149,6 +155,7 @@ interface MediaProjectionAppSelectorComponent { val controller: MediaProjectionAppSelectorController val recentsViewController: MediaProjectionRecentsViewController + val emptyStateProvider: MediaProjectionBlockerEmptyStateProvider @get:HostUserHandle val hostUserHandle: UserHandle @get:PersonalProfile val personalProfileUserHandle: UserHandle diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java index 64a8a146031b3..ad000690a3545 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java @@ -171,8 +171,9 @@ public class ScreenRecordTile extends QSTileImpl getHost().collapsePanels(); }; - Dialog dialog = mController.createScreenRecordDialog(mContext, mFlags, + final Dialog dialog = mController.createScreenRecordDialog(mContext, mFlags, mDialogLaunchAnimator, mActivityStarter, onStartRecordingClicked); + ActivityStarter.OnDismissAction dismissAction = () -> { if (shouldAnimateFromView) { mDialogLaunchAnimator.showFromView(dialog, view, new DialogCuj( diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java index b8684ee30b9ae..db2e62bc95adb 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java @@ -36,6 +36,8 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; +import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver; +import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserContextProvider; import com.android.systemui.settings.UserTracker; @@ -46,6 +48,8 @@ import java.util.concurrent.Executor; import javax.inject.Inject; +import dagger.Lazy; + /** * Helper class to initiate a screen recording */ @@ -60,6 +64,8 @@ public class RecordingController private CountDownTimer mCountDownTimer = null; private final Executor mMainExecutor; private final BroadcastDispatcher mBroadcastDispatcher; + private final Context mContext; + private final FeatureFlags mFlags; private final UserContextProvider mUserContextProvider; private final UserTracker mUserTracker; @@ -70,6 +76,8 @@ public class RecordingController private CopyOnWriteArrayList mListeners = new CopyOnWriteArrayList<>(); + private final Lazy mDevicePolicyResolver; + @VisibleForTesting final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() { @@ -100,22 +108,44 @@ public class RecordingController @Inject public RecordingController(@Main Executor mainExecutor, BroadcastDispatcher broadcastDispatcher, + Context context, + FeatureFlags flags, UserContextProvider userContextProvider, + Lazy devicePolicyResolver, UserTracker userTracker) { mMainExecutor = mainExecutor; + mContext = context; + mFlags = flags; + mDevicePolicyResolver = devicePolicyResolver; mBroadcastDispatcher = broadcastDispatcher; mUserContextProvider = userContextProvider; mUserTracker = userTracker; } - /** Create a dialog to show screen recording options to the user. */ + /** + * MediaProjection host is SystemUI for the screen recorder, so return 'my user handle' + */ + private UserHandle getHostUserHandle() { + return UserHandle.of(UserHandle.myUserId()); + } + + /** Create a dialog to show screen recording options to the user. + * If screen capturing is currently not allowed it will return a dialog + * that warns users about it. */ public Dialog createScreenRecordDialog(Context context, FeatureFlags flags, DialogLaunchAnimator dialogLaunchAnimator, ActivityStarter activityStarter, @Nullable Runnable onStartRecordingClicked) { + if (mFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES) + && mDevicePolicyResolver.get() + .isScreenCaptureCompletelyDisabled(getHostUserHandle())) { + return new ScreenCaptureDisabledDialog(mContext); + } + return flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING) - ? new ScreenRecordPermissionDialog(context, this, activityStarter, - dialogLaunchAnimator, mUserContextProvider, onStartRecordingClicked) + ? new ScreenRecordPermissionDialog(context, getHostUserHandle(), this, + activityStarter, dialogLaunchAnimator, mUserContextProvider, + onStartRecordingClicked) : new ScreenRecordDialog(context, this, activityStarter, mUserContextProvider, flags, dialogLaunchAnimator, onStartRecordingClicked); } diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt index 68e3dcdb63eab..dd21be971b36c 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt @@ -42,6 +42,7 @@ import com.android.systemui.settings.UserContextProvider /** Dialog to select screen recording options */ class ScreenRecordPermissionDialog( context: Context?, + private val hostUserHandle: UserHandle, private val controller: RecordingController, private val activityStarter: ActivityStarter, private val dialogLaunchAnimator: DialogLaunchAnimator, @@ -79,11 +80,9 @@ class ScreenRecordPermissionDialog( CaptureTargetResultReceiver() ) - // Send SystemUI's user handle as the host app user handle because SystemUI - // is the 'host app' (the app that receives screen capture data) intent.putExtra( MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE, - UserHandle.of(UserHandle.myUserId()) + hostUserHandle ) val animationController = dialogLaunchAnimator.createActivityLaunchController(v!!) diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java index 69f3e987ec1d5..33aaa3f1cde92 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java @@ -16,13 +16,15 @@ package com.android.systemui.screenrecord; +import static com.google.common.truth.Truth.assertThat; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import android.app.Dialog; import android.app.PendingIntent; import android.content.Intent; import android.os.Looper; @@ -31,7 +33,13 @@ import android.testing.AndroidTestingRunner; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.flags.FakeFeatureFlags; +import com.android.systemui.flags.Flags; +import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDevicePolicyResolver; +import com.android.systemui.mediaprojection.devicepolicy.ScreenCaptureDisabledDialog; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserContextProvider; import com.android.systemui.settings.UserTracker; import com.android.systemui.util.concurrency.FakeExecutor; @@ -61,8 +69,15 @@ public class RecordingControllerTest extends SysuiTestCase { @Mock private UserContextProvider mUserContextProvider; @Mock + private ScreenCaptureDevicePolicyResolver mDevicePolicyResolver; + @Mock + private DialogLaunchAnimator mDialogLaunchAnimator; + @Mock + private ActivityStarter mActivityStarter; + @Mock private UserTracker mUserTracker; + private FakeFeatureFlags mFeatureFlags; private RecordingController mController; private static final int USER_ID = 10; @@ -70,8 +85,9 @@ public class RecordingControllerTest extends SysuiTestCase { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mController = new RecordingController(mMainExecutor, mBroadcastDispatcher, - mUserContextProvider, mUserTracker); + mFeatureFlags = new FakeFeatureFlags(); + mController = new RecordingController(mMainExecutor, mBroadcastDispatcher, mContext, + mFeatureFlags, mUserContextProvider, () -> mDevicePolicyResolver, mUserTracker); mController.addCallback(mCallback); } @@ -190,4 +206,67 @@ public class RecordingControllerTest extends SysuiTestCase { verify(mCallback).onRecordingEnd(); assertFalse(mController.isRecording()); } + + @Test + public void testPoliciesFlagDisabled_screenCapturingNotAllowed_returnsNullDevicePolicyDialog() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, true); + mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, false); + when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(true); + + Dialog dialog = mController.createScreenRecordDialog(mContext, mFeatureFlags, + mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null); + + assertThat(dialog).isInstanceOf(ScreenRecordPermissionDialog.class); + } + + @Test + public void testPartialScreenSharingDisabled_returnsLegacyDialog() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, false); + mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, false); + + Dialog dialog = mController.createScreenRecordDialog(mContext, mFeatureFlags, + mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null); + + assertThat(dialog).isInstanceOf(ScreenRecordDialog.class); + } + + @Test + public void testPoliciesFlagEnabled_screenCapturingNotAllowed_returnsDevicePolicyDialog() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, true); + mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, true); + when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(true); + + Dialog dialog = mController.createScreenRecordDialog(mContext, mFeatureFlags, + mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null); + + assertThat(dialog).isInstanceOf(ScreenCaptureDisabledDialog.class); + } + + @Test + public void testPoliciesFlagEnabled_screenCapturingAllowed_returnsNullDevicePolicyDialog() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING, true); + mFeatureFlags.set(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES, true); + when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(false); + + Dialog dialog = mController.createScreenRecordDialog(mContext, mFeatureFlags, + mDialogLaunchAnimator, mActivityStarter, /* onStartRecordingClicked= */ null); + + assertThat(dialog).isInstanceOf(ScreenRecordPermissionDialog.class); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt index 0aa36218b3a7e..5b094c93ea9df 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.screenrecord +import android.os.UserHandle import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.view.View @@ -59,6 +60,7 @@ class ScreenRecordPermissionDialogTest : SysuiTestCase() { dialog = ScreenRecordPermissionDialog( context, + UserHandle.of(0), controller, starter, dialogLaunchAnimator,