Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f3ef9103 authored by Nick Chameyev's avatar Nick Chameyev Committed by Android (Google) Code Review
Browse files

Merge "[Partial Screensharing] Handle enterprise policies" into tm-qpr-dev

parents 72426cc2 3733ec3b
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -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)

+54 −14
Original line number Diff line number Diff line
@@ -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<ScreenCaptureDevicePolicyResolver> mScreenCaptureDevicePolicyResolver;

    private String mPackageName;
    private int mUid;
    private IMediaProjectionManager mService;
    private FeatureFlags mFeatureFlags;

    private AlertDialog mDialog;

    @Inject
    public MediaProjectionPermissionActivity(FeatureFlags featureFlags,
            Lazy<ScreenCaptureDevicePolicyResolver> 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 */);
+9 −2
Original line number Diff line number Diff line
@@ -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

+2 −1
Original line number Diff line number Diff line
@@ -171,8 +171,9 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>
            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(
+33 −3
Original line number Diff line number Diff line
@@ -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<RecordingStateChangeCallback> mListeners =
            new CopyOnWriteArrayList<>();

    private final Lazy<ScreenCaptureDevicePolicyResolver> 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<ScreenCaptureDevicePolicyResolver> 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);
    }
Loading