1142ec75cf882bf023853f0321cd559377daccc60Spencer Low/* 2142ec75cf882bf023853f0321cd559377daccc60Spencer Low * Copyright (C) 2015 The Android Open Source Project 3142ec75cf882bf023853f0321cd559377daccc60Spencer Low * 4142ec75cf882bf023853f0321cd559377daccc60Spencer Low * Licensed under the Apache License, Version 2.0 (the "License"); 5142ec75cf882bf023853f0321cd559377daccc60Spencer Low * you may not use this file except in compliance with the License. 6142ec75cf882bf023853f0321cd559377daccc60Spencer Low * You may obtain a copy of the License at 7142ec75cf882bf023853f0321cd559377daccc60Spencer Low * 8142ec75cf882bf023853f0321cd559377daccc60Spencer Low * http://www.apache.org/licenses/LICENSE-2.0 9142ec75cf882bf023853f0321cd559377daccc60Spencer Low * 10142ec75cf882bf023853f0321cd559377daccc60Spencer Low * Unless required by applicable law or agreed to in writing, software 11142ec75cf882bf023853f0321cd559377daccc60Spencer Low * distributed under the License is distributed on an "AS IS" BASIS, 12142ec75cf882bf023853f0321cd559377daccc60Spencer Low * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13142ec75cf882bf023853f0321cd559377daccc60Spencer Low * See the License for the specific language governing permissions and 14142ec75cf882bf023853f0321cd559377daccc60Spencer Low * limitations under the License. 15142ec75cf882bf023853f0321cd559377daccc60Spencer Low */ 16142ec75cf882bf023853f0321cd559377daccc60Spencer Low 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h" 18142ec75cf882bf023853f0321cd559377daccc60Spencer Low 19142ec75cf882bf023853f0321cd559377daccc60Spencer Low#include <stdio.h> 20142ec75cf882bf023853f0321cd559377daccc60Spencer Low 214f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/file.h> 224f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/logging.h> 234f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/strings.h> 24381cfa9a8bc262dcd823a8bb6adc189595a2fe7dElliott Hughes#include <cutils/sockets.h> 25142ec75cf882bf023853f0321cd559377daccc60Spencer Low 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h" 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb_client.h" 28351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low#include "adb_io.h" 29a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi#include "adb_utils.h" 30a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi 31a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi// Return the console authentication command for the emulator, if needed 32a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyistatic std::string adb_construct_auth_command() { 33a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi static const char auth_token_filename[] = ".emulator_console_auth_token"; 34a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi 35e0b7502c7fb12b0ac03a5903562c74820975b833Josh Gao std::string auth_token_path = adb_get_homedir_path(); 36a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi auth_token_path += OS_PATH_SEPARATOR; 37a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi auth_token_path += auth_token_filename; 38a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi 39a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi // read the token 40a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi std::string token; 41a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi if (!android::base::ReadFileToString(auth_token_path, &token) 42a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi || token.empty()) { 43a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi // we either can't read the file, or it doesn't exist, or it's empty - 44a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi // either way we won't add any authentication command. 45a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi return {}; 46a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi } 47a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi 48a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi // now construct and return the actual command: "auth <token>\n" 49a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi std::string command = "auth "; 50a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi command += token; 51a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi command += '\n'; 52a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi return command; 53a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi} 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 55142ec75cf882bf023853f0321cd559377daccc60Spencer Low// Return the console port of the currently connected emulator (if any) or -1 if 56142ec75cf882bf023853f0321cd559377daccc60Spencer Low// there is no emulator, and -2 if there is more than one. 57142ec75cf882bf023853f0321cd559377daccc60Spencer Lowstatic int adb_get_emulator_console_port(const char* serial) { 58142ec75cf882bf023853f0321cd559377daccc60Spencer Low if (serial) { 59142ec75cf882bf023853f0321cd559377daccc60Spencer Low // The user specified a serial number; is it an emulator? 60142ec75cf882bf023853f0321cd559377daccc60Spencer Low int port; 61142ec75cf882bf023853f0321cd559377daccc60Spencer Low return (sscanf(serial, "emulator-%d", &port) == 1) ? port : -1; 62142ec75cf882bf023853f0321cd559377daccc60Spencer Low } 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 64142ec75cf882bf023853f0321cd559377daccc60Spencer Low // No specific device was given, so get the list of connected devices and 65142ec75cf882bf023853f0321cd559377daccc60Spencer Low // search for emulators. If there's one, we'll take it. If there are more 66142ec75cf882bf023853f0321cd559377daccc60Spencer Low // than one, that's an error. 67142ec75cf882bf023853f0321cd559377daccc60Spencer Low std::string devices; 68142ec75cf882bf023853f0321cd559377daccc60Spencer Low std::string error; 69142ec75cf882bf023853f0321cd559377daccc60Spencer Low if (!adb_query("host:devices", &devices, &error)) { 70142ec75cf882bf023853f0321cd559377daccc60Spencer Low fprintf(stderr, "error: no emulator connected: %s\n", error.c_str()); 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 73142ec75cf882bf023853f0321cd559377daccc60Spencer Low 74142ec75cf882bf023853f0321cd559377daccc60Spencer Low int port; 75142ec75cf882bf023853f0321cd559377daccc60Spencer Low size_t emulator_count = 0; 76142ec75cf882bf023853f0321cd559377daccc60Spencer Low for (const auto& device : android::base::Split(devices, "\n")) { 77142ec75cf882bf023853f0321cd559377daccc60Spencer Low if (sscanf(device.c_str(), "emulator-%d", &port) == 1) { 78142ec75cf882bf023853f0321cd559377daccc60Spencer Low if (++emulator_count > 1) { 79142ec75cf882bf023853f0321cd559377daccc60Spencer Low fprintf( 80142ec75cf882bf023853f0321cd559377daccc60Spencer Low stderr, "error: more than one emulator detected; use -s\n"); 81142ec75cf882bf023853f0321cd559377daccc60Spencer Low return -1; 82142ec75cf882bf023853f0321cd559377daccc60Spencer Low } 83142ec75cf882bf023853f0321cd559377daccc60Spencer Low } 84142ec75cf882bf023853f0321cd559377daccc60Spencer Low } 85142ec75cf882bf023853f0321cd559377daccc60Spencer Low 86142ec75cf882bf023853f0321cd559377daccc60Spencer Low if (emulator_count == 0) { 87142ec75cf882bf023853f0321cd559377daccc60Spencer Low fprintf(stderr, "error: no emulator detected\n"); 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 90142ec75cf882bf023853f0321cd559377daccc60Spencer Low 91142ec75cf882bf023853f0321cd559377daccc60Spencer Low return port; 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 94142ec75cf882bf023853f0321cd559377daccc60Spencer Lowstatic int connect_to_console(const char* serial) { 95142ec75cf882bf023853f0321cd559377daccc60Spencer Low int port = adb_get_emulator_console_port(serial); 96142ec75cf882bf023853f0321cd559377daccc60Spencer Low if (port == -1) { 97142ec75cf882bf023853f0321cd559377daccc60Spencer Low return -1; 98142ec75cf882bf023853f0321cd559377daccc60Spencer Low } 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1005200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low std::string error; 1015200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low int fd = network_loopback_client(port, SOCK_STREAM, &error); 102142ec75cf882bf023853f0321cd559377daccc60Spencer Low if (fd == -1) { 1035200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low fprintf(stderr, "error: could not connect to TCP port %d: %s\n", port, 1045200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low error.c_str()); 105142ec75cf882bf023853f0321cd559377daccc60Spencer Low return -1; 106142ec75cf882bf023853f0321cd559377daccc60Spencer Low } 107142ec75cf882bf023853f0321cd559377daccc60Spencer Low return fd; 108142ec75cf882bf023853f0321cd559377daccc60Spencer Low} 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 110142ec75cf882bf023853f0321cd559377daccc60Spencer Lowint adb_send_emulator_command(int argc, const char** argv, const char* serial) { 111142ec75cf882bf023853f0321cd559377daccc60Spencer Low int fd = connect_to_console(serial); 112142ec75cf882bf023853f0321cd559377daccc60Spencer Low if (fd == -1) { 113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 1; 114142ec75cf882bf023853f0321cd559377daccc60Spencer Low } 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 116a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi std::string commands = adb_construct_auth_command(); 117351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low 118142ec75cf882bf023853f0321cd559377daccc60Spencer Low for (int i = 1; i < argc; i++) { 119351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low commands.append(argv[i]); 120a9e2b99a7fdd31bcd6d852c6db26fe592236a24fYurii Zubrytskyi commands.push_back(i == argc - 1 ? '\n' : ' '); 121142ec75cf882bf023853f0321cd559377daccc60Spencer Low } 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 123351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low commands.append("quit\n"); 124351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low 125351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low if (!WriteFdExactly(fd, commands)) { 126351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low fprintf(stderr, "error: cannot write to emulator: %s\n", 127351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low strerror(errno)); 128351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low adb_close(fd); 129351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low return 1; 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 131142ec75cf882bf023853f0321cd559377daccc60Spencer Low 132142ec75cf882bf023853f0321cd559377daccc60Spencer Low // Drain output that the emulator console has sent us to prevent a problem 133142ec75cf882bf023853f0321cd559377daccc60Spencer Low // on Windows where if adb closes the socket without reading all the data, 134142ec75cf882bf023853f0321cd559377daccc60Spencer Low // the emulator's next call to recv() will have an ECONNABORTED error, 135142ec75cf882bf023853f0321cd559377daccc60Spencer Low // preventing the emulator from reading the command that adb has sent. 136142ec75cf882bf023853f0321cd559377daccc60Spencer Low // https://code.google.com/p/android/issues/detail?id=21021 137142ec75cf882bf023853f0321cd559377daccc60Spencer Low int result; 138142ec75cf882bf023853f0321cd559377daccc60Spencer Low do { 139142ec75cf882bf023853f0321cd559377daccc60Spencer Low char buf[BUFSIZ]; 140142ec75cf882bf023853f0321cd559377daccc60Spencer Low result = adb_read(fd, buf, sizeof(buf)); 141351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low // Keep reading until zero bytes (orderly/graceful shutdown) or an 142351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low // error. If 'adb emu kill' is executed, the emulator calls exit() with 143351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low // the socket open (and shutdown(SD_SEND) was not called), which causes 144351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low // Windows to send a TCP RST segment which causes adb to get ECONNRESET. 145351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low // Any other emu command is followed by the quit command that we 146351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low // appended above, and that causes the emulator to close the socket 147351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low // which should cause zero bytes (orderly/graceful shutdown) to be 148351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low // returned. 149142ec75cf882bf023853f0321cd559377daccc60Spencer Low } while (result > 0); 150142ec75cf882bf023853f0321cd559377daccc60Spencer Low 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project adb_close(fd); 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 155