// Copyright 2019 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'dart:async'; import 'package:async/async.dart'; import '../base/context.dart'; import '../base/io.dart'; import '../convert.dart'; /// Default factory that creates a real Android console connection. final AndroidConsoleSocketFactory _kAndroidConsoleSocketFactory = (String host, int port) => Socket.connect( host, port); /// Currently active implementation of the AndroidConsoleFactory. /// /// The default implementation will create real connections to a device. /// Override this in tests with an implementation that returns mock responses. AndroidConsoleSocketFactory get androidConsoleSocketFactory => context.get<AndroidConsoleSocketFactory>() ?? _kAndroidConsoleSocketFactory; typedef AndroidConsoleSocketFactory = Future<Socket> Function(String host, int port); /// Creates a console connection to an Android emulator that can be used to run /// commands such as "avd name" which are not available to ADB. /// /// See documentation at /// https://developer.android.com/studio/run/emulator-console class AndroidConsole { AndroidConsole(this._socket); Socket _socket; StreamQueue<String> _queue; Future<void> connect() async { assert(_socket != null); assert(_queue == null); _queue = StreamQueue<String>(_socket.asyncMap(ascii.decode)); // Discard any initial connection text. await _readResponse(); } Future<String> getAvdName() async { _write('avd name\n'); return _readResponse(); } void destroy() { if (_socket != null) { _socket.destroy(); _socket = null; _queue = null; } } Future<String> _readResponse() async { final StringBuffer output = StringBuffer(); while (true) { final String text = await _queue.next; final String trimmedText = text.trim(); if (trimmedText == 'OK') break; if (trimmedText.endsWith('\nOK')) { output.write(trimmedText.substring(0, trimmedText.length - 3)); break; } output.write(text); } return output.toString().trim(); } void _write(String text) { _socket.add(ascii.encode(text)); } }