1 package com.github.google.bumble.remotehci; 2 3 import android.os.RemoteException; 4 import android.util.Log; 5 6 import java.io.IOException; 7 8 public class HciProxy { 9 private static final String TAG = "HciProxy"; 10 private final HciServer mServer; 11 private final Listener mListener; 12 private int mCommandPacketsReceived; 13 private int mAclPacketsReceived; 14 private int mScoPacketsReceived; 15 private int mEventPacketsSent; 16 private int mAclPacketsSent; 17 private int mScoPacketsSent; 18 HciProxy(int port, Listener listener)19 HciProxy(int port, Listener listener) throws HalException { 20 this.mListener = listener; 21 22 // Instantiate a HAL to communicate with the hardware. 23 HciHal hciHal = HciHal.create(new HciHalCallback() { 24 @Override 25 public void onPacket(HciPacket.Type type, byte[] packet) { 26 mServer.sendPacket(type, packet); 27 28 switch (type) { 29 case EVENT: 30 mEventPacketsSent += 1; 31 break; 32 33 case ACL_DATA: 34 mAclPacketsSent += 1; 35 break; 36 37 case SCO_DATA: 38 mScoPacketsSent += 1; 39 break; 40 } 41 updateHciPacketCount(); 42 } 43 }); 44 if (hciHal == null) { 45 String message = "Could not instantiate a HAL instance"; 46 Log.w(TAG, message); 47 throw new HalException(message); 48 } 49 50 // Initialize the HAL. 51 HciHal.Status status = null; 52 try { 53 status = hciHal.initialize(); 54 } catch (RemoteException | InterruptedException e) { 55 throw new HalException("Exception while initializing"); 56 } 57 if (status != HciHal.Status.SUCCESS) { 58 String message = "HAL initialization failed: " + status.label; 59 Log.w(TAG, message); 60 throw new HalException(message); 61 } 62 63 // Create a server to accept clients. 64 mServer = new HciServer(port, new HciServer.Listener() { 65 @Override 66 public void onHostConnectionState(boolean connected) { 67 mListener.onHostConnectionState(connected); 68 if (connected) { 69 mCommandPacketsReceived = 0; 70 mAclPacketsReceived = 0; 71 mScoPacketsReceived = 0; 72 mEventPacketsSent = 0; 73 mAclPacketsSent = 0; 74 mScoPacketsSent = 0; 75 updateHciPacketCount(); 76 } 77 } 78 79 @Override 80 public void onMessage(String message) { 81 listener.onMessage(message); 82 } 83 84 @Override 85 public void onPacket(HciPacket.Type type, byte[] packet) { 86 Log.d(TAG, String.format("onPacket: type=%s, size=%d", type, packet.length)); 87 hciHal.sendPacket(type, packet); 88 89 switch (type) { 90 case COMMAND: 91 mCommandPacketsReceived += 1; 92 break; 93 94 case ACL_DATA: 95 mAclPacketsReceived += 1; 96 break; 97 98 case SCO_DATA: 99 mScoPacketsReceived += 1; 100 break; 101 } 102 updateHciPacketCount(); 103 } 104 }); 105 } 106 run()107 public void run() throws IOException { 108 mServer.run(); 109 } 110 updateHciPacketCount()111 private void updateHciPacketCount() { 112 mListener.onHciPacketCountChange( 113 mCommandPacketsReceived, 114 mAclPacketsReceived, 115 mScoPacketsReceived, 116 mEventPacketsSent, 117 mAclPacketsSent, 118 mScoPacketsSent 119 ); 120 } 121 122 public interface Listener { onHostConnectionState(boolean connected)123 void onHostConnectionState(boolean connected); 124 onHciPacketCountChange( int commandPacketsReceived, int aclPacketsReceived, int scoPacketsReceived, int eventPacketsSent, int aclPacketsSent, int scoPacketsSent )125 void onHciPacketCountChange( 126 int commandPacketsReceived, 127 int aclPacketsReceived, 128 int scoPacketsReceived, 129 int eventPacketsSent, 130 int aclPacketsSent, 131 int scoPacketsSent 132 ); 133 onMessage(String message)134 void onMessage(String message); 135 } 136 137 public static class HalException extends RuntimeException { 138 public final String message; HalException(String message)139 public HalException(String message) { 140 this.message = message; 141 } 142 } 143 } 144