/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qlowenergycontroller_android_p.h"
#include <QtCore/QLoggingCategory>
#include <QtAndroidExtras/QAndroidJniEnvironment>
#include <QtAndroidExtras/QAndroidJniObject>
#include <QtBluetooth/QLowEnergyServiceData>
#include <QtBluetooth/QLowEnergyCharacteristicData>
#include <QtBluetooth/QLowEnergyDescriptorData>
#include <QtBluetooth/QLowEnergyAdvertisingData>
#include <QtBluetooth/QLowEnergyAdvertisingParameters>
#include <QtBluetooth/QLowEnergyConnectionParameters>


QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QT_BT_ANDROID)

Q_DECLARE_METATYPE(QAndroidJniObject)

// Conversion: QBluetoothUuid -> java.util.UUID
static QAndroidJniObject javaUuidfromQtUuid(const QBluetoothUuid& uuid)
{
    QString output = uuid.toString();
    // cut off leading and trailing brackets
    output = output.mid(1, output.size()-2);

    QAndroidJniObject javaString = QAndroidJniObject::fromString(output);
    QAndroidJniObject javaUuid = QAndroidJniObject::callStaticObjectMethod(
                "java/util/UUID", "fromString", "(Ljava/lang/String;)Ljava/util/UUID;",
                javaString.object());

    return javaUuid;
}

QLowEnergyControllerPrivateAndroid::QLowEnergyControllerPrivateAndroid()
    : QLowEnergyControllerPrivate(),
      hub(0)
{
    registerQLowEnergyControllerMetaType();
}

QLowEnergyControllerPrivateAndroid::~QLowEnergyControllerPrivateAndroid()
{
    if (role == QLowEnergyController::PeripheralRole) {
        if (hub)
            hub->javaObject().callMethod<void>("disconnectServer");
    }
}

void QLowEnergyControllerPrivateAndroid::init()
{
    // Android Central/Client support starts with v18
    // Peripheral/Server support requires Android API v21
    const bool isPeripheral = (role == QLowEnergyController::PeripheralRole);
    const jint version = QtAndroidPrivate::androidSdkVersion();

    if (isPeripheral) {
        if (version < 21) {
            qWarning() << "Qt Bluetooth LE Peripheral support not available"
                          "on Android devices below version 21";
            return;
        }

        qRegisterMetaType<QAndroidJniObject>();

        hub = new LowEnergyNotificationHub(remoteDevice, isPeripheral, this);
        // we only connect to the peripheral role specific signals
        // TODO add connections as they get added later on
        connect(hub, &LowEnergyNotificationHub::connectionUpdated,
                this, &QLowEnergyControllerPrivateAndroid::connectionUpdated);
        connect(hub, &LowEnergyNotificationHub::advertisementError,
                this, &QLowEnergyControllerPrivateAndroid::advertisementError);
        connect(hub, &LowEnergyNotificationHub::serverCharacteristicChanged,
                this, &QLowEnergyControllerPrivateAndroid::serverCharacteristicChanged);
        connect(hub, &LowEnergyNotificationHub::serverDescriptorWritten,
                this, &QLowEnergyControllerPrivateAndroid::serverDescriptorWritten);
    } else {
        if (version < 18) {
            qWarning() << "Qt Bluetooth LE Central/Client support not available"
                          "on Android devices below version 18";
            return;
        }

        hub = new LowEnergyNotificationHub(remoteDevice, isPeripheral, this);
        // we only connect to the central role specific signals
        connect(hub, &LowEnergyNotificationHub::connectionUpdated,
                this, &QLowEnergyControllerPrivateAndroid::connectionUpdated);
        connect(hub, &LowEnergyNotificationHub::servicesDiscovered,
                this, &QLowEnergyControllerPrivateAndroid::servicesDiscovered);
        connect(hub, &LowEnergyNotificationHub::serviceDetailsDiscoveryFinished,
                this, &QLowEnergyControllerPrivateAndroid::serviceDetailsDiscoveryFinished);
        connect(hub, &LowEnergyNotificationHub::characteristicRead,
                this, &QLowEnergyControllerPrivateAndroid::characteristicRead);
        connect(hub, &LowEnergyNotificationHub::descriptorRead,
                this, &QLowEnergyControllerPrivateAndroid::descriptorRead);
        connect(hub, &LowEnergyNotificationHub::characteristicWritten,
                this, &QLowEnergyControllerPrivateAndroid::characteristicWritten);
        connect(hub, &LowEnergyNotificationHub::descriptorWritten,
                this, &QLowEnergyControllerPrivateAndroid::descriptorWritten);
        connect(hub, &LowEnergyNotificationHub::characteristicChanged,
                this, &QLowEnergyControllerPrivateAndroid::characteristicChanged);
    }
}

void QLowEnergyControllerPrivateAndroid::connectToDevice()
{
    if (!hub)
        return; // Android version below v18

    // required to pass unit test on default backend
    if (remoteDevice.isNull()) {
        qWarning() << "Invalid/null remote device address";
        setError(QLowEnergyController::UnknownRemoteDeviceError);
        return;
    }

    setState(QLowEnergyController::ConnectingState);

    if (!hub->javaObject().isValid()) {
        qCWarning(QT_BT_ANDROID) << "Cannot initiate QtBluetoothLE";
        setError(QLowEnergyController::ConnectionError);
        setState(QLowEnergyController::UnconnectedState);
        return;
    }

    bool result = hub->javaObject().callMethod<jboolean>("connect");
    if (!result) {
        setError(QLowEnergyController::ConnectionError);
        setState(QLowEnergyController::UnconnectedState);
        return;
    }
}

void QLowEnergyControllerPrivateAndroid::disconnectFromDevice()
{
    /* Catch an Android timeout bug. If the device is connecting but cannot
     * physically connect it seems to ignore the disconnect call below.
     * At least BluetoothGattCallback.onConnectionStateChange never
     * arrives. The next BluetoothGatt.connect() works just fine though.
     * */

    QLowEnergyController::ControllerState oldState = state;
    setState(QLowEnergyController::ClosingState);

    if (hub) {
        if (role == QLowEnergyController::PeripheralRole)
            hub->javaObject().callMethod<void>("disconnectServer");
        else
            hub->javaObject().callMethod<void>("disconnect");
    }

    if (oldState == QLowEnergyController::ConnectingState)
        setState(QLowEnergyController::UnconnectedState);
}

void QLowEnergyControllerPrivateAndroid::discoverServices()
{
    if (hub && hub->javaObject().callMethod<jboolean>("discoverServices")) {
        qCDebug(QT_BT_ANDROID) << "Service discovery initiated";
    } else {
        //revert to connected state
        setError(QLowEnergyController::NetworkError);
        setState(QLowEnergyController::ConnectedState);
    }
}

void QLowEnergyControllerPrivateAndroid::discoverServiceDetails(const QBluetoothUuid &service)
{
    if (!serviceList.contains(service)) {
        qCWarning(QT_BT_ANDROID) << "Discovery of unknown service" << service.toString()
                                 << "not possible";
        return;
    }

    if (!hub)
        return;

    //cut leading { and trailing } {xxx-xxx}
    QString tempUuid = service.toString();
    tempUuid.chop(1); //remove trailing '}'
    tempUuid.remove(0, 1); //remove first '{'

    QAndroidJniEnvironment env;
    QAndroidJniObject uuid = QAndroidJniObject::fromString(tempUuid);
    bool result = hub->javaObject().callMethod<jboolean>("discoverServiceDetails",
                                                         "(Ljava/lang/String;)Z",
                                                         uuid.object<jstring>());
    if (!result) {
        QSharedPointer<QLowEnergyServicePrivate> servicePrivate =
                serviceList.value(service);
        if (!servicePrivate.isNull()) {
            servicePrivate->setError(QLowEnergyService::UnknownError);
            servicePrivate->setState(QLowEnergyService::DiscoveryRequired);
        }
        qCWarning(QT_BT_ANDROID) << "Cannot discover details for" << service.toString();
        return;
    }

    qCDebug(QT_BT_ANDROID) << "Discovery of" << service << "started";
}

void QLowEnergyControllerPrivateAndroid::writeCharacteristic(
        const QSharedPointer<QLowEnergyServicePrivate> service,
        const QLowEnergyHandle charHandle,
        const QByteArray &newValue,
        QLowEnergyService::WriteMode mode)
{
    //TODO don't ignore WriteWithResponse, right now we assume responses
    Q_ASSERT(!service.isNull());

    if (!service->characteristicList.contains(charHandle))
        return;

    QAndroidJniEnvironment env;
    jbyteArray payload;
    payload = env->NewByteArray(newValue.size());
    env->SetByteArrayRegion(payload, 0, newValue.size(),
                            (jbyte *)newValue.constData());

    bool result = false;
    if (hub) {
        if (role == QLowEnergyController::CentralRole) {
            qCDebug(QT_BT_ANDROID) << "Write characteristic with handle " << charHandle
                     << newValue.toHex() << "(service:" << service->uuid
                     << ", writeWithResponse:" << (mode == QLowEnergyService::WriteWithResponse)
                     << ", signed:" << (mode == QLowEnergyService::WriteSigned) << ")";
            result = hub->javaObject().callMethod<jboolean>("writeCharacteristic", "(I[BI)Z",
                          charHandle, payload, mode);
        } else { // peripheral mode
            qCDebug(QT_BT_ANDROID) << "Write server characteristic with handle " << charHandle
                     << newValue.toHex() << "(service:" << service->uuid;

            const auto &characteristic = characteristicForHandle(charHandle);
            if (characteristic.isValid()) {
                const QAndroidJniObject charUuid = javaUuidfromQtUuid(characteristic.uuid());
                result = hub->javaObject().callMethod<jboolean>(
                            "writeCharacteristic",
                            "(Landroid/bluetooth/BluetoothGattService;Ljava/util/UUID;[B)Z",
                            service->androidService.object(), charUuid.object(), payload);
            }
        }
    }

    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        result = false;
    }

    env->DeleteLocalRef(payload);

    if (!result)
        service->setError(QLowEnergyService::CharacteristicWriteError);
}

void QLowEnergyControllerPrivateAndroid::writeDescriptor(
        const QSharedPointer<QLowEnergyServicePrivate> service,
        const QLowEnergyHandle charHandle,
        const QLowEnergyHandle descHandle,
        const QByteArray &newValue)
{
    Q_ASSERT(!service.isNull());

    QAndroidJniEnvironment env;
    jbyteArray payload;
    payload = env->NewByteArray(newValue.size());
    env->SetByteArrayRegion(payload, 0, newValue.size(),
                            (jbyte *)newValue.constData());

    bool result = false;
    if (hub) {
        if (role == QLowEnergyController::CentralRole) {
            qCDebug(QT_BT_ANDROID) << "Write descriptor with handle " << descHandle
                     << newValue.toHex() << "(service:" << service->uuid << ")";
            result = hub->javaObject().callMethod<jboolean>("writeDescriptor", "(I[B)Z",
                                                            descHandle, payload);
        } else {
            const auto &characteristic = characteristicForHandle(charHandle);
            const auto &descriptor = descriptorForHandle(descHandle);
            if (characteristic.isValid() && descriptor.isValid()) {
                qCDebug(QT_BT_ANDROID) << "Write descriptor" << descriptor.uuid()
                                   << "(service:" << service->uuid
                                   << "char: " << characteristic.uuid() << ")";
                const QAndroidJniObject charUuid = javaUuidfromQtUuid(characteristic.uuid());
                const QAndroidJniObject descUuid = javaUuidfromQtUuid(descriptor.uuid());
                result = hub->javaObject().callMethod<jboolean>(
                            "writeDescriptor",
                            "(Landroid/bluetooth/BluetoothGattService;Ljava/util/UUID;Ljava/util/UUID;[B)Z",
                            service->androidService.object(), charUuid.object(),
                            descUuid.object(), payload);
            }
        }
    }

    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        result = false;
    }

    env->DeleteLocalRef(payload);

    if (!result)
        service->setError(QLowEnergyService::DescriptorWriteError);
}

void QLowEnergyControllerPrivateAndroid::readCharacteristic(
        const QSharedPointer<QLowEnergyServicePrivate> service,
        const QLowEnergyHandle charHandle)
{
    Q_ASSERT(!service.isNull());

    if (!service->characteristicList.contains(charHandle))
        return;

    QAndroidJniEnvironment env;
    bool result = false;
    if (hub) {
        qCDebug(QT_BT_ANDROID) << "Read characteristic with handle"
                               <<  charHandle << service->uuid;
        result = hub->javaObject().callMethod<jboolean>("readCharacteristic",
                      "(I)Z", charHandle);
    }

    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        result = false;
    }

    if (!result)
        service->setError(QLowEnergyService::CharacteristicReadError);
}

void QLowEnergyControllerPrivateAndroid::readDescriptor(
        const QSharedPointer<QLowEnergyServicePrivate> service,
        const QLowEnergyHandle /*charHandle*/,
        const QLowEnergyHandle descriptorHandle)
{
    Q_ASSERT(!service.isNull());

    QAndroidJniEnvironment env;
    bool result = false;
    if (hub) {
        qCDebug(QT_BT_ANDROID) << "Read descriptor with handle"
                               <<  descriptorHandle << service->uuid;
        result = hub->javaObject().callMethod<jboolean>("readDescriptor",
                      "(I)Z", descriptorHandle);
    }

    if (env->ExceptionOccurred()) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        result = false;
    }

    if (!result)
        service->setError(QLowEnergyService::DescriptorReadError);
}

void QLowEnergyControllerPrivateAndroid::connectionUpdated(
        QLowEnergyController::ControllerState newState,
        QLowEnergyController::Error errorCode)
{
    qCDebug(QT_BT_ANDROID) << "Connection updated:"
                           << "error:" << errorCode
                           << "oldState:" << state
                           << "newState:" << newState;

    if (role == QLowEnergyController::PeripheralRole)
        peripheralConnectionUpdated(newState, errorCode);
    else
        centralConnectionUpdated(newState, errorCode);
}

// called if server/peripheral
void QLowEnergyControllerPrivateAndroid::peripheralConnectionUpdated(
        QLowEnergyController::ControllerState newState,
        QLowEnergyController::Error errorCode)
{
    // Java errorCode can be larger than max QLowEnergyController::Error
    if (errorCode > QLowEnergyController::AdvertisingError)
        errorCode = QLowEnergyController::UnknownError;

    if (errorCode != QLowEnergyController::NoError)
        setError(errorCode);

    const QLowEnergyController::ControllerState oldState = state;
    setState(newState);

    // disconnect implies stop of advertisement
    if (newState == QLowEnergyController::UnconnectedState)
        stopAdvertising();


    Q_Q(QLowEnergyController);
    if (oldState == QLowEnergyController::ConnectedState
            && newState != QLowEnergyController::ConnectedState) {
        remoteDevice.clear();
        remoteName.clear();
        emit q->disconnected();
    } else if (newState == QLowEnergyController::ConnectedState
                 && oldState != QLowEnergyController::ConnectedState) {
        if (hub) {
            remoteDevice = QBluetoothAddress(hub->javaObject().callObjectMethod<jstring>("remoteAddress").toString());
            remoteName = hub->javaObject().callObjectMethod<jstring>("remoteName").toString();
        }
        emit q->connected();
    }
}

// called if client/central
void QLowEnergyControllerPrivateAndroid::centralConnectionUpdated(
        QLowEnergyController::ControllerState newState,
        QLowEnergyController::Error errorCode)
{
    Q_Q(QLowEnergyController);

    const QLowEnergyController::ControllerState oldState = state;

    if (errorCode != QLowEnergyController::NoError) {
        // ConnectionError if transition from Connecting to Connected
        if (oldState == QLowEnergyController::ConnectingState) {
            setError(QLowEnergyController::ConnectionError);
            /* There is a bug in Android, when connecting to an unconnectable
             * device. The connection times out and Android sends error code
             * 133 (doesn't exist) and STATE_CONNECTED. A subsequent disconnect()
             * call never sends a STATE_DISCONNECTED either.
             * As workaround we will trigger disconnect when we encounter
             * error during connect attempt. This leaves the controller
             * in a cleaner state.
             * */
            newState = QLowEnergyController::UnconnectedState;
        }
        else
            setError(errorCode);
    }

    setState(newState);
    if (newState == QLowEnergyController::UnconnectedState
            && !(oldState == QLowEnergyController::UnconnectedState
                || oldState == QLowEnergyController::ConnectingState)) {

        // Invalidate the services if the disconnect came from the remote end.
        // Qtherwise we disconnected via QLowEnergyController::disconnectDevice() which
        // triggered invalidation already
        if (!serviceList.isEmpty()) {
            Q_ASSERT(oldState != QLowEnergyController::ClosingState);
            invalidateServices();
        }
        emit q->disconnected();
    } else if (newState == QLowEnergyController::ConnectedState
               && oldState != QLowEnergyController::ConnectedState ) {
        emit q->connected();
    }
}

void QLowEnergyControllerPrivateAndroid::servicesDiscovered(
        QLowEnergyController::Error errorCode, const QString &foundServices)
{
    Q_Q(QLowEnergyController);

    if (errorCode == QLowEnergyController::NoError) {
        //Android delivers all services in one go
        const QStringList list = foundServices.split(QStringLiteral(" "), QString::SkipEmptyParts);
        for (const QString &entry : list) {
            const QBluetoothUuid service(entry);
            if (service.isNull())
                return;

            QLowEnergyServicePrivate *priv = new QLowEnergyServicePrivate();
            priv->uuid = service;
            priv->setController(this);

            QSharedPointer<QLowEnergyServicePrivate> pointer(priv);
            serviceList.insert(service, pointer);

            emit q->serviceDiscovered(QBluetoothUuid(entry));
        }

        setState(QLowEnergyController::DiscoveredState);
        emit q->discoveryFinished();
    } else {
        setError(errorCode);
        setState(QLowEnergyController::ConnectedState);
    }
}

void QLowEnergyControllerPrivateAndroid::serviceDetailsDiscoveryFinished(
        const QString &serviceUuid, int startHandle, int endHandle)
{
    const QBluetoothUuid service(serviceUuid);
    if (!serviceList.contains(service)) {
        qCWarning(QT_BT_ANDROID) << "Discovery done of unknown service:"
                                 << service.toString();
        return;
    }

    //update service data
    QSharedPointer<QLowEnergyServicePrivate> pointer =
            serviceList.value(service);
    pointer->startHandle = startHandle;
    pointer->endHandle = endHandle;

    if (hub && hub->javaObject().isValid()) {
        QAndroidJniObject uuid = QAndroidJniObject::fromString(serviceUuid);
        QAndroidJniObject javaIncludes = hub->javaObject().callObjectMethod(
                                        "includedServices",
                                        "(Ljava/lang/String;)Ljava/lang/String;",
                                        uuid.object<jstring>());
        if (javaIncludes.isValid()) {
            const QStringList list = javaIncludes.toString()
                                                 .split(QStringLiteral(" "),
                                                        QString::SkipEmptyParts);
            for (const QString &entry : list) {
                const QBluetoothUuid service(entry);
                if (service.isNull())
                    return;

                pointer->includedServices.append(service);

                // update the type of the included service
                QSharedPointer<QLowEnergyServicePrivate> otherService =
                        serviceList.value(service);
                if (!otherService.isNull())
                    otherService->type |= QLowEnergyService::IncludedService;
            }
        }
    }

    qCDebug(QT_BT_ANDROID) << "Service" << serviceUuid << "discovered (start:"
              << startHandle << "end:" << endHandle << ")" << pointer.data();

    pointer->setState(QLowEnergyService::ServiceDiscovered);
}

void QLowEnergyControllerPrivateAndroid::characteristicRead(
        const QBluetoothUuid &serviceUuid, int handle,
        const QBluetoothUuid &charUuid, int properties, const QByteArray &data)
{
    if (!serviceList.contains(serviceUuid))
        return;

    QSharedPointer<QLowEnergyServicePrivate> service =
            serviceList.value(serviceUuid);
    QLowEnergyHandle charHandle = handle;

    QLowEnergyServicePrivate::CharData &charDetails =
            service->characteristicList[charHandle];

    //Android uses same property value as Qt which is the Bluetooth LE standard
    charDetails.properties = QLowEnergyCharacteristic::PropertyType(properties);
    charDetails.uuid = charUuid;
    charDetails.value = data;
    //value handle always one larger than characteristics value handle
    charDetails.valueHandle = charHandle + 1;

    if (service->state == QLowEnergyService::ServiceDiscovered) {
        QLowEnergyCharacteristic characteristic = characteristicForHandle(charHandle);
        if (!characteristic.isValid()) {
            qCWarning(QT_BT_ANDROID) << "characteristicRead: Cannot find characteristic";
            return;
        }
        emit service->characteristicRead(characteristic, data);
    }
}

void QLowEnergyControllerPrivateAndroid::descriptorRead(
        const QBluetoothUuid &serviceUuid, const QBluetoothUuid &charUuid,
        int descHandle, const QBluetoothUuid &descUuid, const QByteArray &data)
{
    if (!serviceList.contains(serviceUuid))
        return;

    QSharedPointer<QLowEnergyServicePrivate> service =
            serviceList.value(serviceUuid);

    bool entryUpdated = false;

    CharacteristicDataMap::iterator charIt = service->characteristicList.begin();
    for ( ; charIt != service->characteristicList.end(); ++charIt) {
        QLowEnergyServicePrivate::CharData &charDetails = charIt.value();

        if (charDetails.uuid != charUuid)
            continue;

        // new entry created if it doesn't exist
        QLowEnergyServicePrivate::DescData &descDetails =
                charDetails.descriptorList[descHandle];
        descDetails.uuid = descUuid;
        descDetails.value = data;
        entryUpdated = true;
        break;
    }

    if (!entryUpdated) {
        qCWarning(QT_BT_ANDROID) << "Cannot find/update descriptor"
                                 << descUuid << charUuid << serviceUuid;
    } else if (service->state == QLowEnergyService::ServiceDiscovered){
        QLowEnergyDescriptor descriptor = descriptorForHandle(descHandle);
        if (!descriptor.isValid()) {
            qCWarning(QT_BT_ANDROID) << "descriptorRead: Cannot find descriptor";
            return;
        }
        emit service->descriptorRead(descriptor, data);
    }
}

void QLowEnergyControllerPrivateAndroid::characteristicWritten(
        int charHandle, const QByteArray &data, QLowEnergyService::ServiceError errorCode)
{
    QSharedPointer<QLowEnergyServicePrivate> service =
            serviceForHandle(charHandle);
    if (service.isNull())
        return;

    qCDebug(QT_BT_ANDROID) << "Characteristic write confirmation" << service->uuid
                           << charHandle << data.toHex() << errorCode;

    if (errorCode != QLowEnergyService::NoError) {
        service->setError(errorCode);
        return;
    }

    QLowEnergyCharacteristic characteristic = characteristicForHandle(charHandle);
    if (!characteristic.isValid()) {
        qCWarning(QT_BT_ANDROID) << "characteristicWritten: Cannot find characteristic";
        return;
    }

    // only update cache when property is readable. Otherwise it remains
    // empty.
    if (characteristic.properties() & QLowEnergyCharacteristic::Read)
        updateValueOfCharacteristic(charHandle, data, false);
    emit service->characteristicWritten(characteristic, data);
}

void QLowEnergyControllerPrivateAndroid::descriptorWritten(
        int descHandle, const QByteArray &data, QLowEnergyService::ServiceError errorCode)
{
    QSharedPointer<QLowEnergyServicePrivate> service =
            serviceForHandle(descHandle);
    if (service.isNull())
        return;

    qCDebug(QT_BT_ANDROID) << "Descriptor write confirmation" << service->uuid
                           << descHandle << data.toHex() << errorCode;

    if (errorCode != QLowEnergyService::NoError) {
        service->setError(errorCode);
        return;
    }

    QLowEnergyDescriptor descriptor = descriptorForHandle(descHandle);
    if (!descriptor.isValid()) {
        qCWarning(QT_BT_ANDROID) << "descriptorWritten: Cannot find descriptor";
        return;
    }

    updateValueOfDescriptor(descriptor.characteristicHandle(),
                            descHandle, data, false);
    emit service->descriptorWritten(descriptor, data);
}

void QLowEnergyControllerPrivateAndroid::serverDescriptorWritten(
        const QAndroidJniObject &jniDesc, const QByteArray &newValue)
{
    qCDebug(QT_BT_ANDROID) << "Server descriptor change notification" << newValue.toHex();

    // retrieve service, char and desc uuids
    QAndroidJniObject jniChar = jniDesc.callObjectMethod(
                                    "getCharacteristic", "()Landroid/bluetooth/BluetoothGattCharacteristic;");
    if (!jniChar.isValid())
        return;

    QAndroidJniObject jniService = jniChar.callObjectMethod(
                                    "getService", "()Landroid/bluetooth/BluetoothGattService;");
    if (!jniService.isValid())
        return;

    QAndroidJniObject jniUuid = jniService.callObjectMethod("getUuid", "()Ljava/util/UUID;");
    const QBluetoothUuid serviceUuid(jniUuid.toString());
    if (serviceUuid.isNull())
        return;

    // TODO test if two service with same uuid exist
    if (!localServices.contains(serviceUuid))
        return;

    jniUuid = jniChar.callObjectMethod("getUuid", "()Ljava/util/UUID;");
    const QBluetoothUuid characteristicUuid(jniUuid.toString());
    if (characteristicUuid.isNull())
        return;

    jniUuid = jniDesc.callObjectMethod("getUuid", "()Ljava/util/UUID;");
    const QBluetoothUuid descriptorUuid(jniUuid.toString());
    if (descriptorUuid.isNull())
        return;

    // find matching QLEDescriptor
    auto servicePrivate = localServices.value(serviceUuid);
    // TODO test if service contains two characteristics with same uuid
    // or characteristic contains two descriptors with same uuid
    const auto handleList = servicePrivate->characteristicList.keys();
    for (const auto charHandle: handleList) {
        const auto &charData = servicePrivate->characteristicList.value(charHandle);
        if (charData.uuid != characteristicUuid)
            continue;

        const auto &descHandleList = charData.descriptorList.keys();
        for (const auto descHandle: descHandleList) {
            const auto &descData = charData.descriptorList.value(descHandle);
            if (descData.uuid != descriptorUuid)
                continue;

            qCDebug(QT_BT_ANDROID) << "serverDescriptorChanged: Matching descriptor"
                                   << descriptorUuid << "in char" << characteristicUuid
                                   << "of service" << serviceUuid;

            servicePrivate->characteristicList[charHandle].descriptorList[descHandle].value = newValue;

            emit servicePrivate->descriptorWritten(
                        QLowEnergyDescriptor(servicePrivate, charHandle, descHandle),
                        newValue);
            return;
        }
    }
}

void QLowEnergyControllerPrivateAndroid::characteristicChanged(
        int charHandle, const QByteArray &data)
{
    QSharedPointer<QLowEnergyServicePrivate> service =
            serviceForHandle(charHandle);
    if (service.isNull())
        return;

    qCDebug(QT_BT_ANDROID) << "Characteristic change notification" << service->uuid
                           << charHandle << data.toHex();

    QLowEnergyCharacteristic characteristic = characteristicForHandle(charHandle);
    if (!characteristic.isValid()) {
        qCWarning(QT_BT_ANDROID) << "characteristicChanged: Cannot find characteristic";
        return;
    }

    // only update cache when property is readable. Otherwise it remains
    // empty.
    if (characteristic.properties() & QLowEnergyCharacteristic::Read)
        updateValueOfCharacteristic(characteristic.attributeHandle(),
                                data, false);
    emit service->characteristicChanged(characteristic, data);
}

void QLowEnergyControllerPrivateAndroid::serverCharacteristicChanged(
        const QAndroidJniObject &characteristic, const QByteArray &newValue)
{
    qCDebug(QT_BT_ANDROID) << "Server characteristic change notification" << newValue.toHex();

    // match characteristic to servicePrivate
    QAndroidJniObject service = characteristic.callObjectMethod(
                                    "getService", "()Landroid/bluetooth/BluetoothGattService;");
    if (!service.isValid())
        return;

    QAndroidJniObject jniUuid = service.callObjectMethod("getUuid", "()Ljava/util/UUID;");
    QBluetoothUuid serviceUuid(jniUuid.toString());
    if (serviceUuid.isNull())
        return;

    // TODO test if two service with same uuid exist
    if (!localServices.contains(serviceUuid))
        return;

    auto servicePrivate = localServices.value(serviceUuid);

    jniUuid = characteristic.callObjectMethod("getUuid", "()Ljava/util/UUID;");
    QBluetoothUuid characteristicUuid(jniUuid.toString());
    if (characteristicUuid.isNull())
        return;

    QLowEnergyHandle foundHandle = 0;
    const auto handleList = servicePrivate->characteristicList.keys();
    // TODO test if service contains two characteristics with same uuid
    for (const auto handle: handleList) {
        QLowEnergyServicePrivate::CharData &charData = servicePrivate->characteristicList[handle];
        if (charData.uuid != characteristicUuid)
            continue;

        qCDebug(QT_BT_ANDROID) << "serverCharacteristicChanged: Matching characteristic"
                               << characteristicUuid << " on " << serviceUuid;
        charData.value = newValue;
        foundHandle = handle;
        break;
    }

    if (!foundHandle)
        return;

    emit servicePrivate->characteristicChanged(
                QLowEnergyCharacteristic(servicePrivate, foundHandle), newValue);
}

void QLowEnergyControllerPrivateAndroid::serviceError(
        int attributeHandle, QLowEnergyService::ServiceError errorCode)
{
    // ignore call if it isn't really an error
    if (errorCode == QLowEnergyService::NoError)
        return;

    QSharedPointer<QLowEnergyServicePrivate> service =
            serviceForHandle(attributeHandle);
    Q_ASSERT(!service.isNull());

    // ATM we don't really use attributeHandle but later on we might
    // want to associate the error code with a char or desc
    service->setError(errorCode);
}

void QLowEnergyControllerPrivateAndroid::advertisementError(int errorCode)
{
    Q_Q(QLowEnergyController);

    switch (errorCode)
    {
    case 1: // AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE
        errorString = QLowEnergyController::tr("Advertisement data is larger than 31 bytes");
        break;
    case 2: // AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED
        errorString = QLowEnergyController::tr("Advertisement feature not supported on the platform");
        break;
    case 3: // AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR
        errorString = QLowEnergyController::tr("Error occurred trying to start advertising");
        break;
    case 4: // AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS
        errorString = QLowEnergyController::tr("Failed due to too many advertisers");
        break;
    default:
        errorString = QLowEnergyController::tr("Unknown advertisement error");
        break;
    }

    error = QLowEnergyController::AdvertisingError;
    emit q->error(error);

    // not relevant states in peripheral mode
    Q_ASSERT(state != QLowEnergyController::DiscoveredState);
    Q_ASSERT(state != QLowEnergyController::DiscoveringState);

    switch (state)
    {
    case QLowEnergyController::UnconnectedState:
    case QLowEnergyController::ConnectingState:
    case QLowEnergyController::ConnectedState:
    case QLowEnergyController::ClosingState:
        // noop as remote is already connected or about to disconnect.
        // when connection drops we reset to unconnected anyway
        break;

    case QLowEnergyController::AdvertisingState:
        setState(QLowEnergyController::UnconnectedState);
        break;
    default:
        break;
    }
}

static QAndroidJniObject javaParcelUuidfromQtUuid(const QBluetoothUuid &uuid)
{
    QString output = uuid.toString();
    // cut off leading and trailing brackets
    output = output.mid(1, output.size()-2);

    QAndroidJniObject javaString = QAndroidJniObject::fromString(output);
    QAndroidJniObject parcelUuid = QAndroidJniObject::callStaticObjectMethod(
                "android/os/ParcelUuid", "fromString",
                "(Ljava/lang/String;)Landroid/os/ParcelUuid;", javaString.object());

    return parcelUuid;
}

static QAndroidJniObject createJavaAdvertiseData(const QLowEnergyAdvertisingData &data)
{
    QAndroidJniObject builder = QAndroidJniObject("android/bluetooth/le/AdvertiseData$Builder");

    // device name cannot be set but there is choice to show it or not
    builder = builder.callObjectMethod("setIncludeDeviceName", "(Z)Landroid/bluetooth/le/AdvertiseData$Builder;",
                                       !data.localName().isEmpty());
    builder = builder.callObjectMethod("setIncludeTxPowerLevel", "(Z)Landroid/bluetooth/le/AdvertiseData$Builder;",
                                       data.includePowerLevel());
    for (const auto service: data.services())
    {
        builder = builder.callObjectMethod("addServiceUuid",
                                       "(Landroid/os/ParcelUuid;)Landroid/bluetooth/le/AdvertiseData$Builder;",
                                       javaParcelUuidfromQtUuid(service).object());
    }

    if (!data.manufacturerData().isEmpty()) {
        QAndroidJniEnvironment env;
        const qint32 nativeSize = data.manufacturerData().size();
        jbyteArray nativeData = env->NewByteArray(nativeSize);
        env->SetByteArrayRegion(nativeData, 0, nativeSize,
                                reinterpret_cast<const jbyte*>(data.manufacturerData().constData()));
        builder = builder.callObjectMethod("addManufacturerData",
                                       "(I[B)Landroid/bluetooth/le/AdvertiseData$Builder;",
                                       data.manufacturerId(), nativeData);
        env->DeleteLocalRef(nativeData);

        if (env->ExceptionCheck()) {
            qCWarning(QT_BT_ANDROID) << "Cannot set manufacturer id/data";
            env->ExceptionDescribe();
            env->ExceptionClear();
        }
    }

    /*// TODO Qt vs Java API mismatch
          -> Qt assumes rawData() is a global field
          -> Android pairs rawData() per service uuid
    if (!data.rawData().isEmpty()) {
        QAndroidJniEnvironment env;
        qint32 nativeSize = data.rawData().size();
        jbyteArray nativeData = env->NewByteArray(nativeSize);
        env->SetByteArrayRegion(nativeData, 0, nativeSize,
                                reinterpret_cast<const jbyte*>(data.rawData().constData()));
        builder = builder.callObjectMethod("addServiceData",
                                       "(Landroid/os/ParcelUuid;[B])Landroid/bluetooth/le/AdvertiseData$Builder;",
                                       data.rawData().object(), nativeData);
        env->DeleteLocalRef(nativeData);

        if (env->ExceptionCheck()) {
            qCWarning(QT_BT_ANDROID) << "Cannot set advertisement raw data";
            env->ExceptionDescribe();
            env->ExceptionClear();
        }
    }*/

    QAndroidJniObject javaAdvertiseData = builder.callObjectMethod("build",
                                       "()Landroid/bluetooth/le/AdvertiseData;");
    return javaAdvertiseData;
}

static QAndroidJniObject createJavaAdvertiseSettings(const QLowEnergyAdvertisingParameters &params)
{
    QAndroidJniObject builder = QAndroidJniObject("android/bluetooth/le/AdvertiseSettings$Builder");

    bool connectable = false;
    switch (params.mode())
    {
    case QLowEnergyAdvertisingParameters::AdvInd:
        connectable = true;
        break;
    case QLowEnergyAdvertisingParameters::AdvScanInd:
    case QLowEnergyAdvertisingParameters::AdvNonConnInd:
        connectable = false;
        break;
    // intentionally no default case
    }
    builder = builder.callObjectMethod("setConnectable", "(Z)Landroid/bluetooth/le/AdvertiseSettings$Builder;",
                                       connectable);

    /* TODO No Android API for further QLowEnergyAdvertisingParameters options
     *      Android TxPowerLevel, AdvertiseMode and Timeout not mappable to Qt
     */

    QAndroidJniObject javaAdvertiseSettings = builder.callObjectMethod("build",
                                            "()Landroid/bluetooth/le/AdvertiseSettings;");
    return javaAdvertiseSettings;
}


void QLowEnergyControllerPrivateAndroid::startAdvertising(const QLowEnergyAdvertisingParameters &params,
        const QLowEnergyAdvertisingData &advertisingData,
        const QLowEnergyAdvertisingData &scanResponseData)
{
    setState(QLowEnergyController::AdvertisingState);

    if (!hub->javaObject().isValid()) {
        qCWarning(QT_BT_ANDROID) << "Cannot initiate QtBluetoothLEServer";
        setError(QLowEnergyController::AdvertisingError);
        setState(QLowEnergyController::UnconnectedState);
        return;
    }

    // Pass on advertisingData, scanResponse & AdvertiseSettings
    QAndroidJniObject jAdvertiseData = createJavaAdvertiseData(advertisingData);
    QAndroidJniObject jScanResponse = createJavaAdvertiseData(scanResponseData);
    QAndroidJniObject jAdvertiseSettings = createJavaAdvertiseSettings(params);

    const bool result = hub->javaObject().callMethod<jboolean>("startAdvertising",
            "(Landroid/bluetooth/le/AdvertiseData;Landroid/bluetooth/le/AdvertiseData;Landroid/bluetooth/le/AdvertiseSettings;)Z",
            jAdvertiseData.object(), jScanResponse.object(), jAdvertiseSettings.object());
    if (!result) {
        setError(QLowEnergyController::AdvertisingError);
        setState(QLowEnergyController::UnconnectedState);
    }
}

void QLowEnergyControllerPrivateAndroid::stopAdvertising()
{
    setState(QLowEnergyController::UnconnectedState);
    hub->javaObject().callMethod<void>("stopAdvertising");
}

void QLowEnergyControllerPrivateAndroid::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
{
    // Possible since Android v21
    // Android does not permit specification of specific latency or min/max
    // connection intervals (see BluetoothGatt.requestConnectionPriority()
    // In fact, each device manufacturer is permitted to change those values via a config
    // file too. Therefore we can only make an approximated guess (see implementation below)
    // In addition there is no feedback signal (known bug) from the hardware layer as per v24.

    // TODO recheck in later Android releases whether callback for
    // BluetoothGatt.requestConnectionPriority() was added

    if (role != QLowEnergyController::CentralRole) {
        qCWarning(QT_BT_ANDROID) << "On Android, connection requests only work for central role";
        return;
    }

    const bool result = hub->javaObject().callMethod<jboolean>("requestConnectionUpdatePriority",
                                                         "(D)Z", params.minimumInterval());
    if (!result)
        qCWarning(QT_BT_ANDROID) << "Cannot set connection update priority";
}

/*
 * Returns the Java char permissions based on the given characteristic data.
 */
static int setupCharPermissions(const QLowEnergyCharacteristicData &charData)
{
    int permission = 0;
    if (charData.properties() & QLowEnergyCharacteristic::Read) {
        if (int(charData.readConstraints()) == 0 // nothing is equivalent to simple read
            || (charData.readConstraints() & QBluetooth::AttAuthorizationRequired)) {
            permission |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattCharacteristic",
                                                "PERMISSION_READ");
        }

        if (charData.readConstraints() & QBluetooth::AttAuthenticationRequired) {
            permission |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattCharacteristic",
                                                "PERMISSION_READ_ENCRYPTED");
        }

        if (charData.readConstraints() & QBluetooth::AttEncryptionRequired) {
            permission |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattCharacteristic",
                                                "PERMISSION_READ_ENCRYPTED_MITM");
        }
    }

    if (charData.properties() &
                (QLowEnergyCharacteristic::Write|QLowEnergyCharacteristic::WriteNoResponse) ) {
        if (int(charData.writeConstraints()) == 0 // no flag is equivalent ti simple write
             || (charData.writeConstraints() & QBluetooth::AttAuthorizationRequired)) {
            permission |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattCharacteristic",
                                                "PERMISSION_WRITE");
        }

        if (charData.writeConstraints() & QBluetooth::AttAuthenticationRequired) {
            permission |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattCharacteristic",
                                                "PERMISSION_WRITE_ENCRYPTED");
        }

        if (charData.writeConstraints() & QBluetooth::AttEncryptionRequired) {
            permission |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattCharacteristic",
                                                "PERMISSION_WRITE_ENCRYPTED_MITM");
        }
    }

    if (charData.properties() & QLowEnergyCharacteristic::WriteSigned) {
        if (charData.writeConstraints() & QBluetooth::AttEncryptionRequired) {
            permission |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattCharacteristic",
                                                "PERMISSION_WRITE_SIGNED_MITM");
        } else {
            permission |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattCharacteristic",
                                                "PERMISSION_WRITE_SIGNED");
        }
    }

    return permission;
}

/*
 * Returns the Java desc permissions based on the given descriptor data.
 */
static int setupDescPermissions(const QLowEnergyDescriptorData &descData)
{
    int permissions = 0;

    if (descData.isReadable()) {
        if (int(descData.readConstraints()) == 0 // empty is equivalent to simple read
            || (descData.readConstraints() & QBluetooth::AttAuthorizationRequired)) {
            permissions |= QAndroidJniObject::getStaticField<jint>(
                                "android/bluetooth/BluetoothGattDescriptor",
                                "PERMISSION_READ");
        }

        if (descData.readConstraints() & QBluetooth::AttAuthenticationRequired) {
            permissions |= QAndroidJniObject::getStaticField<jint>(
                                "android/bluetooth/BluetoothGattDescriptor",
                                "PERMISSION_READ_ENCRYPTED");
        }

        if (descData.readConstraints() & QBluetooth::AttEncryptionRequired) {
            permissions |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattDescriptor",
                                                "PERMISSION_READ_ENCRYPTED_MITM");
        }
    }

    if (descData.isWritable()) {
        if (int(descData.readConstraints()) == 0 // empty is equivalent to simple read
            || (descData.readConstraints() & QBluetooth::AttAuthorizationRequired)) {
            permissions |= QAndroidJniObject::getStaticField<jint>(
                                "android/bluetooth/BluetoothGattDescriptor",
                                "PERMISSION_WRITE");
        }

        if (descData.readConstraints() & QBluetooth::AttAuthenticationRequired) {
            permissions |= QAndroidJniObject::getStaticField<jint>(
                                "android/bluetooth/BluetoothGattDescriptor",
                                "PERMISSION_WRITE_ENCRYPTED");
        }

        if (descData.readConstraints() & QBluetooth::AttEncryptionRequired) {
            permissions |= QAndroidJniObject::getStaticField<jint>(
                                                "android/bluetooth/BluetoothGattDescriptor",
                                                "PERMISSION_WRITE_ENCRYPTED_MITM");
        }
    }

    return permissions;
}

void QLowEnergyControllerPrivateAndroid::addToGenericAttributeList(const QLowEnergyServiceData &serviceData,
                                                            QLowEnergyHandle startHandle)
{
    QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(startHandle);
    if (service.isNull())
        return;

    // create BluetoothGattService object
    jint sType = QAndroidJniObject::getStaticField<jint>(
                            "android/bluetooth/BluetoothGattService", "SERVICE_TYPE_PRIMARY");
    if (serviceData.type() == QLowEnergyServiceData::ServiceTypeSecondary)
        sType = QAndroidJniObject::getStaticField<jint>(
                                    "android/bluetooth/BluetoothGattService", "SERVICE_TYPE_SECONDARY");

    service->androidService = QAndroidJniObject("android/bluetooth/BluetoothGattService",
                                                "(Ljava/util/UUID;I)V",
                                                javaUuidfromQtUuid(service->uuid).object(), sType);

    // add included services, which must have been added earlier already
    const QList<QLowEnergyService*> includedServices = serviceData.includedServices();
    for (const auto includedServiceEntry: includedServices) {
        //TODO test this end-to-end
        const jboolean result = service->androidService.callMethod<jboolean>(
                        "addService", "(Landroid/bluetooth/BluetoothGattService;)Z",
                        includedServiceEntry->d_ptr->androidService.object());
        if (!result)
            qWarning(QT_BT_ANDROID) << "Cannot add included service " << includedServiceEntry->serviceUuid()
                                    << "to current service" << service->uuid;
    }

    // add characteristics
    const QList<QLowEnergyCharacteristicData> serviceCharsData = serviceData.characteristics();
    for (const auto &charData: serviceCharsData) {
        QAndroidJniObject javaChar = QAndroidJniObject("android/bluetooth/BluetoothGattCharacteristic",
                                                       "(Ljava/util/UUID;II)V",
                                                       javaUuidfromQtUuid(charData.uuid()).object(),
                                                       int(charData.properties()),
                                                       setupCharPermissions(charData));

        QAndroidJniEnvironment env;
        jbyteArray jb = env->NewByteArray(charData.value().size());
        env->SetByteArrayRegion(jb, 0, charData.value().size(), (jbyte*)charData.value().data());
        jboolean success = javaChar.callMethod<jboolean>("setValue", "([B)Z", jb);
        if (!success)
            qCWarning(QT_BT_ANDROID) << "Cannot setup initial characteristic value for " << charData.uuid();

        env->DeleteLocalRef(jb);

        const QList<QLowEnergyDescriptorData> descriptorList = charData.descriptors();
        for (const auto &descData: descriptorList) {
            QAndroidJniObject javaDesc = QAndroidJniObject("android/bluetooth/BluetoothGattDescriptor",
                                                           "(Ljava/util/UUID;I)V",
                                                           javaUuidfromQtUuid(descData.uuid()).object(),
                                                           setupDescPermissions(descData));

            jb = env->NewByteArray(descData.value().size());
            env->SetByteArrayRegion(jb, 0, descData.value().size(), (jbyte*)descData.value().data());
            success = javaDesc.callMethod<jboolean>("setValue", "([B)Z", jb);
            if (!success) {
                qCWarning(QT_BT_ANDROID) << "Cannot setup initial descriptor value for "
                                         << descData.uuid() << "(char" << charData.uuid()
                                         << "on service " << service->uuid << ")";
            }

            env->DeleteLocalRef(jb);


            success = javaChar.callMethod<jboolean>("addDescriptor",
                                                    "(Landroid/bluetooth/BluetoothGattDescriptor;)Z",
                                                    javaDesc.object());
            if (!success) {
                qCWarning(QT_BT_ANDROID) << "Cannot add descriptor" << descData.uuid()
                                         << "to service" << service->uuid << "(char:"
                                         << charData.uuid() << ")";
            }
        }

        success = service->androidService.callMethod<jboolean>(
                            "addCharacteristic",
                            "(Landroid/bluetooth/BluetoothGattCharacteristic;)Z", javaChar.object());
        if (!success) {
            qCWarning(QT_BT_ANDROID) << "Cannot add characteristic" << charData.uuid()
                                     << "to service" << service->uuid;
        }
    }

    hub->javaObject().callMethod<void>("addService",
                                       "(Landroid/bluetooth/BluetoothGattService;)V",
                                       service->androidService.object());
}

QT_END_NAMESPACE
