Merge b2g-inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 02 Jul 2015 15:57:05 -0400
changeset 251174 f66705bc0fd5d9cdfad62539f38be9d3c91c21d3
parent 251161 b3b6748dcf2dcf3e7d7907fc6713bd2ed17a7a75 (current diff)
parent 251173 a92c364a6d2e0e8f808909fbc0a197f322467b79 (diff)
child 251175 2f25351c5b058aa1ce52ab8eafe89efce07fff51
push id13833
push userryanvm@gmail.com
push dateThu, 02 Jul 2015 20:00:55 +0000
treeherderfx-team@98101796b275 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone42.0a1
Merge b2g-inbound to m-c. a=merge
--- a/b2g/chrome/content/devtools/hud.js
+++ b/b2g/chrome/content/devtools/hud.js
@@ -26,28 +26,38 @@ XPCOMUtils.defineLazyGetter(this, 'Event
 });
 
 XPCOMUtils.defineLazyGetter(this, 'MemoryFront', function() {
   return devtools.require('devtools/server/actors/memory').MemoryFront;
 });
 
 Cu.import('resource://gre/modules/Frames.jsm');
 
+let _telemetryDebug = true;
+
+function telemetryDebug(...args) {
+  if (_telemetryDebug) {
+    args.unshift('[AdvancedTelemetry]');
+    console.log(...args);
+  }
+}
+
 /**
  * The Developer HUD is an on-device developer tool that displays widgets,
  * showing visual debug information about apps. Each widget corresponds to a
  * metric as tracked by a metric watcher (e.g. consoleWatcher).
  */
 let developerHUD = {
 
   _targets: new Map(),
   _client: null,
   _conn: null,
   _watchers: [],
   _logging: true,
+  _telemetry: false,
 
   /**
    * This method registers a metric watcher that will watch one or more metrics
    * on app frames that are being tracked. A watcher must implement the
    * `trackTarget(target)` and `untrackTarget(target)` methods, register
    * observed metrics with `target.register(metric)`, and keep them up-to-date
    * with `target.update(metric, message)` when necessary.
    */
@@ -85,16 +95,20 @@ let developerHUD = {
     let appFrames = Frames.list().filter(frame => frame.getAttribute('mozapp'));
     for (let frame of appFrames) {
       this.trackFrame(frame);
     }
 
     SettingsListener.observe('hud.logging', this._logging, enabled => {
       this._logging = enabled;
     });
+
+    SettingsListener.observe('debug.performance_data.advanced_telemetry', this._telemetry, enabled => {
+      this._telemetry = enabled;
+    });
   },
 
   uninit: function dwp_uninit() {
     if (!this._client) {
       return;
     }
 
     for (let frame of this._targets.keys()) {
@@ -164,23 +178,34 @@ let developerHUD = {
 
 
 /**
  * A Target object represents all there is to know about a Firefox OS app frame
  * that is being tracked, e.g. a pointer to the frame, current values of watched
  * metrics, and how to notify the front-end when metrics have changed.
  */
 function Target(frame, actor) {
-  this.frame = frame;
+  this._frame = frame;
   this.actor = actor;
   this.metrics = new Map();
 }
 
 Target.prototype = {
 
+  get frame() {
+    let frame = this._frame;
+    let systemapp = document.querySelector('#systemapp');
+
+    return (frame === systemapp ? getContentWindow() : frame);
+  },
+
+  get manifest() {
+    return this._frame.appManifestURL;
+  },
+
   /**
    * Register a metric that can later be updated. Does not update the front-end.
    */
   register: function target_register(metric) {
     this.metrics.set(metric, 0);
   },
 
   /**
@@ -198,31 +223,32 @@ Target.prototype = {
 
     let metrics = this.metrics;
     if (metrics) {
       metrics.set(metric.name, metric.value);
     }
 
     let data = {
       metrics: [], // FIXME(Bug 982066) Remove this field.
-      manifest: this.frame.appManifestURL,
+      manifest: this.manifest,
       metric: metric,
       message: message
     };
 
     // FIXME(Bug 982066) Remove this loop.
     if (metrics && metrics.size > 0) {
       for (let name of metrics.keys()) {
         data.metrics.push({name: name, value: metrics.get(name)});
       }
     }
 
     if (message) {
       developerHUD.log('[' + data.manifest + '] ' + data.message);
     }
+
     this._send(data);
   },
 
   /**
    * Nicer way to call update() when the metric value is a number that needs
    * to be incremented.
    */
   bump: function target_bump(metric, message) {
@@ -246,24 +272,43 @@ Target.prototype = {
   destroy: function target_destroy() {
     delete this.metrics;
     this._send({});
   },
 
   _send: function target_send(data) {
     let frame = this.frame;
 
-    let systemapp = document.querySelector('#systemapp');
-    if (this.frame === systemapp) {
-      frame = getContentWindow();
+    shell.sendEvent(frame, 'developer-hud-update', Cu.cloneInto(data, frame));
+    this._sendTelemetryEvent(data.metric);
+  },
+
+  _sendTelemetryEvent: function target_sendTelemetryEvent(metric) {
+    if (!developerHUD._telemetry || !metric || metric.skipTelemetry) {
+      return;
     }
 
-    shell.sendEvent(frame, 'developer-hud-update', Cu.cloneInto(data, frame));
+    if (!this.appName) {
+      let manifest = this.manifest;
+      if (!manifest) {
+        return;
+      }
+      let start = manifest.indexOf('/') + 2;
+      let end = manifest.indexOf('.', start);
+      this.appName = manifest.substring(start, end).toLowerCase();
+    }
+
+    metric.appName = this.appName;
+
+    let data = { metric: metric };
+    let frame = this.frame;
+
+    telemetryDebug('sending advanced-telemetry-update with this data: ' + JSON.stringify(data));
+    shell.sendEvent(frame, 'advanced-telemetry-update', Cu.cloneInto(data, frame));
   }
-
 };
 
 
 /**
  * The Console Watcher tracks the following metrics in apps: reflows, warnings,
  * and errors, with security errors reported separately.
  */
 let consoleWatcher = {
@@ -354,16 +399,28 @@ let consoleWatcher = {
           output += 'Warning (';
         } else {
           metric.name = 'errors';
           output += 'Error (';
         }
 
         if (this._security.indexOf(pageError.category) > -1) {
           metric.name = 'security';
+
+          // Telemetry sends the security error category not the
+          // count of security errors.
+          target._sendTelemetryEvent({
+            name: 'security',
+            value: pageError.category,
+          });
+
+          // Indicate that the 'hud' security metric (the count of security
+          // errors) should not be sent as a telemetry metric since the
+          // security error category is being sent instead.
+          metric.skipTelemetry = true;
         }
 
         let {errorMessage, sourceName, category, lineNumber, columnNumber} = pageError;
         output += category + '): "' + (errorMessage.initial || errorMessage) +
           '" in ' + sourceName + ':' + lineNumber + ':' + columnNumber;
         break;
 
       case 'consoleAPICall':
@@ -374,31 +431,44 @@ let consoleWatcher = {
             output += 'Error (console)';
             break;
 
           case 'warn':
             metric.name = 'warnings';
             output += 'Warning (console)';
             break;
 
+          case 'info':
+            this.handleTelemetryMessage(target, packet);
+
+            // Currently, informational log entries are tracked only by
+            // advanced telemetry. Nonetheless, for consistency, we
+            // continue here and let the function return normally, when it
+            // concludes 'info' entries are not being watched.
+            metric.name = 'info';
+            break;
+
           default:
             return;
         }
         break;
 
       case 'reflowActivity':
         metric.name = 'reflows';
 
         let {start, end, sourceURL, interruptible} = packet;
         metric.interruptible = interruptible;
         let duration = Math.round((end - start) * 100) / 100;
         output += 'Reflow: ' + duration + 'ms';
         if (sourceURL) {
           output += ' ' + this.formatSourceURL(packet);
         }
+
+        // Telemetry also records reflow duration.
+        target._sendTelemetryEvent({name: 'reflow-duration', value: Math.round(duration)});
         break;
 
       default:
         return;
     }
 
     if (!this._watching[metric.name]) {
       return;
@@ -412,16 +482,59 @@ let consoleWatcher = {
     let source = WebConsoleUtils.abbreviateSourceURL(packet.sourceURL);
 
     // Add function name and line number
     let {functionName, sourceLine} = packet;
     source = 'in ' + (functionName || '<anonymousFunction>') +
       ', ' + source + ':' + sourceLine;
 
     return source;
+  },
+
+  handleTelemetryMessage:
+    function cw_handleTelemetryMessage(target, packet) {
+
+    if (!developerHUD._telemetry) {
+      return;
+    }
+
+    // If this is a 'telemetry' log entry, create a telemetry metric from
+    // the log content.
+    let separator = '|';
+    let logContent = packet.message.arguments.toString();
+
+    if (logContent.indexOf('telemetry') < 0) {
+      return;
+    }
+
+    let telemetryData = logContent.split(separator);
+
+    // Positions of the components of a telemetry log entry.
+    let TELEMETRY_IDENTIFIER_IDX = 0;
+    let NAME_IDX = 1;
+    let VALUE_IDX = 2;
+    let CONTEXT_IDX = 3;
+
+    if (telemetryData[TELEMETRY_IDENTIFIER_IDX] != 'telemetry' ||
+        telemetryData.length < 3 || telemetryData.length > 4) {
+      return;
+    }
+
+    let metric = {
+      name: telemetryData[NAME_IDX],
+      value: telemetryData[VALUE_IDX]
+    };
+
+    // The metric's app name, if a 'context' was provided, is the
+    // specified context appended to the specified app name.
+    if (telemetryData.length === 4) {
+      metric.context = telemetryData[CONTEXT_IDX];
+    }
+
+    target._sendTelemetryEvent(metric);
   }
 };
 developerHUD.registerWatcher(consoleWatcher);
 
 
 let eventLoopLagWatcher = {
   _client: null,
   _fronts: new Map(),
--- a/b2g/components/AboutServiceWorkers.jsm
+++ b/b2g/components/AboutServiceWorkers.jsm
@@ -144,25 +144,25 @@ this.AboutServiceWorkers = {
         self.sendResult(message.id, true);
         break;
 
       case "unregister":
         if (!message.principal ||
             !message.principal.origin ||
             !message.principal.originAttributes ||
             !message.principal.originAttributes.appId ||
-            !message.principal.originAttributes.isInBrowser) {
+            (message.principal.originAttributes.inBrowser == null)) {
           self.sendError(message.id, "MissingPrincipal");
           return;
         }
 
         let principal = Services.scriptSecurityManager.getAppCodebasePrincipal(
           Services.io.newURI(message.principal.origin, null, null),
           message.principal.originAttributes.appId,
-          message.principal.originAttributes.isInBrowser
+          message.principal.originAttributes.inBrowser
         );
 
         if (!message.scope) {
           self.sendError(message.id, "MissingScope");
           return;
         }
 
         let serviceWorkerUnregisterCallback = {
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "4b7ad0dde990bdc44e166818c0bb09a35cd1207f", 
+        "git_revision": "722028715a56a03f327e2e70f2c32dcb6d819d4c", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "4dd94426a71c70db03184cb1e2d9c4c2ad065461", 
+    "revision": "547f049d7e7510b628b5b1074f73b204ab6627df", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="4b7ad0dde990bdc44e166818c0bb09a35cd1207f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="722028715a56a03f327e2e70f2c32dcb6d819d4c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="49192a4e48d080e44a0d66f059e6897f07cf67f8"/>
--- a/dom/bluetooth/BluetoothCommon.h
+++ b/dom/bluetooth/BluetoothCommon.h
@@ -73,22 +73,16 @@ extern bool gBluetoothDebugFlag;
     }                                                                \
   } while(0)
 
 #define BT_LOGR(msg, ...) printf("%s: " msg, __FUNCTION__, ##__VA_ARGS__)
 #define BT_WARNING(msg, ...) printf("%s: " msg, __FUNCTION__, ##__VA_ARGS__)
 #endif
 
 /**
- * Prints 'R'ELEASE build logs for WebBluetooth API v2.
- */
-#define BT_API2_LOGR(msg, ...)                                       \
-  BT_LOGR("[WEBBT-API2] " msg, ##__VA_ARGS__)
-
-/**
  * Wrap literal name and value into a BluetoothNamedValue
  * and append it to the array.
  */
 #define BT_APPEND_NAMED_VALUE(array, name, value)                    \
   array.AppendElement(BluetoothNamedValue(NS_LITERAL_STRING(name),   \
                                           BluetoothValue(value)))
 
 /**
@@ -136,29 +130,29 @@ extern bool gBluetoothDebugFlag;
   } while(0)                                                         \
 
 /**
  * Resolve |promise| with |ret| if |x| is false.
  */
 #define BT_ENSURE_TRUE_RESOLVE(x, promise, ret)                      \
   do {                                                               \
     if (MOZ_UNLIKELY(!(x))) {                                        \
-      BT_API2_LOGR("BT_ENSURE_TRUE_RESOLVE(" #x ") failed");         \
+      BT_LOGR("BT_ENSURE_TRUE_RESOLVE(" #x ") failed");              \
       (promise)->MaybeResolve(ret);                                  \
       return (promise).forget();                                     \
     }                                                                \
   } while(0)
 
 /**
  * Reject |promise| with |ret| if |x| is false.
  */
 #define BT_ENSURE_TRUE_REJECT(x, promise, ret)                       \
   do {                                                               \
     if (MOZ_UNLIKELY(!(x))) {                                        \
-      BT_API2_LOGR("BT_ENSURE_TRUE_REJECT(" #x ") failed");          \
+      BT_LOGR("BT_ENSURE_TRUE_REJECT(" #x ") failed");               \
       (promise)->MaybeReject(ret);                                   \
       return (promise).forget();                                     \
     }                                                                \
   } while(0)
 
 #define BEGIN_BLUETOOTH_NAMESPACE \
   namespace mozilla { namespace dom { namespace bluetooth {
 #define END_BLUETOOTH_NAMESPACE \
--- a/dom/bluetooth/BluetoothInterface.h
+++ b/dom/bluetooth/BluetoothInterface.h
@@ -675,17 +675,17 @@ public:
   virtual void WriteDescriptor() { }
 
   virtual void ExecuteWrite() { }
 
   virtual void RegisterNotification() { }
   virtual void DeregisterNotification() { }
 
   virtual void ReadRemoteRssi() { }
-  virtual void GetDeviceType() { }
+  virtual void GetDeviceType(BluetoothTypeOfDevice type) { }
   virtual void SetAdvData() { }
   virtual void TestCommand() { }
 
 protected:
   virtual ~BluetoothGattClientResultHandler() { }
 };
 
 // TODO: Add GattServerResultHandler
--- a/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.cpp
@@ -870,24 +870,47 @@ BluetoothDaemonGattModule::ClientReadRem
   const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
   BluetoothGattClientResultHandler* aRes)
 {
   ClientResultRunnable::Dispatch(
     aRes, &BluetoothGattClientResultHandler::ReadRemoteRssi,
     UnpackPDUInitOp(aPDU));
 }
 
+// Init operator class for ClientGetDeviceTypeRsp
+class BluetoothDaemonGattModule::ClientGetDeviceTypeInitOp final
+  : private PDUInitOp
+{
+public:
+  ClientGetDeviceTypeInitOp(DaemonSocketPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (BluetoothTypeOfDevice& aArg1) const
+  {
+    /* Read device type */
+    nsresult rv = UnpackPDU(
+      GetPDU(), UnpackConversion<uint8_t, BluetoothTypeOfDevice>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonGattModule::ClientGetDeviceTypeRsp(
   const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
   BluetoothGattClientResultHandler* aRes)
 {
-  ClientResultRunnable::Dispatch(
+  ClientGetDeviceTypeResultRunnable::Dispatch(
     aRes, &BluetoothGattClientResultHandler::GetDeviceType,
-    UnpackPDUInitOp(aPDU));
+    ClientGetDeviceTypeInitOp(aPDU));
 }
 
 void
 BluetoothDaemonGattModule::ClientSetAdvDataRsp(
   const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
   BluetoothGattClientResultHandler* aRes)
 {
   ClientResultRunnable::Dispatch(
--- a/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.h
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonGattInterface.h
@@ -222,16 +222,20 @@ protected:
 
   //
   // Responses
   //
 
   typedef BluetoothResultRunnable0<BluetoothGattClientResultHandler, void>
     ClientResultRunnable;
 
+  typedef BluetoothResultRunnable1<BluetoothGattClientResultHandler, void,
+                                   BluetoothTypeOfDevice, BluetoothTypeOfDevice>
+    ClientGetDeviceTypeResultRunnable;
+
   typedef BluetoothResultRunnable0<BluetoothGattResultHandler, void>
     ResultRunnable;
 
   typedef BluetoothResultRunnable1<BluetoothGattResultHandler, void,
                                    BluetoothStatus, BluetoothStatus>
     ErrorRunnable;
 
   void ErrorRsp(const DaemonSocketPDUHeader& aHeader,
@@ -450,16 +454,17 @@ protected:
   typedef BluetoothNotificationRunnable2<
     ClientNotificationHandlerWrapper, void,
     BluetoothGattStatus, int>
     ClientListenNotification;
 
   class ClientScanResultInitOp;
   class ClientConnectDisconnectInitOp;
   class ClientReadRemoteRssiInitOp;
+  class ClientGetDeviceTypeInitOp;
 
   void ClientRegisterNtf(const DaemonSocketPDUHeader& aHeader,
                                DaemonSocketPDU& aPDU);
 
   void ClientScanResultNtf(const DaemonSocketPDUHeader& aHeader,
                            DaemonSocketPDU& aPDU);
 
   void ClientConnectNtf(const DaemonSocketPDUHeader& aHeader,
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp
@@ -398,16 +398,22 @@ Convert(uint8_t aIn, BluetoothHandsfreeW
   if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sWbsConfig))) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
   aOut = sWbsConfig[aIn];
   return NS_OK;
 }
 
 nsresult
+Convert(uint8_t aIn, BluetoothTypeOfDevice& aOut)
+{
+  return Convert((int32_t)aIn, aOut);
+}
+
+nsresult
 Convert(uint8_t aIn, BluetoothPropertyType& aOut)
 {
   static const BluetoothPropertyType sPropertyType[] = {
     CONVERT(0x00, static_cast<BluetoothPropertyType>(0)), // invalid, required by gcc
     CONVERT(0x01, PROPERTY_BDNAME),
     CONVERT(0x02, PROPERTY_BDADDR),
     CONVERT(0x03, PROPERTY_UUIDS),
     CONVERT(0x04, PROPERTY_CLASS_OF_DEVICE),
--- a/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp
@@ -10,16 +10,21 @@
 BEGIN_BLUETOOTH_NAMESPACE
 
 typedef
   BluetoothHALInterfaceRunnable0<BluetoothGattClientResultHandler, void>
   BluetoothGattClientHALResultRunnable;
 
 typedef
   BluetoothHALInterfaceRunnable1<BluetoothGattClientResultHandler, void,
+                                 BluetoothTypeOfDevice, BluetoothTypeOfDevice>
+  BluetoothGattClientGetDeviceTypeHALResultRunnable;
+
+typedef
+  BluetoothHALInterfaceRunnable1<BluetoothGattClientResultHandler, void,
                                  BluetoothStatus, BluetoothStatus>
   BluetoothGattClientHALErrorRunnable;
 
 typedef
   BluetoothHALInterfaceRunnable0<BluetoothGattResultHandler, void>
   BluetoothGattHALResultRunnable;
 
 typedef
@@ -45,16 +50,45 @@ DispatchBluetoothGattClientHALResult(
   }
   nsresult rv = NS_DispatchToMainThread(runnable);
   if (NS_FAILED(rv)) {
     BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
   }
   return rv;
 }
 
+template <typename ResultRunnable, typename Tin1, typename Arg1>
+static nsresult
+DispatchBluetoothGattClientHALResult(
+  BluetoothGattClientResultHandler* aRes,
+  void (BluetoothGattClientResultHandler::*aMethod)(Arg1),
+  Tin1 aArg1,
+  BluetoothStatus aStatus)
+{
+  MOZ_ASSERT(aRes);
+
+  nsRunnable* runnable;
+  Arg1 arg1;
+
+  if (aStatus != STATUS_SUCCESS) {
+    runnable = new BluetoothGattClientHALErrorRunnable(aRes,
+      &BluetoothGattClientResultHandler::OnError, aStatus);
+  } else if (NS_FAILED(Convert(aArg1, arg1))) {
+    runnable = new BluetoothGattClientHALErrorRunnable(aRes,
+      &BluetoothGattClientResultHandler::OnError, STATUS_PARM_INVALID);
+  } else {
+    runnable = new ResultRunnable(aRes, aMethod, arg1);
+  }
+  nsresult rv = NS_DispatchToMainThread(runnable);
+  if (NS_FAILED(rv)) {
+    BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+  }
+  return rv;
+}
+
 static nsresult
 DispatchBluetoothGattHALResult(
   BluetoothGattResultHandler* aRes,
   void (BluetoothGattResultHandler::*aMethod)(),
   BluetoothStatus aStatus)
 {
   MOZ_ASSERT(aRes);
 
@@ -1002,32 +1036,33 @@ BluetoothGattClientHALInterface::ReadRem
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothGattClientHALInterface::GetDeviceType(
   const nsAString& aBdAddr, BluetoothGattClientResultHandler* aRes)
 {
-  int status;
+  int status = BT_STATUS_FAIL;
+  bt_device_type_t type = BT_DEVICE_DEVTYPE_BLE;
 #if ANDROID_VERSION >= 19
   bt_bdaddr_t bdAddr;
 
   if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
-    status = mInterface->get_device_type(&bdAddr);
-  } else {
-    status = BT_STATUS_PARM_INVALID;
+    status = BT_STATUS_SUCCESS;
+    type = static_cast<bt_device_type_t>(mInterface->get_device_type(&bdAddr));
   }
 #else
   status = BT_STATUS_UNSUPPORTED;
 #endif
 
   if (aRes) {
-    DispatchBluetoothGattClientHALResult(
-      aRes, &BluetoothGattClientResultHandler::GetDeviceType,
+    DispatchBluetoothGattClientHALResult<
+      BluetoothGattClientGetDeviceTypeHALResultRunnable>(
+      aRes, &BluetoothGattClientResultHandler::GetDeviceType, type,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothGattClientHALInterface::SetAdvData(
   int aServerIf, bool aIsScanRsp, bool aIsNameIncluded,
   bool aIsTxPowerIncluded, int aMinInterval, int aMaxInterval, int aApperance,
--- a/dom/bluetooth/bluedroid/BluetoothGattManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothGattManager.cpp
@@ -1350,34 +1350,32 @@ BluetoothGattManager::WriteDescriptorVal
 //
 // Notification Handlers
 //
 void
 BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
                                                  int aClientIf,
                                                  const BluetoothUuid& aAppUuid)
 {
-  BT_API2_LOGR("Client Registered, clientIf = %d", aClientIf);
   MOZ_ASSERT(NS_IsMainThread());
 
   nsString uuid;
   UuidToString(aAppUuid, uuid);
 
   size_t index = sClients->IndexOf(uuid, 0 /* Start */, UuidComparator());
   NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
 
   nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE_VOID(bs);
 
   if (aStatus != GATT_STATUS_SUCCESS) {
-    BT_API2_LOGR(
-      "RegisterClient failed, clientIf = %d, status = %d, appUuid = %s",
-      aClientIf, aStatus, NS_ConvertUTF16toUTF8(uuid).get());
+    BT_LOGD("RegisterClient failed: clientIf = %d, status = %d, appUuid = %s",
+            aClientIf, aStatus, NS_ConvertUTF16toUTF8(uuid).get());
 
     // Notify BluetoothGatt for client disconnected
     bs->DistributeSignal(
       NS_LITERAL_STRING(GATT_CONNECTION_STATE_CHANGED_ID),
       uuid, BluetoothValue(false)); // Disconnected
 
     if (client->mStartLeScanRunnable) {
       // Reject the LE scan request
@@ -1413,63 +1411,99 @@ BluetoothGattManager::RegisterClientNoti
     // Client just registered, proceed remaining connect request.
     sBluetoothGattClientInterface->Connect(
       aClientIf, client->mDeviceAddr, true /* direct connect */,
       TRANSPORT_AUTO,
       new ConnectResultHandler(client));
   }
 }
 
+class BluetoothGattManager::ScanDeviceTypeResultHandler final
+  : public BluetoothGattClientResultHandler
+{
+public:
+  ScanDeviceTypeResultHandler(const nsAString& aBdAddr, int aRssi,
+                              const BluetoothGattAdvData& aAdvData)
+  : mBdAddr(aBdAddr)
+  , mRssi(static_cast<int32_t>(aRssi))
+  {
+    mAdvData.AppendElements(aAdvData.mAdvData, sizeof(aAdvData.mAdvData));
+  }
+
+  void GetDeviceType(BluetoothTypeOfDevice type)
+  {
+    DistributeSignalDeviceFound(type);
+  }
+
+  void OnError(BluetoothStatus aStatus) override
+  {
+    DistributeSignalDeviceFound(TYPE_OF_DEVICE_BLE);
+  }
+
+private:
+  void DistributeSignalDeviceFound(BluetoothTypeOfDevice type)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    InfallibleTArray<BluetoothNamedValue> properties;
+
+    BT_APPEND_NAMED_VALUE(properties, "Address", mBdAddr);
+    BT_APPEND_NAMED_VALUE(properties, "Rssi", mRssi);
+    BT_APPEND_NAMED_VALUE(properties, "GattAdv", mAdvData);
+    BT_APPEND_NAMED_VALUE(properties, "Type", static_cast<uint32_t>(type));
+
+    BluetoothService* bs = BluetoothService::Get();
+    NS_ENSURE_TRUE_VOID(bs);
+
+    bs->DistributeSignal(NS_LITERAL_STRING("LeDeviceFound"),
+                         NS_LITERAL_STRING(KEY_ADAPTER),
+                         BluetoothValue(properties));
+  }
+
+  nsString mBdAddr;
+  int32_t mRssi;
+  nsTArray<uint8_t> mAdvData;
+};
+
 void
 BluetoothGattManager::ScanResultNotification(
   const nsAString& aBdAddr, int aRssi,
   const BluetoothGattAdvData& aAdvData)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  InfallibleTArray<BluetoothNamedValue> properties;
-
-  nsTArray<uint8_t> advData;
-  advData.AppendElements(aAdvData.mAdvData, sizeof(aAdvData.mAdvData));
+  NS_ENSURE_TRUE_VOID(sBluetoothGattClientInterface);
 
-  BT_APPEND_NAMED_VALUE(properties, "Address", nsString(aBdAddr));
-  BT_APPEND_NAMED_VALUE(properties, "Rssi", static_cast<int32_t>(aRssi));
-  BT_APPEND_NAMED_VALUE(properties, "GattAdv", advData);
-  BT_APPEND_NAMED_VALUE(properties, "Type",
-    static_cast<uint32_t>(TYPE_OF_DEVICE_BLE));
-
-  BluetoothService* bs = BluetoothService::Get();
-  NS_ENSURE_TRUE_VOID(bs);
-
-  bs->DistributeSignal(NS_LITERAL_STRING("LeDeviceFound"),
-                       NS_LITERAL_STRING(KEY_ADAPTER),
-                       BluetoothValue(properties));
+  // Distribute "LeDeviceFound" signal after we know the corresponding
+  // BluetoothTypeOfDevice of the device
+  sBluetoothGattClientInterface->GetDeviceType(
+    aBdAddr,
+    new ScanDeviceTypeResultHandler(aBdAddr, aRssi, aAdvData));
 }
 
 void
 BluetoothGattManager::ConnectNotification(int aConnId,
                                           BluetoothGattStatus aStatus,
                                           int aClientIf,
                                           const nsAString& aDeviceAddr)
 {
-  BT_API2_LOGR();
   MOZ_ASSERT(NS_IsMainThread());
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE_VOID(bs);
 
   size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
                                    ClientIfComparator());
   NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
 
   nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
 
   if (aStatus != GATT_STATUS_SUCCESS) {
-    BT_API2_LOGR("Connect failed, clientIf = %d, connId = %d, status = %d",
-                 aClientIf, aConnId, aStatus);
+    BT_LOGD("Connect failed: clientIf = %d, connId = %d, status = %d",
+            aClientIf, aConnId, aStatus);
 
     // Notify BluetoothGatt that the client remains disconnected
     bs->DistributeSignal(
       NS_LITERAL_STRING(GATT_CONNECTION_STATE_CHANGED_ID),
       client->mAppUuid,
       BluetoothValue(false)); // Disconnected
 
     // Reject the connect request
@@ -1498,17 +1532,16 @@ BluetoothGattManager::ConnectNotificatio
 }
 
 void
 BluetoothGattManager::DisconnectNotification(int aConnId,
                                              BluetoothGattStatus aStatus,
                                              int aClientIf,
                                              const nsAString& aDeviceAddr)
 {
-  BT_API2_LOGR();
   MOZ_ASSERT(NS_IsMainThread());
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE_VOID(bs);
 
   size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
                                    ClientIfComparator());
   NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
@@ -2025,32 +2058,31 @@ BluetoothGattManager::ExecuteWriteNotifi
 { }
 
 void
 BluetoothGattManager::ReadRemoteRssiNotification(int aClientIf,
                                                  const nsAString& aBdAddr,
                                                  int aRssi,
                                                  BluetoothGattStatus aStatus)
 {
-  BT_API2_LOGR();
   MOZ_ASSERT(NS_IsMainThread());
 
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE_VOID(bs);
 
   size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
                                    ClientIfComparator());
   NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
 
   nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
 
   if (aStatus != GATT_STATUS_SUCCESS) { // operation failed
-    BT_API2_LOGR("ReadRemoteRssi failed, clientIf = %d, bdAddr = %s, " \
-                 "rssi = %d, status = %d", aClientIf,
-                 NS_ConvertUTF16toUTF8(aBdAddr).get(), aRssi, (int)aStatus);
+    BT_LOGD("ReadRemoteRssi failed: clientIf = %d, bdAddr = %s, rssi = %d, " \
+            "status = %d", aClientIf, NS_ConvertUTF16toUTF8(aBdAddr).get(),
+            aRssi, (int)aStatus);
 
     // Reject the read remote rssi request
     if (client->mReadRemoteRssiRunnable) {
       DispatchReplyError(client->mReadRemoteRssiRunnable,
                          NS_LITERAL_STRING("ReadRemoteRssi failed"));
       client->mReadRemoteRssiRunnable = nullptr;
     }
 
--- a/dom/bluetooth/bluedroid/BluetoothGattManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothGattManager.h
@@ -105,16 +105,17 @@ private:
   class DiscoverResultHandler;
   class ReadRemoteRssiResultHandler;
   class RegisterNotificationsResultHandler;
   class DeregisterNotificationsResultHandler;
   class ReadCharacteristicValueResultHandler;
   class WriteCharacteristicValueResultHandler;
   class ReadDescriptorValueResultHandler;
   class WriteDescriptorValueResultHandler;
+  class ScanDeviceTypeResultHandler;
 
   BluetoothGattManager();
 
   void HandleShutdown();
 
   void RegisterClientNotification(BluetoothGattStatus aStatus,
                                   int aClientIf,
                                   const BluetoothUuid& aAppUuid) override;
--- a/dom/bluetooth/bluetooth2/BluetoothAdapter.cpp
+++ b/dom/bluetooth/bluetooth2/BluetoothAdapter.cpp
@@ -561,18 +561,16 @@ BluetoothAdapter::StartDiscovery(ErrorRe
    */
   BT_ENSURE_TRUE_REJECT(!mDiscovering, promise, NS_ERROR_DOM_INVALID_STATE_ERR);
   BT_ENSURE_TRUE_REJECT(mState == BluetoothAdapterState::Enabled,
                         promise,
                         NS_ERROR_DOM_INVALID_STATE_ERR);
   BluetoothService* bs = BluetoothService::Get();
   BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
 
-  BT_API2_LOGR();
-
   // Clear unpaired devices before start discovery
   for (int32_t i = mDevices.Length() - 1; i >= 0; i--) {
     if (!mDevices[i]->Paired()) {
       mDevices.RemoveElementAt(i);
     }
   }
 
   // Return BluetoothDiscoveryHandle in StartDiscoveryTask
@@ -603,18 +601,16 @@ BluetoothAdapter::StopDiscovery(ErrorRes
    */
   BT_ENSURE_TRUE_RESOLVE(mDiscovering, promise, JS::UndefinedHandleValue);
   BT_ENSURE_TRUE_REJECT(mState == BluetoothAdapterState::Enabled,
                         promise,
                         NS_ERROR_DOM_INVALID_STATE_ERR);
   BluetoothService* bs = BluetoothService::Get();
   BT_ENSURE_TRUE_REJECT(bs, promise, NS_ERROR_NOT_AVAILABLE);
 
-  BT_API2_LOGR();
-
   nsRefPtr<BluetoothReplyRunnable> result =
     new BluetoothVoidReplyRunnable(nullptr /* DOMRequest */,
                                    promise,
                                    NS_LITERAL_STRING("StopDiscovery"));
   bs->StopDiscoveryInternal(result);
 
   return promise.forget();
 }
@@ -1188,18 +1184,16 @@ BluetoothAdapter::DispatchAttributeEvent
 
   DispatchTrustedEvent(event);
 }
 
 void
 BluetoothAdapter::DispatchDeviceEvent(const nsAString& aType,
                                       const BluetoothDeviceEventInit& aInit)
 {
-  BT_API2_LOGR("aType (%s)", NS_ConvertUTF16toUTF8(aType).get());
-
   nsRefPtr<BluetoothDeviceEvent> event =
     BluetoothDeviceEvent::Constructor(this, aType, aInit);
   DispatchTrustedEvent(event);
 }
 
 void
 BluetoothAdapter::DispatchEmptyEvent(const nsAString& aType)
 {
--- a/dom/bluetooth/bluetooth2/BluetoothGatt.cpp
+++ b/dom/bluetooth/bluetooth2/BluetoothGatt.cpp
@@ -243,17 +243,17 @@ BluetoothGatt::DiscoverServices(ErrorRes
   bs->DiscoverGattServicesInternal(mAppUuid, result);
 
   return promise.forget();
 }
 
 void
 BluetoothGatt::UpdateConnectionState(BluetoothConnectionState aState)
 {
-  BT_API2_LOGR("GATT connection state changes to: %d", int(aState));
+  BT_LOGR("GATT connection state changes to: %d", int(aState));
   mConnectionState = aState;
 
   // Dispatch connectionstatechanged event to application
   nsCOMPtr<nsIDOMEvent> event;
   nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
   NS_ENSURE_SUCCESS_VOID(rv);
 
   rv = event->InitEvent(NS_LITERAL_STRING(GATT_CONNECTION_STATE_CHANGED_ID),
--- a/dom/bluetooth/bluetooth2/BluetoothManager.cpp
+++ b/dom/bluetooth/bluetooth2/BluetoothManager.cpp
@@ -76,17 +76,16 @@ class GetAdaptersTask : public Bluetooth
     // Extract the array of all adapters' properties
     const BluetoothValue& adaptersProperties =
       mReply->get_BluetoothReplySuccess().value();
     NS_ENSURE_TRUE(adaptersProperties.type() ==
                    BluetoothValue::TArrayOfBluetoothNamedValue, false);
 
     const InfallibleTArray<BluetoothNamedValue>& adaptersPropertiesArray =
       adaptersProperties.get_ArrayOfBluetoothNamedValue();
-    BT_API2_LOGR("GetAdaptersTask: len[%d]", adaptersPropertiesArray.Length());
 
     // Append a BluetoothAdapter into adapters array for each properties array
     uint32_t numAdapters = adaptersPropertiesArray.Length();
     for (uint32_t i = 0; i < numAdapters; i++) {
       MOZ_ASSERT(adaptersPropertiesArray[i].name().EqualsLiteral("Adapter"));
 
       const BluetoothValue& properties = adaptersPropertiesArray[i].value();
       mManager->AppendAdapter(properties);
@@ -109,17 +108,16 @@ private:
 
 BluetoothManager::BluetoothManager(nsPIDOMWindow *aWindow)
   : DOMEventTargetHelper(aWindow)
   , mDefaultAdapterIndex(-1)
 {
   MOZ_ASSERT(aWindow);
 
   RegisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
-  BT_API2_LOGR("aWindow %p", aWindow);
 
   // Query adapters list from bluetooth backend
   BluetoothService* bs = BluetoothService::Get();
   NS_ENSURE_TRUE_VOID(bs);
 
   nsRefPtr<BluetoothReplyRunnable> result = new GetAdaptersTask(this);
   NS_ENSURE_SUCCESS_VOID(bs->GetAdaptersInternal(result));
 }
@@ -134,18 +132,16 @@ BluetoothManager::DisconnectFromOwner()
 {
   DOMEventTargetHelper::DisconnectFromOwner();
   UnregisterBluetoothSignalHandler(NS_LITERAL_STRING(KEY_MANAGER), this);
 }
 
 BluetoothAdapter*
 BluetoothManager::GetDefaultAdapter()
 {
-  BT_API2_LOGR("mDefaultAdapterIndex: %d", mDefaultAdapterIndex);
-
   return DefaultAdapterExists() ? mAdapters[mDefaultAdapterIndex] : nullptr;
 }
 
 void
 BluetoothManager::AppendAdapter(const BluetoothValue& aValue)
 {
   MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
 
@@ -180,17 +176,16 @@ BluetoothManager::Create(nsPIDOMWindow* 
   nsRefPtr<BluetoothManager> manager = new BluetoothManager(aWindow);
   return manager.forget();
 }
 
 void
 BluetoothManager::HandleAdapterAdded(const BluetoothValue& aValue)
 {
   MOZ_ASSERT(aValue.type() == BluetoothValue::TArrayOfBluetoothNamedValue);
-  BT_API2_LOGR();
 
   AppendAdapter(aValue);
 
   // Notify application of added adapter
   BluetoothAdapterEventInit init;
   init.mAdapter = mAdapters.LastElement();
   DispatchAdapterEvent(NS_LITERAL_STRING("adapteradded"), init);
 }
@@ -225,39 +220,34 @@ BluetoothManager::HandleAdapterRemoved(c
   }
 }
 
 void
 BluetoothManager::ReselectDefaultAdapter()
 {
   // Select the first of existing/remaining adapters as default adapter
   mDefaultAdapterIndex = mAdapters.IsEmpty() ? -1 : 0;
-  BT_API2_LOGR("mAdapters length: %d => NEW mDefaultAdapterIndex: %d",
-               mAdapters.Length(), mDefaultAdapterIndex);
 
   // Notify application of default adapter change
   DispatchAttributeEvent();
 }
 
 void
 BluetoothManager::DispatchAdapterEvent(const nsAString& aType,
                                        const BluetoothAdapterEventInit& aInit)
 {
-  BT_API2_LOGR("aType (%s)", NS_ConvertUTF16toUTF8(aType).get());
-
   nsRefPtr<BluetoothAdapterEvent> event =
     BluetoothAdapterEvent::Constructor(this, aType, aInit);
   DispatchTrustedEvent(event);
 }
 
 void
 BluetoothManager::DispatchAttributeEvent()
 {
   MOZ_ASSERT(NS_IsMainThread());
-  BT_API2_LOGR();
 
   Sequence<nsString> types;
   BT_APPEND_ENUM_STRING_FALLIBLE(types,
                                  BluetoothManagerAttribute,
                                  BluetoothManagerAttribute::DefaultAdapter);
 
   // Notify application of default adapter change
   BluetoothAttributeEventInit init;
--- a/dom/bluetooth/bluetooth2/BluetoothReplyRunnable.cpp
+++ b/dom/bluetooth/bluetooth2/BluetoothReplyRunnable.cpp
@@ -18,21 +18,17 @@ USING_BLUETOOTH_NAMESPACE
 
 BluetoothReplyRunnable::BluetoothReplyRunnable(nsIDOMDOMRequest* aReq,
                                                Promise* aPromise,
                                                const nsAString& aName)
   : mDOMRequest(aReq)
   , mPromise(aPromise)
   , mErrorStatus(STATUS_FAIL)
   , mName(aName)
-{
-  if (aPromise) {
-    BT_API2_LOGR("<%s>", NS_ConvertUTF16toUTF8(mName).get());
-  }
-}
+{}
 
 void
 BluetoothReplyRunnable::SetReply(BluetoothReply* aReply)
 {
   mReply = aReply;
 }
 
 void
@@ -56,17 +52,16 @@ BluetoothReplyRunnable::FireReplySuccess
       do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
     NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
 
     return rs->FireSuccessAsync(mDOMRequest, aVal);
   }
 
   // Promise
   if (mPromise) {
-    BT_API2_LOGR("<%s>", NS_ConvertUTF16toUTF8(mName).get());
     mPromise->MaybeResolve(aVal);
   }
 
   return NS_OK;
 }
 
 nsresult
 BluetoothReplyRunnable::FireErrorString()
@@ -77,18 +72,16 @@ BluetoothReplyRunnable::FireErrorString(
       do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
     NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
 
     return rs->FireErrorAsync(mDOMRequest, mErrorString);
   }
 
   // Promise
   if (mPromise) {
-    BT_API2_LOGR("<%s>", NS_ConvertUTF16toUTF8(mName).get());
-
     nsresult rv =
       NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_DOM_BLUETOOTH, mErrorStatus);
     mPromise->MaybeReject(rv);
   }
 
   return NS_OK;
 }