Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.googlecode.android_scripting.facade.bluetooth;
     18 
     19 import android.app.Service;
     20 import android.bluetooth.BluetoothAdapter;
     21 import android.bluetooth.BluetoothDevice;
     22 import android.bluetooth.BluetoothHeadset;
     23 import android.bluetooth.BluetoothProfile;
     24 import android.bluetooth.BluetoothUuid;
     25 import android.os.ParcelUuid;
     26 
     27 import com.googlecode.android_scripting.Log;
     28 import com.googlecode.android_scripting.facade.FacadeManager;
     29 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
     30 import com.googlecode.android_scripting.rpc.Rpc;
     31 import com.googlecode.android_scripting.rpc.RpcParameter;
     32 
     33 import java.util.List;
     34 
     35 public class BluetoothHspFacade extends RpcReceiver {
     36   static final ParcelUuid[] UUIDS = {
     37     BluetoothUuid.HSP, BluetoothUuid.Handsfree
     38   };
     39 
     40   private final Service mService;
     41   private final BluetoothAdapter mBluetoothAdapter;
     42 
     43   private static boolean sIsHspReady = false;
     44   private static BluetoothHeadset sHspProfile = null;
     45 
     46   public BluetoothHspFacade(FacadeManager manager) {
     47     super(manager);
     48     mService = manager.getService();
     49     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
     50     mBluetoothAdapter.getProfileProxy(mService, new HspServiceListener(),
     51         BluetoothProfile.HEADSET);
     52   }
     53 
     54   class HspServiceListener implements BluetoothProfile.ServiceListener {
     55     @Override
     56     public void onServiceConnected(int profile, BluetoothProfile proxy) {
     57       sHspProfile = (BluetoothHeadset) proxy;
     58       sIsHspReady = true;
     59     }
     60 
     61     @Override
     62     public void onServiceDisconnected(int profile) {
     63       sIsHspReady = false;
     64     }
     65   }
     66 
     67   public Boolean hspConnect(BluetoothDevice device) {
     68     if (sHspProfile == null) return false;
     69     return sHspProfile.connect(device);
     70   }
     71 
     72   public Boolean hspDisconnect(BluetoothDevice device) {
     73     if (sHspProfile == null) return false;
     74     return sHspProfile.disconnect(device);
     75   }
     76 
     77   @Rpc(description = "Is Hsp profile ready.")
     78   public Boolean bluetoothHspIsReady() {
     79     return sIsHspReady;
     80   }
     81 
     82   @Rpc(description = "Set priority of the profile")
     83   public void bluetoothHspSetPriority(
     84       @RpcParameter(name = "device", description = "Mac address of a BT device.")
     85       String deviceStr,
     86       @RpcParameter(name = "priority", description = "Priority that needs to be set.")
     87       Integer priority)
     88       throws Exception {
     89     if (sHspProfile == null) return;
     90     BluetoothDevice device =
     91         BluetoothFacade.getDevice(mBluetoothAdapter.getBondedDevices(), deviceStr);
     92     Log.d("Changing priority of device " + device.getAliasName() + " p: " + priority);
     93     sHspProfile.setPriority(device, priority);
     94   }
     95 
     96   @Rpc(description = "Connect to an HSP device.")
     97   public Boolean bluetoothHspConnect(
     98       @RpcParameter(name = "device", description = "Name or MAC address of a bluetooth device.")
     99       String device)
    100       throws Exception {
    101     if (sHspProfile == null)
    102       return false;
    103     BluetoothDevice mDevice = BluetoothFacade.getDevice(BluetoothFacade.DiscoveredDevices, device);
    104     Log.d("Connecting to device " + mDevice.getAliasName());
    105     return hspConnect(mDevice);
    106   }
    107 
    108   @Rpc(description = "Disconnect an HSP device.")
    109   public Boolean bluetoothHspDisconnect(
    110       @RpcParameter(name = "device", description = "Name or MAC address of a device.")
    111       String device)
    112       throws Exception {
    113     if (sHspProfile == null)
    114       return false;
    115     Log.d("Connected devices: " + sHspProfile.getConnectedDevices());
    116     BluetoothDevice mDevice = BluetoothFacade.getDevice(sHspProfile.getConnectedDevices(),
    117                                                         device);
    118     return hspDisconnect(mDevice);
    119   }
    120 
    121   @Rpc(description = "Get all the devices connected through HSP.")
    122   public List<BluetoothDevice> bluetoothHspGetConnectedDevices() {
    123     while (!sIsHspReady);
    124     return sHspProfile.getConnectedDevices();
    125   }
    126 
    127   @Rpc(description = "Get the connection status of a device.")
    128   public Integer bluetoothHspGetConnectionStatus(
    129           @RpcParameter(name = "deviceID",
    130                         description = "Name or MAC address of a bluetooth device.")
    131           String deviceID) {
    132       if (sHspProfile == null) {
    133           return BluetoothProfile.STATE_DISCONNECTED;
    134       }
    135       List<BluetoothDevice> deviceList = sHspProfile.getConnectedDevices();
    136       BluetoothDevice device;
    137       try {
    138           device = BluetoothFacade.getDevice(deviceList, deviceID);
    139       } catch (Exception e) {
    140           return BluetoothProfile.STATE_DISCONNECTED;
    141       }
    142       return sHspProfile.getConnectionState(device);
    143   }
    144 
    145   /**
    146    * Force SCO audio on DUT, ignore all other restrictions
    147    *
    148    * @param force True to force SCO audio, False to resume normal
    149    * @return True if the setup is successful
    150    */
    151   @Rpc(description = "Force SCO audio connection on DUT")
    152   public Boolean bluetoothHspForceScoAudio(
    153           @RpcParameter(name = "force", description = "whether to force SCO audio")
    154                   Boolean force) {
    155     if (sHspProfile == null) {
    156       return false;
    157     }
    158     sHspProfile.setForceScoAudio(force);
    159     return true;
    160   }
    161 
    162   /**
    163    * Connect SCO audio to a remote device
    164    *
    165    * @param deviceAddress the Bluetooth MAC address of remote device
    166    * @return True if connection is successful, False otherwise
    167    */
    168   @Rpc(description = "Connect SCO audio for a remote device")
    169   public Boolean bluetoothHspConnectAudio(
    170           @RpcParameter(name = "deviceAddress", description = "MAC address of a bluetooth device.")
    171                   String deviceAddress) {
    172     if (sHspProfile == null) {
    173       return false;
    174     }
    175     Log.d("Connected devices: " + sHspProfile.getConnectedDevices());
    176     BluetoothDevice device = null;
    177     if (sHspProfile.getConnectedDevices().size() > 1) {
    178       Log.d("More than one device available");
    179     }
    180     try {
    181       device = BluetoothFacade.getDevice(sHspProfile.getConnectedDevices(), deviceAddress);
    182     } catch (Exception e) {
    183       Log.d("Cannot find device " + deviceAddress);
    184       return false;
    185     }
    186     return sHspProfile.connectAudio();
    187   }
    188 
    189   /**
    190    * Disconnect SCO audio for a remote device
    191    *
    192    * @param deviceAddress the Bluetooth MAC address of remote device
    193    * @return True if disconnection is successful, False otherwise
    194    */
    195   @Rpc(description = "Disconnect SCO audio for a remote device")
    196   public Boolean bluetoothHspDisconnectAudio(
    197           @RpcParameter(name = "deviceAddress", description = "MAC address of a bluetooth device.")
    198                   String deviceAddress) {
    199     if (sHspProfile == null) {
    200       return false;
    201     }
    202     Log.d("Connected devices: " + sHspProfile.getConnectedDevices());
    203     BluetoothDevice device = null;
    204     if (sHspProfile.getConnectedDevices().size() > 1) {
    205       Log.d("More than one device available");
    206     }
    207     try {
    208       device = BluetoothFacade.getDevice(sHspProfile.getConnectedDevices(), deviceAddress);
    209     } catch (Exception e) {
    210       Log.d("Cannot find device " + deviceAddress);
    211       return false;
    212     }
    213     if (!sHspProfile.isAudioConnected(device)) {
    214       Log.d("SCO audio is not connected for device " + deviceAddress);
    215       return false;
    216     }
    217     return sHspProfile.disconnectAudio();
    218   }
    219 
    220   /**
    221    * Check if SCO audio is connected for a remote device
    222    *
    223    * @param deviceAddress the Bluetooth MAC address of remote device
    224    * @return True if device is connected to us via SCO audio, False otherwise
    225    */
    226   @Rpc(description = "Check if SCO audio is connected for a remote device")
    227   public Boolean bluetoothHspIsAudioConnected(
    228           @RpcParameter(name = "deviceAddress", description = "MAC address of a bluetooth device.")
    229                   String deviceAddress) {
    230     if (sHspProfile == null) {
    231       return false;
    232     }
    233     Log.d("Connected devices: " + sHspProfile.getConnectedDevices());
    234     BluetoothDevice device = null;
    235     if (sHspProfile.getConnectedDevices().size() > 1) {
    236       Log.d("More than one device available");
    237     }
    238     try {
    239       device = BluetoothFacade.getDevice(sHspProfile.getConnectedDevices(), deviceAddress);
    240     } catch (Exception e) {
    241       Log.d("Cannot find device " + deviceAddress);
    242       return false;
    243     }
    244     return sHspProfile.isAudioConnected(device);
    245   }
    246 
    247   @Override
    248   public void shutdown() {
    249   }
    250 }
    251