116 lines
3.3 KiB
JavaScript
116 lines
3.3 KiB
JavaScript
/* 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;
|