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

Commit e9382820 authored by Roopa Sattiraju's avatar Roopa Sattiraju Committed by Android (Google) Code Review
Browse files

Merge "Add HFP Client NetworkServiceState APIs"

parents b32801ff a4de43b6
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothHeadsetClient.NetworkServiceState;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.hfp.BluetoothHfpProtoEnums;
@@ -359,6 +360,27 @@ public class HeadsetClientStateMachine extends StateMachine {
        HfpClientConnectionService.onCallChanged(c.getDevice(), c);
    }

    private void sendNetworkStateChangedIntent(BluetoothDevice device) {
        if (device == null) {
            return;
        }
        NetworkServiceState networkServiceState = new NetworkServiceState(
                device,
                mIndicatorNetworkState == HeadsetClientHalConstants.NETWORK_STATE_AVAILABLE,
                mOperatorName,
                mIndicatorNetworkSignal,
                mIndicatorNetworkType == HeadsetClientHalConstants.SERVICE_TYPE_ROAMING);

        Intent intent =
                new Intent(BluetoothHeadsetClient.ACTION_NETWORK_SERVICE_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothHeadsetClient.EXTRA_NETWORK_SERVICE_STATE, networkServiceState);

        mService.sendBroadcastMultiplePermissions(intent,
                new String[] {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED},
                Utils.getTempBroadcastOptions());
    }

    private boolean queryCallsStart() {
        logD("queryCallsStart");
        clearPendingAction();
@@ -1429,6 +1451,7 @@ public class HeadsetClientStateMachine extends StateMachine {
                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
                            mService.sendBroadcast(intent, BLUETOOTH_CONNECT,
                                    Utils.getTempAllowlistBroadcastOptions());
                            sendNetworkStateChangedIntent(event.device);

                            if (mIndicatorNetworkState
                                    == HeadsetClientHalConstants.NETWORK_STATE_AVAILABLE) {
@@ -1448,6 +1471,7 @@ public class HeadsetClientStateMachine extends StateMachine {
                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
                            mService.sendBroadcast(intent, BLUETOOTH_CONNECT,
                                    Utils.getTempAllowlistBroadcastOptions());
                            sendNetworkStateChangedIntent(event.device);
                            break;
                        case StackEvent.EVENT_TYPE_NETWORK_SIGNAL:
                            mIndicatorNetworkSignal = event.valueInt;
@@ -1458,6 +1482,7 @@ public class HeadsetClientStateMachine extends StateMachine {
                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
                            mService.sendBroadcast(intent, BLUETOOTH_CONNECT,
                                    Utils.getTempAllowlistBroadcastOptions());
                            sendNetworkStateChangedIntent(event.device);
                            break;
                        case StackEvent.EVENT_TYPE_BATTERY_LEVEL:
                            mIndicatorBatteryLevel = event.valueInt;
@@ -1478,6 +1503,7 @@ public class HeadsetClientStateMachine extends StateMachine {
                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
                            mService.sendBroadcast(intent, BLUETOOTH_CONNECT,
                                    Utils.getTempAllowlistBroadcastOptions());
                            sendNetworkStateChangedIntent(event.device);
                            break;
                        case StackEvent.EVENT_TYPE_VR_STATE_CHANGED:
                            int oldState = mVoiceRecognitionActive;
+12 −0
Original line number Diff line number Diff line
@@ -329,14 +329,26 @@ package android.bluetooth {
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
    method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BluetoothHeadsetClient.NetworkServiceState getNetworkServiceState(@NonNull android.bluetooth.BluetoothDevice);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headsetclient.profile.action.AUDIO_STATE_CHANGED";
    field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headsetclient.profile.action.CONNECTION_STATE_CHANGED";
    field @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public static final String ACTION_NETWORK_SERVICE_STATE_CHANGED = "android.bluetooth.headsetclient.profile.action.NETWORK_SERVICE_STATE_CHANGED";
    field public static final String EXTRA_NETWORK_SERVICE_STATE = "android.bluetooth.headsetclient.extra.EXTRA_NETWORK_SERVICE_STATE";
    field public static final int STATE_AUDIO_CONNECTED = 2; // 0x2
    field public static final int STATE_AUDIO_CONNECTING = 1; // 0x1
    field public static final int STATE_AUDIO_DISCONNECTED = 0; // 0x0
  }

  public static final class BluetoothHeadsetClient.NetworkServiceState implements android.os.Parcelable {
    method @NonNull public android.bluetooth.BluetoothDevice getDevice();
    method @Nullable public String getOperatorName();
    method public int getSignalStrength();
    method public boolean isRoaming();
    method public boolean isServiceAvailable();
    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHeadsetClient.NetworkServiceState> CREATOR;
  }

  public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getHiSyncId(@NonNull android.bluetooth.BluetoothDevice);
+215 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.bluetooth;
import static android.bluetooth.BluetoothUtils.getSyncTimeout;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -31,6 +32,8 @@ import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.CloseGuard;
import android.util.Log;
@@ -1615,6 +1618,218 @@ public final class BluetoothHeadsetClient implements BluetoothProfile, AutoClose
        }
        return defaultValue;
    }

    /**
     * A class that contains the network service info provided by the HFP Client profile
     *
     * @hide
     */
    @SystemApi
    public static final class NetworkServiceState implements Parcelable {
        /** The device associated with this service state */
        private final BluetoothDevice mDevice;

        /** True if there is service available, False otherwise */
        private final boolean mIsServiceAvailable;

        /** The name of the operator associated with the remote device's current network */
        private final String mOperatorName;

        /**
         * The general signal strength
         * (0 - Unknown, 1 - Poor, 2 - Fair, 3 - Good, 4 - Great, 5 - Excellent)
         */
        private final int mSignalStrength;

        /** True if we are network roaming, False otherwise */
        private final boolean mIsRoaming;

        /**
         * Create a NetworkServiceState Object
         *
         * @param device The device associated with this network signal state
         * @param isServiceAvailable True if there is service available, False otherwise
         * @param operatorName The name of the operator associated with the remote device's current
         *                     network. Use Null if the value is unknown
         * @param signalStrength The general signal strength
         * @param isRoaming True if we are network roaming, False otherwise
         *
         * @hide
         */
        public NetworkServiceState(BluetoothDevice device, boolean isServiceAvailable,
                String operatorName, int signalStrength, boolean isRoaming) {
            mDevice = device;
            mIsServiceAvailable = isServiceAvailable;
            mOperatorName = operatorName;
            mSignalStrength = signalStrength;
            mIsRoaming = isRoaming;
        }

        /**
         * Get the device associated with this network service state
         *
         * @return a BluetoothDevice associated with this state
         *
         * @hide
         */
        @SystemApi
        public @NonNull BluetoothDevice getDevice() {
            return mDevice;
        }

        /**
         * Get the network service availablility state
         *
         * @return True if there is service available, False otherwise
         *
         * @hide
         */
        @SystemApi
        public boolean isServiceAvailable() {
            return mIsServiceAvailable;
        }

        /**
         * Get the network operator name
         *
         * @return A string representing the name of the operator the remote device is on, or null
         *         if unknown.
         *
         * @hide
         */
        @SystemApi
        public @Nullable String getOperatorName() {
            return mOperatorName;
        }

        /**
         * Get the network's general signal strength
         *
         * @return The general signal strength (0 - None, 1 - Poor, 2 - Fair, 3 - Good,
         *         4 - Great, 5 - Excellent)
         *
         * @hide
         */
        @SystemApi
        public int getSignalStrength() {
            return mSignalStrength;
        }

        /**
         * Get the network service roaming status
         *
         * * @return True if we are network roaming, False otherwise
         *
         * @hide
         */
        @SystemApi
        public boolean isRoaming() {
            return mIsRoaming;
        }

        /**
         * {@link Parcelable.Creator} interface implementation.
         */
        public static final @NonNull Parcelable.Creator<NetworkServiceState> CREATOR =
                new Parcelable.Creator<NetworkServiceState>() {
            public NetworkServiceState createFromParcel(Parcel in) {
                return new NetworkServiceState((BluetoothDevice) in.readParcelable(null),
                        in.readInt() == 1, in.readString(), in.readInt(), in.readInt() == 1);
            }

            public @NonNull NetworkServiceState[] newArray(int size) {
                return new NetworkServiceState[size];
            }
        };

        /**
         * @hide
         */
        @Override
        public void writeToParcel(@NonNull Parcel out, int flags) {
            out.writeParcelable(mDevice, 0);
            out.writeInt(mIsServiceAvailable ? 1 : 0);
            out.writeString(mOperatorName);
            out.writeInt(mSignalStrength);
            out.writeInt(mIsRoaming ? 1 : 0);
        }

        /**
         * @hide
         */
        @Override
        public int describeContents() {
            return 0;
        }
    }

    /**
     * Intent used to broadcast the change in network service state of an HFP Client device
     *
     * <p>This intent will have 2 extras:
     * <ul>
     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
     * <li> {@link EXTRA_NETWORK_SERVICE_STATE} - A {@link NetworkServiceState} object. </li>
     * </ul>
     *
     * @hide
     */
    @SuppressLint("ActionValue")
    @SystemApi
    @RequiresBluetoothConnectPermission
    @RequiresPermission(allOf = {
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_NETWORK_SERVICE_STATE_CHANGED =
            "android.bluetooth.headsetclient.profile.action.NETWORK_SERVICE_STATE_CHANGED";

    /**
     * Extra for the network service state changed intent.
     *
     * This extra represents the current network service state of a connected Bluetooth device.
     *
     * @hide
     */
    @SuppressLint("ActionValue")
    @SystemApi
    public static final String EXTRA_NETWORK_SERVICE_STATE =
            "android.bluetooth.headsetclient.extra.EXTRA_NETWORK_SERVICE_STATE";

    /**
     * Get the network service state for a device
     *
     * @param device The {@link BluetoothDevice} you want the network service state for
     * @return A {@link NetworkServiceState} representing the network service state of the device,
     *         or null if the device is not connected
     * @hide
     */
    @SystemApi
    @RequiresBluetoothConnectPermission
    @RequiresPermission(allOf = {
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    public @Nullable NetworkServiceState getNetworkServiceState(@NonNull BluetoothDevice device) {
        if (device == null) {
            return null;
        }

        Bundle agEvents = getCurrentAgEvents(device);
        if (agEvents == null) {
            return null;
        }

        boolean isServiceAvailable = (agEvents.getInt(EXTRA_NETWORK_STATUS, 0) == 1);
        int signalStrength = agEvents.getInt(EXTRA_NETWORK_SIGNAL_STRENGTH, 0);
        String operatorName = agEvents.getString(EXTRA_OPERATOR_NAME, null);
        boolean isRoaming = (agEvents.getInt(EXTRA_NETWORK_ROAMING, 0) == 1);

        return new NetworkServiceState(device, isServiceAvailable, operatorName, signalStrength,
                isRoaming);
    }

    private boolean isEnabled() {
        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
    }