Merge "[Partial Screensharing] Handle enterprise policies" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f3ef9103dd
@@ -28,12 +28,15 @@ import android.os.ResultReceiver
|
|||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.android.internal.annotations.VisibleForTesting
|
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.AbstractMultiProfilePagerAdapter.MyUserIdProvider
|
||||||
import com.android.internal.app.ChooserActivity
|
import com.android.internal.app.ChooserActivity
|
||||||
import com.android.internal.app.ResolverListController
|
import com.android.internal.app.ResolverListController
|
||||||
import com.android.internal.app.chooser.NotSelectableTargetInfo
|
import com.android.internal.app.chooser.NotSelectableTargetInfo
|
||||||
import com.android.internal.app.chooser.TargetInfo
|
import com.android.internal.app.chooser.TargetInfo
|
||||||
import com.android.systemui.R
|
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.MediaProjectionAppSelectorComponent
|
||||||
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorController
|
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorController
|
||||||
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
|
import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorResultHandler
|
||||||
@@ -47,6 +50,7 @@ import javax.inject.Inject
|
|||||||
class MediaProjectionAppSelectorActivity(
|
class MediaProjectionAppSelectorActivity(
|
||||||
private val componentFactory: MediaProjectionAppSelectorComponent.Factory,
|
private val componentFactory: MediaProjectionAppSelectorComponent.Factory,
|
||||||
private val activityLauncher: AsyncActivityLauncher,
|
private val activityLauncher: AsyncActivityLauncher,
|
||||||
|
private val featureFlags: FeatureFlags,
|
||||||
/** This is used to override the dependency in a screenshot test */
|
/** This is used to override the dependency in a screenshot test */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)?
|
private val listControllerFactory: ((userHandle: UserHandle) -> ResolverListController)?
|
||||||
@@ -56,7 +60,8 @@ class MediaProjectionAppSelectorActivity(
|
|||||||
constructor(
|
constructor(
|
||||||
componentFactory: MediaProjectionAppSelectorComponent.Factory,
|
componentFactory: MediaProjectionAppSelectorComponent.Factory,
|
||||||
activityLauncher: AsyncActivityLauncher,
|
activityLauncher: AsyncActivityLauncher,
|
||||||
) : this(componentFactory, activityLauncher, null)
|
featureFlags: FeatureFlags
|
||||||
|
) : this(componentFactory, activityLauncher, featureFlags, listControllerFactory = null)
|
||||||
|
|
||||||
private lateinit var configurationController: ConfigurationController
|
private lateinit var configurationController: ConfigurationController
|
||||||
private lateinit var controller: MediaProjectionAppSelectorController
|
private lateinit var controller: MediaProjectionAppSelectorController
|
||||||
@@ -91,6 +96,13 @@ class MediaProjectionAppSelectorActivity(
|
|||||||
|
|
||||||
override fun appliedThemeResId(): Int = R.style.Theme_SystemUI_MediaProjectionAppSelector
|
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 =
|
override fun createListController(userHandle: UserHandle): ResolverListController =
|
||||||
listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)
|
listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)
|
||||||
|
|
||||||
|
|||||||
@@ -45,33 +45,46 @@ import android.text.style.StyleSpan;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
|
|
||||||
import com.android.systemui.Dependency;
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.flags.FeatureFlags;
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.flags.Flags;
|
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.MediaProjectionPermissionDialog;
|
||||||
import com.android.systemui.screenrecord.ScreenShareOption;
|
import com.android.systemui.screenrecord.ScreenShareOption;
|
||||||
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
import com.android.systemui.statusbar.phone.SystemUIDialog;
|
||||||
import com.android.systemui.util.Utils;
|
import com.android.systemui.util.Utils;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.Lazy;
|
||||||
|
|
||||||
public class MediaProjectionPermissionActivity extends Activity
|
public class MediaProjectionPermissionActivity extends Activity
|
||||||
implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
|
implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
|
||||||
private static final String TAG = "MediaProjectionPermissionActivity";
|
private static final String TAG = "MediaProjectionPermissionActivity";
|
||||||
private static final float MAX_APP_NAME_SIZE_PX = 500f;
|
private static final float MAX_APP_NAME_SIZE_PX = 500f;
|
||||||
private static final String ELLIPSIS = "\u2026";
|
private static final String ELLIPSIS = "\u2026";
|
||||||
|
|
||||||
|
private final FeatureFlags mFeatureFlags;
|
||||||
|
private final Lazy<ScreenCaptureDevicePolicyResolver> mScreenCaptureDevicePolicyResolver;
|
||||||
|
|
||||||
private String mPackageName;
|
private String mPackageName;
|
||||||
private int mUid;
|
private int mUid;
|
||||||
private IMediaProjectionManager mService;
|
private IMediaProjectionManager mService;
|
||||||
private FeatureFlags mFeatureFlags;
|
|
||||||
|
|
||||||
private AlertDialog mDialog;
|
private AlertDialog mDialog;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public MediaProjectionPermissionActivity(FeatureFlags featureFlags,
|
||||||
|
Lazy<ScreenCaptureDevicePolicyResolver> screenCaptureDevicePolicyResolver) {
|
||||||
|
mFeatureFlags = featureFlags;
|
||||||
|
mScreenCaptureDevicePolicyResolver = screenCaptureDevicePolicyResolver;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
|
||||||
mFeatureFlags = Dependency.get(FeatureFlags.class);
|
|
||||||
mPackageName = getCallingPackage();
|
mPackageName = getCallingPackage();
|
||||||
IBinder b = ServiceManager.getService(MEDIA_PROJECTION_SERVICE);
|
IBinder b = ServiceManager.getService(MEDIA_PROJECTION_SERVICE);
|
||||||
mService = IMediaProjectionManager.Stub.asInterface(b);
|
mService = IMediaProjectionManager.Stub.asInterface(b);
|
||||||
@@ -104,6 +117,12 @@ public class MediaProjectionPermissionActivity extends Activity
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING_ENTERPRISE_POLICIES)) {
|
||||||
|
if (showScreenCaptureDisabledDialogIfNeeded()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextPaint paint = new TextPaint();
|
TextPaint paint = new TextPaint();
|
||||||
paint.setTextSize(42);
|
paint.setTextSize(42);
|
||||||
|
|
||||||
@@ -171,16 +190,7 @@ public class MediaProjectionPermissionActivity extends Activity
|
|||||||
mDialog = dialogBuilder.create();
|
mDialog = dialogBuilder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemUIDialog.registerDismissListener(mDialog);
|
setUpDialog(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);
|
|
||||||
|
|
||||||
mDialog.show();
|
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) {
|
private void grantMediaProjectionPermission(int screenShareMode) {
|
||||||
try {
|
try {
|
||||||
if (screenShareMode == ENTIRE_SCREEN) {
|
if (screenShareMode == ENTIRE_SCREEN) {
|
||||||
@@ -211,7 +247,7 @@ public class MediaProjectionPermissionActivity extends Activity
|
|||||||
intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
|
intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION,
|
||||||
projection.asBinder());
|
projection.asBinder());
|
||||||
intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
|
intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
|
||||||
UserHandle.getUserHandleForUid(getLaunchedFromUid()));
|
getHostUserHandle());
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
|
intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
|
||||||
|
|
||||||
// Start activity from the current foreground user to avoid creating a separate
|
// 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 {
|
private IMediaProjection createProjection(int uid, String packageName) throws RemoteException {
|
||||||
return mService.createProjection(uid, packageName,
|
return mService.createProjection(uid, packageName,
|
||||||
MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */);
|
MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.android.launcher3.icons.IconFactory
|
|||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.media.MediaProjectionAppSelectorActivity
|
import com.android.systemui.media.MediaProjectionAppSelectorActivity
|
||||||
import com.android.systemui.media.MediaProjectionAppSelectorActivity.Companion.EXTRA_HOST_APP_USER_HANDLE
|
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.ActivityTaskManagerLabelLoader
|
||||||
import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader
|
import com.android.systemui.mediaprojection.appselector.data.ActivityTaskManagerThumbnailLoader
|
||||||
import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
|
import com.android.systemui.mediaprojection.appselector.data.AppIconLoader
|
||||||
@@ -45,10 +46,10 @@ import dagger.Provides
|
|||||||
import dagger.Subcomponent
|
import dagger.Subcomponent
|
||||||
import dagger.multibindings.ClassKey
|
import dagger.multibindings.ClassKey
|
||||||
import dagger.multibindings.IntoMap
|
import dagger.multibindings.IntoMap
|
||||||
import javax.inject.Qualifier
|
|
||||||
import javax.inject.Scope
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import javax.inject.Qualifier
|
||||||
|
import javax.inject.Scope
|
||||||
|
|
||||||
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class MediaProjectionAppSelector
|
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class MediaProjectionAppSelector
|
||||||
|
|
||||||
@@ -67,6 +68,11 @@ interface MediaProjectionModule {
|
|||||||
fun provideMediaProjectionAppSelectorActivity(
|
fun provideMediaProjectionAppSelectorActivity(
|
||||||
activity: MediaProjectionAppSelectorActivity
|
activity: MediaProjectionAppSelectorActivity
|
||||||
): Activity
|
): Activity
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ClassKey(MediaProjectionPermissionActivity::class)
|
||||||
|
fun bindsMediaProjectionPermissionActivity(impl: MediaProjectionPermissionActivity): Activity
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,6 +155,7 @@ interface MediaProjectionAppSelectorComponent {
|
|||||||
|
|
||||||
val controller: MediaProjectionAppSelectorController
|
val controller: MediaProjectionAppSelectorController
|
||||||
val recentsViewController: MediaProjectionRecentsViewController
|
val recentsViewController: MediaProjectionRecentsViewController
|
||||||
|
val emptyStateProvider: MediaProjectionBlockerEmptyStateProvider
|
||||||
@get:HostUserHandle val hostUserHandle: UserHandle
|
@get:HostUserHandle val hostUserHandle: UserHandle
|
||||||
@get:PersonalProfile val personalProfileUserHandle: UserHandle
|
@get:PersonalProfile val personalProfileUserHandle: UserHandle
|
||||||
|
|
||||||
|
|||||||
@@ -171,8 +171,9 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>
|
|||||||
getHost().collapsePanels();
|
getHost().collapsePanels();
|
||||||
};
|
};
|
||||||
|
|
||||||
Dialog dialog = mController.createScreenRecordDialog(mContext, mFlags,
|
final Dialog dialog = mController.createScreenRecordDialog(mContext, mFlags,
|
||||||
mDialogLaunchAnimator, mActivityStarter, onStartRecordingClicked);
|
mDialogLaunchAnimator, mActivityStarter, onStartRecordingClicked);
|
||||||
|
|
||||||
ActivityStarter.OnDismissAction dismissAction = () -> {
|
ActivityStarter.OnDismissAction dismissAction = () -> {
|
||||||
if (shouldAnimateFromView) {
|
if (shouldAnimateFromView) {
|
||||||
mDialogLaunchAnimator.showFromView(dialog, view, new DialogCuj(
|
mDialogLaunchAnimator.showFromView(dialog, view, new DialogCuj(
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ import com.android.systemui.dagger.SysUISingleton;
|
|||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.flags.FeatureFlags;
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
import com.android.systemui.flags.Flags;
|
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.plugins.ActivityStarter;
|
||||||
import com.android.systemui.settings.UserContextProvider;
|
import com.android.systemui.settings.UserContextProvider;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
@@ -46,6 +48,8 @@ import java.util.concurrent.Executor;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import dagger.Lazy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to initiate a screen recording
|
* Helper class to initiate a screen recording
|
||||||
*/
|
*/
|
||||||
@@ -60,6 +64,8 @@ public class RecordingController
|
|||||||
private CountDownTimer mCountDownTimer = null;
|
private CountDownTimer mCountDownTimer = null;
|
||||||
private final Executor mMainExecutor;
|
private final Executor mMainExecutor;
|
||||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||||
|
private final Context mContext;
|
||||||
|
private final FeatureFlags mFlags;
|
||||||
private final UserContextProvider mUserContextProvider;
|
private final UserContextProvider mUserContextProvider;
|
||||||
private final UserTracker mUserTracker;
|
private final UserTracker mUserTracker;
|
||||||
|
|
||||||
@@ -70,6 +76,8 @@ public class RecordingController
|
|||||||
private CopyOnWriteArrayList<RecordingStateChangeCallback> mListeners =
|
private CopyOnWriteArrayList<RecordingStateChangeCallback> mListeners =
|
||||||
new CopyOnWriteArrayList<>();
|
new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
private final Lazy<ScreenCaptureDevicePolicyResolver> mDevicePolicyResolver;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final UserTracker.Callback mUserChangedCallback =
|
final UserTracker.Callback mUserChangedCallback =
|
||||||
new UserTracker.Callback() {
|
new UserTracker.Callback() {
|
||||||
@@ -100,22 +108,44 @@ public class RecordingController
|
|||||||
@Inject
|
@Inject
|
||||||
public RecordingController(@Main Executor mainExecutor,
|
public RecordingController(@Main Executor mainExecutor,
|
||||||
BroadcastDispatcher broadcastDispatcher,
|
BroadcastDispatcher broadcastDispatcher,
|
||||||
|
Context context,
|
||||||
|
FeatureFlags flags,
|
||||||
UserContextProvider userContextProvider,
|
UserContextProvider userContextProvider,
|
||||||
|
Lazy<ScreenCaptureDevicePolicyResolver> devicePolicyResolver,
|
||||||
UserTracker userTracker) {
|
UserTracker userTracker) {
|
||||||
mMainExecutor = mainExecutor;
|
mMainExecutor = mainExecutor;
|
||||||
|
mContext = context;
|
||||||
|
mFlags = flags;
|
||||||
|
mDevicePolicyResolver = devicePolicyResolver;
|
||||||
mBroadcastDispatcher = broadcastDispatcher;
|
mBroadcastDispatcher = broadcastDispatcher;
|
||||||
mUserContextProvider = userContextProvider;
|
mUserContextProvider = userContextProvider;
|
||||||
mUserTracker = userTracker;
|
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,
|
public Dialog createScreenRecordDialog(Context context, FeatureFlags flags,
|
||||||
DialogLaunchAnimator dialogLaunchAnimator,
|
DialogLaunchAnimator dialogLaunchAnimator,
|
||||||
ActivityStarter activityStarter,
|
ActivityStarter activityStarter,
|
||||||
@Nullable Runnable onStartRecordingClicked) {
|
@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)
|
return flags.isEnabled(Flags.WM_ENABLE_PARTIAL_SCREEN_SHARING)
|
||||||
? new ScreenRecordPermissionDialog(context, this, activityStarter,
|
? new ScreenRecordPermissionDialog(context, getHostUserHandle(), this,
|
||||||
dialogLaunchAnimator, mUserContextProvider, onStartRecordingClicked)
|
activityStarter, dialogLaunchAnimator, mUserContextProvider,
|
||||||
|
onStartRecordingClicked)
|
||||||
: new ScreenRecordDialog(context, this, activityStarter,
|
: new ScreenRecordDialog(context, this, activityStarter,
|
||||||
mUserContextProvider, flags, dialogLaunchAnimator, onStartRecordingClicked);
|
mUserContextProvider, flags, dialogLaunchAnimator, onStartRecordingClicked);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import com.android.systemui.settings.UserContextProvider
|
|||||||
/** Dialog to select screen recording options */
|
/** Dialog to select screen recording options */
|
||||||
class ScreenRecordPermissionDialog(
|
class ScreenRecordPermissionDialog(
|
||||||
context: Context?,
|
context: Context?,
|
||||||
|
private val hostUserHandle: UserHandle,
|
||||||
private val controller: RecordingController,
|
private val controller: RecordingController,
|
||||||
private val activityStarter: ActivityStarter,
|
private val activityStarter: ActivityStarter,
|
||||||
private val dialogLaunchAnimator: DialogLaunchAnimator,
|
private val dialogLaunchAnimator: DialogLaunchAnimator,
|
||||||
@@ -79,11 +80,9 @@ class ScreenRecordPermissionDialog(
|
|||||||
CaptureTargetResultReceiver()
|
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(
|
intent.putExtra(
|
||||||
MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
|
MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE,
|
||||||
UserHandle.of(UserHandle.myUserId())
|
hostUserHandle
|
||||||
)
|
)
|
||||||
|
|
||||||
val animationController = dialogLaunchAnimator.createActivityLaunchController(v!!)
|
val animationController = dialogLaunchAnimator.createActivityLaunchController(v!!)
|
||||||
|
|||||||
@@ -16,13 +16,15 @@
|
|||||||
|
|
||||||
package com.android.systemui.screenrecord;
|
package com.android.systemui.screenrecord;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static junit.framework.Assert.assertFalse;
|
import static junit.framework.Assert.assertFalse;
|
||||||
import static junit.framework.Assert.assertTrue;
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -31,7 +33,13 @@ import android.testing.AndroidTestingRunner;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.animation.DialogLaunchAnimator;
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
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.UserContextProvider;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||||
@@ -61,8 +69,15 @@ public class RecordingControllerTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
private UserContextProvider mUserContextProvider;
|
private UserContextProvider mUserContextProvider;
|
||||||
@Mock
|
@Mock
|
||||||
|
private ScreenCaptureDevicePolicyResolver mDevicePolicyResolver;
|
||||||
|
@Mock
|
||||||
|
private DialogLaunchAnimator mDialogLaunchAnimator;
|
||||||
|
@Mock
|
||||||
|
private ActivityStarter mActivityStarter;
|
||||||
|
@Mock
|
||||||
private UserTracker mUserTracker;
|
private UserTracker mUserTracker;
|
||||||
|
|
||||||
|
private FakeFeatureFlags mFeatureFlags;
|
||||||
private RecordingController mController;
|
private RecordingController mController;
|
||||||
|
|
||||||
private static final int USER_ID = 10;
|
private static final int USER_ID = 10;
|
||||||
@@ -70,8 +85,9 @@ public class RecordingControllerTest extends SysuiTestCase {
|
|||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mController = new RecordingController(mMainExecutor, mBroadcastDispatcher,
|
mFeatureFlags = new FakeFeatureFlags();
|
||||||
mUserContextProvider, mUserTracker);
|
mController = new RecordingController(mMainExecutor, mBroadcastDispatcher, mContext,
|
||||||
|
mFeatureFlags, mUserContextProvider, () -> mDevicePolicyResolver, mUserTracker);
|
||||||
mController.addCallback(mCallback);
|
mController.addCallback(mCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,4 +206,67 @@ public class RecordingControllerTest extends SysuiTestCase {
|
|||||||
verify(mCallback).onRecordingEnd();
|
verify(mCallback).onRecordingEnd();
|
||||||
assertFalse(mController.isRecording());
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.systemui.screenrecord
|
package com.android.systemui.screenrecord
|
||||||
|
|
||||||
|
import android.os.UserHandle
|
||||||
import android.testing.AndroidTestingRunner
|
import android.testing.AndroidTestingRunner
|
||||||
import android.testing.TestableLooper
|
import android.testing.TestableLooper
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -59,6 +60,7 @@ class ScreenRecordPermissionDialogTest : SysuiTestCase() {
|
|||||||
dialog =
|
dialog =
|
||||||
ScreenRecordPermissionDialog(
|
ScreenRecordPermissionDialog(
|
||||||
context,
|
context,
|
||||||
|
UserHandle.of(0),
|
||||||
controller,
|
controller,
|
||||||
starter,
|
starter,
|
||||||
dialogLaunchAnimator,
|
dialogLaunchAnimator,
|
||||||
|
|||||||
Reference in New Issue
Block a user