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

Commit 21b2641a authored by Andre Le's avatar Andre Le Committed by Android (Google) Code Review
Browse files

Merge "QSDetailedView: Add view binder to ScreenRecordDetailsViewModel" into main

parents e32d6120 016dce89
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -191,8 +191,9 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState>

    @Override
    public boolean getDetailsViewModel(Consumer<TileDetailsViewModel> callback) {
        handleClick(() ->
                callback.accept(new ScreenRecordDetailsViewModel())
        handleClick(() -> executeWhenUnlockedKeyguard(
                () -> callback.accept(new ScreenRecordDetailsViewModel(mController,
                                        this::onStartRecordingClicked)))
        );
        return true;
    }
+24 −10
Original line number Diff line number Diff line
@@ -17,27 +17,45 @@
package com.android.systemui.qs.tiles.dialog

import android.view.LayoutInflater
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.android.systemui.plugins.qs.TileDetailsViewModel
import com.android.systemui.res.R
import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.screenrecord.ScreenRecordPermissionViewBinder

/** The view model used for the screen record details view in the Quick Settings */
class ScreenRecordDetailsViewModel() : TileDetailsViewModel() {
class ScreenRecordDetailsViewModel(
    private val recordingController: RecordingController,
    private val onStartRecordingClicked: Runnable,
) : TileDetailsViewModel() {

    private var viewBinder: ScreenRecordPermissionViewBinder =
        recordingController.createScreenRecordPermissionViewBinder(onStartRecordingClicked)

    @Composable
    override fun GetContentView() {
        // TODO(b/378514312): Finish implementing this function.

        if (recordingController.isScreenCaptureDisabled) {
            // TODO(b/388345506): Show disabled page here.
            return
        }

        AndroidView(
            modifier = Modifier.fillMaxWidth().heightIn(max = VIEW_MAX_HEIGHT),
            modifier = Modifier.fillMaxWidth().fillMaxHeight(),
            factory = { context ->
                // Inflate with the existing dialog xml layout
                LayoutInflater.from(context).inflate(R.layout.screen_share_dialog, null)
                val view = LayoutInflater.from(context).inflate(R.layout.screen_share_dialog, null)
                viewBinder.bind(view)

                view
                // TODO(b/378514473): Revamp the details view according to the spec.
            },
            onRelease = { viewBinder.unbind() },
        )
    }

@@ -54,8 +72,4 @@ class ScreenRecordDetailsViewModel() : TileDetailsViewModel() {
        // No sub-title in this tile.
        return ""
    }

    companion object {
        private val VIEW_MAX_HEIGHT: Dp = 320.dp
    }
}
+27 −3
Original line number Diff line number Diff line
@@ -70,6 +70,8 @@ public class RecordingController
    private final ScreenCaptureDisabledDialogDelegate mScreenCaptureDisabledDialogDelegate;
    private final ScreenRecordPermissionDialogDelegate.Factory
            mScreenRecordPermissionDialogDelegateFactory;
    private final ScreenRecordPermissionViewBinder.Factory
            mScreenRecordPermissionViewBinderFactory;

    protected static final String INTENT_UPDATE_STATE =
            "com.android.systemui.screenrecord.UPDATE_STATE";
@@ -118,7 +120,8 @@ public class RecordingController
            MediaProjectionMetricsLogger mediaProjectionMetricsLogger,
            ScreenCaptureDisabledDialogDelegate screenCaptureDisabledDialogDelegate,
            ScreenRecordPermissionDialogDelegate.Factory
                    screenRecordPermissionDialogDelegateFactory) {
                    screenRecordPermissionDialogDelegateFactory,
            ScreenRecordPermissionViewBinder.Factory screenRecordPermissionViewBinderFactory) {
        mMainExecutor = mainExecutor;
        mDevicePolicyResolver = devicePolicyResolver;
        mBroadcastDispatcher = broadcastDispatcher;
@@ -127,6 +130,7 @@ public class RecordingController
        mMediaProjectionMetricsLogger = mediaProjectionMetricsLogger;
        mScreenCaptureDisabledDialogDelegate = screenCaptureDisabledDialogDelegate;
        mScreenRecordPermissionDialogDelegateFactory = screenRecordPermissionDialogDelegateFactory;
        mScreenRecordPermissionViewBinderFactory = screenRecordPermissionViewBinderFactory;

        BroadcastOptions options = BroadcastOptions.makeBasic();
        options.setInteractive(true);
@@ -151,8 +155,7 @@ public class RecordingController
     *  If screen capturing is currently not allowed it will return a dialog
     *  that warns users about it. */
    public Dialog createScreenRecordDialog(@Nullable Runnable onStartRecordingClicked) {
        if (mDevicePolicyResolver.get()
                        .isScreenCaptureCompletelyDisabled(getHostUserHandle())) {
        if (isScreenCaptureDisabled()) {
            return mScreenCaptureDisabledDialogDelegate.createSysUIDialog();
        }

@@ -164,6 +167,27 @@ public class RecordingController
                .createDialog();
    }

    /**
     * Create a view binder that controls the logic of views inside the screen record permission
     * view.
     * @param onStartRecordingClicked the callback that is run when the start button is clicked.
     */
    public ScreenRecordPermissionViewBinder createScreenRecordPermissionViewBinder(
            @Nullable Runnable onStartRecordingClicked
    ) {
        return mScreenRecordPermissionViewBinderFactory
                .create(getHostUserHandle(), getHostUid(), this,
                        onStartRecordingClicked);
    }

    /**
     * Check if screen capture is currently disabled for this device and user.
     */
    public boolean isScreenCaptureDisabled() {
        return mDevicePolicyResolver.get()
                .isScreenCaptureCompletelyDisabled(getHostUserHandle());
    }

    /**
     * Start counting down in preparation to start a recording
     * @param ms Total time in ms to wait before starting
+35 −0
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ import com.android.systemui.mediaprojection.permission.ScreenShareOption
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.res.R
import com.android.systemui.settings.UserContextProvider
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject

class ScreenRecordPermissionViewBinder(
    private val hostUserHandle: UserHandle,
@@ -68,6 +71,38 @@ class ScreenRecordPermissionViewBinder(
        mediaProjectionMetricsLogger,
        defaultSelectedMode,
    ) {
    @AssistedInject
    constructor(
        @Assisted hostUserHandle: UserHandle,
        @Assisted hostUid: Int,
        mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
        displayManager: DisplayManager,
        @Assisted controller: RecordingController,
        activityStarter: ActivityStarter,
        userContextProvider: UserContextProvider,
        @Assisted onStartRecordingClicked: Runnable?,
    ) : this(
        hostUserHandle,
        hostUid,
        mediaProjectionMetricsLogger,
        defaultSelectedMode = SINGLE_APP,
        displayManager,
        controller,
        activityStarter,
        userContextProvider,
        onStartRecordingClicked,
    )

    @AssistedFactory
    interface Factory {
        fun create(
            hostUserHandle: UserHandle,
            hostUid: Int,
            recordingController: RecordingController,
            onStartRecordingClicked: Runnable?,
        ): ScreenRecordPermissionViewBinder
    }

    private lateinit var tapsSwitch: Switch
    private lateinit var audioSwitch: Switch
    private lateinit var tapsView: View
+29 −1
Original line number Diff line number Diff line
@@ -88,8 +88,13 @@ public class RecordingControllerTest extends SysuiTestCase {
    private ScreenRecordPermissionDialogDelegate.Factory
            mScreenRecordPermissionDialogDelegateFactory;
    @Mock
    private ScreenRecordPermissionViewBinder.Factory
            mScreenRecordPermissionViewBinderFactory;
    @Mock
    private ScreenRecordPermissionDialogDelegate mScreenRecordPermissionDialogDelegate;
    @Mock
    private ScreenRecordPermissionViewBinder mScreenRecordPermissionViewBinder;
    @Mock
    private SystemUIDialog mScreenRecordSystemUIDialog;

    private RecordingController mController;
@@ -106,6 +111,8 @@ public class RecordingControllerTest extends SysuiTestCase {
                .thenReturn(mScreenCaptureDisabledDialog);
        when(mScreenRecordPermissionDialogDelegateFactory.create(any(), any(), anyInt(), any()))
                .thenReturn(mScreenRecordPermissionDialogDelegate);
        when(mScreenRecordPermissionViewBinderFactory.create(any(), anyInt(), any(), any()))
                .thenReturn(mScreenRecordPermissionViewBinder);
        when(mScreenRecordPermissionDialogDelegate.createDialog())
                .thenReturn(mScreenRecordSystemUIDialog);
        mController = new RecordingController(
@@ -116,7 +123,8 @@ public class RecordingControllerTest extends SysuiTestCase {
                new RecordingControllerLogger(logcatLogBuffer("RecordingControllerTest")),
                mMediaProjectionMetricsLogger,
                mScreenCaptureDisabledDialogDelegate,
                mScreenRecordPermissionDialogDelegateFactory
                mScreenRecordPermissionDialogDelegateFactory,
                mScreenRecordPermissionViewBinderFactory
        );
        mController.addCallback(mCallback);
    }
@@ -237,6 +245,26 @@ public class RecordingControllerTest extends SysuiTestCase {
                .isInstanceOf(ScreenRecordPermissionDialogDelegate.class);
    }

    @Test
    public void testCreateScreenRecordPermissionViewBinder() {
        ScreenRecordPermissionViewBinder viewBinder =
                mController.createScreenRecordPermissionViewBinder(
                        /* onStartRecordingClicked= */ null);
        assertThat(viewBinder).isEqualTo(mScreenRecordPermissionViewBinder);
    }

    @Test
    public void testScreenCapturingAllowed_returnsFalseIsScreenCaptureDisabled() {
        when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(false);
        assertFalse(mController.isScreenCaptureDisabled());
    }

    @Test
    public void testScreenCapturingNotAllowed_returnsTrueIsScreenCaptureDisabled() {
        when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(true);
        assertTrue(mController.isScreenCaptureDisabled());
    }

    @Test
    public void testScreenCapturingAllowed_logsProjectionInitiated() {
        when(mDevicePolicyResolver.isScreenCaptureCompletelyDisabled((any()))).thenReturn(false);