/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * A module to track device changes * Adapted from adb.js at * https://github.com/mozilla/adbhelper/tree/f44386c2d8cb7635a7d2c5a51191c89b886f8327 */ "use strict"; const { AdbSocket, } = require("resource://devtools/client/shared/remote-debugging/adb/adb-socket.js"); const { dumpn } = require("resource://devtools/shared/DevToolsUtils.js"); const OKAY = 0x59414b4f; const FAIL = 0x4c494146; // Return buffer, which differs between Gecko versions function getBuffer(packet) { return packet.buffer ? packet.buffer : packet; } /** * Decode an adb packet into a JS object with length (number) and data (string) * properties. * * @param packet * The packet to get the content from. * @param * ignoreResponse True if this packet has no OKAY/FAIL. * @return * A js object with the following properties: * - length (number): length of the decoded data * - data (string): the decoded data as a string. Can be multiline (\n) */ function unpackPacket(packet, ignoreResponse) { const buffer = getBuffer(packet); dumpn("Len buffer: " + buffer.byteLength); if (buffer.byteLength === 4 && !ignoreResponse) { dumpn("Packet empty"); return { length: 0, data: "" }; } let index = 0; let totalLength = 0; const decodedText = []; // Prepare a decoder. const decoder = new TextDecoder(); // Loop over all lines in the packet while (index < buffer.byteLength) { // Set the index to 4 if we need to skip the response bytes. index += ignoreResponse ? 0 : 4; // Read the packet line length. const lengthView = new Uint8Array(buffer, index, 4); const length = parseInt(decoder.decode(lengthView), 16); // Move the index after the last size byte. index += 4; // Read the packet line content and append it to the decodedText array. const text = new Uint8Array(buffer, index, length); decodedText.push(decoder.decode(text)); // Move the index after the last read byte for this packet line. index += length; // Note: totalLength is only used for logging purposes. totalLength += length; } return { length: totalLength, data: decodedText.join("\n") }; } // Checks if the response is expected (defaults to OKAY). // @return true if response equals expected. function checkResponse(packet, expected = OKAY) { const buffer = getBuffer(packet); const view = new Uint32Array(buffer, 0, 1); if (view[0] == FAIL) { dumpn("Response: FAIL"); } dumpn("view[0] = " + view[0]); return view[0] == expected; } // @param aCommand A protocol-level command as described in // http://androidxref.com/4.0.4/xref/system/core/adb/OVERVIEW.TXT and // http://androidxref.com/4.0.4/xref/system/core/adb/SERVICES.TXT // @return A 8 bit typed array. function createRequest(command) { let length = command.length.toString(16).toUpperCase(); while (length.length < 4) { length = "0" + length; } const encoder = new TextEncoder(); dumpn("Created request: " + length + command); return encoder.encode(length + command); } function connect() { return new AdbSocket(); } const client = { getBuffer, unpackPacket, checkResponse, createRequest, connect, }; module.exports = client;