adb-client.js (3418B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* 6 * A module to track device changes 7 * Adapted from adb.js at 8 * https://github.com/mozilla/adbhelper/tree/f44386c2d8cb7635a7d2c5a51191c89b886f8327 9 */ 10 11 "use strict"; 12 13 const { 14 AdbSocket, 15 } = require("resource://devtools/client/shared/remote-debugging/adb/adb-socket.js"); 16 const { dumpn } = require("resource://devtools/shared/DevToolsUtils.js"); 17 18 const OKAY = 0x59414b4f; 19 const FAIL = 0x4c494146; 20 21 // Return buffer, which differs between Gecko versions 22 function getBuffer(packet) { 23 return packet.buffer ? packet.buffer : packet; 24 } 25 26 /** 27 * Decode an adb packet into a JS object with length (number) and data (string) 28 * properties. 29 * 30 * @param packet 31 * The packet to get the content from. 32 * @param 33 * ignoreResponse True if this packet has no OKAY/FAIL. 34 * @return 35 * A js object with the following properties: 36 * - length (number): length of the decoded data 37 * - data (string): the decoded data as a string. Can be multiline (\n) 38 */ 39 function unpackPacket(packet, ignoreResponse) { 40 const buffer = getBuffer(packet); 41 dumpn("Len buffer: " + buffer.byteLength); 42 if (buffer.byteLength === 4 && !ignoreResponse) { 43 dumpn("Packet empty"); 44 return { length: 0, data: "" }; 45 } 46 let index = 0; 47 let totalLength = 0; 48 const decodedText = []; 49 50 // Prepare a decoder. 51 const decoder = new TextDecoder(); 52 53 // Loop over all lines in the packet 54 while (index < buffer.byteLength) { 55 // Set the index to 4 if we need to skip the response bytes. 56 index += ignoreResponse ? 0 : 4; 57 58 // Read the packet line length. 59 const lengthView = new Uint8Array(buffer, index, 4); 60 const length = parseInt(decoder.decode(lengthView), 16); 61 62 // Move the index after the last size byte. 63 index += 4; 64 65 // Read the packet line content and append it to the decodedText array. 66 const text = new Uint8Array(buffer, index, length); 67 decodedText.push(decoder.decode(text)); 68 69 // Move the index after the last read byte for this packet line. 70 index += length; 71 // Note: totalLength is only used for logging purposes. 72 totalLength += length; 73 } 74 return { length: totalLength, data: decodedText.join("\n") }; 75 } 76 77 // Checks if the response is expected (defaults to OKAY). 78 // @return true if response equals expected. 79 function checkResponse(packet, expected = OKAY) { 80 const buffer = getBuffer(packet); 81 const view = new Uint32Array(buffer, 0, 1); 82 if (view[0] == FAIL) { 83 dumpn("Response: FAIL"); 84 } 85 dumpn("view[0] = " + view[0]); 86 return view[0] == expected; 87 } 88 89 // @param aCommand A protocol-level command as described in 90 // http://androidxref.com/4.0.4/xref/system/core/adb/OVERVIEW.TXT and 91 // http://androidxref.com/4.0.4/xref/system/core/adb/SERVICES.TXT 92 // @return A 8 bit typed array. 93 function createRequest(command) { 94 let length = command.length.toString(16).toUpperCase(); 95 while (length.length < 4) { 96 length = "0" + length; 97 } 98 99 const encoder = new TextEncoder(); 100 dumpn("Created request: " + length + command); 101 return encoder.encode(length + command); 102 } 103 104 function connect() { 105 return new AdbSocket(); 106 } 107 108 const client = { 109 getBuffer, 110 unpackPacket, 111 checkResponse, 112 createRequest, 113 connect, 114 }; 115 116 module.exports = client;