diff options
| author | 2025-01-08 22:40:12 +0000 | |
|---|---|---|
| committer | 2025-01-14 21:54:18 +0000 | |
| commit | 016dce89e5774bfe8a8a54ed5cec154346d6db1c (patch) | |
| tree | a2ff70ca86104fe75b3d72759359258fde272675 | |
| parent | c84a0332517e30fc9fd364e4b7a3fa94faa4a2cd (diff) | |
QSDetailedView: Add view binder to ScreenRecordDetailsViewModel
Add an instance of ScreenRecordPermissionViewBinder and
RecordingController to ScreenRecordDetailsViewModel to control the logic
within the UI of screen record details view. With CL, we can complete
the full flow of start screen recording with any configurations within
the screen record details view.
Bug: b/378514312
Flag: com.android.systemui.qs_tile_detailed_view
Test: ScreenRecordTileTest, ScreenRecordPermissionDialogDelegateTest
Test: Click on screen record tile in the QS -> can start do screen
recording within the details view.
Change-Id: Ifc64cfed4243e885694c0e99edc5f7ab898ce464
5 files changed, 118 insertions, 16 deletions
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 e93cec875429..42b35c736d42 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java @@ -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; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsViewModel.kt index 42cb1248ccff..54e4a521c239 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/ScreenRecordDetailsViewModel.kt @@ -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 - } } diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java index 9ee99e45ceeb..140fbf340f8b 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java @@ -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(); } @@ -165,6 +168,27 @@ public class RecordingController } /** + * 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 * @param interval Time in ms per countdown step diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt index 9fcb3dfc0ad3..23df1c5441bf 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt @@ -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 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 a17f100904be..e5376d26840d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java @@ -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); } @@ -238,6 +246,26 @@ public class RecordingControllerTest extends SysuiTestCase { } @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); |