Запись экрана не работает при вызове из кода - PullRequest
0 голосов
/ 16 декабря 2018

Я пытаюсь получить видео неудачных тестов на моем CI-сервере.

Цель состоит в том, чтобы начать снимок экрана при каждом тесте, а затем, когда он не удается, сохранить видео где-нибудь и когда оно пройдет, удалите видео.CI-сервер будет подбирать файлы, используя adb.

Я рассматриваю возможность использования screenrecord для этой цели.Я подумал, что это было легко, потому что этот двоичный файл уже присутствует на устройстве и действительно хорошо работает при использовании через ADB.

Вот как я использую его программно: откройте поток, который запустится и будет следовать процессу, изапустите его до начала теста:

@Before
fun baseBefore() {
    startScreenRecording()
}

private fun startScreenRecording() {
    Timber.d("screenrecord: start record thread")
    screenRecordThread = Thread(screenRecordRunnable)
    screenRecordThread.start()
    Timber.d("screenrecord: wait a bit")
    Thread.sleep(5000)
    Timber.d("screenrecord: go")
}

Я жду 5 секунд, потому что screenrecord может потребоваться некоторое время для запуска.

Вот фактический screenrecord вызов:

private class ScreenRecordRunnable : Runnable {
    private lateinit var process: Process

    override fun run() {
        try {
            Timber.d("screenrecord-record: start")

// tried also with the following: no luck
//          process = ProcessBuilder(
//                  "/system/bin/screenrecord",
//                  "--time-limit", "60",
//                  "--verbose",
//                  "--bit-rate", "4M",
//                  "--bugreport",
//                  "/sdcard/test.mp4",
//                  "&"
//          )
//                  .redirectErrorStream(true)
//                  .start()

           process = Runtime.getRuntime().exec("/system/bin/screenrecord --time-limit 60 --verbose --bit-rate 4M --bugreport /sdcard/test.mp4")
            val reader = BufferedReader(InputStreamReader(process.inputStream))
            while (true) {
                val line = reader.readLine() ?: break
                Timber.d("screenrecord-record: log: $line")
            }

            Timber.d("screenrecord-record: wait for (isAlive: ${process.isAlive})")
            process.waitFor()

            Timber.d("screenrecord-record: wait stopped; exit value: ${process.exitValue()}")
            reader.close()
        } catch (e: IOException) {
            throw Exception(e)
        } catch (e: InterruptedException) {
            throw Exception(e)
        }
    }
}

В методе @After я извлекаю PID процесса screenrecord (через pgrep, он работает) и отправляю его kill -2 $pid, чтобы имитировать Ctrl-C на этомпроцесс, чтобы остановить запись экрана.
Код для этого не включен, потому что он не выглядит актуальным.

Вот что происходит:

12-16 21:11:31.527  5487  5543 D InstrumentedTestBase: screenrecord: start record thread
12-16 21:11:31.528  5487  5543 D InstrumentedTestBase: screenrecord: wait a bit
12-16 21:11:31.528  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: start
12-16 21:11:31.633  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Main display is 1440x2960 @60.00fps (orientation=0)
12-16 21:11:31.633  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Configuring recorder for 1440x2960 video/avc at 4.00Mbps
12-16 21:11:32.362  5574  5574 W screenrecord: type=1400 audit(0.0:22906): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=19753 scontext=u:r:untrusted_app:s0:c242,c256,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
12-16 21:11:32.492  5574  5574 W screenrecord: type=1400 audit(0.0:22907): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=19753 scontext=u:r:untrusted_app:s0:c242,c256,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
12-16 21:11:32.543  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Bugreport overlay created
12-16 21:11:32.544  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Content area is 1440x2960 at offset x=0 y=0
12-16 21:11:39.780  5487  5543 D InstrumentedTestBase: screenrecord: go
12-16 21:11:43.546  5487  5543 D InstrumentedTestBase: screenrecord: wait for record thread to stop
12-16 21:11:43.546  5487  5543 D InstrumentedTestBase$ScreenRecordStopperRunnable: screenrecord-stopper: get pid
12-16 21:11:43.578  5487  5543 D InstrumentedTestBase$ScreenRecordStopperRunnable: screenrecord-stopper: getpid log: 5574
12-16 21:11:43.579  5487  5543 D InstrumentedTestBase$ScreenRecordStopperRunnable: screenrecord-stopper: kill -2 5574
12-16 21:11:43.679  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Encoder stopping; recorded 1 frames in 7 seconds
12-16 21:11:43.680  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Stopping encoder and muxer
12-16 21:11:43.784  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Executing: /system/bin/am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/test.mp4
12-16 21:11:43.860  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///sdcard/test.mp4 flg=0x400000 }
12-16 21:11:43.919  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: wait for (isAlive: true)
12-16 21:11:43.919  5487  5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: wait stopped; exit value: 0
12-16 21:11:44.013  5487  5543 D InstrumentedTestBase: screenrecord: rename video file to /sdcard/failed_test_emptyDeclarationState.mp4

Как вы можете видеть всевыглядит хорошо, за исключением того, что сохраняется только один кадр:

Остановка кодера;записал 1 кадр за 7 секунд

, этот кадр является --bugreport результатом, с информацией об устройстве (производитель, модель и т.видео этого теста?

...