summaryrefslogtreecommitdiffstats
path: root/devtools/client/shared/remote-debugging/adb/adb-client.js
blob: ff238d6392e036b254e4479ebf2e989e5ef69755 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/* 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;
}

// @param aPacket         The packet to get the length from.
// @param aIgnoreResponse True if this packet has no OKAY/FAIL.
// @return                A js object { length:...; data:... }
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: "" };
  }
  const lengthView = new Uint8Array(buffer, ignoreResponse ? 0 : 4, 4);
  const decoder = new TextDecoder();
  const length = parseInt(decoder.decode(lengthView), 16);
  const text = new Uint8Array(buffer, ignoreResponse ? 4 : 8, length);
  return { length, data: decoder.decode(text) };
}

// 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;