summaryrefslogtreecommitdiff
path: root/logcat
diff options
context:
space:
mode:
authorSergey Prigogin <sprigogin@google.com>2022-06-28 21:59:11 -0700
committerTreeHugger Robot <treehugger-gerrit@google.com>2022-06-29 20:30:56 +0000
commit3319c4f1b15fbaab8dc93f4ad2b410d65f7fc4f0 (patch)
treef1bc35ec40fb83803732db869a1216145764bac9 /logcat
parent0a037ddffd036227825118049e552b3db0b3c458 (diff)
downloadidea-3319c4f1b15fbaab8dc93f4ad2b410d65f7fc4f0.tar.gz
Split intellij.android.adb.ui module from intellij.android.adb
Also mode screen recording code to intellij.android.adb.ui. This is the first step for using it in the Running Devices window. Splitting of intellij.android.adb.ui was necessary to avoid a circular dependency between modules. Test: existing Bug: 218601935 Change-Id: I53a0f518f96e383be95f5317416b86bb8536f06b
Diffstat (limited to 'logcat')
-rw-r--r--logcat/BUILD1
-rw-r--r--logcat/intellij.android.logcat.iml1
-rw-r--r--logcat/resources/messages/LogcatBundle.properties23
-rw-r--r--logcat/src/META-INF/logcat.xml7
-rw-r--r--logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt2
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/EmulatorConsoleRecordingProvider.kt95
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/RecordingProvider.kt33
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorder.kt193
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderAction.kt217
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderDialog.kt135
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptions.kt33
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptionsDialog.form75
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptionsDialog.java156
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderPersistentOptions.kt75
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecordingSupportedCache.kt31
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecordingSupportedCacheImpl.kt97
-rw-r--r--logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ShellCommandRecordingProvider.kt99
-rw-r--r--logcat/testSrc/META-INF/plugin.xml5
-rw-r--r--logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/EmulatorConsoleRecordingProviderTest.kt38
-rw-r--r--logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderActionTest.kt101
-rw-r--r--logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderPersistentOptionsTest.kt68
-rw-r--r--logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ShellCommandRecordingProviderTest.kt33
22 files changed, 7 insertions, 1511 deletions
diff --git a/logcat/BUILD b/logcat/BUILD
index 78fd37a20ee..ba8b07f1615 100644
--- a/logcat/BUILD
+++ b/logcat/BUILD
@@ -26,6 +26,7 @@ iml_module(
"//tools/analytics-library/tracker:analytics-tracker[module]",
"//tools/adt/idea/.idea/libraries:studio-analytics-proto",
"//tools/adt/idea/.idea/libraries:kotlinx-coroutines-guava",
+ "//tools/adt/idea/android-adb-ui:intellij.android.adb.ui[module]",
],
)
diff --git a/logcat/intellij.android.logcat.iml b/logcat/intellij.android.logcat.iml
index f8c9b151e8e..b92af772d43 100644
--- a/logcat/intellij.android.logcat.iml
+++ b/logcat/intellij.android.logcat.iml
@@ -22,5 +22,6 @@
<orderEntry type="module" module-name="analytics-tracker" />
<orderEntry type="library" name="studio-analytics-proto" level="project" />
<orderEntry type="library" name="kotlinx-coroutines-guava" level="project" />
+ <orderEntry type="module" module-name="intellij.android.adb.ui" />
</component>
</module> \ No newline at end of file
diff --git a/logcat/resources/messages/LogcatBundle.properties b/logcat/resources/messages/LogcatBundle.properties
index 5a393855a58..95e11aab654 100644
--- a/logcat/resources/messages/LogcatBundle.properties
+++ b/logcat/resources/messages/LogcatBundle.properties
@@ -98,27 +98,4 @@ logcat.help.tooltip=Help
logcat.toggle.filter.add=Add "{0}" to Filter
logcat.toggle.filter.remove=Remove "{0}" from Filter
-screenrecord.action.title=Screen Record
-screenrecord.action.description=Record a video of the device display
-screenrecord.action.stopping=Stopping...
-screenrecord.action.save.as=Save As
-screenrecord.action.show.in=Show in {0}
-screenrecord.action.open=Open
-screenrecord.action.open.file=Open File
-screenrecord.action.view.recording=Video Recording saved as {0}
-screenrecord.error.popup.title=Screen Recorder Error
-screenrecord.error=Failed to record the screen
-screenrecord.error.exception=Failed to record the screen\n\n{0}
-screenrecord.options.ok.button.text=Start Recording
-screenrecord.options.info=<html>Screen Recorder can record the device's display for a maximum of 3 minutes.</html>
-screenrecord.options.bit.rate=Bit Rate (Mbps):
-screenrecord.options.bit.rate.invalid=Bit Rate must be an integer.
-screenrecord.options.resolution=Resolution (% of native):
-screenrecord.options.show.taps=Show Taps
-screenrecord.options.show.taps.tooltip=Show visual feedback for taps
-screenrecord.options.use.emulator.recording=Use Emulator Recording (webm)
-screenrecord.options.use.emulator.recording.tooltip=Record using the emulator recording API. If unchecked, will use adb recording instead.
-screenrecord.dialog.progress=Recording: {0}
-screenrecord.dialog.stop.recording=Stop Recording
-
logcat.open.embedded.data.text=Create a Scratch File from {0} \ No newline at end of file
diff --git a/logcat/src/META-INF/logcat.xml b/logcat/src/META-INF/logcat.xml
index afc850d8e5e..37f40b55f57 100644
--- a/logcat/src/META-INF/logcat.xml
+++ b/logcat/src/META-INF/logcat.xml
@@ -56,12 +56,7 @@
<applicationService serviceImplementation="com.android.tools.idea.logcat.messages.AndroidLogcatFormattingOptions"/>
<applicationService serviceImplementation="com.android.tools.idea.logcat.filters.AndroidLogcatNamedFilters"/>
<applicationService serviceImplementation="com.android.tools.idea.logcat.filters.AndroidLogcatFilterHistory"/>
- <applicationService serviceImplementation="com.android.tools.idea.logcat.actions.screenrecord.ScreenRecorderPersistentOptions"/>
-
- <projectService
- serviceInterface="com.android.tools.idea.logcat.actions.screenrecord.ScreenRecordingSupportedCache"
- serviceImplementation="com.android.tools.idea.logcat.actions.screenrecord.ScreenRecordingSupportedCacheImpl"
- />
+ <applicationService serviceImplementation="com.android.tools.idea.ui.screenrecording.ScreenRecorderPersistentOptions"/>
<additionalTextAttributes scheme="Default" file="colorSchemes/LogcatColorSchemeDefault.xml"/>
<additionalTextAttributes scheme="Darcula" file="colorSchemes/LogcatColorSchemeDarcula.xml"/>
diff --git a/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt b/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt
index b9b8665cb9e..e6d3493abe3 100644
--- a/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt
+++ b/logcat/src/com/android/tools/idea/logcat/LogcatMainPanel.kt
@@ -41,7 +41,6 @@ import com.android.tools.idea.logcat.actions.PauseLogcatAction
import com.android.tools.idea.logcat.actions.PreviousOccurrenceToolbarAction
import com.android.tools.idea.logcat.actions.RestartLogcatAction
import com.android.tools.idea.logcat.actions.ToggleFilterAction
-import com.android.tools.idea.logcat.actions.screenrecord.ScreenRecorderAction
import com.android.tools.idea.logcat.devices.Device
import com.android.tools.idea.logcat.filters.AndroidLogcatFilterHistory
import com.android.tools.idea.logcat.filters.LogcatFilter
@@ -76,6 +75,7 @@ import com.android.tools.idea.logcat.util.isCaretAtBottom
import com.android.tools.idea.logcat.util.isScrollAtBottom
import com.android.tools.idea.logcat.util.toggleFilterTerm
import com.android.tools.idea.run.ClearLogcatListener
+import com.android.tools.idea.ui.screenrecording.ScreenRecorderAction
import com.android.tools.idea.ui.screenshot.DeviceArtScreenshotOptions
import com.android.tools.idea.ui.screenshot.ScreenshotAction
import com.google.wireless.android.sdk.stats.LogcatUsageEvent
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/EmulatorConsoleRecordingProvider.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/EmulatorConsoleRecordingProvider.kt
deleted file mode 100644
index 5f35a302961..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/EmulatorConsoleRecordingProvider.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.android.adblib.AdbLibSession
-import com.android.adblib.tools.EmulatorConsole
-import com.android.adblib.tools.localConsoleAddress
-import com.android.adblib.tools.openEmulatorConsole
-import com.google.common.annotations.VisibleForTesting
-import com.intellij.util.io.exists
-import com.intellij.util.io.move
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import java.nio.file.Files
-import java.nio.file.Path
-import java.nio.file.StandardCopyOption.REPLACE_EXISTING
-
-private const val SERIAL_NUMBER_PREFIX = "emulator-"
-
-/**
- * A [RecordingProvider] that uses [EmulatorConsole]
- */
-internal class EmulatorConsoleRecordingProvider(
- private val serialNumber: String,
- private val localPath: Path,
- private val options: ScreenRecorderOptions,
- private val adbLibSession: AdbLibSession,
-) : RecordingProvider {
- override val fileExtension = "webm"
-
- private lateinit var emulatorConsole: EmulatorConsole
-
- override suspend fun startRecording() {
- emulatorConsole = adbLibSession.openEmulatorConsole(localConsoleAddress(serialNumber.getEmulatorPort()))
- emulatorConsole.startScreenRecording(localPath, *getRecorderOptions(options))
- }
-
- override suspend fun stopRecording() {
- if (!this::emulatorConsole.isInitialized) {
- throw IllegalStateException("emulatorConsole not initialized. Did you call startRecording()?")
- }
- emulatorConsole.stopScreenRecording()
- }
-
- override suspend fun doesRecordingExist(): Boolean = localPath.exists()
-
- override suspend fun pullRecording(target: Path) {
- withContext(Dispatchers.IO) {
- localPath.move(target)
- }
- }
-
- companion object {
- // Note that this is very similar to ShellCommandRecordingProvider getScreenRecordCommand() but there is guarantee that the args will be the
- // same in the future so best to keep separate versions
- @VisibleForTesting
- internal fun getRecorderOptions(options: ScreenRecorderOptions): Array<String> {
- val args = mutableListOf<String>()
- if (options.width > 0 && options.height > 0) {
- args.add("--size")
- args.add("${options.width}x${options.height}")
- }
- if (options.bitrateMbps > 0) {
- args.add("--bit-rate")
- args.add((options.bitrateMbps * 1000000).toString())
- }
- return args.toTypedArray()
- }
- }
-}
-
-private fun String.getEmulatorPort(): Int {
- if (!startsWith(SERIAL_NUMBER_PREFIX)) {
- throw IllegalArgumentException("Not an emulator serial number: $this")
- }
- try {
- return substring(SERIAL_NUMBER_PREFIX.length).toInt()
- }
- catch (e: NumberFormatException) {
- throw IllegalArgumentException("Not an emulator serial number: $this", e)
- }
-}
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/RecordingProvider.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/RecordingProvider.kt
deleted file mode 100644
index 9e097d27f39..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/RecordingProvider.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import java.nio.file.Path
-
-/**
- * Provides screen recording functionality
- */
-interface RecordingProvider {
- val fileExtension: String
-
- suspend fun startRecording()
-
- suspend fun stopRecording()
-
- suspend fun doesRecordingExist(): Boolean
-
- suspend fun pullRecording(target: Path)
-} \ No newline at end of file
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorder.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorder.kt
deleted file mode 100644
index c833af350ed..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorder.kt
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.android.annotations.concurrency.UiThread
-import com.android.tools.idea.concurrency.AndroidDispatchers.uiThread
-import com.android.tools.idea.logcat.LogcatBundle
-import com.intellij.CommonBundle
-import com.intellij.ide.actions.RevealFileAction
-import com.intellij.ide.util.PropertiesComponent
-import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.fileChooser.FileChooserFactory
-import com.intellij.openapi.fileChooser.FileSaverDescriptor
-import com.intellij.openapi.fileChooser.FileSaverDialog
-import com.intellij.openapi.fileTypes.NativeFileType
-import com.intellij.openapi.progress.ProcessCanceledException
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.ui.DialogWrapper
-import com.intellij.openapi.ui.Messages
-import com.intellij.openapi.util.SystemInfo
-import com.intellij.openapi.vfs.LocalFileSystem
-import com.intellij.openapi.vfs.VfsUtil
-import com.intellij.openapi.vfs.VirtualFileWrapper
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.withContext
-import java.io.File
-import java.time.Clock
-import java.util.Calendar
-import java.util.Locale
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.TimeUnit
-import java.util.concurrent.TimeUnit.MILLISECONDS
-
-private val MAX_RECORDING_TIME_MILLIS = TimeUnit.MINUTES.toMillis(3)
-private const val SAVE_PATH_KEY = "ScreenRecorder.SavePath"
-
-/**
- * Records the screen of a device.
- *
- * Mostly based on com.android.tools.idea.ddms.actions.ScreenRecorderTask but changed to use coroutines and AdbLib.
- *
- * TODO(b/235094713): Add tests
- */
-internal class ScreenRecorder(
- private val project: Project,
- private val recordingProvider: RecordingProvider,
- private val clock: Clock = Clock.systemDefaultZone(),
-) {
- suspend fun recordScreen() {
- recordingProvider.startRecording()
-
- val start = clock.millis()
-
- val stoppingLatch = CountDownLatch(1)
- val dialog = ScreenRecorderDialog(LogcatBundle.message("screenrecord.action.title")) { stoppingLatch.countDown() }
- val dialogWrapper: DialogWrapper
- withContext(uiThread) {
- dialogWrapper = dialog.createWrapper(project)
- dialogWrapper.show()
- }
-
- try {
- withContext(Dispatchers.IO) {
- while (!stoppingLatch.await(millisUntilNextSecondTick(start), MILLISECONDS) && clock.millis() - start < MAX_RECORDING_TIME_MILLIS) {
- withContext(uiThread) {
- dialog.recordingTimeMillis = clock.millis() - start
- }
- }
- }
- withContext(uiThread) {
- dialog.recordingLabelText = LogcatBundle.message("screenrecord.action.stopping")
- }
- recordingProvider.stopRecording()
- }
- catch (e: InterruptedException) {
- recordingProvider.stopRecording()
- throw ProcessCanceledException()
- }
- finally {
- withContext(uiThread) {
- dialogWrapper.close(DialogWrapper.CLOSE_EXIT_CODE)
- }
- }
-
- pullRecording()
- }
-
- private suspend fun pullRecording() {
- if (!recordingProvider.doesRecordingExist()) {
- // TODO(aalbert): See if we can get the error for the non-emulator impl.
- withContext(uiThread) {
- Messages.showErrorDialog(
- LogcatBundle.message("screenrecord.error"),
- LogcatBundle.message("screenrecord.error.popup.title"))
- }
- return
- }
-
- val fileWrapper: VirtualFileWrapper?
- withContext(uiThread) {
- fileWrapper = getTargetFile(recordingProvider.fileExtension)
- }
- if (fileWrapper == null) {
- return
- }
-
- recordingProvider.pullRecording(fileWrapper.file.toPath())
-
- withContext(uiThread) {
- handleSavedRecording(fileWrapper)
- }
- }
-
- private fun getTargetFile(extension: String): VirtualFileWrapper? {
- val properties = PropertiesComponent.getInstance(project)
- val descriptor = FileSaverDescriptor(LogcatBundle.message("screenrecord.action.save.as"), "", extension)
- val saveFileDialog: FileSaverDialog = FileChooserFactory.getInstance().createSaveFileDialog(descriptor, project)
- val lastPath = properties.getValue(SAVE_PATH_KEY)
- val baseDir = if (lastPath != null) LocalFileSystem.getInstance().findFileByPath(lastPath) else VfsUtil.getUserHomeDir()
- val saveFileWrapper = saveFileDialog.save(baseDir, getDefaultFileName(extension))
- if (saveFileWrapper != null) {
- val saveFile = saveFileWrapper.file
- properties.setValue(SAVE_PATH_KEY, saveFile.path)
- }
- return saveFileWrapper
- }
-
- private fun millisUntilNextSecondTick(start: Long): Long {
- return 1000 - (clock.millis() - start) % 1000
- }
-
- @UiThread
- private fun handleSavedRecording(fileWrapper: VirtualFileWrapper) {
- val path = fileWrapper.file.absolutePath
- val message = LogcatBundle.message("screenrecord.action.view.recording", path)
- val cancel = CommonBundle.getOkButtonText()
- val icon = Messages.getInformationIcon()
- if (RevealFileAction.isSupported()) {
- val no = LogcatBundle.message("screenrecord.action.show.in", RevealFileAction.getFileManagerName())
- val exitCode: Int = Messages.showYesNoCancelDialog(
- project,
- message,
- LogcatBundle.message("screenrecord.action.title"),
- LogcatBundle.message("screenrecord.action.open"),
- no,
- cancel,
- icon)
- if (exitCode == Messages.YES) {
- openSavedFile(fileWrapper)
- }
- else if (exitCode == Messages.NO) {
- RevealFileAction.openFile(File(path))
- }
- }
- else if (Messages.showOkCancelDialog(
- project,
- message,
- LogcatBundle.message("screenrecord.action.title"),
- LogcatBundle.message("screenrecord.action.open.file"),
- cancel,
- icon) == Messages.OK) {
- openSavedFile(fileWrapper)
- }
- }
-}
-
-private fun getDefaultFileName(extension: String): String {
- val now = Calendar.getInstance()
- val fileName = "device-%tF-%tH%tM%tS"
- // Add extension to filename on Mac only see: b/38447816.
- return String.format(Locale.US, if (SystemInfo.isMac) "$fileName.$extension" else fileName, now, now, now, now)
-}
-
-// Tries to open the file at myLocalPath
-private fun openSavedFile(fileWrapper: VirtualFileWrapper) {
- val file = fileWrapper.virtualFile
- if (file != null) {
- NativeFileType.openAssociatedApplication(file)
- }
-}
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderAction.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderAction.kt
deleted file mode 100644
index d7b964aca45..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderAction.kt
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2013 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.tools.idea.logcat.actions.screenrecord
-
-import com.android.adblib.AdbLibSession
-import com.android.adblib.DeviceSelector
-import com.android.adblib.shellAsText
-import com.android.annotations.concurrency.UiThread
-import com.android.prefs.AndroidLocationsException
-import com.android.sdklib.internal.avd.AvdInfo
-import com.android.sdklib.internal.avd.AvdManager
-import com.android.tools.idea.adblib.AdbLibService
-import com.android.tools.idea.concurrency.AndroidCoroutineScope
-import com.android.tools.idea.concurrency.AndroidDispatchers.uiThread
-import com.android.tools.idea.log.LogWrapper
-import com.android.tools.idea.logcat.LogcatBundle
-import com.android.tools.idea.sdk.AndroidSdks
-import com.intellij.openapi.Disposable
-import com.intellij.openapi.actionSystem.AnActionEvent
-import com.intellij.openapi.actionSystem.DataKey
-import com.intellij.openapi.diagnostic.thisLogger
-import com.intellij.openapi.project.DumbAwareAction
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.ui.Messages
-import icons.StudioIcons
-import kotlinx.coroutines.CoroutineExceptionHandler
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import java.awt.Dimension
-import java.nio.file.Path
-import java.time.Clock
-import java.time.Duration
-import kotlin.coroutines.CoroutineContext
-import kotlin.coroutines.EmptyCoroutineContext
-
-private const val REMOTE_PATH = "/sdcard/screen-recording-%d.mp4"
-private val WM_SIZE_OUTPUT_REGEX = Regex("(?<width>\\d+)x(?<height>\\d+)")
-private const val EMU_TMP_FILENAME = "tmp.webm"
-private val COMMAND_TIMEOUT = Duration.ofSeconds(2)
-
-/**
- * A [DumbAwareAction] that records the screen.
- *
- * Based on com.android.tools.idea.ddms.actions.ScreenRecorderAction but uses AdbLib instead of DDMLIB.
- *
- * TODO(b/235094713): Add more tests. Existing tests are just for completeness with tests in DDMS
- */
-internal class ScreenRecorderAction(
- private val disposableParent: Disposable,
- private val project: Project,
- private val adbLibSession: AdbLibSession = AdbLibService.getSession(project),
- private val clock: Clock = Clock.systemDefaultZone(),
- coroutineContext: CoroutineContext = EmptyCoroutineContext
-) : DumbAwareAction(
- LogcatBundle.message("screenrecord.action.title"),
- LogcatBundle.message("screenrecord.action.description"), StudioIcons.Logcat.Toolbar.VIDEO_CAPTURE
-) {
- private val logger = thisLogger()
- private val exceptionHandler = coroutineExceptionHandler()
- private val screenRecordingSupportedCache = ScreenRecordingSupportedCache.getInstance(project)
- private val coroutineScope = AndroidCoroutineScope(disposableParent, coroutineContext)
-
- /**
- * Devices that are currently recording.
- */
- private val recordingInProgress = mutableSetOf<String>()
-
- override fun update(event: AnActionEvent) {
- val presentation = event.presentation
- val serialNumber = event.getData(SERIAL_NUMBER_KEY)
- val sdk = event.getData(SDK_KEY) ?: 0
-
- if (serialNumber == null || sdk < 19) {
- presentation.isEnabled = false
- return
- }
- presentation.isEnabled = screenRecordingSupportedCache.isScreenRecordingSupported(serialNumber, sdk)
-
- }
-
- override fun actionPerformed(event: AnActionEvent) {
- val serialNumber = event.getData(SERIAL_NUMBER_KEY) ?: return
- val dialog = ScreenRecorderOptionsDialog(project, serialNumber.isEmulator())
- if (!dialog.showAndGet()) {
- return
- }
-
- startRecordingAsync(dialog.useEmulatorRecording, serialNumber, event.getData(AVD_NAME_KEY))
- }
-
- private suspend fun execute(serialNumber: String, command: String) =
- adbLibSession.deviceServices.shellAsText(DeviceSelector.fromSerialNumber(serialNumber), command, commandTimeout = COMMAND_TIMEOUT)
-
- @UiThread
- private fun startRecordingAsync(useEmulatorRecording: Boolean, serialNumber: String, avdName: String?,) {
- val manager: AvdManager? = getVirtualDeviceManager()
- val emulatorRecordingFile =
- if (manager != null && useEmulatorRecording && avdName != null) getTemporaryVideoPathForVirtualDevice(avdName, manager) else null
- recordingInProgress.add(serialNumber)
-
- coroutineScope.launch(exceptionHandler) {
- val showTouchEnabled = isShowTouchEnabled(serialNumber)
- val size = getDeviceScreenSize(serialNumber)
- val options: ScreenRecorderOptions = ScreenRecorderPersistentOptions.getInstance().toScreenRecorderOptions(size)
- if (options.showTouches != showTouchEnabled) {
- setShowTouch(serialNumber, options.showTouches)
- }
- try {
- val recodingProvider = when (emulatorRecordingFile) {
- null -> ShellCommandRecordingProvider(
- disposableParent,
- serialNumber,
- REMOTE_PATH.format(clock.millis()),
- options,
- adbLibSession)
- else -> EmulatorConsoleRecordingProvider(
- serialNumber,
- emulatorRecordingFile,
- options,
- adbLibSession)
- }
- ScreenRecorder(project, recodingProvider).recordScreen()
- }
- finally {
- if (options.showTouches != showTouchEnabled) {
- setShowTouch(serialNumber, showTouchEnabled)
- }
- withContext(uiThread) {
- recordingInProgress.remove(serialNumber)
- }
- }
- }
- }
-
- private fun getVirtualDeviceManager(): AvdManager? {
- return try {
- AvdManager.getInstance(AndroidSdks.getInstance().tryToChooseSdkHandler(), LogWrapper(logger))
- }
- catch (exception: AndroidLocationsException) {
- logger.warn(exception)
- null
- }
- }
-
- private suspend fun getDeviceScreenSize(serialNumber: String): Dimension? {
- try {
- val out = execute(serialNumber, "wm size")
- val matchResult = WM_SIZE_OUTPUT_REGEX.find(out)
- if (matchResult == null) {
- logger.warn("Unexpected output from 'wm size': $out")
- return null
- }
- val width = matchResult.groups["width"]
- val height = matchResult.groups["height"]
- if (width == null || height == null) {
- logger.warn("Unexpected output from 'wm size': $out")
- return null
- }
- return Dimension(width.value.toInt(), height.value.toInt())
- }
- catch (e: Exception) {
- logger.warn("Failed to get device screen size.", e)
- }
- return null
- }
-
- private suspend fun setShowTouch(serialNumber: String, isEnabled: Boolean) {
- val value = if (isEnabled) 1 else 0
- try {
- execute(serialNumber, "settings put system show_touches $value")
- }
- catch (e: Exception) {
- logger.warn("Failed to set show taps to $isEnabled", e)
- }
- }
-
- private suspend fun isShowTouchEnabled(serialNumber: String): Boolean {
- val out = execute(serialNumber, "settings get system show_touches")
- return out.trim() == "1"
- }
-
- private fun coroutineExceptionHandler() = CoroutineExceptionHandler { _, throwable ->
- logger.warn("Failed to record screen", throwable)
- coroutineScope.launch(uiThread) {
- Messages.showErrorDialog(
- project,
- LogcatBundle.message("screenrecord.error.exception", throwable.toString()),
- LogcatBundle.message("screenrecord.action.title"))
- }
- }
-
- companion object {
- val SERIAL_NUMBER_KEY = DataKey.create<String>("ScreenRecorderDeviceSerialNumber")
- val AVD_NAME_KEY = DataKey.create<String>("ScreenRecorderDeviceAvdName")
- val SDK_KEY = DataKey.create<Int>("ScreenRecorderDeviceSdk")
- }
-}
-
-private fun getTemporaryVideoPathForVirtualDevice(avdName: String, manager: AvdManager): Path? {
- val virtualDevice: AvdInfo = manager.getAvd(avdName, true) ?: return null
- return virtualDevice.dataFolderPath.resolve(EMU_TMP_FILENAME)
-}
-
-private fun String.isEmulator() = startsWith("emulator-")
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderDialog.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderDialog.kt
deleted file mode 100644
index 5b8e4d706c8..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderDialog.kt
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2021 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.tools.idea.logcat.actions.screenrecord
-
-import com.android.tools.idea.logcat.LogcatBundle
-import com.intellij.openapi.project.Project
-import com.intellij.openapi.ui.DialogPanel
-import com.intellij.openapi.ui.DialogWrapper
-import com.intellij.openapi.ui.DialogWrapperDialog
-import com.intellij.ui.PopupBorder
-import com.intellij.ui.TitlePanel
-import com.intellij.ui.WindowMoveListener
-import com.intellij.ui.components.DialogPanel
-import com.intellij.ui.components.Label
-import com.intellij.ui.scale.JBUIScale
-import com.intellij.util.ui.JBUI.Borders
-import com.intellij.util.ui.components.BorderLayoutPanel
-import java.awt.BorderLayout
-import java.awt.Component
-import java.awt.Dimension
-import javax.swing.Box
-import javax.swing.JButton
-import javax.swing.JComponent
-import javax.swing.JLabel
-import javax.swing.JPanel
-import javax.swing.JRootPane
-import javax.swing.SwingUtilities
-import javax.swing.border.Border
-
-/**
- * Modeless dialog shown during device screen recording.
- *
- * Copied from com.android.tools.idea.ddms.actions.ScreenRecorderDialog
- */
-internal class ScreenRecorderDialog(private val dialogTitle: String, private val onStop: Runnable) {
-
- var recordingTimeMillis: Long = 0
- set(value) {
- field = value
- recordingLabelText = recordingTimeText(value)
- }
-
- var recordingLabelText = recordingTimeText(recordingTimeMillis)
- set(value) {
- field = value
- recordingLabel.text = value
- }
-
- private lateinit var recordingLabel: JLabel
-
- private fun recordingTimeText(timeMillis: Long): String {
- val seconds = (timeMillis / 1000).toInt()
- return LogcatBundle.message("screenrecord.dialog.progress", String.format("%02d:%02d", seconds / 60, seconds % 60))
- }
-
- /**
- * Creates contents of the dialog.
- */
- private fun createPanel(): DialogPanel {
- val dialogPanel = DialogPanel(dialogTitle)
- val titlePanel = TitlePanel()
- titlePanel.setText(dialogTitle)
- titlePanel.setActive(true)
- // WindowMoveListener allows the window to be moved by dragging the title panel.
- val moveListener: WindowMoveListener = object : WindowMoveListener(titlePanel) {
- override fun getView(component: Component): Component {
- return SwingUtilities.getAncestorOfClass(DialogWrapperDialog::class.java, component)
- }
- }
- titlePanel.addMouseListener(moveListener)
- titlePanel.addMouseMotionListener(moveListener)
- dialogPanel.add(titlePanel, BorderLayout.NORTH)
-
- val centerPanel = BorderLayoutPanel()
- centerPanel.border = Borders.empty(15, 10)
- recordingLabel = Label(recordingTimeText(recordingTimeMillis))
- centerPanel.addToLeft(recordingLabel)
- centerPanel.addToCenter(Box.createRigidArea(Dimension(JBUIScale.scale(20), 0)))
- val stopButton = JButton(LogcatBundle.message("screenrecord.dialog.stop.recording"))
- stopButton.addActionListener { onStop.run() }
- centerPanel.addToRight(stopButton)
- dialogPanel.add(centerPanel, BorderLayout.CENTER)
- return dialogPanel
- }
-
- /**
- * Creates the dialog wrapper.
- */
- fun createWrapper(project: Project): DialogWrapper {
- return MyDialogWrapper(project, createPanel())
- }
-
- private class MyDialogWrapper(
- project: Project?,
- private val panel: JPanel
- ) : DialogWrapper(project, false, IdeModalityType.MODELESS) {
-
- init {
- init()
- }
-
- override fun init() {
- super.init()
- setUndecorated(true)
- rootPane.windowDecorationStyle = JRootPane.NONE
- panel.border = PopupBorder.Factory.create(true, true)
- cancelAction.isEnabled = false
- }
-
- override fun createCenterPanel(): JComponent {
- return panel
- }
-
- override fun createSouthPanel(): JComponent? {
- return null
- }
-
- override fun createContentPaneBorder(): Border? {
- return null
- }
- }
-}
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptions.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptions.kt
deleted file mode 100644
index 5e6a6030fdc..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptions.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2013 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.tools.idea.logcat.actions.screenrecord
-
-/**
- * Contains options for recording device screen.
- *
- * Based on com.android.ddmlib.ScreenRecorderOptions
- */
-internal class ScreenRecorderOptions(
- // video size is given by width x height, defaults to device's main display resolution or 1280x720.
- val width: Int,
- val height: Int,
-
- // bit rate in Mbps. Defaults to 4Mbps
- val bitrateMbps: Int,
-
- // display touches
- val showTouches: Boolean,
-)
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptionsDialog.form b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptionsDialog.form
deleted file mode 100644
index 09f63433fb5..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptionsDialog.form
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.android.tools.idea.logcat.actions.screenrecord.ScreenRecorderOptionsDialog">
- <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
- <margin top="0" left="0" bottom="0" right="0"/>
- <constraints>
- <xy x="20" y="20" width="592" height="346"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="7e50e" class="com.intellij.ui.components.JBLabel">
- <constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="messages/LogcatBundle" key="screenrecord.options.bit.rate"/>
- </properties>
- </component>
- <vspacer id="51685">
- <constraints>
- <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
- </constraints>
- </vspacer>
- <component id="4d085" class="javax.swing.JTextField" binding="myBitRateTextField">
- <constraints>
- <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
- <minimum-size width="150" height="-1"/>
- <preferred-size width="150" height="-1"/>
- </grid>
- </constraints>
- <properties/>
- </component>
- <component id="b2f88" class="com.intellij.ui.components.JBLabel">
- <constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="messages/LogcatBundle" key="screenrecord.options.resolution"/>
- </properties>
- </component>
- <component id="2a448" class="com.intellij.ui.components.JBLabel">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="messages/LogcatBundle" key="screenrecord.options.info"/>
- </properties>
- </component>
- <component id="9e826" class="javax.swing.JCheckBox" binding="myShowTouchCheckBox">
- <constraints>
- <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="messages/LogcatBundle" key="screenrecord.options.show.taps"/>
- <toolTipText resource-bundle="messages/LogcatBundle" key="screenrecord.options.show.taps.tooltip"/>
- </properties>
- </component>
- <component id="a355" class="javax.swing.JCheckBox" binding="myEmulatorRecordingCheckBox">
- <constraints>
- <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="messages/LogcatBundle" key="screenrecord.options.use.emulator.recording"/>
- <toolTipText resource-bundle="messages/LogcatBundle" key="screenrecord.options.use.emulator.recording.tooltip"/>
- </properties>
- </component>
- <component id="ab3b0" class="javax.swing.JComboBox" binding="myResolutionPercentComboBox">
- <constraints>
- <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- </component>
- </children>
- </grid>
-</form>
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptionsDialog.java b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptionsDialog.java
deleted file mode 100644
index de880c8b9ee..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderOptionsDialog.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2013 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.tools.idea.logcat.actions.screenrecord;
-
-import com.android.tools.idea.help.AndroidWebHelpProvider;
-import com.android.tools.idea.logcat.LogcatBundle;
-import com.google.common.annotations.VisibleForTesting;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.ui.ValidationInfo;
-import javax.swing.Action;
-import javax.swing.DefaultComboBoxModel;
-import javax.swing.JCheckBox;
-import javax.swing.JComboBox;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JTextField;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.Document;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * A dialog for setting the options for a screen recording.
- *
- * Copied from com.android.tools.idea.ddms.screenrecord.ScreenRecorderOptionsDialog
- *
- * TODO(b/235094713): Add tests
- */
-class ScreenRecorderOptionsDialog extends DialogWrapper {
- @NonNls private static final String SCREENRECORDER_DIMENSIONS_KEY = "ScreenshotRecorder.Options.Dimensions";
- private final DefaultComboBoxModel<Integer> myComboBoxModel = new DefaultComboBoxModel<>(new Integer[]{100, 50, 30});
-
- private JPanel myPanel;
- @VisibleForTesting JTextField myBitRateTextField;
- @VisibleForTesting JCheckBox myShowTouchCheckBox;
- private JCheckBox myEmulatorRecordingCheckBox;
- private JComboBox<Integer> myResolutionPercentComboBox;
-
- public ScreenRecorderOptionsDialog(@NotNull Project project, boolean isEmulator) {
- super(project, true);
-
- myResolutionPercentComboBox.setModel(myComboBoxModel);
-
- ScreenRecorderPersistentOptions options = ScreenRecorderPersistentOptions.getInstance();
- myComboBoxModel.setSelectedItem(options.getResolutionPercent());
-
- if (options.getBitRateMbps() > 0) {
- myBitRateTextField.setText(Integer.toString(options.getBitRateMbps()));
- }
-
- myShowTouchCheckBox.setSelected(options.getShowTaps());
- myEmulatorRecordingCheckBox.setSelected(options.getUseEmulatorRecording());
- myEmulatorRecordingCheckBox.setVisible(isEmulator);
-
- setTitle("Screen Recorder Options");
- init();
- }
-
- @Nullable
- @Override
- protected JComponent createCenterPanel() {
- return myPanel;
- }
-
- @Nullable
- @Override
- protected String getDimensionServiceKey() {
- return SCREENRECORDER_DIMENSIONS_KEY;
- }
-
- @Nullable
- @Override
- protected String getHelpId() {
- return AndroidWebHelpProvider.HELP_PREFIX + "r/studio-ui/am-video.html";
- }
-
- @Override
- protected void createDefaultActions() {
- super.createDefaultActions();
- getOKAction().putValue(Action.NAME, LogcatBundle.message("screenrecord.options.ok.button.text"));
- }
-
- @Nullable
- @Override
- protected ValidationInfo doValidate() {
- ValidationInfo info =
- validateInteger(myBitRateTextField, LogcatBundle.message("screenrecord.options.bit.rate.invalid"));
- if (info != null) {
- return info;
- }
-
- return super.doValidate();
- }
-
- @Nullable
- private static ValidationInfo validateInteger(JTextField textField, String errorMessage) {
- String s = getText(textField);
- if (s.isEmpty()) {
- return null;
- }
-
- try {
- Integer.parseInt(s);
- }
- catch (NumberFormatException e) {
- return new ValidationInfo(errorMessage, textField);
- }
-
- return null;
- }
-
- @Override
- protected void doOKAction() {
- ScreenRecorderPersistentOptions options = ScreenRecorderPersistentOptions.getInstance();
- options.setBitRateMbps(getIntegerValue(myBitRateTextField));
- options.setResolutionPercent((Integer)myComboBoxModel.getSelectedItem());
- options.setShowTaps(myShowTouchCheckBox.isSelected());
- options.setUseEmulatorRecording(myEmulatorRecordingCheckBox.isSelected());
- super.doOKAction();
- }
-
- private static int getIntegerValue(JTextField textField) {
- String s = getText(textField);
- return s.isEmpty() ? 0 : Integer.parseInt(s);
- }
-
- private static String getText(JTextField textField) {
- Document doc = textField.getDocument();
- try {
- return doc.getText(0, doc.getLength()).trim();
- }
- catch (BadLocationException e) { // can't happen
- return "";
- }
- }
-
- public boolean getUseEmulatorRecording() {
- return ScreenRecorderPersistentOptions.getInstance().getUseEmulatorRecording();
- }
-}
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderPersistentOptions.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderPersistentOptions.kt
deleted file mode 100644
index 1bc5c56cd3f..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderPersistentOptions.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.intellij.openapi.application.ApplicationManager
-import com.intellij.openapi.components.PersistentStateComponent
-import com.intellij.openapi.components.State
-import com.intellij.openapi.components.Storage
-import com.intellij.util.xmlb.XmlSerializerUtil
-import java.awt.Dimension
-import kotlin.math.roundToInt
-
-private const val DEFAULT_BIT_RATE_MBPS = 4
-private const val DEFAULT_RESOLUTION_PERCENT = 100
-
-/**
- * A [PersistentStateComponent] of [ScreenRecorderOptionsDialog]
- *
- * Copied from com.android.tools.idea.ddms.screenrecord.ScreenRecorderPersistentOptions
- */
-@State(name = "ScreenRecorderOptions", storages = [Storage("screenRecorderOptions.xml")])
-internal class ScreenRecorderPersistentOptions : PersistentStateComponent<ScreenRecorderPersistentOptions> {
-
- var bitRateMbps = DEFAULT_BIT_RATE_MBPS
- var resolutionPercent: Int = DEFAULT_RESOLUTION_PERCENT
- var showTaps = false
- var useEmulatorRecording = true
-
- companion object {
- @JvmStatic
- fun getInstance(): ScreenRecorderPersistentOptions =
- ApplicationManager.getApplication().getService(ScreenRecorderPersistentOptions::class.java)
- }
-
- override fun getState(): ScreenRecorderPersistentOptions = this
-
- override fun loadState(state: ScreenRecorderPersistentOptions) {
- XmlSerializerUtil.copyBean(state, this)
- }
-
- fun toScreenRecorderOptions(size: Dimension?): ScreenRecorderOptions {
- val width: Int
- val height: Int
- if (size != null && resolutionPercent != 100) {
- val ratio = resolutionPercent.toDouble() / 100
- width = roundToMultipleOf16(size.width * ratio)
- height = roundToMultipleOf16(size.height * ratio)
- }
- else {
- width = 0
- height = 0
- }
-
- return ScreenRecorderOptions(
- width,
- height,
- bitRateMbps,
- showTaps)
- }
-}
-
-private fun roundToMultipleOf16(n: Double): Int = ((n / 16).roundToInt() * 16)
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecordingSupportedCache.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecordingSupportedCache.kt
deleted file mode 100644
index 2877454fc5a..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecordingSupportedCache.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.android.annotations.concurrency.UiThread
-import com.intellij.openapi.project.Project
-
-/**
- * A cache of mapping of a device to a boolean indicating if it supports screen recording.
- */
-interface ScreenRecordingSupportedCache {
- @UiThread
- fun isScreenRecordingSupported(serialNumber: String, sdk: Int): Boolean
-
- companion object {
- fun getInstance(project: Project): ScreenRecordingSupportedCache = project.getService(ScreenRecordingSupportedCache::class.java)
- }
-}
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecordingSupportedCacheImpl.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecordingSupportedCacheImpl.kt
deleted file mode 100644
index 5773413f4c9..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecordingSupportedCacheImpl.kt
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.android.adblib.AdbLibSession
-import com.android.adblib.CoroutineScopeCache.Key
-import com.android.adblib.DevicePropertyNames.RO_BUILD_CHARACTERISTICS
-import com.android.adblib.DeviceSelector
-import com.android.adblib.deviceCache
-import com.android.adblib.shellAsText
-import com.android.annotations.concurrency.UiThread
-import com.android.sdklib.repository.AndroidSdkHandler
-import com.android.tools.idea.adblib.AdbLibService
-import com.android.tools.idea.avdmanager.EmulatorAdvFeatures
-import com.android.tools.idea.log.LogWrapper
-import com.android.tools.idea.progress.StudioLoggerProgressIndicator
-import com.android.tools.idea.sdk.AndroidSdks
-import com.android.utils.ILogger
-import com.intellij.openapi.diagnostic.thisLogger
-import com.intellij.openapi.project.Project
-import kotlinx.coroutines.delay
-import java.time.Duration
-
-private const val SCREEN_RECORDER_DEVICE_PATH = "/system/bin/screenrecord"
-private val COMMAND_TIMEOUT = Duration.ofSeconds(2)
-private val IS_SUPPORTED_RETRY_TIMEOUT = Duration.ofSeconds(2)
-
-/**
- * A cache of mapping of a device to a boolean indicating if it supports screen recording.
- *
- * TODO(b/235094713): Add tests
- */
-internal class ScreenRecordingSupportedCacheImpl(project: Project) : ScreenRecordingSupportedCache {
- private val adbLibSession: AdbLibSession = AdbLibService.getSession(project)
- private val cacheKey = Key<Boolean>("ScreenRecordingSupportedCache")
-
- @UiThread
- override fun isScreenRecordingSupported(serialNumber: String, sdk: Int): Boolean {
- return adbLibSession.deviceCache(serialNumber)
- .getOrPutSuspending(cacheKey,
- fastDefaultValue = { false },
- defaultValue = { computeIsSupported(serialNumber, sdk) })
- }
-
- private suspend fun computeIsSupported(serialNumber: String, sdk: Int): Boolean {
- // The default value (from the cache) is "false" until this function terminates,
- // so we try every 2 seconds until we can answer without error.
- while (true)
- try {
- return when {
- serialNumber.isEmulator() && isEmulatorRecordingEnabled() -> true
- isWatch(serialNumber) && sdk < 30 -> false
- sdk < 19 -> false
- else -> hasBinary(serialNumber)
- }
- }
- catch (e: Throwable) {
- thisLogger().info("Failure to retrieve screen recording support status for device $serialNumber, retrying in 2 seconds", e)
- delay(IS_SUPPORTED_RETRY_TIMEOUT.toMillis())
- }
- }
-
- private suspend fun isWatch(serialNumber: String): Boolean {
- val out = execute(serialNumber, "getprop $RO_BUILD_CHARACTERISTICS")
- return out.trim().split(",").contains("watch")
- }
-
- private suspend fun hasBinary(serialNumber: String): Boolean {
- val out = execute(serialNumber, "ls $SCREEN_RECORDER_DEVICE_PATH")
- return out.trim() == SCREEN_RECORDER_DEVICE_PATH
- }
-
- private suspend fun execute(serialNumber: String, command: String) =
- adbLibSession.deviceServices.shellAsText(DeviceSelector.fromSerialNumber(serialNumber), command, commandTimeout = COMMAND_TIMEOUT)
-}
-
-private fun String.isEmulator() = startsWith("emulator-")
-
-private fun isEmulatorRecordingEnabled(): Boolean {
- val handler: AndroidSdkHandler = AndroidSdks.getInstance().tryToChooseSdkHandler()
- val indicator = StudioLoggerProgressIndicator(ScreenRecorderAction::class.java)
- val logger: ILogger = LogWrapper(ScreenRecorderAction::class.java)
- return EmulatorAdvFeatures.emulatorSupportsScreenRecording(handler, indicator, logger)
-}
diff --git a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ShellCommandRecordingProvider.kt b/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ShellCommandRecordingProvider.kt
deleted file mode 100644
index 1c06bdc38e3..00000000000
--- a/logcat/src/com/android/tools/idea/logcat/actions/screenrecord/ShellCommandRecordingProvider.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.android.adblib.AdbLibSession
-import com.android.adblib.DeviceSelector
-import com.android.adblib.shellAsText
-import com.android.tools.idea.concurrency.AndroidCoroutineScope
-import com.google.common.annotations.VisibleForTesting
-import com.intellij.openapi.Disposable
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.launch
-import java.nio.file.Path
-import java.time.Duration
-
-private val CMD_TIMEOUT = Duration.ofSeconds(2)
-
-/**
- * A [RecordingProvider] that uses the `screenrecord` shell command.
- */
-internal class ShellCommandRecordingProvider(
- private val disposableParent: Disposable,
- serialNumber: String,
- private val remotePath: String,
- private val options: ScreenRecorderOptions,
- private val adbLibSession: AdbLibSession,
-) : RecordingProvider {
- private val deviceSelector = DeviceSelector.fromSerialNumber(serialNumber)
- private var job: Job? = null
-
- override val fileExtension: String = "mp4"
-
- override suspend fun startRecording() {
- job = AndroidCoroutineScope(disposableParent).launch {
- adbLibSession.deviceServices.shellAsText(deviceSelector, getScreenRecordCommand(options, remotePath))
- }
- }
-
- override suspend fun stopRecording() {
- job?.cancel()
- job = null
- }
-
- override suspend fun pullRecording(target: Path) {
- adbLibSession.deviceServices.sync(deviceSelector).use { sync ->
- try {
- adbLibSession.channelFactory.createNewFile(target).use {
- sync.recv(remotePath, it, progress = null)
- }
- }
- finally {
- adbLibSession.deviceServices.shellAsText(deviceSelector, "rm $remotePath", commandTimeout = CMD_TIMEOUT)
- }
- }
- }
-
- override suspend fun doesRecordingExist(): Boolean {
- val out = adbLibSession.deviceServices.shellAsText(deviceSelector, "ls $remotePath", commandTimeout = CMD_TIMEOUT)
- return out.trim() == remotePath
- }
-
- companion object {
- // Note that this is very similar to EmulatorConsoleRecordingProvider getRecorderOptions() but there is guarantee that the args will be the
- // same in the future so best to keep separate versions
- @VisibleForTesting
- internal fun getScreenRecordCommand(options: ScreenRecorderOptions, path: String): String {
- val sb = StringBuilder()
- sb.append("screenrecord")
- sb.append(' ')
- if (options.width > 0 && options.height > 0) {
- sb.append("--size ")
- sb.append(options.width)
- sb.append('x')
- sb.append(options.height)
- sb.append(' ')
- }
- if (options.bitrateMbps > 0) {
- sb.append("--bit-rate ")
- sb.append(options.bitrateMbps * 1000000)
- sb.append(' ')
- }
- sb.append(path)
- return sb.toString()
- }
- }
-}
diff --git a/logcat/testSrc/META-INF/plugin.xml b/logcat/testSrc/META-INF/plugin.xml
index 08ef668b3f3..2fa4118c471 100644
--- a/logcat/testSrc/META-INF/plugin.xml
+++ b/logcat/testSrc/META-INF/plugin.xml
@@ -14,11 +14,12 @@
~ limitations under the License.
-->
<idea-plugin xmlns:xi="http://www.w3.org/2001/XInclude">
- <name>Android Lang Data Binding Tests</name>
+ <name>Android Logcat Tests</name>
<id>com.android.tools.idea.logcat.tests</id>
+ <xi:include href="/META-INF/android-adb-ui.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/android-plugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/logcat.xml" xpointer="xpointer(/idea-plugin/*)"/>
- <xi:include href="/META-INF/project-system-plugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/project-system-gradle-plugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/project-system-gradle-upgrade.xml" xpointer="xpointer(/idea-plugin/*)"/>
+ <xi:include href="/META-INF/project-system-plugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
</idea-plugin>
diff --git a/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/EmulatorConsoleRecordingProviderTest.kt b/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/EmulatorConsoleRecordingProviderTest.kt
deleted file mode 100644
index ec784f83688..00000000000
--- a/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/EmulatorConsoleRecordingProviderTest.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-/**
- * Tests for [EmulatorConsoleRecordingProvider]
- */
-class EmulatorConsoleRecordingProviderTest {
- @Test
- fun getRecorderOptions() {
- val options = ScreenRecorderOptions(width = 600, height = 400, bitrateMbps = 6, showTouches = true)
-
- val args = EmulatorConsoleRecordingProvider.getRecorderOptions(options)
-
- assertThat(args).asList().containsExactly(
- "--size",
- "600x400",
- "--bit-rate",
- "6000000"
- ).inOrder()
- }
-} \ No newline at end of file
diff --git a/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderActionTest.kt b/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderActionTest.kt
deleted file mode 100644
index 6a86828dd5b..00000000000
--- a/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderActionTest.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.android.adblib.testing.FakeAdbLibSession
-import com.android.testutils.MockitoKt.any
-import com.android.testutils.MockitoKt.mock
-import com.android.testutils.MockitoKt.whenever
-import com.android.tools.idea.logcat.actions.screenrecord.ScreenRecorderAction.Companion.SDK_KEY
-import com.android.tools.idea.logcat.actions.screenrecord.ScreenRecorderAction.Companion.SERIAL_NUMBER_KEY
-import com.android.tools.idea.testartifacts.instrumented.AVD_NAME_KEY
-import com.google.common.truth.Truth.assertThat
-import com.intellij.testFramework.ProjectRule
-import com.intellij.testFramework.RuleChain
-import com.intellij.testFramework.TestActionEvent
-import com.intellij.testFramework.replaceService
-import kotlinx.coroutines.test.runBlockingTest
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.mockito.Mockito.anyInt
-
-/**
- * Tests for [ScreenRecorderAction]
- *
- * Based on com.android.tools.idea.ddms.actions.ScreenRecorderActionTest.
- * We only include tests that exist in the above file, so we don't lose coverage. Tests of getTemporaryVideoPathForVirtualDevice() are not
- * included because the new impl of this function is simpler and doesn't require these tests.
- *
- * The getEmulatorScreenRecorderOptions() has been moved to EmulatorConsoleRecordingProviderTest
- */
-@Suppress("OPT_IN_USAGE") // runBlockingTest is experimental
-class ScreenRecorderActionTest {
- private val projectRule = ProjectRule()
-
- @get:Rule
- val rule = RuleChain(projectRule)
-
- private val project get() = projectRule.project
- private val userData = mutableMapOf<String, Any?>()
- private val mockScreenRecordingSupportedCache = mock<ScreenRecordingSupportedCache>()
-
- @Before
- fun setUp() {
- project.replaceService(ScreenRecordingSupportedCache::class.java, mockScreenRecordingSupportedCache, project)
-
-
- userData[SERIAL_NUMBER_KEY.name] = "device"
- userData[SDK_KEY.name] = 30
- }
-
- @Test
- fun update_noSerial_disabled() {
- userData[SERIAL_NUMBER_KEY.name] = null
- val event = TestActionEvent { userData[it] }
- val action = ScreenRecorderAction(project, project, FakeAdbLibSession())
-
- action.update(event)
-
- assertThat(event.presentation.isEnabled).isFalse()
- }
-
- @Test
- fun update_deviceDoesNotSupportScreenRecording_disabled() = runBlockingTest {
- whenever(mockScreenRecordingSupportedCache.isScreenRecordingSupported(any(), anyInt())).thenReturn(false)
- userData[SERIAL_NUMBER_KEY.name] = "device"
- val event = TestActionEvent { userData[it] }
- val action = ScreenRecorderAction(project, project, FakeAdbLibSession(), coroutineContext = coroutineContext)
-
- action.update(event)
-
- assertThat(event.presentation.isEnabled).isFalse()
- }
-
- @Test
- fun update_deviceDoesSupportScreenRecording_enabled() = runBlockingTest {
- userData[SERIAL_NUMBER_KEY.name] = "device"
- userData[SDK_KEY.name] = 30
- userData[AVD_NAME_KEY.name] = null
- whenever(mockScreenRecordingSupportedCache.isScreenRecordingSupported("device", 30)).thenReturn(true)
- val event = TestActionEvent { userData[it] }
- val action = ScreenRecorderAction(project, project, FakeAdbLibSession(), coroutineContext = coroutineContext)
-
- action.update(event)
-
- assertThat(event.presentation.isEnabled).isTrue()
- }
-} \ No newline at end of file
diff --git a/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderPersistentOptionsTest.kt b/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderPersistentOptionsTest.kt
deleted file mode 100644
index 3ffd8941a7c..00000000000
--- a/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ScreenRecorderPersistentOptionsTest.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2021 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.tools.idea.logcat.actions.screenrecord
-
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import java.awt.Dimension
-
-/**
- * Tests for [ScreenRecorderPersistentOptions]
- *
- * Copied from com.android.tools.idea.ddms.screenrecord.ScreenRecorderPersistentOptionsTest
- */
-internal class ScreenRecorderPersistentOptionsTest {
- @Test
- fun toScreenRecorderOptions_defaultValues() {
- val options = ScreenRecorderPersistentOptions().toScreenRecorderOptions(size = null)
-
- assertThat(options.bitrateMbps).isEqualTo(4)
- assertThat(options.showTouches).isFalse()
- assertThat(options.height).isEqualTo(0)
- assertThat(options.width).isEqualTo(0)
- }
-
- @Test
- fun toScreenRecorderOptions_setBitrate() {
- val options = ScreenRecorderPersistentOptions().apply { bitRateMbps = 10 }.toScreenRecorderOptions(size = null)
-
- assertThat(options.bitrateMbps).isEqualTo(10)
- }
-
- @Test
- fun toScreenRecorderOptions_setBShowTaps() {
- val options = ScreenRecorderPersistentOptions().apply { showTaps = true }.toScreenRecorderOptions(size = null)
-
- assertThat(options.showTouches).isTrue()
- }
-
- @Test
- fun toScreenRecorderOptions_withSize_defaultResolution() {
- val options = ScreenRecorderPersistentOptions().toScreenRecorderOptions(Dimension(1000, 2000))
-
- // Don't specify size if 100%, just record at native resolution.
- assertThat(options.height).isEqualTo(0)
- assertThat(options.width).isEqualTo(0)
- }
-
- @Test
- fun toScreenRecorderOptions_withSize_roundsTo16() {
- val options = ScreenRecorderPersistentOptions().apply { resolutionPercent = 25 } .toScreenRecorderOptions(Dimension(1000, 2000))
-
- assertThat(options.width).isEqualTo(256)
- assertThat(options.height).isEqualTo(496)
- }
-} \ No newline at end of file
diff --git a/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ShellCommandRecordingProviderTest.kt b/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ShellCommandRecordingProviderTest.kt
deleted file mode 100644
index e4d937272e0..00000000000
--- a/logcat/testSrc/com/android/tools/idea/logcat/actions/screenrecord/ShellCommandRecordingProviderTest.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.tools.idea.logcat.actions.screenrecord
-
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-
-/**
- * Tests for [ShellCommandRecordingProvider]
- */
-class ShellCommandRecordingProviderTest {
- @Test
- fun getScreenRecordCommand() {
- val options = ScreenRecorderOptions(width = 600, height = 400, bitrateMbps = 6, showTouches = true)
-
- val command = ShellCommandRecordingProvider.getScreenRecordCommand(options, "/sdcard/foo.mp4")
-
- assertThat(command).isEqualTo("screenrecord --size 600x400 --bit-rate 6000000 /sdcard/foo.mp4")
- }
-} \ No newline at end of file