1 /* 2 * Copyright 2023 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.android.bluetooth.hid; 18 19 import android.util.Log; 20 21 import com.android.internal.annotations.GuardedBy; 22 import com.android.internal.annotations.VisibleForTesting; 23 24 /** Provides Bluetooth Hid Host profile, as a service in the Bluetooth application. */ 25 public class HidHostNativeInterface { 26 private static final String TAG = HidHostNativeInterface.class.getSimpleName(); 27 28 private HidHostService mHidHostService; 29 30 @GuardedBy("INSTANCE_LOCK") 31 private static HidHostNativeInterface sInstance; 32 33 private static final Object INSTANCE_LOCK = new Object(); 34 getInstance()35 static HidHostNativeInterface getInstance() { 36 synchronized (INSTANCE_LOCK) { 37 if (sInstance == null) { 38 sInstance = new HidHostNativeInterface(); 39 } 40 return sInstance; 41 } 42 } 43 44 /** Set singleton instance. */ 45 @VisibleForTesting setInstance(HidHostNativeInterface instance)46 public static void setInstance(HidHostNativeInterface instance) { 47 synchronized (INSTANCE_LOCK) { 48 sInstance = instance; 49 } 50 } 51 init(HidHostService service)52 void init(HidHostService service) { 53 mHidHostService = service; 54 initializeNative(); 55 } 56 cleanup()57 void cleanup() { 58 cleanupNative(); 59 } 60 connectHid(byte[] address, int addressType, int transport)61 boolean connectHid(byte[] address, int addressType, int transport) { 62 return connectHidNative(address, addressType, transport); 63 } 64 disconnectHid( byte[] address, int addressType, int transport, boolean reconnectAllowed)65 boolean disconnectHid( 66 byte[] address, int addressType, int transport, boolean reconnectAllowed) { 67 return disconnectHidNative(address, addressType, transport, reconnectAllowed); 68 } 69 getProtocolMode(byte[] address, int addressType, int transport)70 boolean getProtocolMode(byte[] address, int addressType, int transport) { 71 return getProtocolModeNative(address, addressType, transport); 72 } 73 virtualUnPlug(byte[] address, int addressType, int transport)74 boolean virtualUnPlug(byte[] address, int addressType, int transport) { 75 return virtualUnPlugNative(address, addressType, transport); 76 } 77 setProtocolMode(byte[] address, int addressType, int transport, byte protocolMode)78 boolean setProtocolMode(byte[] address, int addressType, int transport, byte protocolMode) { 79 return setProtocolModeNative(address, addressType, transport, protocolMode); 80 } 81 getReport( byte[] address, int addressType, int transport, byte reportType, byte reportId, int bufferSize)82 boolean getReport( 83 byte[] address, 84 int addressType, 85 int transport, 86 byte reportType, 87 byte reportId, 88 int bufferSize) { 89 return getReportNative(address, addressType, transport, reportType, reportId, bufferSize); 90 } 91 setReport( byte[] address, int addressType, int transport, byte reportType, String report)92 boolean setReport( 93 byte[] address, int addressType, int transport, byte reportType, String report) { 94 return setReportNative(address, addressType, transport, reportType, report); 95 } 96 sendData(byte[] address, int addressType, int transport, String report)97 boolean sendData(byte[] address, int addressType, int transport, String report) { 98 return sendDataNative(address, addressType, transport, report); 99 } 100 setIdleTime(byte[] address, int addressType, int transport, byte idleTime)101 boolean setIdleTime(byte[] address, int addressType, int transport, byte idleTime) { 102 return setIdleTimeNative(address, addressType, transport, idleTime); 103 } 104 getIdleTime(byte[] address, int addressType, int transport)105 boolean getIdleTime(byte[] address, int addressType, int transport) { 106 return getIdleTimeNative(address, addressType, transport); 107 } 108 convertHalState(int halState)109 private static int convertHalState(int halState) { 110 switch (halState) { 111 case CONN_STATE_CONNECTED: 112 return HidHostService.STATE_CONNECTED; 113 case CONN_STATE_CONNECTING: 114 return HidHostService.STATE_CONNECTING; 115 case CONN_STATE_DISCONNECTED: 116 return HidHostService.STATE_DISCONNECTED; 117 case CONN_STATE_DISCONNECTING: 118 return HidHostService.STATE_DISCONNECTING; 119 case CONN_STATE_ACCEPTING: 120 return HidHostService.STATE_ACCEPTING; 121 default: 122 Log.e(TAG, "bad hid connection state: " + halState); 123 return HidHostService.STATE_DISCONNECTED; 124 } 125 } 126 127 /**********************************************************************************************/ 128 /*********************************** callbacks from native ************************************/ 129 /**********************************************************************************************/ 130 onConnectStateChanged(byte[] address, int addressType, int transport, int state)131 private void onConnectStateChanged(byte[] address, int addressType, int transport, int state) { 132 Log.d(TAG, "onConnectStateChanged: state=" + state); 133 mHidHostService.onConnectStateChanged( 134 address, addressType, transport, convertHalState(state)); 135 } 136 onGetProtocolMode(byte[] address, int addressType, int transport, int mode)137 private void onGetProtocolMode(byte[] address, int addressType, int transport, int mode) { 138 Log.d(TAG, "onGetProtocolMode()"); 139 mHidHostService.onGetProtocolMode(address, addressType, transport, mode); 140 } 141 onGetReport( byte[] address, int addressType, int transport, byte[] report, int rptSize)142 private void onGetReport( 143 byte[] address, int addressType, int transport, byte[] report, int rptSize) { 144 Log.d(TAG, "onGetReport()"); 145 mHidHostService.onGetReport(address, addressType, transport, report, rptSize); 146 } 147 onHandshake(byte[] address, int addressType, int transport, int status)148 private void onHandshake(byte[] address, int addressType, int transport, int status) { 149 Log.d(TAG, "onHandshake: status=" + status); 150 mHidHostService.onHandshake(address, addressType, transport, status); 151 } 152 onVirtualUnplug(byte[] address, int addressType, int transport, int status)153 private void onVirtualUnplug(byte[] address, int addressType, int transport, int status) { 154 Log.d(TAG, "onVirtualUnplug: status=" + status); 155 mHidHostService.onVirtualUnplug(address, addressType, transport, status); 156 } 157 onGetIdleTime(byte[] address, int addressType, int transport, int idleTime)158 private void onGetIdleTime(byte[] address, int addressType, int transport, int idleTime) { 159 Log.d(TAG, "onGetIdleTime()"); 160 mHidHostService.onGetIdleTime(address, addressType, transport, idleTime); 161 } 162 163 /**********************************************************************************************/ 164 /******************************************* native *******************************************/ 165 /**********************************************************************************************/ 166 167 // Constants matching Hal header file bt_hh.h 168 // bthh_connection_state_t 169 private static final int CONN_STATE_CONNECTED = 0; 170 171 private static final int CONN_STATE_CONNECTING = 1; 172 private static final int CONN_STATE_DISCONNECTED = 2; 173 private static final int CONN_STATE_DISCONNECTING = 3; 174 private static final int CONN_STATE_ACCEPTING = 4; 175 initializeNative()176 private native void initializeNative(); 177 cleanupNative()178 private native void cleanupNative(); 179 connectHidNative(byte[] btAddress, int addressType, int transport)180 private native boolean connectHidNative(byte[] btAddress, int addressType, int transport); 181 disconnectHidNative( byte[] btAddress, int addressType, int transport, boolean reconnectAllowed)182 private native boolean disconnectHidNative( 183 byte[] btAddress, int addressType, int transport, boolean reconnectAllowed); 184 getProtocolModeNative(byte[] btAddress, int addressType, int transport)185 private native boolean getProtocolModeNative(byte[] btAddress, int addressType, int transport); 186 virtualUnPlugNative(byte[] btAddress, int addressType, int transport)187 private native boolean virtualUnPlugNative(byte[] btAddress, int addressType, int transport); 188 setProtocolModeNative( byte[] btAddress, int addressType, int transport, byte protocolMode)189 private native boolean setProtocolModeNative( 190 byte[] btAddress, int addressType, int transport, byte protocolMode); 191 getReportNative( byte[] btAddress, int addressType, int transport, byte reportType, byte reportId, int bufferSize)192 private native boolean getReportNative( 193 byte[] btAddress, 194 int addressType, 195 int transport, 196 byte reportType, 197 byte reportId, 198 int bufferSize); 199 setReportNative( byte[] btAddress, int addressType, int transport, byte reportType, String report)200 private native boolean setReportNative( 201 byte[] btAddress, int addressType, int transport, byte reportType, String report); 202 sendDataNative( byte[] btAddress, int addressType, int transport, String report)203 private native boolean sendDataNative( 204 byte[] btAddress, int addressType, int transport, String report); 205 setIdleTimeNative( byte[] btAddress, int addressType, int transport, byte idleTime)206 private native boolean setIdleTimeNative( 207 byte[] btAddress, int addressType, int transport, byte idleTime); 208 getIdleTimeNative(byte[] btAddress, int addressType, int transport)209 private native boolean getIdleTimeNative(byte[] btAddress, int addressType, int transport); 210 } 211