Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e28d3cb0 authored by Pomai Ahlo's avatar Pomai Ahlo
Browse files

Separate Existing Metrics

Move metrics logic from BluetothSocket.java and
BluetoothServerSocket.java into a new SocketMetrics.java

Bug: 306760576
Flag: EXEMPT strictly mechanical refactor
Test: m Bluetooth
Change-Id: Iad667d59a45d5f5d729acc6613bc41aeccd7d113
parent 14810918
Loading
Loading
Loading
Loading
+14 −40
Original line number Diff line number Diff line
@@ -16,20 +16,16 @@

package android.bluetooth;

import static android.bluetooth.BluetoothUtils.getSyncTimeout;

import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;

import com.android.modules.utils.SynchronousResultReceiver;

import java.io.Closeable;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * A listening Bluetooth socket.
@@ -192,54 +188,32 @@ public final class BluetoothServerSocket implements Closeable {
        BluetoothSocket acceptedSocket = null;
        try {
            acceptedSocket = mSocket.accept(timeout);
            logL2capcocServerConnection(
            SocketMetrics.logSocketAccept(
                    acceptedSocket,
                    mSocket,
                    mType,
                    mChannel,
                    timeout,
                    BluetoothSocket.RESULT_L2CAP_CONN_SUCCESS,
                    SocketMetrics.RESULT_L2CAP_CONN_SUCCESS,
                    mSocketCreationTimeMillis,
                    mSocketCreationLatencyMillis,
                    socketConnectionTime);
            return acceptedSocket;
        } catch (IOException e) {
            logL2capcocServerConnection(
            SocketMetrics.logSocketAccept(
                    acceptedSocket,
                    mSocket,
                    mType,
                    mChannel,
                    timeout,
                    BluetoothSocket.RESULT_L2CAP_CONN_SERVER_FAILURE,
                    SocketMetrics.RESULT_L2CAP_CONN_SERVER_FAILURE,
                    mSocketCreationTimeMillis,
                    mSocketCreationLatencyMillis,
                    socketConnectionTime);
            throw e;
        }
    }

    private void logL2capcocServerConnection(
            BluetoothSocket acceptedSocket,
            int timeout,
            int result,
            long socketConnectionTimeMillis) {
        if (mType != BluetoothSocket.TYPE_L2CAP_LE) {
            return;
        }
        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
        if (bluetoothProxy == null) {
            Log.w(TAG, "bluetoothProxy is null while trying to log l2cap soc server connection");
            return;
        }
        try {
            final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
            bluetoothProxy.logL2capcocServerConnection(
                    acceptedSocket == null ? null : acceptedSocket.getRemoteDevice(),
                    getPsm(),
                    mSocket.isAuth(),
                    result,
                    mSocketCreationTimeMillis, // pass creation time to calculate end to end latency
                    mSocketCreationLatencyMillis, // socket creation latency
                    socketConnectionTimeMillis, // send connection start time for connection latency
                    timeout,
                    recv);
            recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);

        } catch (RemoteException | TimeoutException e) {
            Log.w(TAG, "logL2capcocServerConnection failed due to remote exception");
        }
    }

    /**
     * Immediately close this socket, and release all associated resources.
     *
+35 −78
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package android.bluetooth;

import static android.bluetooth.BluetoothUtils.getSyncTimeout;

import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
@@ -29,8 +27,6 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.util.Log;

import com.android.modules.utils.SynchronousResultReceiver;

import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -41,7 +37,6 @@ import java.nio.ByteOrder;
import java.util.Arrays;
import java.util.Locale;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

/**
 * A connected or connecting Bluetooth socket.
@@ -129,16 +124,6 @@ public final class BluetoothSocket implements Closeable {
    /*package*/ static final int SEC_FLAG_AUTH_MITM = 1 << 3;
    /*package*/ static final int SEC_FLAG_AUTH_16_DIGIT = 1 << 4;

    // Defined in BluetoothProtoEnums.L2capCocConnectionResult of proto logging
    /*package*/ static final int RESULT_L2CAP_CONN_SUCCESS = 1;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_FAILED = 1000;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_CLOSED = 1001;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_UNABLE_TO_SEND_RPC = 1002;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_NULL_BLUETOOTH_DEVICE = 1003;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_GET_SOCKET_MANAGER_FAILED = 1004;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_NULL_FILE_DESCRIPTOR = 1005;
    /*package*/ static final int RESULT_L2CAP_CONN_SERVER_FAILURE = 2000;

    private final int mType; /* one of TYPE_RFCOMM etc */
    private BluetoothDevice mDevice; /* remote device */
    private String mAddress; /* remote address */
@@ -449,46 +434,26 @@ public final class BluetoothSocket implements Closeable {
        if (bluetoothProxy == null) {
            throw new BluetoothSocketException(BluetoothSocketException.BLUETOOTH_OFF_FAILURE);
        }
        try {
            if (mDevice == null) {
            logL2capcocClientConnection(
                    bluetoothProxy,
                    RESULT_L2CAP_CONN_BLUETOOTH_NULL_BLUETOOTH_DEVICE,
                    socketConnectionTimeMillis);
                throw new BluetoothSocketException(BluetoothSocketException.NULL_DEVICE);
            }
        try {
            if (mSocketState == SocketState.CLOSED) {
                logL2capcocClientConnection(
                        bluetoothProxy,
                        RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_CLOSED,
                        socketConnectionTimeMillis);
                throw new BluetoothSocketException(BluetoothSocketException.SOCKET_CLOSED);
            }

            IBluetoothSocketManager socketManager = bluetoothProxy.getSocketManager();
            if (socketManager == null) {
                logL2capcocClientConnection(
                        bluetoothProxy,
                        RESULT_L2CAP_CONN_BLUETOOTH_GET_SOCKET_MANAGER_FAILED,
                        socketConnectionTimeMillis);
                throw new BluetoothSocketException(BluetoothSocketException.SOCKET_MANAGER_FAILURE);
            }
            mPfd = socketManager.connectSocket(mDevice, mType, mUuid, mPort, getSecurityFlags());
            synchronized (this) {
                if (DBG) Log.d(TAG, "connect(), SocketState: " + mSocketState + ", mPfd: " + mPfd);
                if (mSocketState == SocketState.CLOSED) {
                    logL2capcocClientConnection(
                            bluetoothProxy,
                            RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_CLOSED,
                            socketConnectionTimeMillis);
                    throw new BluetoothSocketException(
                            BluetoothSocketException.SOCKET_CLOSED);
                }
                if (mPfd == null) {
                    logL2capcocClientConnection(
                            bluetoothProxy,
                            RESULT_L2CAP_CONN_BLUETOOTH_NULL_FILE_DESCRIPTOR,
                            socketConnectionTimeMillis);
                    throw new BluetoothSocketException(
                        BluetoothSocketException.UNIX_FILE_SOCKET_CREATION_FAILURE);
                }
@@ -500,14 +465,9 @@ public final class BluetoothSocket implements Closeable {
            int channel = readInt(mSocketIS);
            if (channel == 0) {
                int errCode = (int) mSocketIS.read();
                logL2capcocClientConnection(bluetoothProxy, errCode, socketConnectionTimeMillis);
                throw new BluetoothSocketException(errCode);
            }
            if (channel < 0) {
                logL2capcocClientConnection(
                        bluetoothProxy,
                        RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_FAILED,
                        socketConnectionTimeMillis);
                throw new BluetoothSocketException(
                        BluetoothSocketException.SOCKET_CONNECTION_FAILURE);
            }
@@ -515,26 +475,45 @@ public final class BluetoothSocket implements Closeable {
            waitSocketSignal(mSocketIS);
            synchronized (this) {
                if (mSocketState == SocketState.CLOSED) {
                    logL2capcocClientConnection(
                            bluetoothProxy,
                            RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_CLOSED,
                            socketConnectionTimeMillis);
                    throw new BluetoothSocketException(BluetoothSocketException.SOCKET_CLOSED);
                }
                mSocketState = SocketState.CONNECTED;
                if (DBG) Log.d(TAG, "connect(), socket connected");
            }
            logL2capcocClientConnection(
                    bluetoothProxy, RESULT_L2CAP_CONN_SUCCESS, socketConnectionTimeMillis);
        } catch (BluetoothSocketException e) {
            SocketMetrics.logSocketConnect(
                    e.getErrorCode(),
                    socketConnectionTimeMillis,
                    mType,
                    mDevice,
                    mPort,
                    mAuth,
                    mSocketCreationTimeMillis,
                    mSocketCreationLatencyMillis);
            throw e;
        } catch (RemoteException e) {
            Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
            logL2capcocClientConnection(
                    bluetoothProxy,
                    RESULT_L2CAP_CONN_BLUETOOTH_UNABLE_TO_SEND_RPC,
                    socketConnectionTimeMillis);
            throw new BluetoothSocketException(
                    BluetoothSocketException.RPC_FAILURE, "unable to send RPC: " + e.getMessage());
        }
            SocketMetrics.logSocketConnect(
                    BluetoothSocketException.RPC_FAILURE,
                    socketConnectionTimeMillis,
                    mType,
                    mDevice,
                    mPort,
                    mAuth,
                    mSocketCreationTimeMillis,
                    mSocketCreationLatencyMillis);
            throw new BluetoothSocketException(BluetoothSocketException.RPC_FAILURE,
                    "unable to send RPC: " + e.getMessage());
        }
        SocketMetrics.logSocketConnect(
                SocketMetrics.SOCKET_NO_ERROR,
                socketConnectionTimeMillis,
                mType,
                mDevice,
                mPort,
                mAuth,
                mSocketCreationTimeMillis,
                mSocketCreationLatencyMillis);
    }

    /**
@@ -759,28 +738,6 @@ public final class BluetoothSocket implements Closeable {
        }
    }

    private void logL2capcocClientConnection(
            IBluetooth bluetoothProxy, int errCode, long socketConnectionTimeMillis) {
        if (mType != TYPE_L2CAP_LE) {
            return;
        }
        try {
            final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
            bluetoothProxy.logL2capcocClientConnection(
                    mDevice,
                    mPort,
                    mAuth,
                    errCode,
                    mSocketCreationTimeMillis, // to calculate end to end latency
                    mSocketCreationLatencyMillis, // latency of the constructor
                    socketConnectionTimeMillis, // to calculate the latency of connect()
                    recv);
            recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
        } catch (RemoteException | TimeoutException e) {
            Log.w(TAG, "logL2capcocClientConnection failed due to remote exception");
        }
    }

    /*package */ void removeChannel() {}

    /*package */ int getPort() {
+137 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.bluetooth;

import static android.bluetooth.BluetoothUtils.getSyncTimeout;

import android.os.RemoteException;
import android.util.Log;

import com.android.modules.utils.SynchronousResultReceiver;

import java.util.concurrent.TimeoutException;

/** Utility class for socket metrics */
class SocketMetrics {
    private static final String TAG = SocketMetrics.class.getSimpleName();

    /*package*/ static final int SOCKET_NO_ERROR = -1;

    // Defined in BluetoothProtoEnums.L2capCocConnectionResult of proto logging
    private static final int RESULT_L2CAP_CONN_UNKNOWN = 0;
    /*package*/ static final int RESULT_L2CAP_CONN_SUCCESS = 1;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_FAILED = 1000;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_CLOSED = 1001;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_UNABLE_TO_SEND_RPC = 1002;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_NULL_BLUETOOTH_DEVICE = 1003;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_GET_SOCKET_MANAGER_FAILED = 1004;
    private static final int RESULT_L2CAP_CONN_BLUETOOTH_NULL_FILE_DESCRIPTOR = 1005;
    /*package*/ static final int RESULT_L2CAP_CONN_SERVER_FAILURE = 2000;

    static void logSocketConnect(
            int socketExceptionCode,
            long socketConnectionTimeMillis,
            int connType,
            BluetoothDevice device,
            int port,
            boolean auth,
            long socketCreationTimeMillis,
            long socketCreationLatencyMillis) {
        if (connType != BluetoothSocket.TYPE_L2CAP_LE) {
            return;
        }
        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
        if (bluetoothProxy == null) {
            Log.w(TAG, "logSocketConnect: bluetoothProxy is null");
            return;
        }
        int errCode = getL2capLeConnectStatusCode(socketExceptionCode);
        try {
            final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
            bluetoothProxy.logL2capcocClientConnection(
                    device,
                    port,
                    auth,
                    errCode,
                    socketCreationTimeMillis, // to calculate end to end latency
                    socketCreationLatencyMillis, // latency of the constructor
                    socketConnectionTimeMillis, // to calculate the latency of connect()
                    recv);
            recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
        } catch (RemoteException | TimeoutException e) {
            Log.w(TAG, "logL2capcocClientConnection failed", e);
        }
    }

    static void logSocketAccept(
            BluetoothSocket acceptedSocket,
            BluetoothSocket socket,
            int connType,
            int channel,
            int timeout,
            int result,
            long socketCreationTimeMillis,
            long socketCreationLatencyMillis,
            long socketConnectionTimeMillis) {
        if (connType != BluetoothSocket.TYPE_L2CAP_LE) {
            return;
        }
        IBluetooth bluetoothProxy = BluetoothAdapter.getDefaultAdapter().getBluetoothService();
        if (bluetoothProxy == null) {
            Log.w(TAG, "logSocketConnect: bluetoothProxy is null");
            return;
        }
        try {
            final SynchronousResultReceiver recv = SynchronousResultReceiver.get();
            bluetoothProxy.logL2capcocServerConnection(
                    acceptedSocket == null ? null : acceptedSocket.getRemoteDevice(),
                    channel,
                    socket.isAuth(),
                    result,
                    socketCreationTimeMillis, // pass creation time to calculate end to end latency
                    socketCreationLatencyMillis, // socket creation latency
                    socketConnectionTimeMillis, // send connection start time for connection latency
                    timeout,
                    recv);
            recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);

        } catch (RemoteException | TimeoutException e) {
            Log.w(TAG, "logL2capcocServerConnection failed", e);
        }
    }

    private static int getL2capLeConnectStatusCode(int socketExceptionCode) {
        switch (socketExceptionCode) {
            case (SOCKET_NO_ERROR):
                return RESULT_L2CAP_CONN_SUCCESS;
            case (BluetoothSocketException.NULL_DEVICE):
                return RESULT_L2CAP_CONN_BLUETOOTH_NULL_BLUETOOTH_DEVICE;
            case (BluetoothSocketException.SOCKET_MANAGER_FAILURE):
                return RESULT_L2CAP_CONN_BLUETOOTH_GET_SOCKET_MANAGER_FAILED;
            case (BluetoothSocketException.SOCKET_CLOSED):
                return RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_CLOSED;
            case (BluetoothSocketException.SOCKET_CONNECTION_FAILURE):
                return RESULT_L2CAP_CONN_BLUETOOTH_SOCKET_CONNECTION_FAILED;
            case (BluetoothSocketException.RPC_FAILURE):
                return RESULT_L2CAP_CONN_BLUETOOTH_UNABLE_TO_SEND_RPC;
            case (BluetoothSocketException.UNIX_FILE_SOCKET_CREATION_FAILURE):
                return RESULT_L2CAP_CONN_BLUETOOTH_NULL_FILE_DESCRIPTOR;
            default:
                return RESULT_L2CAP_CONN_UNKNOWN;
        }
    }
}