Loading packages/SystemUI/res/layout/screen_record_dialog.xml +14 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,20 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <!-- Temporary entrypoint for the partial screensharing used for teamfooding --> <!-- TODO(b/236838395) remove this and use redesigned dialog --> <TextView android:id="@+id/button_app" android:visibility="gone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0" android:layout_gravity="end" android:layout_marginEnd="8dp" android:text="App" style="@style/Widget.Dialog.Button.BorderButton" /> <TextView android:id="@+id/button_start" android:layout_width="wrap_content" Loading packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt +34 −8 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.media.projection.MediaProjectionManager.EXTRA_MEDIA_PROJECTION import android.os.Binder import android.os.Bundle import android.os.IBinder import android.os.ResultReceiver import android.view.View import com.android.internal.app.ChooserActivity import com.android.internal.app.chooser.NotSelectableTargetInfo Loading Loading @@ -103,6 +104,19 @@ class MediaProjectionAppSelectorActivity @Inject constructor( } private fun onTargetActivityLaunched(launchToken: IBinder) { if (intent.hasExtra(EXTRA_CAPTURE_REGION_RESULT_RECEIVER)) { // The client requested to return the result in the result receiver instead of // activity result, let's send the media projection to the result receiver val resultReceiver = intent .getParcelableExtra(EXTRA_CAPTURE_REGION_RESULT_RECEIVER, ResultReceiver::class.java) as ResultReceiver val captureRegion = MediaProjectionCaptureTarget(launchToken) val data = Bundle().apply { putParcelable(KEY_CAPTURE_TARGET, captureRegion) } resultReceiver.send(RESULT_OK, data) } else { // Return the media projection instance as activity result val mediaProjectionBinder = intent.getIBinderExtra(EXTRA_MEDIA_PROJECTION) val projection = IMediaProjection.Stub.asInterface(mediaProjectionBinder) Loading @@ -112,8 +126,20 @@ class MediaProjectionAppSelectorActivity @Inject constructor( intent.putExtra(EXTRA_MEDIA_PROJECTION, projection.asBinder()) setResult(RESULT_OK, intent) setForceSendResultForMediaProjection() } finish() } override fun shouldGetOnlyDefaultActivities() = false companion object { /** * When EXTRA_CAPTURE_REGION_RESULT_RECEIVER is passed as intent extra * the activity will send the [CaptureRegion] to the result receiver * instead of returning media projection instance through activity result. */ const val EXTRA_CAPTURE_REGION_RESULT_RECEIVER = "capture_region_result_receiver" const val KEY_CAPTURE_TARGET = "capture_region" } } packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt 0 → 100644 +49 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.media import android.os.IBinder import android.os.Parcel import android.os.Parcelable /** * Class that represents an area that should be captured. * Currently it has only a launch cookie that represents a task but * we potentially could add more identifiers e.g. for a pair of tasks. */ data class MediaProjectionCaptureTarget( val launchCookie: IBinder? ): Parcelable { constructor(parcel: Parcel) : this(parcel.readStrongBinder()) override fun writeToParcel(dest: Parcel, flags: Int) { dest.writeStrongBinder(launchCookie) } override fun describeContents(): Int = 0 companion object CREATOR : Parcelable.Creator<MediaProjectionCaptureTarget> { override fun createFromParcel(parcel: Parcel): MediaProjectionCaptureTarget { return MediaProjectionCaptureTarget(parcel) } override fun newArray(size: Int): Array<MediaProjectionCaptureTarget?> { return arrayOfNulls(size) } } } packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +6 −2 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import com.android.systemui.animation.DialogCuj; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; Loading Loading @@ -61,6 +62,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> private final KeyguardStateController mKeyguardStateController; private final Callback mCallback = new Callback(); private final DialogLaunchAnimator mDialogLaunchAnimator; private final FeatureFlags mFlags; private long mMillisUntilFinished = 0; Loading @@ -71,6 +73,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> @Main Handler mainHandler, FalsingManager falsingManager, MetricsLogger metricsLogger, FeatureFlags flags, StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, Loading @@ -83,6 +86,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> statusBarStateController, activityStarter, qsLogger); mController = controller; mController.observe(this, mCallback); mFlags = flags; mKeyguardDismissUtil = keyguardDismissUtil; mKeyguardStateController = keyguardStateController; mDialogLaunchAnimator = dialogLaunchAnimator; Loading Loading @@ -164,8 +168,8 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); getHost().collapsePanels(); }; ScreenRecordDialog dialog = mController.createScreenRecordDialog(mContext, onStartRecordingClicked); ScreenRecordDialog dialog = mController.createScreenRecordDialog(mContext, mFlags, mDialogLaunchAnimator, mActivityStarter, onStartRecordingClicked); ActivityStarter.OnDismissAction dismissAction = () -> { if (shouldAnimateFromView) { Loading packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java +7 −2 Original line number Diff line number Diff line Loading @@ -29,8 +29,11 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserContextProvider; import com.android.systemui.statusbar.policy.CallbackController; Loading Loading @@ -94,9 +97,11 @@ public class RecordingController } /** Create a dialog to show screen recording options to the user. */ public ScreenRecordDialog createScreenRecordDialog(Context context, public ScreenRecordDialog createScreenRecordDialog(Context context, FeatureFlags flags, DialogLaunchAnimator dialogLaunchAnimator, ActivityStarter activityStarter, @Nullable Runnable onStartRecordingClicked) { return new ScreenRecordDialog(context, this, mUserContextProvider, onStartRecordingClicked); return new ScreenRecordDialog(context, this, activityStarter, mUserContextProvider, flags, dialogLaunchAnimator, onStartRecordingClicked); } /** Loading Loading
packages/SystemUI/res/layout/screen_record_dialog.xml +14 −0 Original line number Diff line number Diff line Loading @@ -148,6 +148,20 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1"/> <!-- Temporary entrypoint for the partial screensharing used for teamfooding --> <!-- TODO(b/236838395) remove this and use redesigned dialog --> <TextView android:id="@+id/button_app" android:visibility="gone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="0" android:layout_gravity="end" android:layout_marginEnd="8dp" android:text="App" style="@style/Widget.Dialog.Button.BorderButton" /> <TextView android:id="@+id/button_start" android:layout_width="wrap_content" Loading
packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt +34 −8 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.media.projection.MediaProjectionManager.EXTRA_MEDIA_PROJECTION import android.os.Binder import android.os.Bundle import android.os.IBinder import android.os.ResultReceiver import android.view.View import com.android.internal.app.ChooserActivity import com.android.internal.app.chooser.NotSelectableTargetInfo Loading Loading @@ -103,6 +104,19 @@ class MediaProjectionAppSelectorActivity @Inject constructor( } private fun onTargetActivityLaunched(launchToken: IBinder) { if (intent.hasExtra(EXTRA_CAPTURE_REGION_RESULT_RECEIVER)) { // The client requested to return the result in the result receiver instead of // activity result, let's send the media projection to the result receiver val resultReceiver = intent .getParcelableExtra(EXTRA_CAPTURE_REGION_RESULT_RECEIVER, ResultReceiver::class.java) as ResultReceiver val captureRegion = MediaProjectionCaptureTarget(launchToken) val data = Bundle().apply { putParcelable(KEY_CAPTURE_TARGET, captureRegion) } resultReceiver.send(RESULT_OK, data) } else { // Return the media projection instance as activity result val mediaProjectionBinder = intent.getIBinderExtra(EXTRA_MEDIA_PROJECTION) val projection = IMediaProjection.Stub.asInterface(mediaProjectionBinder) Loading @@ -112,8 +126,20 @@ class MediaProjectionAppSelectorActivity @Inject constructor( intent.putExtra(EXTRA_MEDIA_PROJECTION, projection.asBinder()) setResult(RESULT_OK, intent) setForceSendResultForMediaProjection() } finish() } override fun shouldGetOnlyDefaultActivities() = false companion object { /** * When EXTRA_CAPTURE_REGION_RESULT_RECEIVER is passed as intent extra * the activity will send the [CaptureRegion] to the result receiver * instead of returning media projection instance through activity result. */ const val EXTRA_CAPTURE_REGION_RESULT_RECEIVER = "capture_region_result_receiver" const val KEY_CAPTURE_TARGET = "capture_region" } }
packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt 0 → 100644 +49 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.media import android.os.IBinder import android.os.Parcel import android.os.Parcelable /** * Class that represents an area that should be captured. * Currently it has only a launch cookie that represents a task but * we potentially could add more identifiers e.g. for a pair of tasks. */ data class MediaProjectionCaptureTarget( val launchCookie: IBinder? ): Parcelable { constructor(parcel: Parcel) : this(parcel.readStrongBinder()) override fun writeToParcel(dest: Parcel, flags: Int) { dest.writeStrongBinder(launchCookie) } override fun describeContents(): Int = 0 companion object CREATOR : Parcelable.Creator<MediaProjectionCaptureTarget> { override fun createFromParcel(parcel: Parcel): MediaProjectionCaptureTarget { return MediaProjectionCaptureTarget(parcel) } override fun newArray(size: Int): Array<MediaProjectionCaptureTarget?> { return arrayOfNulls(size) } } }
packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +6 −2 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import com.android.systemui.animation.DialogCuj; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QSTile; Loading Loading @@ -61,6 +62,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> private final KeyguardStateController mKeyguardStateController; private final Callback mCallback = new Callback(); private final DialogLaunchAnimator mDialogLaunchAnimator; private final FeatureFlags mFlags; private long mMillisUntilFinished = 0; Loading @@ -71,6 +73,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> @Main Handler mainHandler, FalsingManager falsingManager, MetricsLogger metricsLogger, FeatureFlags flags, StatusBarStateController statusBarStateController, ActivityStarter activityStarter, QSLogger qsLogger, Loading @@ -83,6 +86,7 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> statusBarStateController, activityStarter, qsLogger); mController = controller; mController.observe(this, mCallback); mFlags = flags; mKeyguardDismissUtil = keyguardDismissUtil; mKeyguardStateController = keyguardStateController; mDialogLaunchAnimator = dialogLaunchAnimator; Loading Loading @@ -164,8 +168,8 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations(); getHost().collapsePanels(); }; ScreenRecordDialog dialog = mController.createScreenRecordDialog(mContext, onStartRecordingClicked); ScreenRecordDialog dialog = mController.createScreenRecordDialog(mContext, mFlags, mDialogLaunchAnimator, mActivityStarter, onStartRecordingClicked); ActivityStarter.OnDismissAction dismissAction = () -> { if (shouldAnimateFromView) { Loading
packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java +7 −2 Original line number Diff line number Diff line Loading @@ -29,8 +29,11 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserContextProvider; import com.android.systemui.statusbar.policy.CallbackController; Loading Loading @@ -94,9 +97,11 @@ public class RecordingController } /** Create a dialog to show screen recording options to the user. */ public ScreenRecordDialog createScreenRecordDialog(Context context, public ScreenRecordDialog createScreenRecordDialog(Context context, FeatureFlags flags, DialogLaunchAnimator dialogLaunchAnimator, ActivityStarter activityStarter, @Nullable Runnable onStartRecordingClicked) { return new ScreenRecordDialog(context, this, mUserContextProvider, onStartRecordingClicked); return new ScreenRecordDialog(context, this, activityStarter, mUserContextProvider, flags, dialogLaunchAnimator, onStartRecordingClicked); } /** Loading