From 55fcc0a04cf012e75e4f39e0500cda177dc8e130 Mon Sep 17 00:00:00 2001 From: kenway214 Date: Mon, 3 Nov 2025 00:30:44 +0530 Subject: [PATCH] GameBar: Add screen recording support and add "take screen record" in gesture quick actions menu Signed-off-by: kenway214 --- Android.bp | 3 +- res/values/arrays.xml | 2 + src/com/android/gamebar/GameBar.kt | 80 ++++++++++++++++++- .../screenrecord/IRecordingCallback.aidl | 6 ++ .../screenrecord/IRemoteRecording.aidl | 12 +++ 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/com/android/systemui/screenrecord/IRecordingCallback.aidl create mode 100644 src/com/android/systemui/screenrecord/IRemoteRecording.aidl diff --git a/Android.bp b/Android.bp index 0652f15..6e26d9f 100644 --- a/Android.bp +++ b/Android.bp @@ -11,7 +11,8 @@ android_app { srcs: [ "src/**/*.kt", - "src/**/*.java" + "src/**/*.java", + "src/**/*.aidl" ], certificate: "platform", diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 400773b..81f64e3 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -85,6 +85,7 @@ Start/Stop Log Capture Open GameBar Settings Take Screenshot + Start/Stop Screen Record no_action @@ -92,6 +93,7 @@ capture_logs open_settings take_screenshot + screen_record diff --git a/src/com/android/gamebar/GameBar.kt b/src/com/android/gamebar/GameBar.kt index d1a4680..8ec05b8 100644 --- a/src/com/android/gamebar/GameBar.kt +++ b/src/com/android/gamebar/GameBar.kt @@ -35,6 +35,13 @@ import java.io.IOException import java.text.SimpleDateFormat import java.util.* +import android.content.ComponentName +import android.content.ServiceConnection +import android.os.IBinder +import android.os.UserHandle +import com.android.systemui.screenrecord.IRemoteRecording +import com.android.systemui.screenrecord.IRecordingCallback + class GameBar private constructor(context: Context) { companion object { @@ -131,6 +138,17 @@ class GameBar private constructor(context: Context) { private var longPressFunction = "open_settings" private var bgDrawable: GradientDrawable? = null + private var isRecorderBound = false + private var remoteRecording: IRemoteRecording? = null + private val recorderConnection = object : ServiceConnection { + override fun onServiceConnected(name: ComponentName?, service: IBinder?) { + remoteRecording = IRemoteRecording.Stub.asInterface(service) + } + override fun onServiceDisconnected(name: ComponentName?) { + remoteRecording = null + } + } + private var itemSpacingDp = 8 private var layoutChanged = false @@ -208,6 +226,9 @@ class GameBar private constructor(context: Context) { "take_screenshot" -> { takeScreenshot() } + "screen_record" -> { + toggleScreenRecording() + } } } @@ -302,7 +323,9 @@ class GameBar private constructor(context: Context) { } overlayView = null } - + + bindScreenRecorder() + applyPreferences() layoutParams = WindowManager.LayoutParams( @@ -433,6 +456,8 @@ class GameBar private constructor(context: Context) { rootLayout = null layoutParams = null layoutChanged = true // Mark layout as changed + + unbindScreenRecorder() } fun cleanup() { @@ -1167,6 +1192,59 @@ class GameBar private constructor(context: Context) { Toast.makeText(context, "Failed to take screenshot", Toast.LENGTH_SHORT).show() } } + + private fun bindScreenRecorder() { + try { + isRecorderBound = context.bindServiceAsUser(Intent().apply { + component = ComponentName( + "com.android.systemui", + "com.android.systemui.screenrecord.RecordingService" + ) + }, recorderConnection, Context.BIND_AUTO_CREATE, UserHandle.CURRENT) + } catch (e: Exception) { + android.util.Log.e("GameBar", "Failed to bind screen recorder: ${e.message}") + isRecorderBound = false + } + } + + private fun unbindScreenRecorder() { + if (isRecorderBound) { + try { + context.unbindService(recorderConnection) + } catch (e: Exception) { + android.util.Log.w("GameBar", "Failed to unbind screen recorder: ${e.message}") + } finally { + isRecorderBound = false + remoteRecording = null + } + } + } + + private fun toggleScreenRecording() { + val recorder = remoteRecording + if (recorder == null) { + Toast.makeText(context, "Screen recorder not available", Toast.LENGTH_SHORT).show() + return + } + + try { + val isStarting = try { recorder.isStarting } catch (e: Exception) { false } + val isRecording = try { recorder.isRecording } catch (e: Exception) { false } + + if (!isStarting) { + if (!isRecording) { + recorder.startRecording() + Toast.makeText(context, "Screen recording started", Toast.LENGTH_SHORT).show() + } else { + recorder.stopRecording() + Toast.makeText(context, "Screen recording stopped", Toast.LENGTH_SHORT).show() + } + } + } catch (e: Exception) { + Toast.makeText(context, "Failed to toggle screen recording", Toast.LENGTH_SHORT).show() + android.util.Log.e("GameBar", "Screen recording error: ${e.message}") + } + } private fun openOverlaySettings() { try { diff --git a/src/com/android/systemui/screenrecord/IRecordingCallback.aidl b/src/com/android/systemui/screenrecord/IRecordingCallback.aidl new file mode 100644 index 0000000..ee4a463 --- /dev/null +++ b/src/com/android/systemui/screenrecord/IRecordingCallback.aidl @@ -0,0 +1,6 @@ +package com.android.systemui.screenrecord; + +interface IRecordingCallback { + void onRecordingStart(); + void onRecordingEnd(); +} diff --git a/src/com/android/systemui/screenrecord/IRemoteRecording.aidl b/src/com/android/systemui/screenrecord/IRemoteRecording.aidl new file mode 100644 index 0000000..13cbf8d --- /dev/null +++ b/src/com/android/systemui/screenrecord/IRemoteRecording.aidl @@ -0,0 +1,12 @@ +package com.android.systemui.screenrecord; + +import com.android.systemui.screenrecord.IRecordingCallback; + +interface IRemoteRecording { + void startRecording(); + void stopRecording(); + boolean isRecording(); + boolean isStarting(); + void addRecordingCallback(in IRecordingCallback callback); + void removeRecordingCallback(in IRecordingCallback callback); +}