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

Commit 5fbf8782 authored by Mohammad Sabri's avatar Mohammad Sabri Committed by Mohammad Kh Sabri
Browse files

Floss: Pandora GATT: Fix ReadCharacteristicsFromUuid return status

This patch also:
-Replaces raise with context.abort
-Fixes typo

Bug: 300942866
Test: mma packages/modules/Bluetooth && pts-bot GATT
Tag: #floss
Flag: EXEMPT floss only changes
Change-Id: I0254ece08a27aa70e84e5fb7564f703eb1a35e0e
parent 0cfbfaa8
Loading
Loading
Loading
Loading
+34 −33
Original line number Diff line number Diff line
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# 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
#
#     https://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,
# 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.
@@ -92,31 +92,31 @@ class GattServerCallbacks:
        """
        pass

    def on_characteristic_write_request(self, addr, trans_id, offset, len, is_prep, need_rsp, handle, value):
    def on_characteristic_write_request(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value):
        """Called when there is a request to write a characteristic.

        Args:
            addr: Remote device MAC address.
            trans_id: Transaction id.
            offset: Represents the offset at which the attribute value should be written.
            len: The length of the attribute value that should be written.
            is_prep: A boolean value representing whether it's a "prepare write" command.
            need_rsp: A boolean value representing whether it's a "write no response" command.
            length: The length of the attribute value that should be written.
            is_prep: A boolean value representing whether it's a 'prepare write' command.
            need_rsp: A boolean value representing whether it's a 'write no response' command.
            handle: The characteristic handle.
            value: The value that should be written to the attribute.
        """
        pass

    def on_descriptor_write_request(self, addr, trans_id, offset, len, is_prep, need_rsp, handle, value):
    def on_descriptor_write_request(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value):
        """Called when there is a request to write a descriptor.

        Args:
            addr: Remote device MAC address.
            trans_id: Transaction id.
            offset: The offset value at which the value should be written.
            len: The length of the value that should be written.
            is_prep: A boolean value representing whether it's a "prepare write" command.
            need_rsp: A boolean value representing whether it's a "write no response" command.
            length: The length of the value that should be written.
            is_prep: A boolean value representing whether it's a 'prepare write' command.
            need_rsp: A boolean value representing whether it's a 'write no response' command.
            handle: The descriptor handle.
            value: The value that should be written to the descriptor.
        """
@@ -300,7 +300,7 @@ class FlossGattServer(GattServerCallbacks):
                    <arg type="s" name="addr" direction="in" />
                    <arg type="i" name="trans_id" direction="in" />
                    <arg type="i" name="offset" direction="in" />
                    <arg type="i" name="len" direction="in" />
                    <arg type="i" name="length" direction="in" />
                    <arg type="b" name="is_prep" direction="in" />
                    <arg type="b" name="need_rsp" direction="in" />
                    <arg type="i" name="handle" direction="in" />
@@ -310,7 +310,7 @@ class FlossGattServer(GattServerCallbacks):
                    <arg type="s" name="addr" direction="in" />
                    <arg type="i" name="trans_id" direction="in" />
                    <arg type="i" name="offset" direction="in" />
                    <arg type="i" name="len" direction="in" />
                    <arg type="i" name="length" direction="in" />
                    <arg type="b" name="is_prep" direction="in" />
                    <arg type="b" name="need_rsp" direction="in" />
                    <arg type="i" name="handle" direction="in" />
@@ -419,21 +419,22 @@ class FlossGattServer(GattServerCallbacks):
            for observer in self.observers.values():
                observer.on_characteristic_read_request(addr, trans_id, offset, is_long, handle)

        def OnCharacteristicWriteRequest(self, addr, trans_id, offset, len, is_prep, need_rsp, handle, value):
        def OnCharacteristicWriteRequest(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value):
            """Handles characteristic write request callback.

            Args:
                addr: Remote device MAC address.
                trans_id: Transaction id.
                offset: Represents the offset from which the attribute value should be read.
                len: The length of the value that should be written.
                length: The length of the value that should be written.
                is_prep: A boolean value representing whether it's a 'prepare write' command.
                need_rsp: A boolean value representing whether it's a 'write no response' command.
                handle: The descriptor handle.
                value: The value that should be written to the descriptor.
            """
            for observer in self.observers.values():
                observer.on_characteristic_write_request(addr, trans_id, offset, len, is_prep, need_rsp, handle, value)
                observer.on_characteristic_write_request(addr, trans_id, offset, length, is_prep, need_rsp, handle,
                                                         value)

        def OnDescriptorReadRequest(self, addr, trans_id, offset, is_long, handle):
            """Handles descriptor read request callback.
@@ -449,21 +450,21 @@ class FlossGattServer(GattServerCallbacks):
            for observer in self.observers.values():
                observer.on_descriptor_read_request(addr, trans_id, offset, is_long, handle)

        def OnDescriptorWriteRequest(self, addr, trans_id, offset, len, is_prep, need_rsp, handle, value):
        def OnDescriptorWriteRequest(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value):
            """Handles descriptor write request callback.

            Args:
                addr: Remote device MAC address.
                trans_id: Transaction id.
                offset: The offset value at which the value should be written.
                len: The length of the value that should be written.
                is_prep: A boolean value representing whether it's a "prepare write" command.
                need_rsp: A boolean value representing whether it's a "write no response" command.
                length: The length of the value that should be written.
                is_prep: A boolean value representing whether it's a 'prepare write' command.
                need_rsp: A boolean value representing whether it's a 'write no response' command.
                handle: The descriptor handle.
                value: The value that should be written to the descriptor.
            """
            for observer in self.observers.values():
                observer.on_descriptor_write_request(addr, trans_id, offset, len, is_prep, need_rsp, handle, value)
                observer.on_descriptor_write_request(addr, trans_id, offset, length, is_prep, need_rsp, handle, value)

        def OnExecuteWrite(self, addr, trans_id, exec_write):
            """Handles execute write callback.
@@ -561,7 +562,7 @@ class FlossGattServer(GattServerCallbacks):
        self.objpath = self.GATT_OBJECT_PATTERN.format(hci)
        self.cb_dbus_objpath = utils.generate_dbus_cb_objpath(self.GATT_CB_OBJ_NAME, self.hci)

        # Create and publish callbacks
        # Create and publish callbacks.
        self.callbacks = self.ExportedGattServerCallbacks()
        self.callbacks.add_observer('gatt_testing_server', self)
        self.bus.register_object(self.cb_dbus_objpath, self.callbacks, None)
@@ -1173,42 +1174,42 @@ class FlossGattServer(GattServerCallbacks):
        self.on_attr_read(addr, trans_id, offset, is_long, handle)

    @utils.glib_callback()
    def on_characteristic_write_request(self, addr, trans_id, offset, len, is_prep, need_rsp, handle, value):
    def on_characteristic_write_request(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value):
        """Handles the write request of the characteristic callback.

        Args:
            addr: Remote device MAC address.
            trans_id: Transaction id.
            offset: Represents the offset at which the attribute value should be written.
            len: The length of the attribute value that should be written.
            is_prep: A boolean value representing whether it's a "prepare write" command.
            need_rsp: A boolean value representing whether it's a "write no response" command.
            length: The length of the attribute value that should be written.
            is_prep: A boolean value representing whether it's a 'prepare write' command.
            need_rsp: A boolean value representing whether it's a 'write no response' command.
            handle: The characteristic handle.
            value: The value that should be written to the attribute.
        """
        logging.debug(
            'on_characteristic_write_request: device address: %s, trans_id: %s, offset: %s, length: %s, is_prep: %s, '
            'need_rsp: %s, handle: %s, values: %s', addr, trans_id, offset, len, is_prep, need_rsp, handle, value)
        self.on_attr_write(addr, trans_id, offset, len, is_prep, need_rsp, handle, value)
            'need_rsp: %s, handle: %s, values: %s', addr, trans_id, offset, length, is_prep, need_rsp, handle, value)
        self.on_attr_write(addr, trans_id, offset, length, is_prep, need_rsp, handle, value)

    @utils.glib_callback()
    def on_descriptor_write_request(self, addr, trans_id, offset, len, is_prep, need_rsp, handle, value):
    def on_descriptor_write_request(self, addr, trans_id, offset, length, is_prep, need_rsp, handle, value):
        """Handles the write request of the descriptor callback.

        Args:
            addr: Remote device MAC address.
            trans_id: Transaction id.
            offset: The offset value at which the value should be written.
            len: The length of the value that should be written.
            is_prep: A boolean value representing whether it's a "prepare write" command.
            need_rsp: A boolean value representing whether it's a "write no response" command.
            length: The length of the value that should be written.
            is_prep: A boolean value representing whether it's a 'prepare write' command.
            need_rsp: A boolean value representing whether it's a 'write no response' command.
            handle: The descriptor handle.
            value: The value that should be written to the descriptor.
        """
        logging.debug(
            'on_descriptor_write_request: device address: %s, trans_id: %s, offset: %s, length: %s, is_prep: %s, '
            'need_rsp: %s, handle: %s, values: %s', addr, trans_id, offset, len, is_prep, need_rsp, handle, value)
        self.on_attr_write(addr, trans_id, offset, len, is_prep, need_rsp, handle, value)
            'need_rsp: %s, handle: %s, values: %s', addr, trans_id, offset, length, is_prep, need_rsp, handle, value)
        self.on_attr_write(addr, trans_id, offset, length, is_prep, need_rsp, handle, value)

    @utils.glib_callback()
    def on_execute_write(self, addr, trans_id, exec_write):
+26 −37
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.configure_mtu(address, request.mtu)
            status = await configure_mtu
            if status != floss_enums.GattStatus.SUCCESS:
                raise RuntimeError('Failed to configure MTU.')
                await context.abort(grpc.StatusCode.INTERNAL, 'Failed to configure MTU.')
        finally:
            self.bluetooth.gatt_client.unregister_callback_observer(name, observer)
        return gatt_pb2.ExchangeMTUResponse()
@@ -255,7 +255,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):

            services, status = await search_services
            if status != floss_enums.GattStatus.SUCCESS:
                raise RuntimeError('Failed to find services.')
                await context.abort(grpc.StatusCode.INTERNAL, 'Failed to find services.')
            response = gatt_pb2.DiscoverServicesResponse()
            for serv in services:
                response.services.append(self.create_gatt_service(serv))
@@ -295,8 +295,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):

                status = self.bluetooth.fetch_remote(address)
                if not status:
                    raise RuntimeError(f'Failed to fetch remote device {address} '
                                       f'uuids.')
                    await context.abort(grpc.StatusCode.INTERNAL, f'Failed to fetch remote device {address} uuids.')
                await device_uuids_changed
                uuids = self.bluetooth.get_remote_uuids(address)
            response = gatt_pb2.DiscoverServicesSdpResponse()
@@ -335,7 +334,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.refresh_device(address)
            status = await refresh
            if status != floss_enums.GattStatus.SUCCESS:
                raise RuntimeError('Failed to clear cache.')
                await context.abort(grpc.StatusCode.INTERNAL, 'Failed to clear cache.')
        finally:
            self.bluetooth.gatt_client.unregister_callback_observer(name, observer)
        return gatt_pb2.ClearCacheResponse()
@@ -370,8 +369,6 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.gatt_client.register_callback_observer(name, observer)
            self.bluetooth.read_characteristic(address, request.handle, self.AUTHENTICATION_NONE)
            value, status = await characteristic_from_handle
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Found no characteristic with supported handle.')
        finally:
            self.bluetooth.gatt_client.unregister_callback_observer(name, observer)

@@ -407,8 +404,6 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            def on_characteristic_read(self, addr, status, handle, value):
                if addr != self.task['address']:
                    return
                if handle < self.task['start_handle'] or handle > self.task['end_handle']:
                    return
                if floss_enums.GattStatus(status) != floss_enums.GattStatus.SUCCESS:
                    logging.error('Failed to read characteristic from handle. Status: %s', status)
                future = self.task['characteristic_from_uuid']
@@ -427,8 +422,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.discover_services(address)
            services, status = await search_services
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Found no services.')

                await context.abort(grpc.StatusCode.INTERNAL, 'Found no services.')
            characteristic_from_uuid = asyncio.get_running_loop().create_future()
            observer = ReadCharacteristicsFromUuidObserver({
                'characteristic_from_uuid': characteristic_from_uuid,
@@ -449,27 +443,26 @@ class GATTService(gatt_grpc_aio.GATTServicer):
                                                                      characteristic['instance_id'],
                                                                      self.AUTHENTICATION_NONE)
                        status, handle, value = await characteristic_from_uuid
                        if status != floss_enums.GattStatus.SUCCESS:
                            raise ValueError(f'Found no characteristic from uuid={request.uuid}.')
                        characteristics.append((status, handle, value))
        finally:
            for name, observer in observers:
                self.bluetooth.gatt_client.unregister_callback_observer(name, observer)

            if not characteristics:
            return gatt_pb2.ReadCharacteristicsFromUuidResponse(characteristics_read=[
                gatt_pb2.ReadCharacteristicResponse(
                    value=gatt_pb2.AttValue(value=bytes(), handle=request.start_handle),
                    status=gatt_pb2.UNKNOWN_ERROR,
                )
                self.bluetooth.read_using_characteristic_uuid(address, request.uuid, request.start_handle,
                                                              request.end_handle, self.AUTHENTICATION_NONE)
                status, handle, value = await characteristic_from_uuid
                result = gatt_pb2.ReadCharacteristicsFromUuidResponse(characteristics_read=[
                    gatt_pb2.ReadCharacteristicResponse(value=gatt_pb2.AttValue(value=bytes(value), handle=handle),
                                                        status=status)
                ])

        return gatt_pb2.ReadCharacteristicsFromUuidResponse(characteristics_read=[
            else:
                result = gatt_pb2.ReadCharacteristicsFromUuidResponse(characteristics_read=[
                    gatt_pb2.ReadCharacteristicResponse(
                        value=gatt_pb2.AttValue(value=bytes(value), handle=handle),
                        status=status,
                    ) for status, handle, value in characteristics
                ])
        finally:
            for name, observer in observers:
                self.bluetooth.gatt_client.unregister_callback_observer(name, observer)
        return result

    async def ReadCharacteristicDescriptorFromHandle(
            self, request: gatt_pb2.ReadCharacteristicDescriptorRequest,
@@ -502,8 +495,6 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.gatt_client.register_callback_observer(name, observer)
            self.bluetooth.read_descriptor(address, request.handle, self.AUTHENTICATION_NONE)
            value, status = await descriptor
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Found no descriptor with supported handle.')
        finally:
            self.bluetooth.gatt_client.unregister_callback_observer(name, observer)

@@ -569,7 +560,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.add_service(serv_dic)
            status, service = await register_service
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Failed to register service.')
                await context.abort(grpc.StatusCode.INTERNAL, 'Failed to register service.')
        finally:
            self.bluetooth.gatt_server.unregister_callback_observer(name, observer)

@@ -634,7 +625,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.read_descriptor(address, request.handle, self.AUTHENTICATION_NONE)
            value, status = await descriptor_futures['read_descriptor']
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Found no descriptor with supported handle.')
                await context.abort(grpc.StatusCode.INTERNAL, 'Found no descriptor with supported handle.')

            search_services = asyncio.get_running_loop().create_future()
            observer = DiscoveryObserver({'search_services': search_services, 'address': address})
@@ -644,7 +635,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.discover_services(address)
            services, status = await search_services
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Found no device services.')
                await context.abort(grpc.StatusCode.INTERNAL, 'Found no device services.')

            characteristic_handle = None
            for serv in services:
@@ -665,8 +656,6 @@ class GATTService(gatt_grpc_aio.GATTServicer):
                self.bluetooth.write_descriptor(address, request.handle, self.AUTHENTICATION_NONE,
                                                self.ENABLE_NOTIFICATION_VALUE)
            status = await descriptor_futures['write_descriptor']
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Can not write descriptor.')
        finally:
            for name, observer in observers:
                self.bluetooth.gatt_client.unregister_callback_observer(name, observer)
@@ -722,7 +711,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.read_descriptor(address, request.handle, self.AUTHENTICATION_NONE)
            value, status = await read_descriptor
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Found no descriptor with supported handle.')
                await context.abort(grpc.StatusCode.INTERNAL, 'Found no descriptor with supported handle.')

            search_services = asyncio.get_running_loop().create_future()
            observer = DiscoveryObserver({'search_services': search_services, 'address': address})
@@ -732,7 +721,7 @@ class GATTService(gatt_grpc_aio.GATTServicer):
            self.bluetooth.discover_services(address)
            services, status = await search_services
            if status != floss_enums.GattStatus.SUCCESS:
                raise ValueError('Found no device services.')
                await context.abort(grpc.StatusCode.INTERNAL, 'Found no device services.')

            characteristic_handle = None
            for serv in services: