1// Copyright 2019 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5import 'dart:async'; 6 7import 'package:async/async.dart'; 8import '../base/context.dart'; 9import '../base/io.dart'; 10import '../convert.dart'; 11 12/// Default factory that creates a real Android console connection. 13final AndroidConsoleSocketFactory _kAndroidConsoleSocketFactory = (String host, int port) => Socket.connect( host, port); 14 15/// Currently active implementation of the AndroidConsoleFactory. 16/// 17/// The default implementation will create real connections to a device. 18/// Override this in tests with an implementation that returns mock responses. 19AndroidConsoleSocketFactory get androidConsoleSocketFactory => context.get<AndroidConsoleSocketFactory>() ?? _kAndroidConsoleSocketFactory; 20 21typedef AndroidConsoleSocketFactory = Future<Socket> Function(String host, int port); 22 23/// Creates a console connection to an Android emulator that can be used to run 24/// commands such as "avd name" which are not available to ADB. 25/// 26/// See documentation at 27/// https://developer.android.com/studio/run/emulator-console 28class AndroidConsole { 29 AndroidConsole(this._socket); 30 31 Socket _socket; 32 StreamQueue<String> _queue; 33 34 Future<void> connect() async { 35 assert(_socket != null); 36 assert(_queue == null); 37 38 _queue = StreamQueue<String>(_socket.asyncMap(ascii.decode)); 39 40 // Discard any initial connection text. 41 await _readResponse(); 42 } 43 44 Future<String> getAvdName() async { 45 _write('avd name\n'); 46 return _readResponse(); 47 } 48 49 void destroy() { 50 if (_socket != null) { 51 _socket.destroy(); 52 _socket = null; 53 _queue = null; 54 } 55 } 56 57 Future<String> _readResponse() async { 58 final StringBuffer output = StringBuffer(); 59 while (true) { 60 final String text = await _queue.next; 61 final String trimmedText = text.trim(); 62 if (trimmedText == 'OK') 63 break; 64 if (trimmedText.endsWith('\nOK')) { 65 output.write(trimmedText.substring(0, trimmedText.length - 3)); 66 break; 67 } 68 output.write(text); 69 } 70 return output.toString().trim(); 71 } 72 73 void _write(String text) { 74 _socket.add(ascii.encode(text)); 75 } 76} 77