mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[scenarios] Use adb to take screenshot, block on screenshot operation. (flutter/engine#51879)
Use the screenshotUtil signal to have the runner take a screenshot with adb. Block the screenshotter until this has completed.
This commit is contained in:
parent
4059931118
commit
b951d15850
@ -4,15 +4,14 @@
|
||||
|
||||
package dev.flutter.scenariosui;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import dev.flutter.scenarios.TestableFlutterActivity;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@ -30,24 +29,28 @@ public class ScreenshotUtil {
|
||||
private static class Connection {
|
||||
final Socket clientSocket;
|
||||
final OutputStream out;
|
||||
final InputStream in;
|
||||
|
||||
Connection(Socket socket) throws IOException {
|
||||
clientSocket = socket;
|
||||
out = socket.getOutputStream();
|
||||
in = socket.getInputStream();
|
||||
}
|
||||
|
||||
synchronized void writeFile(String name, byte[] fileContent, int pixelCount)
|
||||
throws IOException {
|
||||
final ByteBuffer buffer = ByteBuffer.allocate(name.length() + fileContent.length + 12);
|
||||
synchronized void writeFile(String name) throws IOException {
|
||||
final ByteBuffer buffer = ByteBuffer.allocate(name.length() + 12);
|
||||
// See ScreenshotBlobTransformer#bind in screenshot_transformer.dart for consumer side.
|
||||
buffer.putInt(name.length());
|
||||
buffer.putInt(fileContent.length);
|
||||
buffer.putInt(pixelCount);
|
||||
buffer.putInt(0);
|
||||
buffer.putInt(0);
|
||||
buffer.put(name.getBytes());
|
||||
buffer.put(fileContent);
|
||||
final byte[] bytes = buffer.array();
|
||||
out.write(bytes, 0, bytes.length);
|
||||
out.flush();
|
||||
|
||||
// Wait on run_android_tests.dart to write a single byte into the socket
|
||||
// as a signal that adb screencapture has completed.
|
||||
in.read();
|
||||
}
|
||||
|
||||
synchronized void close() throws IOException {
|
||||
@ -95,14 +98,16 @@ public class ScreenshotUtil {
|
||||
* @param fileContent The file content.
|
||||
*/
|
||||
public static synchronized void writeFile(
|
||||
@NonNull String filename, @NonNull byte[] fileContent, int pixelCount) {
|
||||
@NonNull String filename, @NonNull CountDownLatch latch) {
|
||||
if (executor != null && conn != null) {
|
||||
executor.execute(
|
||||
() -> {
|
||||
try {
|
||||
conn.writeFile(filename, fileContent, pixelCount);
|
||||
conn.writeFile(filename);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -119,16 +124,9 @@ public class ScreenshotUtil {
|
||||
*/
|
||||
public static void capture(@NonNull TestableFlutterActivity activity, @NonNull String captureName)
|
||||
throws Exception {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
activity.waitUntilFlutterRendered();
|
||||
|
||||
final Bitmap bitmap =
|
||||
InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
|
||||
if (bitmap == null) {
|
||||
throw new RuntimeException("failed to capture screenshot");
|
||||
}
|
||||
int pixelCount = bitmap.getWidth() * bitmap.getHeight();
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
ScreenshotUtil.writeFile(captureName, out.toByteArray(), pixelCount);
|
||||
ScreenshotUtil.writeFile(captureName, latch);
|
||||
latch.await();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:dir_contents_diff/dir_contents_diff.dart' show dirContentsDiff;
|
||||
import 'package:engine_repo_tools/engine_repo_tools.dart';
|
||||
@ -191,19 +190,32 @@ Future<void> _run({
|
||||
stdout.writeln('client connected ${client.remoteAddress.address}:${client.remotePort}');
|
||||
}
|
||||
pendingConnections.add(client);
|
||||
client.transform(const ScreenshotBlobTransformer()).listen((Screenshot screenshot) {
|
||||
client.transform(const ScreenshotBlobTransformer()).listen((Screenshot screenshot) async {
|
||||
final String fileName = screenshot.filename;
|
||||
final Uint8List fileContent = screenshot.fileContent;
|
||||
if (verbose) {
|
||||
log('host received ${fileContent.lengthInBytes} bytes for screenshot `$fileName`');
|
||||
final String filePath = join(screenshotPath, fileName);
|
||||
{
|
||||
const String remotePath = '/data/local/tmp/flutter_screenshot.png';
|
||||
ProcessResult result = await pm.run(<String>['adb', 'shell', 'screencap', '-p', remotePath]);
|
||||
if (result.exitCode != 0) {
|
||||
panic(<String>['Failed to capture screenshot']);
|
||||
}
|
||||
result = await pm.run(
|
||||
<String>['adb', 'pull', remotePath, filePath],
|
||||
);
|
||||
if (result.exitCode != 0) {
|
||||
panic(<String>['Failed to pull screenshot']);
|
||||
}
|
||||
result = await pm.run(<String>['adb', 'shell', 'rm', remotePath]);
|
||||
if (result.exitCode != 0) {
|
||||
stderr.writeln('Warning: failed to delete old screenshot on device.');
|
||||
}
|
||||
}
|
||||
// Write a single byte into the socket as a signal to ScreenshotUtil.java
|
||||
// that the screenshot was taken.
|
||||
client.write(0x8);
|
||||
|
||||
assert(skiaGoldClient != null, 'expected Skia Gold client');
|
||||
late File goldenFile;
|
||||
try {
|
||||
goldenFile = File(join(screenshotPath, fileName))..writeAsBytesSync(fileContent, flush: true);
|
||||
} on FileSystemException catch (err) {
|
||||
panic(<String>['failed to create screenshot $fileName: $err']);
|
||||
}
|
||||
final File goldenFile = File(filePath);
|
||||
if (verbose) {
|
||||
log('wrote ${goldenFile.absolute.path}');
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user