servo: Merge #12875 - WebBluetooth Android support (from dati91:android); r=larsbergstrom
authorAttila Dusnoki <dati91@gmail.com>
Tue, 06 Sep 2016 10:44:41 -0500
changeset 339653 f4fd62827532083d5158e0ac93b54c8514b1234f
parent 339652 75f47b6c87cc20b592232ec1b00d32dc54cfe2ca
child 339654 bcca1e4087195a0b026b7a52ea28a2d8cf184315
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslarsbergstrom
servo: Merge #12875 - WebBluetooth Android support (from dati91:android); r=larsbergstrom <!-- Please describe your changes on the following line: --> Add android support for Webbluetooth. Also adjust to the changed device api. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [X] These changes do not require tests because there is no test api yet. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 057bcddd0f63a97b8cd1954310878c423d02e056
servo/components/net/bluetooth_thread.rs
servo/components/servo/Cargo.lock
servo/ports/cef/Cargo.lock
servo/python/servo/package_commands.py
servo/support/android/apk/AndroidManifest.xml
servo/support/android/apk/src/com/mozilla/servo/MainActivity.java
--- a/servo/components/net/bluetooth_thread.rs
+++ b/servo/components/net/bluetooth_thread.rs
@@ -1,15 +1,14 @@
 /* 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/. */
 
 use device::bluetooth::BluetoothAdapter;
 use device::bluetooth::BluetoothDevice;
-use device::bluetooth::BluetoothDiscoverySession;
 use device::bluetooth::BluetoothGATTCharacteristic;
 use device::bluetooth::BluetoothGATTDescriptor;
 use device::bluetooth::BluetoothGATTService;
 use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
 use net_traits::bluetooth_scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions};
 use net_traits::bluetooth_thread::{BluetoothCharacteristicMsg, BluetoothCharacteristicsMsg};
 use net_traits::bluetooth_thread::{BluetoothDescriptorMsg, BluetoothDescriptorsMsg};
 use net_traits::bluetooth_thread::{BluetoothDeviceMsg, BluetoothError, BluetoothMethodMsg};
@@ -289,18 +288,18 @@ impl BluetoothManager {
                                    adapter: &mut BluetoothAdapter,
                                    device_id: &str)
                                    -> Vec<BluetoothGATTService> {
         let services = match self.get_device(adapter, device_id) {
             Some(d) => d.get_gatt_services().unwrap_or(vec!()),
             None => vec!(),
         };
         for service in &services {
-            self.cached_services.insert(service.get_object_path(), service.clone());
-            self.service_to_device.insert(service.get_object_path(), device_id.to_owned());
+            self.cached_services.insert(service.get_id(), service.clone());
+            self.service_to_device.insert(service.get_id(), device_id.to_owned());
         }
         services
     }
 
     fn get_gatt_service(&mut self, adapter: &mut BluetoothAdapter, service_id: &str) -> Option<&BluetoothGATTService> {
         return_if_cached!(self.cached_services, service_id);
         let device_id = match self.service_to_device.get(service_id) {
             Some(d) => d.clone(),
@@ -327,18 +326,18 @@ impl BluetoothManager {
                                           service_id: &str)
                                           -> Vec<BluetoothGATTCharacteristic> {
         let characteristics = match self.get_gatt_service(adapter, service_id) {
             Some(s) => s.get_gatt_characteristics().unwrap_or(vec!()),
             None => vec!(),
         };
 
         for characteristic in &characteristics {
-            self.cached_characteristics.insert(characteristic.get_object_path(), characteristic.clone());
-            self.characteristic_to_service.insert(characteristic.get_object_path(), service_id.to_owned());
+            self.cached_characteristics.insert(characteristic.get_id(), characteristic.clone());
+            self.characteristic_to_service.insert(characteristic.get_id(), service_id.to_owned());
         }
         characteristics
     }
 
     fn get_gatt_characteristic(&mut self,
                                adapter: &mut BluetoothAdapter,
                                characteristic_id: &str)
                                -> Option<&BluetoothGATTCharacteristic> {
@@ -390,18 +389,18 @@ impl BluetoothManager {
                                       characteristic_id: &str)
                                       -> Vec<BluetoothGATTDescriptor> {
         let descriptors = match self.get_gatt_characteristic(adapter, characteristic_id) {
             Some(c) => c.get_gatt_descriptors().unwrap_or(vec!()),
             None => vec!(),
         };
 
         for descriptor in &descriptors {
-            self.cached_descriptors.insert(descriptor.get_object_path(), descriptor.clone());
-            self.descriptor_to_characteristic.insert(descriptor.get_object_path(), characteristic_id.to_owned());
+            self.cached_descriptors.insert(descriptor.get_id(), descriptor.clone());
+            self.descriptor_to_characteristic.insert(descriptor.get_id(), characteristic_id.to_owned());
         }
         descriptors
     }
 
     fn get_gatt_descriptor(&mut self,
                            adapter: &mut BluetoothAdapter,
                            descriptor_id: &str)
                            -> Option<&BluetoothGATTDescriptor> {
@@ -427,17 +426,17 @@ impl BluetoothManager {
     }
 
     // Methods
 
     fn request_device(&mut self,
                       options: RequestDeviceoptions,
                       sender: IpcSender<BluetoothResult<BluetoothDeviceMsg>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
-        if let Some(ref session) = BluetoothDiscoverySession::create_session(adapter.get_object_path()).ok() {
+        if let Ok(ref session) = adapter.create_discovery_session() {
             if session.start_discovery().is_ok() {
                 thread::sleep(Duration::from_millis(DISCOVERY_TIMEOUT_MS));
             }
             let _ = session.stop_discovery();
         }
         let devices = self.get_and_cache_devices(&mut adapter);
         let matched_devices: Vec<BluetoothDevice> = devices.into_iter()
                                                            .filter(|d| matches_filters(d, options.get_filters()))
@@ -521,17 +520,17 @@ impl BluetoothManager {
             return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         for service in services {
             if service.is_primary().unwrap_or(false) {
                 if let Ok(uuid) = service.get_uuid() {
                     return drop(sender.send(Ok(BluetoothServiceMsg {
                                                    uuid: uuid,
                                                    is_primary: true,
-                                                   instance_id: service.get_object_path(),
+                                                   instance_id: service.get_id(),
                                                })));
                 }
             }
         }
         return drop(sender.send(Err(BluetoothError::NotFound)));
     }
 
     fn get_primary_services(&mut self,
@@ -553,17 +552,17 @@ impl BluetoothManager {
         }
         let mut services_vec = vec!();
         for service in services {
             if service.is_primary().unwrap_or(false) {
                 if let Ok(uuid) = service.get_uuid() {
                     services_vec.push(BluetoothServiceMsg {
                                           uuid: uuid,
                                           is_primary: true,
-                                          instance_id: service.get_object_path(),
+                                          instance_id: service.get_id(),
                                       });
                 }
             }
         }
         if services_vec.is_empty() {
             return drop(sender.send(Err(BluetoothError::NotFound)));
         }
 
@@ -584,17 +583,17 @@ impl BluetoothManager {
         };
         let services = primary_service.get_includes().unwrap_or(vec!());
         for service in services {
             if let Ok(service_uuid) = service.get_uuid() {
                 if uuid == service_uuid {
                     return drop(sender.send(Ok(BluetoothServiceMsg {
                                                    uuid: uuid,
                                                    is_primary: service.is_primary().unwrap_or(false),
-                                                   instance_id: service.get_object_path(),
+                                                   instance_id: service.get_id(),
                                                })));
                 }
             }
         }
         return drop(sender.send(Err(BluetoothError::NotFound)));
     }
 
     fn get_included_services(&mut self,
@@ -611,17 +610,17 @@ impl BluetoothManager {
         };
         let services = primary_service.get_includes().unwrap_or(vec!());
         let mut services_vec = vec!();
         for service in services {
             if let Ok(service_uuid) = service.get_uuid() {
                 services_vec.push(BluetoothServiceMsg {
                                       uuid: service_uuid,
                                       is_primary: service.is_primary().unwrap_or(false),
-                                      instance_id: service.get_object_path(),
+                                      instance_id: service.get_id(),
                                   });
             }
         }
         if let Some(uuid) = uuid {
             services_vec.retain(|ref s| s.uuid == uuid);
         }
         if services_vec.is_empty() {
             return drop(sender.send(Err(BluetoothError::NotFound)));
@@ -639,17 +638,17 @@ impl BluetoothManager {
         if characteristics.is_empty() {
             return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         for characteristic in characteristics {
             if let Ok(uuid) = characteristic.get_uuid() {
                 let properties = self.get_characteristic_properties(&characteristic);
                 let message = Ok(BluetoothCharacteristicMsg {
                                      uuid: uuid,
-                                     instance_id: characteristic.get_object_path(),
+                                     instance_id: characteristic.get_id(),
                                      broadcast: properties.contains(BROADCAST),
                                      read: properties.contains(READ),
                                      write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
                                      write: properties.contains(WRITE),
                                      notify: properties.contains(NOTIFY),
                                      indicate: properties.contains(INDICATE),
                                      authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
                                      reliable_write: properties.contains(RELIABLE_WRITE),
@@ -675,17 +674,17 @@ impl BluetoothManager {
         }
         let mut characteristics_vec = vec!();
         for characteristic in characteristics {
             if let Ok(uuid) = characteristic.get_uuid() {
                 let properties = self.get_characteristic_properties(&characteristic);
                 characteristics_vec.push(
                                 BluetoothCharacteristicMsg {
                                     uuid: uuid,
-                                    instance_id: characteristic.get_object_path(),
+                                    instance_id: characteristic.get_id(),
                                     broadcast: properties.contains(BROADCAST),
                                     read: properties.contains(READ),
                                     write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
                                     write: properties.contains(WRITE),
                                     notify: properties.contains(NOTIFY),
                                     indicate: properties.contains(INDICATE),
                                     authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
                                     reliable_write: properties.contains(RELIABLE_WRITE),
@@ -708,17 +707,17 @@ impl BluetoothManager {
         let descriptors = self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &uuid);
         if descriptors.is_empty() {
             return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         for descriptor in descriptors {
             if let Ok(uuid) = descriptor.get_uuid() {
                 return drop(sender.send(Ok(BluetoothDescriptorMsg {
                                                uuid: uuid,
-                                               instance_id: descriptor.get_object_path(),
+                                               instance_id: descriptor.get_id(),
                                            })));
             }
         }
         return drop(sender.send(Err(BluetoothError::NotFound)));
     }
 
     fn get_descriptors(&mut self,
                        characteristic_id: String,
@@ -732,17 +731,17 @@ impl BluetoothManager {
         if descriptors.is_empty() {
             return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         let mut descriptors_vec = vec!();
         for descriptor in descriptors {
             if let Ok(uuid) = descriptor.get_uuid() {
                 descriptors_vec.push(BluetoothDescriptorMsg {
                                          uuid: uuid,
-                                         instance_id: descriptor.get_object_path(),
+                                         instance_id: descriptor.get_id(),
                                      });
             }
         }
         if descriptors_vec.is_empty() {
             return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         let _ = sender.send(Ok(descriptors_vec));
     }
--- a/servo/components/servo/Cargo.lock
+++ b/servo/components/servo/Cargo.lock
@@ -176,18 +176,23 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "block"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "blurdroid"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "blurz"
-version = "0.1.7"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dbus 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "brotli"
@@ -472,19 +477,20 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "device"
 version = "0.0.1"
-source = "git+https://github.com/servo/devices#09ab8682bddfa73ba36025a150625504212d34da"
+source = "git+https://github.com/servo/devices#6d40b1412fb496b0d9434ee2f46e9dfc4dc67ae7"
 dependencies = [
- "blurz 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blurdroid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blurz 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "devtools"
 version = "0.0.1"
 dependencies = [
  "devtools_traits 0.0.1",
  "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2723,17 +2729,18 @@ dependencies = [
 "checksum azure 0.8.0 (git+https://github.com/servo/rust-azure)" = "<none>"
 "checksum backtrace 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "346d7644f0b5f9bc73082d3b2236b69a05fd35cce0cfa3724e184e6a5c9e2a2f"
 "checksum backtrace-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ff73785ae8e06bb4a7b09e09f06d7434f9748b86d2f67bdf334b603354497e08"
 "checksum bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fbba641f73d3e74a5431d4a6d9e42a70bcce76d466d796c852ba1db31ba41bc"
 "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
 "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
-"checksum blurz 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a18fbcef6db7f58d135f77ad561e8f9b7fc809c91619c33422714cf5548004ed"
+"checksum blurdroid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5fce4ea3366b583e9d49e1aa3a42252e53b42911bccd06f31c3e81c48ccfc79e"
+"checksum blurz 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96134f6ac62fa6925761dbdb4096617d65d7c1d383d90e5c2d4c489919f773dc"
 "checksum brotli 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bff2d5511b5ba5840f46cc3f9c0c3ab09db20e9b9a4db344ef7df3fb547a627a"
 "checksum browserhtml 0.1.17 (git+https://github.com/browserhtml/browserhtml?branch=crate)" = "<none>"
 "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
 "checksum caseless 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6893f86ac0c9275b5cbba9212ccd71020b447d4c3e2eebad70e1bc47fdd6dfb"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8bdd78cca65a739cb5475dbf6b6bbb49373e327f4a6f2b499c0f98632df38c10"
 "checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978"
 "checksum cocoa 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d24ed9a15e9c0892cdb20c7acc3e50441501b990ee6dc318c176981829a7941"
--- a/servo/ports/cef/Cargo.lock
+++ b/servo/ports/cef/Cargo.lock
@@ -150,18 +150,23 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "block"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
+name = "blurdroid"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
 name = "blurz"
-version = "0.1.7"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dbus 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "brotli"
@@ -430,19 +435,20 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "device"
 version = "0.0.1"
-source = "git+https://github.com/servo/devices#09ab8682bddfa73ba36025a150625504212d34da"
+source = "git+https://github.com/servo/devices#6d40b1412fb496b0d9434ee2f46e9dfc4dc67ae7"
 dependencies = [
- "blurz 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blurdroid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blurz 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "devtools"
 version = "0.0.1"
 dependencies = [
  "devtools_traits 0.0.1",
  "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2583,17 +2589,18 @@ dependencies = [
 "checksum azure 0.8.0 (git+https://github.com/servo/rust-azure)" = "<none>"
 "checksum backtrace 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "346d7644f0b5f9bc73082d3b2236b69a05fd35cce0cfa3724e184e6a5c9e2a2f"
 "checksum backtrace-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ff73785ae8e06bb4a7b09e09f06d7434f9748b86d2f67bdf334b603354497e08"
 "checksum bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fbba641f73d3e74a5431d4a6d9e42a70bcce76d466d796c852ba1db31ba41bc"
 "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
 "checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
-"checksum blurz 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a18fbcef6db7f58d135f77ad561e8f9b7fc809c91619c33422714cf5548004ed"
+"checksum blurdroid 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5fce4ea3366b583e9d49e1aa3a42252e53b42911bccd06f31c3e81c48ccfc79e"
+"checksum blurz 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96134f6ac62fa6925761dbdb4096617d65d7c1d383d90e5c2d4c489919f773dc"
 "checksum brotli 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "bff2d5511b5ba5840f46cc3f9c0c3ab09db20e9b9a4db344ef7df3fb547a627a"
 "checksum browserhtml 0.1.17 (git+https://github.com/browserhtml/browserhtml?branch=crate)" = "<none>"
 "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
 "checksum caseless 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6893f86ac0c9275b5cbba9212ccd71020b447d4c3e2eebad70e1bc47fdd6dfb"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum cgl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8bdd78cca65a739cb5475dbf6b6bbb49373e327f4a6f2b499c0f98632df38c10"
 "checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978"
 "checksum cocoa 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d24ed9a15e9c0892cdb20c7acc3e50441501b990ee6dc318c176981829a7941"
--- a/servo/python/servo/package_commands.py
+++ b/servo/python/servo/package_commands.py
@@ -130,16 +130,25 @@ class PackageCommands(CommandBase):
                 env["ANT_FLAVOR"] = "debug"
                 dev_flag = "-d"
             else:
                 env["ANT_FLAVOR"] = "release"
                 dev_flag = ""
 
             target_dir = path.dirname(binary_path)
             output_apk = "{}.apk".format(binary_path)
+            blurdroid_path = find_dep_path_newest('blurdroid', binary_path)
+            if blurdroid_path is None:
+                print("Could not find blurdroid package; perhaps you haven't built Servo.")
+                return 1
+            else:
+                dir_to_libs = path.join("support", "android", "apk", "libs")
+                if not path.exists(dir_to_libs):
+                    os.makedirs(dir_to_libs)
+                shutil.copy2(blurdroid_path + '/out/blurdroid.jar', dir_to_libs)
             try:
                 with cd(path.join("support", "android", "build-apk")):
                     subprocess.check_call(["cargo", "run", "--", dev_flag, "-o", output_apk, "-t", target_dir,
                                            "-r", self.get_top_dir()], env=env)
             except subprocess.CalledProcessError as e:
                 print("Packaging Android exited with return value %d" % e.returncode)
                 return e.returncode
         elif is_macosx():
--- a/servo/support/android/apk/AndroidManifest.xml
+++ b/servo/support/android/apk/AndroidManifest.xml
@@ -3,19 +3,22 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.mozilla.servo"
         android:versionCode="1"
         android:versionName="1.0">
 
     <uses-sdk android:minSdkVersion="18" />
 
     <uses-feature android:glEsVersion="0x00020000" android:required="true"></uses-feature>
+    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
 
     <application android:label="Servo" android:icon="@mipmap/servo">
         <activity android:name="com.mozilla.servo.MainActivity"
                 android:label="Servo"
                 android:configChanges="orientation|keyboardHidden">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
--- a/servo/support/android/apk/src/com/mozilla/servo/MainActivity.java
+++ b/servo/support/android/apk/src/com/mozilla/servo/MainActivity.java
@@ -8,16 +8,17 @@ import java.io.FileOutputStream;
 import java.io.PrintStream;
 import java.lang.System;
 
 
 public class MainActivity extends android.app.NativeActivity {
     private static final String LOGTAG="servo_wrapper";
     static {
         Log.i(LOGTAG, "Loading the NativeActivity");
+        System.loadLibrary("main");
     }
 
     private void set_url(String url) {
         try {
             PrintStream out = new PrintStream(new FileOutputStream("/sdcard/servo/android_params"));
             out.println("# The first line here should be the \"servo\" argument (without quotes) and the");
             out.println("# last should be the URL to load.");
             out.println("# Blank lines and those beginning with a '#' are ignored.");