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 java.util.List; 20 21 import android.app.Service; 22 import android.bluetooth.BluetoothInputDevice; 23 import android.bluetooth.BluetoothAdapter; 24 import android.bluetooth.BluetoothDevice; 25 import android.bluetooth.BluetoothProfile; 26 import android.bluetooth.BluetoothUuid; 27 import android.os.ParcelUuid; 28 29 import com.googlecode.android_scripting.Log; 30 import com.googlecode.android_scripting.facade.FacadeManager; 31 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 32 import com.googlecode.android_scripting.rpc.Rpc; 33 import com.googlecode.android_scripting.rpc.RpcDefault; 34 import com.googlecode.android_scripting.rpc.RpcParameter; 35 36 public class BluetoothHidFacade extends RpcReceiver { 37 public final static ParcelUuid[] UUIDS = { BluetoothUuid.Hid }; 38 39 private final Service mService; 40 private final BluetoothAdapter mBluetoothAdapter; 41 42 private static boolean sIsHidReady = false; 43 private static BluetoothInputDevice sHidProfile = null; 44 45 public BluetoothHidFacade(FacadeManager manager) { 46 super(manager); 47 mService = manager.getService(); 48 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 49 mBluetoothAdapter.getProfileProxy(mService, new HidServiceListener(), 50 BluetoothProfile.INPUT_DEVICE); 51 } 52 53 class HidServiceListener implements BluetoothProfile.ServiceListener { 54 @Override 55 public void onServiceConnected(int profile, BluetoothProfile proxy) { 56 sHidProfile = (BluetoothInputDevice) proxy; 57 sIsHidReady = true; 58 } 59 60 @Override 61 public void onServiceDisconnected(int profile) { 62 sIsHidReady = false; 63 } 64 } 65 66 public Boolean hidConnect(BluetoothDevice device) { 67 if (sHidProfile == null) return false; 68 return sHidProfile.connect(device); 69 } 70 71 public Boolean hidDisconnect(BluetoothDevice device) { 72 if (sHidProfile == null) return false; 73 return sHidProfile.disconnect(device); 74 } 75 76 @Rpc(description = "Is Hid profile ready.") 77 public Boolean bluetoothHidIsReady() { 78 return sIsHidReady; 79 } 80 81 @Rpc(description = "Connect to an HID device.") 82 public Boolean bluetoothHidConnect( 83 @RpcParameter(name = "device", description = "Name or MAC address of a bluetooth device.") 84 String device) 85 throws Exception { 86 if (sHidProfile == null) 87 return false; 88 BluetoothDevice mDevice = BluetoothFacade.getDevice(BluetoothFacade.DiscoveredDevices, device); 89 Log.d("Connecting to device " + mDevice.getAliasName()); 90 return hidConnect(mDevice); 91 } 92 93 @Rpc(description = "Disconnect an HID device.") 94 public Boolean bluetoothHidDisconnect( 95 @RpcParameter(name = "device", description = "Name or MAC address of a device.") 96 String device) 97 throws Exception { 98 if (sHidProfile == null) 99 return false; 100 Log.d("Connected devices: " + sHidProfile.getConnectedDevices()); 101 BluetoothDevice mDevice = BluetoothFacade.getDevice(sHidProfile.getConnectedDevices(), 102 device); 103 return hidDisconnect(mDevice); 104 } 105 106 @Rpc(description = "Get all the devices connected through HID.") 107 public List<BluetoothDevice> bluetoothHidGetConnectedDevices() { 108 while (!sIsHidReady); 109 return sHidProfile.getConnectedDevices(); 110 } 111 112 @Rpc(description = "Get the connection status of a device.") 113 public Integer bluetoothHidGetConnectionStatus( 114 @RpcParameter(name = "deviceID", 115 description = "Name or MAC address of a bluetooth device.") 116 String deviceID) { 117 if (sHidProfile == null) { 118 return BluetoothProfile.STATE_DISCONNECTED; 119 } 120 List<BluetoothDevice> deviceList = sHidProfile.getConnectedDevices(); 121 BluetoothDevice device; 122 try { 123 device = BluetoothFacade.getDevice(deviceList, deviceID); 124 } catch (Exception e) { 125 return BluetoothProfile.STATE_DISCONNECTED; 126 } 127 return sHidProfile.getConnectionState(device); 128 } 129 130 @Rpc(description = "Send Set_Report command to the connected HID input device.") 131 public Boolean bluetoothHidSetReport( 132 @RpcParameter(name = "deviceID", 133 description = "Name or MAC address of a bluetooth device.") 134 String deviceID, 135 @RpcParameter(name = "type") 136 @RpcDefault(value = "1") 137 String type, 138 @RpcParameter(name = "report") 139 String report) throws Exception { 140 BluetoothDevice device = BluetoothFacade.getDevice(sHidProfile.getConnectedDevices(), 141 deviceID); 142 Log.d("type " + type.getBytes()[0]); 143 return sHidProfile.setReport(device, type.getBytes()[0], report); 144 } 145 146 @Rpc(description = "Send Get_Report command to the connected HID input device.") 147 public Boolean bluetoothHidGetReport( 148 @RpcParameter(name = "deviceID", 149 description = "Name or MAC address of a bluetooth device.") 150 String deviceID, 151 @RpcParameter(name = "type") 152 @RpcDefault(value = "1") 153 String type, 154 @RpcParameter(name = "reportId") 155 String reportId, 156 @RpcParameter(name = "buffSize") 157 Integer buffSize) throws Exception { 158 BluetoothDevice device = BluetoothFacade.getDevice(sHidProfile.getConnectedDevices(), 159 deviceID); 160 Log.d("type " + type.getBytes()[0] + "reportId " + reportId.getBytes()[0]); 161 return sHidProfile.getReport(device, type.getBytes()[0], reportId.getBytes()[0], buffSize); 162 } 163 164 @Rpc(description = "Send data to a connected HID device.") 165 public Boolean bluetoothHidSendData( 166 @RpcParameter(name = "deviceID", 167 description = "Name or MAC address of a bluetooth device.") 168 String deviceID, 169 @RpcParameter(name = "report") 170 String report) throws Exception { 171 BluetoothDevice device = BluetoothFacade.getDevice(sHidProfile.getConnectedDevices(), 172 deviceID); 173 return sHidProfile.sendData(device, report); 174 } 175 176 @Rpc(description = "Send virtual unplug to a connected HID device.") 177 public Boolean bluetoothHidVirtualUnplug( 178 @RpcParameter(name = "deviceID", 179 description = "Name or MAC address of a bluetooth device.") 180 String deviceID) throws Exception { 181 BluetoothDevice device = BluetoothFacade.getDevice(sHidProfile.getConnectedDevices(), 182 deviceID); 183 return sHidProfile.virtualUnplug(device); 184 } 185 186 @Rpc(description = "Test byte transfer.") 187 public byte[] testByte() { 188 byte[] bts = {0b01,0b10,0b11,0b100}; 189 return bts; 190 } 191 192 @Override 193 public void shutdown() { 194 } 195 } 196