Fix bugs in sl4a bluetooth connection APIs.

Restructure receivers in connection facade.
Fix a name in media player facade.

Merging kwd commit 9c02e91c1fed90f743eda49dff5c7263a76c1a49
Change-Id: Ibd00c2df6311efd075a2e38fd71e2ad4a18b90cf
diff --git a/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothA2dpFacade.java b/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothA2dpFacade.java
index c3a2e6d..805c78f 100644
--- a/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothA2dpFacade.java
+++ b/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothA2dpFacade.java
@@ -16,85 +16,88 @@
 import com.googlecode.android_scripting.rpc.Rpc;
 import com.googlecode.android_scripting.rpc.RpcParameter;
 
-
 public class BluetoothA2dpFacade extends RpcReceiver {
-  static final ParcelUuid[] SINK_UUIDS = {
-      BluetoothUuid.AudioSink,
-      BluetoothUuid.AdvAudioDist,
-  };
+  static final ParcelUuid[] SINK_UUIDS = { BluetoothUuid.AudioSink,
+      BluetoothUuid.AdvAudioDist, };
 
   private final Service mService;
   private final BluetoothAdapter mBluetoothAdapter;
 
-  private boolean mIsA2dpReady = false;
-  private BluetoothA2dp mA2dpProfile = null;
+  private static boolean sIsA2dpReady = false;
+  private static BluetoothA2dp sA2dpProfile = null;
 
   public BluetoothA2dpFacade(FacadeManager manager) {
     super(manager);
     mService = manager.getService();
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-    mBluetoothAdapter.getProfileProxy(mService, new A2dpServiceListener(), BluetoothProfile.A2DP);
+    mBluetoothAdapter.getProfileProxy(mService, new A2dpServiceListener(),
+        BluetoothProfile.A2DP);
   }
 
   class A2dpServiceListener implements BluetoothProfile.ServiceListener {
     @Override
     public void onServiceConnected(int profile, BluetoothProfile proxy) {
-      mA2dpProfile = (BluetoothA2dp) proxy;
-      mIsA2dpReady = true;
+      sA2dpProfile = (BluetoothA2dp) proxy;
+      sIsA2dpReady = true;
     }
+
     @Override
     public void onServiceDisconnected(int profile) {
-      mIsA2dpReady = false;
+      sIsA2dpReady = false;
     }
   }
 
   public Boolean a2dpConnect(BluetoothDevice device) {
-    List<BluetoothDevice> sinks = mA2dpProfile.getConnectedDevices();
+    List<BluetoothDevice> sinks = sA2dpProfile.getConnectedDevices();
     if (sinks != null) {
-        for (BluetoothDevice sink : sinks) {
-          mA2dpProfile.disconnect(sink);
-        }
+      for (BluetoothDevice sink : sinks) {
+        sA2dpProfile.disconnect(sink);
+      }
     }
-    return mA2dpProfile.connect(device);
+    return sA2dpProfile.connect(device);
   }
 
   public Boolean a2dpDisconnect(BluetoothDevice device) {
-    if (mA2dpProfile.getPriority(device) > BluetoothProfile.PRIORITY_ON){
-      mA2dpProfile.setPriority(device, BluetoothProfile.PRIORITY_ON);
+    if (sA2dpProfile.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+      sA2dpProfile.setPriority(device, BluetoothProfile.PRIORITY_ON);
     }
-    return mA2dpProfile.disconnect(device);
+    return sA2dpProfile.disconnect(device);
   }
 
-  @Rpc(description="Is A2dp profile ready.")
+  @Rpc(description = "Is A2dp profile ready.")
   public Boolean bluetoothA2dpIsReady() {
-    return mIsA2dpReady;
+    return sIsA2dpReady;
   }
-  @Rpc(description="Connect to an A2DP device.")
+
+  @Rpc(description = "Connect to an A2DP device.")
   public Boolean bluetoothA2dpConnect(
-      @RpcParameter(
-          name = "device",
-          description = "Name or MAC address of a bluetooth device.")
-          String device) throws Exception {
-    if (mA2dpProfile == null) return false;
-    BluetoothDevice mDevice = BluetoothFacade.getDevice(BluetoothFacade.DiscoveredDevices, device);
+      @RpcParameter(name = "device", description = "Name or MAC address of a bluetooth device.") String device)
+      throws Exception {
+    if (sA2dpProfile == null)
+      return false;
+    BluetoothDevice mDevice = BluetoothFacade.getDevice(
+        BluetoothFacade.DiscoveredDevices, device);
     Log.d("Connecting to device " + mDevice.getAliasName());
     return a2dpConnect(mDevice);
   }
 
-  @Rpc(description="Disconnect an A2DP device.")
+  @Rpc(description = "Disconnect an A2DP device.")
   public Boolean bluetoothA2dpDisconnect(
-      @RpcParameter(
-          name = "device",
-          description = "Name or MAC address of a device.")
-          String device) throws Exception {
-    if (mA2dpProfile == null) return false;
-    BluetoothDevice mDevice = BluetoothFacade.getDevice(mA2dpProfile.getConnectedDevices(), device);
+      @RpcParameter(name = "device", description = "Name or MAC address of a device.") String device)
+      throws Exception {
+    if (sA2dpProfile == null)
+      return false;
+    Log.d("Connected devices: " + sA2dpProfile.getConnectedDevices());
+    BluetoothDevice mDevice = BluetoothFacade.getDevice(
+        sA2dpProfile.getConnectedDevices(), device);
     return a2dpDisconnect(mDevice);
   }
 
-  @Rpc(description="Get all the devices connected through A2DP.")
+  @Rpc(description = "Get all the devices connected through A2DP.")
   public List<BluetoothDevice> bluetoothA2dpGetConnectedDevices() {
-    return mA2dpProfile.getConnectedDevices();
+    while (!sIsA2dpReady)
+      ;
+    return sA2dpProfile.getConnectedDevices();
   }
 
   @Override
diff --git a/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothConnectionFacade.java b/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothConnectionFacade.java
index 16b7713..9fb98b4 100644
--- a/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothConnectionFacade.java
+++ b/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothConnectionFacade.java
@@ -1,10 +1,17 @@
+
 package com.googlecode.android_scripting.bluetooth;
 
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 import android.app.Service;
+import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothUuid;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -21,181 +28,260 @@
 import com.googlecode.android_scripting.rpc.RpcParameter;
 
 public class BluetoothConnectionFacade extends RpcReceiver {
-  static final ParcelUuid[] SINK_UUIDS = {
-      BluetoothUuid.AudioSink,
-      BluetoothUuid.AdvAudioDist,
-  };
-  static final ParcelUuid[] HSP_UUIDS = {
-    BluetoothUuid.HSP,
-    BluetoothUuid.Handsfree,
-  };
+    static final ParcelUuid[] SINK_UUIDS = {
+            BluetoothUuid.AudioSink, BluetoothUuid.AdvAudioDist,
+    };
+    static final ParcelUuid[] HSP_UUIDS = {
+            BluetoothUuid.HSP, BluetoothUuid.Handsfree,
+    };
 
-  private final Service mService;
-  private final BluetoothAdapter mBluetoothAdapter;
-  private final BluetoothPairingHelper mPairingHelper;
-  private final ConcurrentHashMap<String, BroadcastReceiver> listeningDevices;
+    private final Service mService;
+    private final BluetoothAdapter mBluetoothAdapter;
+    private final BluetoothPairingHelper mPairingHelper;
+    private final Map<String, BroadcastReceiver> listeningDevices;
 
-  private final EventFacade mEventFacade;
-  private BluetoothHspFacade mHspProfile;
-  private BluetoothA2dpFacade mA2dpProfile;
+    private final EventFacade mEventFacade;
+    private BluetoothHspFacade mHspProfile;
+    private BluetoothA2dpFacade mA2dpProfile;
 
-  private final IntentFilter mDiscoverConnectFilter;
-  private final IntentFilter mPairingFilter;
+    private final IntentFilter mDiscoverConnectFilter;
+    private final IntentFilter mPairingFilter;
+    private final IntentFilter mBondStateChangeFilter;
+    private final IntentFilter mA2dpStateChangeFilter;
+    private final IntentFilter mHspStateChangeFilter;
 
-  public BluetoothConnectionFacade(FacadeManager manager) {
-    super(manager);
-    mService = manager.getService();
-    mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-    mPairingHelper = new BluetoothPairingHelper();
-    listeningDevices = new ConcurrentHashMap<String, BroadcastReceiver>();
+    public BluetoothConnectionFacade(FacadeManager manager) {
+        super(manager);
+        mService = manager.getService();
+        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+        mPairingHelper = new BluetoothPairingHelper();
+        // Use a synchronized map to avoid running problems
+        listeningDevices = Collections.synchronizedMap(new HashMap<String, BroadcastReceiver>());
 
-    mEventFacade = manager.getReceiver(EventFacade.class);
-    mA2dpProfile = manager.getReceiver(BluetoothA2dpFacade.class);
-    mHspProfile = manager.getReceiver(BluetoothHspFacade.class);
+        mEventFacade = manager.getReceiver(EventFacade.class);
+        mA2dpProfile = manager.getReceiver(BluetoothA2dpFacade.class);
+        mHspProfile = manager.getReceiver(BluetoothHspFacade.class);
 
-    mDiscoverConnectFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
-    mDiscoverConnectFilter.addAction(BluetoothDevice.ACTION_UUID);
-    mDiscoverConnectFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
+        mDiscoverConnectFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
+        mDiscoverConnectFilter.addAction(BluetoothDevice.ACTION_UUID);
+        mDiscoverConnectFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
 
-    mPairingFilter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
-  }
+        mPairingFilter = new IntentFilter(BluetoothDevice.ACTION_PAIRING_REQUEST);
 
-  /**
-   * Connect to a specific device upon its discovery
-   * @author angli
-   *
-   */
-  public class DiscoverConnectReceiver extends BroadcastReceiver {
-    private final String mDeviceID;
-    private final Boolean mBond;
-    private BluetoothDevice mDevice;
+        mBondStateChangeFilter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
+        mA2dpStateChangeFilter = new IntentFilter(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+        mHspStateChangeFilter = new IntentFilter(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
+    }
+
     /**
-     * Constructor
-     * @param deviceID Either the device alias name or mac address.
-     * @param bond If true, create bond to the device only.
+     * Connect to a specific device upon its discovery
      */
-    public DiscoverConnectReceiver(String deviceID, Boolean bond) {
-      super();
-      mDeviceID = deviceID;
-      mBond = bond;
+    public class DiscoverConnectReceiver extends BroadcastReceiver {
+        private final String mDeviceID;
+        private final Boolean mBond;
+        private BluetoothDevice mDevice;
+
+        /**
+         * Constructor
+         * 
+         * @param deviceID Either the device alias name or mac address.
+         * @param bond If true, bond the device only.
+         */
+        public DiscoverConnectReceiver(String deviceID, Boolean bond) {
+            super();
+            mDeviceID = deviceID;
+            mBond = bond;
+        }
+
+        public DiscoverConnectReceiver(String deviceID) {
+            this(deviceID, false);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            // The specified device is found.
+            if (action.equals(BluetoothDevice.ACTION_FOUND)) {
+                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+                if (BluetoothFacade.deviceMatch(device, mDeviceID)) {
+                    Log.d("Found device " + device.getAliasName() + " for connection.");
+                    mBluetoothAdapter.cancelDiscovery();
+                    mDevice = device;
+                }
+                // After discovery stops.
+            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
+                if (mDevice == null) {
+                    Log.d("Device " + mDeviceID + " was not discovered.");
+                    return;
+                }
+                // Attempt to initiate bonding if this is a bond request.
+                if (mBond) {
+                    Log.d("Bond with " + mDevice.getAliasName());
+                    StateChangeReceiver receiver = new StateChangeReceiver(mDeviceID);
+                    listeningDevices.put("Bonding" + mDeviceID, receiver);
+                    mService.registerReceiver(receiver, mBondStateChangeFilter);
+                    if (mDevice.createBond()) {
+                        Log.d("Bonding started.");
+                    } else {
+                        Log.e("Failed to bond with " + mDevice.getAliasName());
+                        mService.unregisterReceiver(listeningDevices.remove("Bonding" + mDeviceID));
+                    }
+                    mService.unregisterReceiver(listeningDevices.remove("Bond" + mDeviceID));
+                    // Otherwise fetch the device's UUID.
+                } else {
+                    Log.d("Discovery finished, start fetching UUIDs.");
+                    boolean status = mDevice.fetchUuidsWithSdp();
+                    Log.d("Initiated ACL connection: " + status);
+                }
+                // Initiate connection based on the UUIDs retrieved.
+            } else if (action.equals(BluetoothDevice.ACTION_UUID)) {
+                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+                if (BluetoothFacade.deviceMatch(device, mDeviceID)) {
+                    Log.d("Initiating connections.");
+                    connectProfile(device, mDeviceID);
+                    mService.unregisterReceiver(listeningDevices.remove(mDeviceID));
+                }
+            }
+        }
     }
-    public DiscoverConnectReceiver(String deviceID) {
-      this(deviceID, false);
+
+    public class StateChangeReceiver extends BroadcastReceiver {
+        private final String mDeviceID;
+
+        public StateChangeReceiver(String deviceID) {
+            mDeviceID = deviceID;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
+                int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
+                if (state == BluetoothDevice.BOND_BONDED) {
+                    mEventFacade.postEvent("Bonded" + mDeviceID, new Bundle());
+                    mService.unregisterReceiver(listeningDevices.remove("Bonding" + mDeviceID));
+                }
+            } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
+                int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1);
+                if (state == BluetoothA2dp.STATE_CONNECTED) {
+                    mEventFacade.postEvent("A2dpConnected" + mDeviceID, new Bundle());
+                    mService.unregisterReceiver(listeningDevices.remove("A2dpConnecting"
+                            + mDeviceID));
+                }
+            } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
+                int state = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, -1);
+                if (state == BluetoothHeadset.STATE_CONNECTED) {
+                    mEventFacade.postEvent("HspConnected" + mDeviceID, new Bundle());
+                    mService.unregisterReceiver(listeningDevices
+                            .remove("HspConnecting" + mDeviceID));
+                }
+            }
+        }
     }
+
+    private void connectProfile(BluetoothDevice device, String deviceID) {
+        ParcelUuid[] deviceUuids = device.getUuids();
+        Log.d("Device uuid is " + deviceUuids);
+        mService.registerReceiver(mPairingHelper, mPairingFilter);
+        if (BluetoothUuid.containsAnyUuid(SINK_UUIDS, deviceUuids)) {
+            Log.d("Connecting to " + device.getAliasName());
+            boolean status = mA2dpProfile.a2dpConnect(device);
+            if (status) {
+                Log.d("Connecting A2dp...");
+                StateChangeReceiver receiver = new StateChangeReceiver(deviceID);
+                mService.registerReceiver(receiver, mA2dpStateChangeFilter);
+                listeningDevices.put("A2dpConnecting" + deviceID, receiver);
+            } else {
+                Log.d("Failed starting A2dp connection.");
+            }
+        }
+        if (BluetoothUuid.containsAnyUuid(HSP_UUIDS, deviceUuids)) {
+            boolean status = mHspProfile.hspConnect(device);
+            if (status) {
+                Log.d("Posting event.");
+                StateChangeReceiver receiver = new StateChangeReceiver(deviceID);
+                mService.registerReceiver(receiver, mHspStateChangeFilter);
+                listeningDevices.put("HspConnecting" + deviceID, receiver);
+            } else {
+                Log.d("Failed starting Hsp connection.");
+            }
+        }
+        mService.unregisterReceiver(mPairingHelper);
+    }
+
+    private Set<BluetoothDevice> getConnectedDevices() {
+        Set<BluetoothDevice> a2dp = new HashSet<BluetoothDevice>(
+                mA2dpProfile.bluetoothA2dpGetConnectedDevices());
+        Set<BluetoothDevice> hsp = new HashSet<BluetoothDevice>(
+                mHspProfile.bluetoothHspGetConnectedDevices());
+        a2dp.addAll(hsp);
+        return a2dp;
+    }
+
+    @Rpc(description = "Connect to a specified device once it's discovered.",
+         returns = "Whether discovery started successfully.")
+    public Boolean bluetoothDiscoverAndConnect(
+            @RpcParameter(name = "deviceID",
+                          description = "Name or MAC address of a bluetooth device.")
+            String deviceID) {
+        mBluetoothAdapter.cancelDiscovery();
+        if (listeningDevices.containsKey(deviceID)) {
+            Log.d("This device is already in the process of discovery and connecting.");
+            return false;
+        }
+        if (BluetoothFacade.deviceExists(getConnectedDevices(), deviceID)) {
+            Log.d("Device " + deviceID + " is already connected through A2DP.");
+            return false;
+        }
+        DiscoverConnectReceiver receiver = new DiscoverConnectReceiver(deviceID);
+        listeningDevices.put(deviceID, receiver);
+        mService.registerReceiver(receiver, mDiscoverConnectFilter);
+        return mBluetoothAdapter.startDiscovery();
+    }
+
+    @Rpc(description = "Bond to a specified device once it's discovered.",
+         returns = "Whether discovery started successfully. ")
+    public Boolean bluetoothDiscoverAndBond(
+            @RpcParameter(name = "device",
+                          description = "Name or MAC address of a bluetooth device.")
+            String deviceID) {
+        mBluetoothAdapter.cancelDiscovery();
+        if (listeningDevices.containsKey(deviceID)) {
+            Log.d("This device is already in the process of discovery and bonding.");
+            return false;
+        }
+        if (BluetoothFacade.deviceExists(mBluetoothAdapter.getBondedDevices(), deviceID)) {
+            Log.d("Device " + deviceID + " is already bonded.");
+            return false;
+        }
+        DiscoverConnectReceiver receiver = new DiscoverConnectReceiver(deviceID, true);
+        listeningDevices.put("Bond" + deviceID, receiver);
+        mService.registerReceiver(receiver, mDiscoverConnectFilter);
+        return mBluetoothAdapter.startDiscovery();
+    }
+
+    @Rpc(description = "Remove bond to a device.",
+         returns = "Whether the device was successfully unbonded.")
+    public Boolean bluetoothUnbond(
+            @RpcParameter(name = "device",
+                          description = "Name or MAC address of a bluetooth device.")
+            String device) throws Exception {
+        BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(),
+                device);
+        return mDevice.removeBond();
+    }
+
+    @Rpc(description = "Connect to a device that is already bonded.")
+    public void bluetoothConnectBonded(
+            @RpcParameter(name = "device",
+                          description = "Name or MAC address of a bluetooth device.")
+            String device) throws Exception {
+        BluetoothDevice mDevice = BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(),
+                device);
+        connectProfile(mDevice, device);
+    }
+
     @Override
-    public void onReceive(Context context, Intent intent) {
-      String action = intent.getAction();
-      if (action.equals(BluetoothDevice.ACTION_FOUND)) {
-        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-        if(mDeviceID.equals(device.getAliasName()) || mDeviceID.equals(device.getAddress())) {
-          Log.d("Found device " + device.getAliasName() + " for connection.");
-          mBluetoothAdapter.cancelDiscovery();
-          mDevice = device;
-        }
-      }else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
-        if(mBond) {
-          Log.d("Bond with " + mDevice.getAliasName());
-          if (!mDevice.createBond()) {
-            Log.e("Failed to bond with " + mDevice.getAliasName());
-          }
-          mService.unregisterReceiver(this);
-        }else{
-          Log.d("Discovery finished, start fetching UUIDs.");
-          mDevice.fetchUuidsWithSdp();
-        }
-      }else if (action.equals(BluetoothDevice.ACTION_UUID)) {
-        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-        if(mDeviceID.equals(device.getAliasName()) || mDeviceID.equals(device.getAddress())) {
-          connectProfile(device, mDeviceID);
-        }
-      }
+    public void shutdown() {
     }
-  }
-
-  private void connectProfile(BluetoothDevice device, String deviceID) {
-    ParcelUuid[] deviceUuids = device.getUuids();
-    Log.d("Device uuid is " + deviceUuids);
-    mService.registerReceiver(mPairingHelper, mPairingFilter);
-    if (BluetoothUuid.containsAnyUuid(SINK_UUIDS, deviceUuids)) {
-      Log.d("Connecting to " + device.getAliasName());
-      boolean status = mA2dpProfile.a2dpConnect(device);
-      Log.d("Status " + status);
-      if(status) {
-        Log.d("Posting event.");
-        Bundle mResults = new Bundle();
-        mEventFacade.postEvent("A2dpConnected" + deviceID, mResults);
-      }
-    }
-    if (BluetoothUuid.containsAnyUuid(HSP_UUIDS, deviceUuids)) {
-      boolean status = mHspProfile.hspConnect(device);
-      if(status) {
-        Log.d("Posting event.");
-        Bundle mResults = new Bundle();
-        mEventFacade.postEvent("HspConnected" + deviceID, mResults);
-      }
-    }
-    mService.unregisterReceiver(listeningDevices.remove(deviceID));
-    mService.unregisterReceiver(mPairingHelper);
-  }
-
-  @Rpc(description = "Connect to a specified device once it's discovered.",
-       returns = "Whether discovery started successfully.")
-  public Boolean bluetoothDiscoverAndConnect(
-      @RpcParameter(
-          name = "device",
-          description = "Name or MAC address of a bluetooth device.")
-          String device) {
-    if (listeningDevices.containsKey(device)) {
-      Log.d("This device is already in the process of discovery and connecting.");
-      return false;
-    }
-    DiscoverConnectReceiver receiver = new DiscoverConnectReceiver(device);
-    listeningDevices.put(device, receiver);
-    mService.registerReceiver(receiver, mDiscoverConnectFilter);
-    return mBluetoothAdapter.startDiscovery();
-  }
-
-  @Rpc(description = "Bond to a specified device once it's discovered.",
-      returns = "Whether discovery started successfully. ")
-  public Boolean bluetoothDiscoverAndBond(
-      @RpcParameter(
-          name = "device",
-          description = "Name or MAC address of a bluetooth device.")
-          String device) {
-    if (listeningDevices.containsKey(device)) {
-      Log.d("This device is already in the process of discovery and bonding.");
-      return false;
-    }
-    DiscoverConnectReceiver receiver = new DiscoverConnectReceiver(device, true);
-    listeningDevices.put(device, receiver);
-    mService.registerReceiver(receiver, mDiscoverConnectFilter);
-    return mBluetoothAdapter.startDiscovery();
-  }
-
-  @Rpc(description = "Remove bond to a device.",
-      returns = "Whether the device was successfully unbonded.")
-  public Boolean bluetoothUnbond(
-      @RpcParameter(
-          name = "device",
-          description = "Name or MAC address of a bluetooth device.")
-          String device) throws Exception {
-    BluetoothDevice mDevice =
-        BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), device);
-    return mDevice.removeBond();
-  }
-
-  @Rpc(description = "Connect to a device that is already bonded.")
-  public void bluetoothConnectBonded(
-      @RpcParameter(
-          name = "device",
-          description = "Name or MAC address of a bluetooth device.")
-          String device) throws Exception {
-    BluetoothDevice mDevice =
-        BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), device);
-    connectProfile(mDevice, device);
-  }
-
-  @Override
-  public void shutdown() {
-  }
 }
diff --git a/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothFacade.java b/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothFacade.java
index 1f2293e..1d6edf5 100644
--- a/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothFacade.java
+++ b/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothFacade.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Google Inc.
+ * Copyright (C) 2014 Google Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
@@ -23,10 +23,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.Bundle;
 import android.os.ParcelUuid;
 
 import com.googlecode.android_scripting.Log;
 import com.googlecode.android_scripting.MainThread;
+import com.googlecode.android_scripting.facade.EventFacade;
 import com.googlecode.android_scripting.facade.FacadeManager;
 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
 import com.googlecode.android_scripting.rpc.Rpc;
@@ -44,207 +46,232 @@
 
 /**
  * Basic Bluetooth functions.
- *
  */
 @RpcMinSdk(5)
 public class BluetoothFacade extends RpcReceiver {
-  private final Service mService;
-  private final BroadcastReceiver mDiscoveryReceiver;
-  private final IntentFilter discoveryFilter;
-  private Map<String, BluetoothConnection>
-          connections = new HashMap<String, BluetoothConnection>();
-  private BluetoothAdapter mBluetoothAdapter;
+    private final Service mService;
+    private final BroadcastReceiver mDiscoveryReceiver;
+    private final IntentFilter discoveryFilter;
+    private final EventFacade mEventFacade;
+    private Map<String, BluetoothConnection> connections =
+            new HashMap<String, BluetoothConnection>();
+    private BluetoothAdapter mBluetoothAdapter;
 
-  public static ConcurrentHashMap<String, BluetoothDevice> DiscoveredDevices;
+    public static ConcurrentHashMap<String, BluetoothDevice> DiscoveredDevices;
 
-  public BluetoothFacade(FacadeManager manager) {
-    super(manager);
-    mBluetoothAdapter = MainThread.run(manager.getService(), new Callable<BluetoothAdapter>() {
-      @Override
-      public BluetoothAdapter call() throws Exception {
-        return BluetoothAdapter.getDefaultAdapter();
-      }
-    });
-    mService = manager.getService();
+    public BluetoothFacade(FacadeManager manager) {
+        super(manager);
+        mBluetoothAdapter = MainThread.run(manager.getService(), new Callable<BluetoothAdapter>() {
+            @Override
+            public BluetoothAdapter call() throws Exception {
+                return BluetoothAdapter.getDefaultAdapter();
+            }
+        });
+        mEventFacade = manager.getReceiver(EventFacade.class);
+        mService = manager.getService();
 
-    DiscoveredDevices = new ConcurrentHashMap<String, BluetoothDevice>();
-    discoveryFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
-    mDiscoveryReceiver = new DiscoveryCacheReceiver();
-  }
+        DiscoveredDevices = new ConcurrentHashMap<String, BluetoothDevice>();
+        discoveryFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
+        discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
+        mDiscoveryReceiver = new DiscoveryCacheReceiver();
+    }
 
-  class DiscoveryCacheReceiver extends BroadcastReceiver {
-    @Override
-    public void onReceive(Context context, Intent intent) {
-      String action = intent.getAction();
-      if (action.equals(BluetoothDevice.ACTION_FOUND)) {
-        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-        Log.d("Found device " + device.getAliasName());
-        if (!DiscoveredDevices.containsKey(device.getAddress())) {
-          String name = device.getAliasName();
-          if(name != null) {
-            DiscoveredDevices.put(device.getAliasName(), device);
-          }
-          DiscoveredDevices.put(device.getAddress(), device);
+    class DiscoveryCacheReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (action.equals(BluetoothDevice.ACTION_FOUND)) {
+                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+                Log.d("Found device " + device.getAliasName());
+                if (!DiscoveredDevices.containsKey(device.getAddress())) {
+                    String name = device.getAliasName();
+                    if (name != null) {
+                        DiscoveredDevices.put(device.getAliasName(), device);
+                    }
+                    DiscoveredDevices.put(device.getAddress(), device);
+                }
+            } else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
+                mEventFacade.postEvent("BluetoothDiscoveryFinished", new Bundle());
+                mService.unregisterReceiver(mDiscoveryReceiver);
+            }
         }
-      }
     }
-  }
 
-  public static <T> BluetoothDevice getDevice(ConcurrentHashMap<String, T> devices,
-                                              String device)throws Exception {
-    if(devices.containsKey(device)) {
-      return (BluetoothDevice) devices.get(device);
-    }else{
-      throw new Exception("Can't find device " + device);
+    public static boolean deviceMatch(BluetoothDevice device, String deviceID) {
+        return deviceID.equals(device.getAliasName()) || deviceID.equals(device.getAddress());
     }
-  }
 
-  public static BluetoothDevice getDevice(Collection<BluetoothDevice> devices,
-                                          String deviceID) throws Exception {
-    for(BluetoothDevice bd : devices) {
-      if (deviceID.equals(bd.getAliasName()) || deviceID.equals(bd.getAddress())) {
-        Log.d("Found match " + bd.getAliasName() + " " + bd.getAddress());
-        return bd;
-      }
+    public static <T> BluetoothDevice getDevice(ConcurrentHashMap<String, T> devices, String device)
+            throws Exception {
+        if (devices.containsKey(device)) {
+            return (BluetoothDevice) devices.get(device);
+        } else {
+            throw new Exception("Can't find device " + device);
+        }
     }
-    throw new Exception("Can't find device " + deviceID);
-  }
 
-  @Rpc(description = "Requests that the device be discoverable for Bluetooth connections.")
-  public void bluetoothMakeDiscoverable(
-      @RpcParameter(name = "duration",
-      description = "period of time, in seconds, during which the device should be discoverable")
-      @RpcDefault("300")
-      Integer duration) {
-    Log.d("Making discoverable for "+duration+" seconds.\n");
-    mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, duration);
-  }
-
-  @Rpc(description = "Requests that the device be not discoverable.")
-  public void bluetoothMakeUndiscoverable() {
-    Log.d("Making undiscoverable\n");
-    mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_NONE);
-  }
-
-  @Rpc(description = "Queries a remote device for it's name or null if it can't be resolved")
-  public String bluetoothGetRemoteDeviceName(
-      @RpcParameter(name = "address", description = "Bluetooth Address For Target Device")
-      String address) {
-    try {
-      BluetoothDevice mDevice;
-      mDevice = mBluetoothAdapter.getRemoteDevice(address);
-      return mDevice.getName();
-    } catch (Exception e) {
-      return null;
+    public static BluetoothDevice getDevice(Collection<BluetoothDevice> devices, String deviceID)
+            throws Exception {
+        Log.d("Looking for " + deviceID);
+        for (BluetoothDevice bd : devices) {
+            Log.d(bd.getAliasName() + " " + bd.getAddress());
+            if (deviceMatch(bd, deviceID)) {
+                Log.d("Found match " + bd.getAliasName() + " " + bd.getAddress());
+                return bd;
+            }
+        }
+        throw new Exception("Can't find device " + deviceID);
     }
-  }
 
-  @Rpc(description = "Get local Bluetooth device name")
-  public String bluetoothGetLocalName() {
-    return mBluetoothAdapter.getName();
-  }
-
-  @Rpc(description = "Returns the hardware address of the local Bluetooth adapter. ")
-  public String bluetoothGetLocalAddress() {
-    return mBluetoothAdapter.getAddress();
-  }
-
-  @Rpc(description = "Returns the UUIDs supported by local Bluetooth adapter.")
-  public ParcelUuid[] bluetoothGetLocalUuids() {
-    return mBluetoothAdapter.getUuids();
-  }
-
-  @Rpc(description = "Gets the scan mode for the local dongle.\r\n" + "Return values:\r\n"
-      + "\t-1 when Bluetooth is disabled.\r\n" + "\t0 if non discoverable and non connectable.\r\n"
-      + "\r1 connectable non discoverable." + "\r3 connectable and discoverable.")
-  public int bluetoothGetScanMode() {
-    if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF
-        || mBluetoothAdapter.getState() == BluetoothAdapter.STATE_TURNING_OFF) {
-      return -1;
+    public static boolean deviceExists(Collection<BluetoothDevice> devices, String deviceID) {
+        for (BluetoothDevice bd : devices) {
+            if (deviceMatch(bd, deviceID)) {
+                Log.d("Found match " + bd.getAliasName() + " " + bd.getAddress());
+                return true;
+            }
+        }
+        return false;
     }
-    switch (mBluetoothAdapter.getScanMode()) {
-    case BluetoothAdapter.SCAN_MODE_NONE:
-      return 0;
-    case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
-      return 1;
-    case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
-      return 3;
-    default:
-      return mBluetoothAdapter.getScanMode() - 20;
+
+    @Rpc(description = "Requests that the device be discoverable for Bluetooth connections.")
+    public void bluetoothMakeDiscoverable(
+            @RpcParameter(name = "duration",
+                          description = "period of time, in seconds,"
+                                      + "during which the device should be discoverable")
+            @RpcDefault("300")
+            Integer duration) {
+        Log.d("Making discoverable for " + duration + " seconds.\n");
+        mBluetoothAdapter
+                .setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, duration);
     }
-  }
 
-  @Rpc(description = "Return the set of BluetoothDevice that are paired to the local adapter.")
-  public Set<BluetoothDevice> bluetoothGetBondedDevices() {
-    return mBluetoothAdapter.getBondedDevices();
-  }
-
-  @Rpc(description = "Checks Bluetooth state.", returns = "True if Bluetooth is enabled.")
-  public Boolean bluetoothCheckState() {
-    return mBluetoothAdapter.isEnabled();
-  }
-
-  @Rpc(description = "Sets the Bluetooth visible device name", returns = "true on success")
-  public boolean bluetoothSetLocalName(
-      @RpcParameter(name = "name", description = "New local name") String name) {
-    return mBluetoothAdapter.setName(name);
-  }
-
-  @Rpc(description = "Toggle Bluetooth on and off.", returns = "True if Bluetooth is enabled.")
-  public Boolean bluetoothToggleState(
-      @RpcParameter(name = "enabled") @RpcOptional
-      Boolean enabled,
-      @RpcParameter(name = "prompt",
-                    description = "Prompt the user to confirm changing the Bluetooth state.")
-      @RpcDefault("false")
-      Boolean prompt
-      ) {
-    if (enabled == null) {
-      enabled = !bluetoothCheckState();
+    @Rpc(description = "Requests that the device be not discoverable.")
+    public void bluetoothMakeUndiscoverable() {
+        Log.d("Making undiscoverable\n");
+        mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_NONE);
     }
-    if (enabled) {
-      // TODO(damonkohler): Make this synchronous as well.
-      mBluetoothAdapter.enable();
-    } else {
-      // TODO(damonkohler): Add support for prompting on disable.
-      // TODO(damonkohler): Make this synchronous as well.
-      shutdown();
-      mBluetoothAdapter.disable();
+
+    @Rpc(description = "Queries a remote device for it's name or null if it can't be resolved")
+    public String bluetoothGetRemoteDeviceName(
+            @RpcParameter(name = "address", description = "Bluetooth Address For Target Device")
+            String address) {
+        try {
+            BluetoothDevice mDevice;
+            mDevice = mBluetoothAdapter.getRemoteDevice(address);
+            return mDevice.getName();
+        } catch (Exception e) {
+            return null;
+        }
     }
-    return enabled;
-  }
 
-  @Rpc(description = "Start the remote device discovery process. ",
-       returns = "true on success, false on error")
-  public Boolean bluetoothStartDiscovery() {
-    mService.registerReceiver(mDiscoveryReceiver, discoveryFilter);
-    return mBluetoothAdapter.startDiscovery();
-  }
-
-  @Rpc(description = "Cancel the current device discovery process.",
-       returns = "true on success, false on error")
-  public Boolean bluetoothCancelDiscovery() {
-    mService.unregisterReceiver(mDiscoveryReceiver);
-    return mBluetoothAdapter.cancelDiscovery();
-  }
-
-  @Rpc(description =
-       "If the local Bluetooth adapter is currently in the device discovery process.")
-  public Boolean bluetoothIsDiscovering() {
-    return mBluetoothAdapter.isDiscovering();
-  }
-
-  @Rpc(description = "Get all the discovered bluetooth devices.")
-  public Collection<BluetoothDevice> bluetoothGetDiscoveredDevices() {
-    while(bluetoothIsDiscovering());
-    return DiscoveredDevices.values();
-  }
-
-  @Override
-  public void shutdown() {
-    for (Map.Entry<String, BluetoothConnection> entry : connections.entrySet()) {
-      entry.getValue().stop();
+    @Rpc(description = "Get local Bluetooth device name")
+    public String bluetoothGetLocalName() {
+        return mBluetoothAdapter.getName();
     }
-    connections.clear();
-  }
+
+    @Rpc(description = "Returns the hardware address of the local Bluetooth adapter. ")
+    public String bluetoothGetLocalAddress() {
+        return mBluetoothAdapter.getAddress();
+    }
+
+    @Rpc(description = "Returns the UUIDs supported by local Bluetooth adapter.")
+    public ParcelUuid[] bluetoothGetLocalUuids() {
+        return mBluetoothAdapter.getUuids();
+    }
+
+    @Rpc(description = "Gets the scan mode for the local dongle.\r\n" + "Return values:\r\n"
+            + "\t-1 when Bluetooth is disabled.\r\n"
+            + "\t0 if non discoverable and non connectable.\r\n"
+            + "\r1 connectable non discoverable." + "\r3 connectable and discoverable.")
+    public int bluetoothGetScanMode() {
+        if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF
+                || mBluetoothAdapter.getState() == BluetoothAdapter.STATE_TURNING_OFF) {
+            return -1;
+        }
+        switch (mBluetoothAdapter.getScanMode()) {
+            case BluetoothAdapter.SCAN_MODE_NONE:
+                return 0;
+            case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
+                return 1;
+            case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
+                return 3;
+            default:
+                return mBluetoothAdapter.getScanMode() - 20;
+        }
+    }
+
+    @Rpc(description = "Return the set of BluetoothDevice that are paired to the local adapter.")
+    public Set<BluetoothDevice> bluetoothGetBondedDevices() {
+        return mBluetoothAdapter.getBondedDevices();
+    }
+
+    @Rpc(description = "Checks Bluetooth state.", returns = "True if Bluetooth is enabled.")
+    public Boolean bluetoothCheckState() {
+        return mBluetoothAdapter.isEnabled();
+    }
+
+    @Rpc(description = "Sets the Bluetooth visible device name", returns = "true on success")
+    public boolean bluetoothSetLocalName(@RpcParameter(name = "name",
+                                                       description = "New local name")
+    String name) {
+        return mBluetoothAdapter.setName(name);
+    }
+
+    @Rpc(description = "Toggle Bluetooth on and off.", returns = "True if Bluetooth is enabled.")
+    public Boolean bluetoothToggleState(@RpcParameter(name = "enabled")
+    @RpcOptional
+    Boolean enabled,
+            @RpcParameter(name = "prompt",
+                          description = "Prompt the user to confirm changing the Bluetooth state.")
+            @RpcDefault("false")
+            Boolean prompt) {
+        if (enabled == null) {
+            enabled = !bluetoothCheckState();
+        }
+        if (enabled) {
+            // TODO(damonkohler): Make this synchronous as well.
+            mBluetoothAdapter.enable();
+        } else {
+            // TODO(damonkohler): Add support for prompting on disable.
+            // TODO(damonkohler): Make this synchronous as well.
+            shutdown();
+            mBluetoothAdapter.disable();
+        }
+        return enabled;
+    }
+
+    @Rpc(description = "Start the remote device discovery process. ",
+         returns = "true on success, false on error")
+    public Boolean bluetoothStartDiscovery() {
+        mService.registerReceiver(mDiscoveryReceiver, discoveryFilter);
+        return mBluetoothAdapter.startDiscovery();
+    }
+
+    @Rpc(description = "Cancel the current device discovery process.",
+         returns = "true on success, false on error")
+    public Boolean bluetoothCancelDiscovery() {
+        mService.unregisterReceiver(mDiscoveryReceiver);
+        return mBluetoothAdapter.cancelDiscovery();
+    }
+
+    @Rpc(description = "If the local Bluetooth adapter is currently"
+                     + "in the device discovery process.")
+    public Boolean bluetoothIsDiscovering() {
+        return mBluetoothAdapter.isDiscovering();
+    }
+
+    @Rpc(description = "Get all the discovered bluetooth devices.")
+    public Collection<BluetoothDevice> bluetoothGetDiscoveredDevices() {
+        while (bluetoothIsDiscovering())
+            ;
+        return DiscoveredDevices.values();
+    }
+
+    @Override
+    public void shutdown() {
+        for (Map.Entry<String, BluetoothConnection> entry : connections.entrySet()) {
+            entry.getValue().stop();
+        }
+        connections.clear();
+    }
 }
diff --git a/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothHspFacade.java b/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothHspFacade.java
index 2e87b09..2b35e90 100644
--- a/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothHspFacade.java
+++ b/Common/src/com/googlecode/android_scripting/bluetooth/BluetoothHspFacade.java
@@ -1,5 +1,7 @@
 package com.googlecode.android_scripting.bluetooth;
 
+import java.util.List;
+
 import android.app.Service;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
@@ -14,12 +16,9 @@
 import com.googlecode.android_scripting.rpc.Rpc;
 import com.googlecode.android_scripting.rpc.RpcParameter;
 
-
 public class BluetoothHspFacade extends RpcReceiver {
-  static final ParcelUuid[] HSP_UUIDS = {
-    BluetoothUuid.HSP,
-    BluetoothUuid.Handsfree,
-  };
+  static final ParcelUuid[] HSP_UUIDS = { BluetoothUuid.HSP,
+      BluetoothUuid.Handsfree, };
 
   private final Service mService;
   private final BluetoothAdapter mBluetoothAdapter;
@@ -31,7 +30,8 @@
     super(manager);
     mService = manager.getService();
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-    mBluetoothAdapter.getProfileProxy(mService, new HspServiceListener(), BluetoothProfile.HEADSET);
+    mBluetoothAdapter.getProfileProxy(mService, new HspServiceListener(),
+        BluetoothProfile.HEADSET);
   }
 
   class HspServiceListener implements BluetoothProfile.ServiceListener {
@@ -40,6 +40,7 @@
       mHspProfile = (BluetoothHeadset) proxy;
       mIsHspReady = true;
     }
+
     @Override
     public void onServiceDisconnected(int profile) {
       mIsHspReady = false;
@@ -57,34 +58,41 @@
     return mHspProfile.disconnect(device);
   }
 
-  @Rpc(description="Is Hsp profile ready.")
+  @Rpc(description = "Is Hsp profile ready.")
   public Boolean bluetoothHspIsReady() {
     return mIsHspReady;
   }
 
-  @Rpc(description="Connect to HSP device.")
+  @Rpc(description = "Connect to HSP device.")
   public Boolean bluetoothHspConnect(
-      @RpcParameter(
-          name = "device",
-          description = "Name or MAC address of a bluetooth device.")
-          String device) throws Exception {
-    if (mHspProfile == null) return false;
-    BluetoothDevice mDevice = BluetoothFacade.getDevice(BluetoothFacade.DiscoveredDevices, device);
+      @RpcParameter(name = "device", description = "Name or MAC address of a bluetooth device.")
+      String device)
+      throws Exception {
+    if (mHspProfile == null)
+      return false;
+    BluetoothDevice mDevice = BluetoothFacade.getDevice(
+        BluetoothFacade.DiscoveredDevices, device);
     Log.d("Connecting to device " + mDevice.getAliasName());
     return hspConnect(mDevice);
   }
 
-  @Rpc(description="Disconnect an HSP device.")
+  @Rpc(description = "Disconnect an HSP device.")
   public Boolean bluetoothHspDisconnect(
-      @RpcParameter(
-          name = "device",
-          description = "Name or MAC address of a bluetooth device.")
-          String device) throws Exception {
-    if (mHspProfile == null) return false;
-    BluetoothDevice mDevice = BluetoothFacade.getDevice(mHspProfile.getConnectedDevices(), device);
+      @RpcParameter(name = "device", description = "Name or MAC address of a bluetooth device.")
+      String device)
+      throws Exception {
+    if (mHspProfile == null)
+      return false;
+    BluetoothDevice mDevice = BluetoothFacade.getDevice(
+        mHspProfile.getConnectedDevices(), device);
     return hspDisconnect(mDevice);
   }
 
+  @Rpc(description = "Return the list of devices connected through Hsp.")
+  public List<BluetoothDevice> bluetoothHspGetConnectedDevices() {
+    return mHspProfile.getConnectedDevices();
+  }
+
   @Override
   public void shutdown() {
   }
diff --git a/Common/src/com/googlecode/android_scripting/facade/MediaPlayerFacade.java b/Common/src/com/googlecode/android_scripting/facade/MediaPlayerFacade.java
index 6468925..2fbebb1 100644
--- a/Common/src/com/googlecode/android_scripting/facade/MediaPlayerFacade.java
+++ b/Common/src/com/googlecode/android_scripting/facade/MediaPlayerFacade.java
@@ -108,7 +108,7 @@
   }

 

   @Rpc(description = "Open a media file", returns = "true if play successful")

-  public synchronized boolean mediaPlay(

+  public synchronized boolean mediaPlayOpen(

       @RpcParameter(name = "url", description = "url of media resource") String url,

       @RpcParameter(name = "tag", description = "string identifying resource") @RpcDefault(value = "default") String tag,

       @RpcParameter(name = "play", description = "start playing immediately") @RpcDefault(value = "true") Boolean play) {