1 /* 2 * Copyright (C) 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 android.bluetooth; 18 19 import android.os.RemoteException; 20 import android.util.Log; 21 22 /** Utility class for socket metrics */ 23 class SocketMetrics { 24 private static final String TAG = SocketMetrics.class.getSimpleName(); 25 26 /*package*/ static final int SOCKET_NO_ERROR = -1; 27 28 // Defined in BluetoothProtoEnums.L2capCocConnectionResult of proto logging 29 private static final int RESULT_L2CAP_CONN_UNKNOWN = 0; 30 /*package*/ static final int RESULT_L2CAP_CONN_SUCCESS = 1; 31 private static final int RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_FAILED = 1000; 32 private static final int RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_CLOSED = 1001; 33 private static final int RESULT_L2CAP_CONN_BLUETOOTH_UNABLE_TO_SEND_RPC = 1002; 34 private static final int RESULT_L2CAP_CONN_BLUETOOTH_NULL_BLUETOOTH_DEVICE = 1003; 35 private static final int RESULT_L2CAP_CONN_BLUETOOTH_GET_SOCKET_MANAGER_FAILED = 1004; 36 private static final int RESULT_L2CAP_CONN_BLUETOOTH_NULL_FILE_DESCRIPTOR = 1005; 37 /*package*/ static final int RESULT_L2CAP_CONN_SERVER_FAILURE = 2000; 38 39 // Defined in BluetoothRfcommProtoEnums.RfcommConnectionResult of proto logging 40 private static final int RFCOMM_CONN_RESULT_FAILURE_UNKNOWN = 0; 41 private static final int RFCOMM_CONN_RESULT_SUCCESS = 1; 42 private static final int RFCOMM_CONN_RESULT_SOCKET_CONNECTION_FAILED = 2; 43 private static final int RFCOMM_CONN_RESULT_SOCKET_CONNECTION_CLOSED = 3; 44 private static final int RFCOMM_CONN_RESULT_UNABLE_TO_SEND_RPC = 4; 45 private static final int RFCOMM_CONN_RESULT_NULL_BLUETOOTH_DEVICE = 5; 46 private static final int RFCOMM_CONN_RESULT_GET_SOCKET_MANAGER_FAILED = 6; 47 private static final int RFCOMM_CONN_RESULT_NULL_FILE_DESCRIPTOR = 7; 48 logSocketConnect( int socketExceptionCode, long socketConnectionTimeNanos, int connType, BluetoothDevice device, int port, boolean auth, long socketCreationTimeNanos, long socketCreationLatencyNanos)49 static void logSocketConnect( 50 int socketExceptionCode, 51 long socketConnectionTimeNanos, 52 int connType, 53 BluetoothDevice device, 54 int port, 55 boolean auth, 56 long socketCreationTimeNanos, 57 long socketCreationLatencyNanos) { 58 IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(); 59 if (bluetoothProxy == null) { 60 Log.w(TAG, "logSocketConnect: bluetoothProxy is null"); 61 return; 62 } 63 if (connType == BluetoothSocket.TYPE_L2CAP_LE) { 64 try { 65 bluetoothProxy.logL2capcocClientConnection( 66 device, 67 port, 68 auth, 69 getL2capLeConnectStatusCode(socketExceptionCode), 70 socketCreationTimeNanos, // to calculate end to end latency 71 socketCreationLatencyNanos, // latency of the constructor 72 socketConnectionTimeNanos); // to calculate the latency of connect() 73 } catch (RemoteException e) { 74 Log.w(TAG, "logL2capcocServerConnection failed", e); 75 } 76 } else if (connType == BluetoothSocket.TYPE_RFCOMM) { 77 boolean isSerialPort = true; // BluetoothSocket#connect API always uses serial port uuid 78 try { 79 bluetoothProxy.logRfcommConnectionAttempt( 80 device, 81 auth, 82 getRfcommConnectStatusCode(socketExceptionCode), 83 socketCreationTimeNanos, // to calculate end to end latency 84 isSerialPort); 85 } catch (RemoteException e) { 86 Log.w(TAG, "logL2capcocServerConnection failed", e); 87 } 88 } else { 89 Log.d(TAG, "No metrics for connection type " + connType); 90 } 91 } 92 logSocketAccept( BluetoothSocket acceptedSocket, BluetoothSocket socket, int connType, int channel, int timeout, int result, long socketCreationTimeMillis, long socketCreationLatencyMillis, long socketConnectionTimeMillis)93 static void logSocketAccept( 94 BluetoothSocket acceptedSocket, 95 BluetoothSocket socket, 96 int connType, 97 int channel, 98 int timeout, 99 int result, 100 long socketCreationTimeMillis, 101 long socketCreationLatencyMillis, 102 long socketConnectionTimeMillis) { 103 if (connType != BluetoothSocket.TYPE_L2CAP_LE) { 104 return; 105 } 106 IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService(); 107 if (bluetoothProxy == null) { 108 Log.w(TAG, "logSocketConnect: bluetoothProxy is null"); 109 return; 110 } 111 try { 112 bluetoothProxy.logL2capcocServerConnection( 113 acceptedSocket == null ? null : acceptedSocket.getRemoteDevice(), 114 channel, 115 socket.isAuth(), 116 result, 117 socketCreationTimeMillis, // pass creation time to calculate end to end latency 118 socketCreationLatencyMillis, // socket creation latency 119 socketConnectionTimeMillis, // send connection start time for connection latency 120 timeout); 121 } catch (RemoteException e) { 122 Log.w(TAG, "logL2capcocServerConnection failed", e); 123 } 124 } 125 getL2capLeConnectStatusCode(int socketExceptionCode)126 private static int getL2capLeConnectStatusCode(int socketExceptionCode) { 127 switch (socketExceptionCode) { 128 case (SOCKET_NO_ERROR): 129 return RESULT_L2CAP_CONN_SUCCESS; 130 case (BluetoothSocketException.NULL_DEVICE): 131 return RESULT_L2CAP_CONN_BLUETOOTH_NULL_BLUETOOTH_DEVICE; 132 case (BluetoothSocketException.SOCKET_MANAGER_FAILURE): 133 return RESULT_L2CAP_CONN_BLUETOOTH_GET_SOCKET_MANAGER_FAILED; 134 case (BluetoothSocketException.SOCKET_CLOSED): 135 return RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_CLOSED; 136 case (BluetoothSocketException.SOCKET_CONNECTION_FAILURE): 137 return RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_FAILED; 138 case (BluetoothSocketException.RPC_FAILURE): 139 return RESULT_L2CAP_CONN_BLUETOOTH_UNABLE_TO_SEND_RPC; 140 case (BluetoothSocketException.UNIX_FILE_SOCKET_CREATION_FAILURE): 141 return RESULT_L2CAP_CONN_BLUETOOTH_NULL_FILE_DESCRIPTOR; 142 default: 143 return RESULT_L2CAP_CONN_UNKNOWN; 144 } 145 } 146 getRfcommConnectStatusCode(int socketExceptionCode)147 private static int getRfcommConnectStatusCode(int socketExceptionCode) { 148 switch (socketExceptionCode) { 149 case (SOCKET_NO_ERROR): 150 return RFCOMM_CONN_RESULT_SUCCESS; 151 case (BluetoothSocketException.NULL_DEVICE): 152 return RFCOMM_CONN_RESULT_NULL_BLUETOOTH_DEVICE; 153 case (BluetoothSocketException.SOCKET_MANAGER_FAILURE): 154 return RFCOMM_CONN_RESULT_GET_SOCKET_MANAGER_FAILED; 155 case (BluetoothSocketException.SOCKET_CLOSED): 156 return RFCOMM_CONN_RESULT_SOCKET_CONNECTION_CLOSED; 157 case (BluetoothSocketException.SOCKET_CONNECTION_FAILURE): 158 return RFCOMM_CONN_RESULT_SOCKET_CONNECTION_FAILED; 159 case (BluetoothSocketException.RPC_FAILURE): 160 return RFCOMM_CONN_RESULT_UNABLE_TO_SEND_RPC; 161 case (BluetoothSocketException.UNIX_FILE_SOCKET_CREATION_FAILURE): 162 return RFCOMM_CONN_RESULT_NULL_FILE_DESCRIPTOR; 163 default: 164 return RFCOMM_CONN_RESULT_FAILURE_UNKNOWN; 165 } 166 } 167 } 168