Bug 1507126: Corresponds to USB device disconnection. r=jdescottes
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Wed, 19 Dec 2018 09:02:23 +0000
changeset 451374 67c2abcdadaf194f39619fc68794e144221a1f1d
parent 451373 8b4fdcb28dbf6b950f7e1f7afff32192d124970f
child 451375 dbec2be2c7f62ed264e471dec06b539edf6f0e69
push id75024
push userjdescottes@mozilla.com
push dateWed, 19 Dec 2018 19:58:52 +0000
treeherderautoland@67c2abcdadaf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes
bugs1507126
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1507126: Corresponds to USB device disconnection. r=jdescottes Depends on D14709 So far, because we supported only single device, we could correspond to disconnection by following code. From now, because we will support multi devices, fix the code that changes the status. Differential Revision: https://phabricator.services.mozilla.com/D14831
devtools/shared/adb/commands/track-devices.js
--- a/devtools/shared/adb/commands/track-devices.js
+++ b/devtools/shared/adb/commands/track-devices.js
@@ -8,24 +8,26 @@
 
 const EventEmitter = require("devtools/shared/event-emitter");
 const { dumpn } = require("devtools/shared/DevToolsUtils");
 const { setTimeout } = require("resource://gre/modules/Timer.jsm");
 
 const { adbProcess } = require("../adb-process");
 const client = require("../adb-client");
 
+const ADB_STATUS_OFFLINE = "offline";
 const OKAY = 0x59414b4f;
 
 // Start tracking devices connecting and disconnecting from the host.
 // We can't reuse runCommand here because we keep the socket alive.
 class TrackDevicesCommand extends EventEmitter {
   run() {
     this._waitForFirst = true;
-    this._devices = {};
+    // Hold device statuses. key: device id, value: status.
+    this._devices = new Map();
     this._socket = client.connect();
 
     this._socket.s.onopen = this._onOpen.bind(this);
     this._socket.s.onerror = this._onError.bind(this);
     this._socket.s.onclose = this._onClose.bind(this);
     this._socket.s.ondata = this._onData.bind(this);
   }
 
@@ -49,20 +51,17 @@ class TrackDevicesCommand extends EventE
   _onError(event) {
     dumpn("trackDevices onerror: " + event);
   }
 
   _onClose() {
     dumpn("trackDevices onclose");
 
     // Report all devices as disconnected
-    for (const dev in this._devices) {
-      this._devices[dev] = false;
-      this.emit("device-disconnected", dev);
-    }
+    this._disconnectAllDevices();
 
     // When we lose connection to the server,
     // and the adb is still on, we most likely got our server killed
     // by local adb. So we do try to reconnect to it.
 
     // Give some time to the new adb to start
     setTimeout(() => {
       // Only try to reconnect/restart if the add-on is still enabled
@@ -91,39 +90,60 @@ class TrackDevicesCommand extends EventE
       }
     }
 
     const packet = client.unpackPacket(data, !this._waitForFirst);
     this._waitForFirst = false;
 
     if (packet.data == "") {
       // All devices got disconnected.
-      for (const dev in this._devices) {
-        this._devices[dev] = false;
-        this.emit("device-disconnected", dev);
-      }
+      this._disconnectAllDevices();
     } else {
       // One line per device, each line being $DEVICE\t(offline|device)
       const lines = packet.data.split("\n");
-      const newDev = {};
+      const newDevices = new Map();
       lines.forEach(function(line) {
         if (line.length == 0) {
           return;
         }
 
-        const [dev, status] = line.split("\t");
-        newDev[dev] = status !== "offline";
+        const [deviceId, status] = line.split("\t");
+        newDevices.set(deviceId, status);
       });
-      // Check which device changed state.
-      for (const dev in newDev) {
-        if (this._devices[dev] != newDev[dev]) {
-          if (dev in this._devices || newDev[dev]) {
-            const topic = newDev[dev] ? "device-connected"
-                                      : "device-disconnected";
-            this.emit(topic, dev);
-          }
-          this._devices[dev] = newDev[dev];
-        }
+
+      // Fire events if needed.
+      const deviceIds = new Set([...this._devices.keys(), ...newDevices.keys()]);
+      for (const deviceId of deviceIds) {
+        const currentStatus = this._devices.get(deviceId);
+        const newStatus = newDevices.get(deviceId);
+        this._fireConnectionEventIfNeeded(deviceId, currentStatus, newStatus);
       }
+
+      // Update devices.
+      this._devices = newDevices;
+    }
+  }
+
+  _disconnectAllDevices() {
+    for (const [deviceId, status] of this._devices.entries()) {
+      if (status !== ADB_STATUS_OFFLINE) {
+        this.emit("device-disconnected", deviceId);
+      }
+    }
+    this._devices = new Map();
+  }
+
+  _fireConnectionEventIfNeeded(deviceId, currentStatus, newStatus) {
+    const isCurrentOnline = !!(currentStatus && currentStatus !== ADB_STATUS_OFFLINE);
+    const isNewOnline = !!(newStatus && newStatus !== ADB_STATUS_OFFLINE);
+
+    if (isCurrentOnline === isNewOnline) {
+      return;
+    }
+
+    if (isNewOnline) {
+      this.emit("device-connected", deviceId);
+    } else {
+      this.emit("device-disconnected", deviceId);
     }
   }
 }
 exports.TrackDevicesCommand = TrackDevicesCommand;