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

Commit 5579e237 authored by Aayush Gupta's avatar Aayush Gupta
Browse files

Merge remote-tracking branch 'origin/lineage-18.1' into v1-r

parents 82fd8f52 99e87bb3
Loading
Loading
Loading
Loading
+173 −0
Original line number Diff line number Diff line
@@ -66,6 +66,9 @@ import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
@@ -1867,6 +1870,22 @@ public final class BluetoothAdapter {
        return false;
    }

    /** @hide */
    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public boolean isBroadcastActive() {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.isBroadcastActive();
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        } finally {
            mServiceLock.readLock().unlock();
        }
        return false;
    }

    /**
     * Connects all enabled and supported bluetooth profiles between the local and remote device.
     * Connection is asynchronous and you should listen to each profile's broadcast intent
@@ -2780,6 +2799,92 @@ public final class BluetoothAdapter {
        return null;
    }

    private void closeBCProfile(BluetoothProfile proxy) {
        Class<?> bshClass = null;
        Method bshClose = null;
        try {
            bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper");
        } catch (ClassNotFoundException ex) {
            Log.e(TAG, "no BSH: exists");
            bshClass = null;
        }
        if (bshClass != null) {
            Log.d(TAG, "Able to get BSH class handle");
            try {
                bshClose =  bshClass.getDeclaredMethod("close", null);
            } catch (NoSuchMethodException e) {
                Log.e(TAG, "no BSH:isSupported method exists");
            }
            if (bshClose != null) {
                try {
                   bshClose.invoke(proxy, null);
                } catch(IllegalAccessException e) {
                   Log.e(TAG, "bshClose IllegalAccessException");
                } catch (InvocationTargetException e) {
                   Log.e(TAG, "bshClose InvocationTargetException");
                }
            }
        }
        Log.d(TAG, "CloseBCProfile returns");
    }

    private boolean getBCProfile(Context context, BluetoothProfile.ServiceListener sl) {
        boolean ret = true;
        boolean isProfileSupported = false;
        Class<?> bshClass = null;
        Method bshSupported = null;
        Constructor bshCons = null;
        Object bshObj = null;
        try {
            bshClass = Class.forName("android.bluetooth.BluetoothSyncHelper");
        } catch (ClassNotFoundException ex) {
            Log.e(TAG, "no BSH: exists");
            bshClass = null;
        }
        if (bshClass != null) {
            Log.d(TAG, "Able to get BSH class handle");
            try {
                bshSupported =  bshClass.getDeclaredMethod("isSupported", null);
            } catch (NoSuchMethodException e) {
                Log.e(TAG, "no BSH:isSupported method exists: gdm");
            }
            try {
                bshCons =
                  bshClass.getDeclaredConstructor(
                    new Class[]{Context.class,
                        BluetoothProfile.ServiceListener.class});
            } catch (NoSuchMethodException ex) {
                Log.e(TAG, "bshCons: NoSuchMethodException: gdm" + ex);
            }
        }
        if (bshClass != null && bshSupported != null && bshCons != null) {
            try {
                isProfileSupported = (boolean)bshSupported.invoke(null, null);
            } catch(IllegalAccessException e) {
                Log.e(TAG, "BSH:isSupported IllegalAccessException");
            } catch (InvocationTargetException e) {
                Log.e(TAG, "BSH:isSupported InvocationTargetException");
            }
            if (isProfileSupported) {
                try {
                    bshObj = bshCons.newInstance(
                                       context, sl);
                } catch (InstantiationException ex) {
                    Log.e(TAG, "bshCons InstantiationException:" + ex);
                } catch (IllegalAccessException ex) {
                    Log.e(TAG, "bshCons InstantiationException:" + ex);
                } catch (InvocationTargetException ex) {
                    Log.e(TAG, "bshCons InvocationTargetException:" + ex);
                }
             }
        }
        if (bshObj == null) {
            ret = false;
        }
        Log.d(TAG, "getBCService returns" + ret);
        return ret;
    }

    /**
     * Get the profile proxy object associated with the profile.
     *
@@ -2844,6 +2949,10 @@ public final class BluetoothAdapter {
        } else if (profile == BluetoothProfile.HID_DEVICE) {
            BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
            return true;
        } else if (profile == BluetoothProfile.BC_PROFILE) {
            return getBCProfile(context, listener);
        } else if (profile == BluetoothProfile.BROADCAST) {
            return getBroadcastProfile(context, listener);
        } else if (profile == BluetoothProfile.HEARING_AID) {
            if (isHearingAidProfileSupported()) {
                BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener);
@@ -2931,12 +3040,76 @@ public final class BluetoothAdapter {
                BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
                hidDevice.close();
                break;
            case BluetoothProfile.BC_PROFILE:
                closeBCProfile(proxy);
                break;
            case BluetoothProfile.BROADCAST:
                closeBroadcastProfile(proxy);
                break;
            case BluetoothProfile.HEARING_AID:
                BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
                hearingAid.close();
        }
    }

    private boolean getBroadcastProfile(Context context,
                                      BluetoothProfile.ServiceListener listener) {
        boolean ret = true;
        Class<?> broadcastClass = null;
        Constructor bcastConstructor = null;
        Object broadcastObj = null;
        try {
            broadcastClass = Class.forName("android.bluetooth.BluetoothBroadcast");
        } catch (ClassNotFoundException ex) {
            Log.e(TAG, "no BluetoothBroadcast: exists");
        }
        if (broadcastClass != null) {
            try {
               bcastConstructor =
                        broadcastClass.getDeclaredConstructor(new Class[]{Context.class,
                                             BluetoothProfile.ServiceListener.class});
            } catch (NoSuchMethodException ex) {
               Log.e(TAG, "bcastConstructor: NoSuchMethodException: gdm" + ex);
            }
        }
        if (bcastConstructor != null) {
            try {
                broadcastObj = bcastConstructor.newInstance(context, listener);
            } catch (InstantiationException | IllegalAccessException |
                InvocationTargetException ex) {
                ex.printStackTrace();
            }
        }
        if (broadcastObj == null) {
            return false;
        }
        return true;
    }

    private void closeBroadcastProfile(BluetoothProfile proxy) {
        Class<?> broadcastClass = null;
        Method broadcastClose = null;
        try {
            broadcastClass = Class.forName("android.bluetooth.BluetootBroadcast");
        } catch (ClassNotFoundException ex) {
            Log.e(TAG, "no BluetoothBroadcast: exists");
        }
        if (broadcastClass != null) {
            try {
                broadcastClose =  broadcastClass.getDeclaredMethod("close", null);
            } catch (NoSuchMethodException e) {
                Log.e(TAG, "no Broadcast:close method exists");
            }
            if (broadcastClose != null) {
                try {
                    broadcastClose.invoke(proxy, null);
                } catch(IllegalAccessException | InvocationTargetException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }

    private final IBluetoothManagerCallback mManagerCallback =
            new IBluetoothManagerCallback.Stub() {
                public void onBluetoothServiceUp(IBluetooth bluetoothService) {
+43 −1
Original line number Diff line number Diff line
@@ -2355,6 +2355,48 @@ public final class BluetoothDevice implements Parcelable {
    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
            BluetoothGattCallback callback, int transport,
            boolean opportunistic, int phy, Handler handler) {
        return connectGatt(context, autoConnect, callback, transport, opportunistic,
                phy, handler, false);
    }

    /**
     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
     * The callback is used to deliver results to Caller, such as connection status as well
     * as any further GATT client operations.
     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
     * GATT client operations.
     *
     * @param callback GATT callback handler that will receive asynchronous callbacks.
     * @param autoConnect Whether to directly connect to the remote device (false) or to
     * automatically connect as soon as the remote device becomes available (true).
     * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
     * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
     * BluetoothDevice#TRANSPORT_LE}
     * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client
     * does not hold a GATT connection. It automatically disconnects when no other GATT connections
     * are active for the remote device.
     * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
     * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link
     * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
     * is set to true.
     * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on
     * an un-specified background thread.
     * @param eattSupport specifies whether client app needs EATT channel for client operations.
     * If both local and remote devices support EATT and local app asks for EATT, GATT client
     * operations will be performed using EATT channel.
     * If either local or remote device doesn't support EATT but local App asks for EATT, GATT
     * client operations will be performed using unenhanced ATT channel.
     *
     * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client
     * operations.
     *
     * @throws NullPointerException if callback is null
     *
     * @hide
     */
    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
            BluetoothGattCallback callback, int transport, boolean opportunistic,
            int phy, Handler handler, boolean eattSupport) {
        if (callback == null) {
            throw new NullPointerException("callback is null");
        }
@@ -2370,7 +2412,7 @@ public final class BluetoothDevice implements Parcelable {
                return null;
            }
            BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy);
            gatt.connect(autoConnect, callback, handler);
            gatt.connect(autoConnect, callback, handler, eattSupport);
            return gatt;
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
+61 −3
Original line number Diff line number Diff line
@@ -799,6 +799,28 @@ public final class BluetoothGatt implements BluetoothProfile {
     * error
     */
    private boolean registerApp(BluetoothGattCallback callback, Handler handler) {
        return registerApp(callback, handler, false);
    }

    /**
     * Register an application callback to start using GATT.
     *
     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
     * is used to notify success or failure if the function returns true.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param callback GATT callback handler that will receive asynchronous callbacks.
     * @param eattSupport specifies whether client app needs EATT channel for client operations.
     * If both local and remote devices support EATT and local app asks for EATT, GATT client
     * operations will be performed using EATT channel.
     * If either local or remote device doesn't support EATT but local App asks for EATT, GATT
     * client operations will be performed using unenhanced ATT channel.
     * @return If true, the callback will be called to notify success or failure, false on immediate
     * error
     * @hide
     */
    private boolean registerApp(BluetoothGattCallback callback, Handler handler, boolean eattSupport) {
        if (DBG) Log.d(TAG, "registerApp()");
        if (mService == null) return false;

@@ -808,7 +830,7 @@ public final class BluetoothGatt implements BluetoothProfile {
        if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);

        try {
            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback, eattSupport);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
@@ -859,9 +881,45 @@ public final class BluetoothGatt implements BluetoothProfile {
    @UnsupportedAppUsage
    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
            Handler handler) {
        return connect(autoConnect, callback, handler, false);
    }

    /**
     * Initiate a connection to a Bluetooth GATT capable device.
     *
     * <p>The connection may not be established right away, but will be
     * completed when the remote device is available. A
     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
     * invoked when the connection state changes as a result of this function.
     *
     * <p>The autoConnect parameter determines whether to actively connect to
     * the remote device, or rather passively scan and finalize the connection
     * when the remote device is in range/available. Generally, the first ever
     * connection to a device should be direct (autoConnect set to false) and
     * subsequent connections to known devices should be invoked with the
     * autoConnect parameter set to true.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param device Remote device to connect to
     * @param autoConnect Whether to directly connect to the remote device (false) or to
     * automatically connect as soon as the remote device becomes available (true).
     * @param eattSupport specifies whether client app needs EATT channel for client operations.
     * If both local and remote devices support EATT and local app asks for EATT, GATT client
     * operations will be performed using EATT channel.
     * If either local or remote device doesn't support EATT but local App asks for EATT, GATT
     * client operations will be performed using unenhanced ATT channel.
     * @return true, if the connection attempt was initiated successfully
     *
     * @hide
     */
    @UnsupportedAppUsage
    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
            Handler handler, boolean eattSupport) {
        if (DBG) {
            Log.d(TAG,
                    "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
                    "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect
                    + ", eattSupport: " + eattSupport);
        }
        synchronized (mStateLock) {
            if (mConnState != CONN_STATE_IDLE) {
@@ -872,7 +930,7 @@ public final class BluetoothGatt implements BluetoothProfile {

        mAutoConnect = autoConnect;

        if (!registerApp(callback, handler)) {
        if (!registerApp(callback, handler, eattSupport)) {
            synchronized (mStateLock) {
                mConnState = CONN_STATE_IDLE;
            }
+19 −1
Original line number Diff line number Diff line
@@ -443,6 +443,24 @@ public final class BluetoothGattServer implements BluetoothProfile {
     * error
     */
    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
        return registerCallback(callback, false);
    }

    /**
     * Register an application callback to start using GattServer.
     *
     * <p>This is an asynchronous call. The callback is used to notify
     * success or failure if the function returns true.
     *
     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
     *
     * @param callback GATT callback handler that will receive asynchronous callbacks.
     * @param eattSupport whether eattSupport is needed for Gatt server
     * @return true, the callback will be called to notify success or failure, false on immediate
     * error
     * @hide
     */
    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback, boolean eattSupport) {
        if (DBG) Log.d(TAG, "registerCallback()");
        if (mService == null) {
            Log.e(TAG, "GATT service not available");
@@ -459,7 +477,7 @@ public final class BluetoothGattServer implements BluetoothProfile {

            mCallback = callback;
            try {
                mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
                mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback, eattSupport);
            } catch (RemoteException e) {
                Log.e(TAG, "", e);
                mCallback = null;
+26 −1
Original line number Diff line number Diff line
@@ -233,6 +233,31 @@ public final class BluetoothManager {
     */
    public BluetoothGattServer openGattServer(Context context,
            BluetoothGattServerCallback callback, int transport) {
        return (openGattServer(context, callback, transport, false));
    }

    /**
     * Open a GATT Server
     * The callback is used to deliver results to Caller, such as connection status as well
     * as the results of any other GATT server operations.
     * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
     * to conduct GATT server operations.
     *
     * @param context App context
     * @param callback GATT server callback handler that will receive asynchronous callbacks.
     * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
     * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
     * BluetoothDevice#TRANSPORT_LE}
     * @param eattSupport specifies whether server app needs EATT channel for server operations.
     * If both local and remote devices support EATT, local app asks for EATT using this API and
     * calls server connect, GATT server operations will be performed using EATT channel.
     * If either local or remote device doesn't support EATT but local App asks for EATT, GATT
     * server operations will be performed using unenhanced ATT channel.
     * @return BluetoothGattServer instance
     * @hide
     */
    public BluetoothGattServer openGattServer(Context context,
            BluetoothGattServerCallback callback, int transport, boolean eattSupport) {
        if (context == null || callback == null) {
            throw new IllegalArgumentException("null parameter: " + context + " " + callback);
        }
@@ -248,7 +273,7 @@ public final class BluetoothManager {
                return null;
            }
            BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt, transport);
            Boolean regStatus = mGattServer.registerCallback(callback);
            Boolean regStatus = mGattServer.registerCallback(callback, eattSupport);
            return regStatus ? mGattServer : null;
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
Loading