1 /*
2  * Copyright (C) 2016 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * 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 
BluetoothHidFacade(FacadeManager manager)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
onServiceConnected(int profile, BluetoothProfile proxy)55     public void onServiceConnected(int profile, BluetoothProfile proxy) {
56       sHidProfile = (BluetoothInputDevice) proxy;
57       sIsHidReady = true;
58     }
59 
60     @Override
onServiceDisconnected(int profile)61     public void onServiceDisconnected(int profile) {
62       sIsHidReady = false;
63     }
64   }
65 
hidConnect(BluetoothDevice device)66   public Boolean hidConnect(BluetoothDevice device) {
67     if (sHidProfile == null) return false;
68     return sHidProfile.connect(device);
69   }
70 
hidDisconnect(BluetoothDevice device)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.")
bluetoothHidIsReady()77   public Boolean bluetoothHidIsReady() {
78     return sIsHidReady;
79   }
80 
81   @Rpc(description = "Connect to an HID device.")
bluetoothHidConnect( @pcParametername = "device", description = "Name or MAC address of a bluetooth device.") String 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.")
bluetoothHidDisconnect( @pcParametername = "device", description = "Name or MAC address of a device.") String 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.")
bluetoothHidGetConnectedDevices()107   public List<BluetoothDevice> bluetoothHidGetConnectedDevices() {
108     while (!sIsHidReady);
109     return sHidProfile.getConnectedDevices();
110   }
111 
112   @Rpc(description = "Get the connection status of a device.")
bluetoothHidGetConnectionStatus( @pcParametername = "deviceID", description = "Name or MAC address of a bluetooth device.") String deviceID)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.")
bluetoothHidSetReport( @pcParametername = "deviceID", description = "Name or MAC address of a bluetooth device.") String deviceID, @RpcParameter(name = "type") @RpcDefault(value = "1") String type, @RpcParameter(name = "report") String report)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.")
bluetoothHidGetReport( @pcParametername = "deviceID", description = "Name or MAC address of a bluetooth device.") String deviceID, @RpcParameter(name = "type") @RpcDefault(value = "1") String type, @RpcParameter(name = "reportId") String reportId, @RpcParameter(name = "buffSize") Integer buffSize)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.")
bluetoothHidSendData( @pcParametername = "deviceID", description = "Name or MAC address of a bluetooth device.") String deviceID, @RpcParameter(name = "report") String report)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.")
bluetoothHidVirtualUnplug( @pcParametername = "deviceID", description = "Name or MAC address of a bluetooth device.") String deviceID)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.")
testByte()187   public byte[] testByte() {
188       byte[] bts = {0b01,0b10,0b11,0b100};
189       return bts;
190   }
191 
192   @Override
shutdown()193   public void shutdown() {
194   }
195 }
196