void QBluetoothServiceDiscoveryAgentPrivate::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount) { qDebug() << "NextRecordRequestComplete"; Q_Q(QBluetoothServiceDiscoveryAgent); if (aError == KErrNone && aTotalRecordsCount > 0 && m_sdpAgent && m_attributes) { // request attributes TRAPD(err, m_sdpAgent->AttributeRequestL(aHandle, *m_attributes)); if (err && singleDevice) { error = QBluetoothServiceDiscoveryAgent::UnknownError; emit q->error(error); } } else if (aError == KErrEof) { _q_serviceDiscoveryFinished(); } else { _q_serviceDiscoveryFinished(); } }
void QBluetoothServiceDiscoveryAgentPrivate::_q_processFetchedUuids( const QBluetoothAddress &address, const QList<QBluetoothUuid> &uuids) { //don't leave more data through if we are not interested anymore if (discoveredDevices.count() == 0) return; //could not find any service for the current address/device -> go to next one if (address.isNull() || uuids.isEmpty()) { _q_serviceDiscoveryFinished(); return; } if (QT_BT_ANDROID().isDebugEnabled()) { qCDebug(QT_BT_ANDROID) << "Found UUID for" << address.toString() << "\ncount: " << uuids.count(); QString result; for (int i = 0; i<uuids.count(); i++) result += uuids.at(i).toString() + QStringLiteral("**"); qCDebug(QT_BT_ANDROID) << result; } /* In general there are two uuid events per device. * We'll wait for the second event to arrive before we process the UUIDs. * We utilize a timeout to catch cases when the second * event doesn't arrive at all. * Generally we assume that the second uuid event carries the most up-to-date * set of uuids and discard the first events results. */ if (sdpCache.contains(address)) { //second event QPair<QBluetoothDeviceInfo,QList<QBluetoothUuid> > pair = sdpCache.take(address); //prefer second uuid set over first populateDiscoveredServices(pair.first, uuids); if (discoveredDevices.count() == 1 && sdpCache.isEmpty()) { //last regular uuid data set from OS -> we finish here _q_serviceDiscoveryFinished(); } } else { //first event QPair<QBluetoothDeviceInfo,QList<QBluetoothUuid> > pair; pair.first = discoveredDevices.at(0); pair.second = uuids; if (pair.first.address() != address) return; sdpCache.insert(address, pair); //the discovery on the last device cannot immediately finish //we have to grant the 2 seconds timeout delay if (discoveredDevices.count() == 1) { Q_Q(QBluetoothServiceDiscoveryAgent); QTimer::singleShot(4000, q, SLOT(_q_fetchUuidsTimeout())); return; } _q_serviceDiscoveryFinished(); } }
void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &address) { Q_Q(QBluetoothServiceDiscoveryAgent); if (!btAdapter.isValid()) { error = QBluetoothServiceDiscoveryAgent::UnknownError; errorString = QBluetoothServiceDiscoveryAgent::tr("Platform does not support Bluetooth"); //abort any outstanding discoveries discoveredDevices.clear(); emit q->error(error); _q_serviceDiscoveryFinished(); return; } /* SDP discovery was officially added by Android API v15 * BluetoothDevice.getUuids() existed in earlier APIs already and in the future we may use * reflection to support earlier Android versions than 15. Unfortunately * BluetoothDevice.fetchUuidsWithSdp() and related APIs had some structure changes * over time. Therefore we won't attempt this with reflection. * * TODO: Use reflection to support getUuuids() where possible. * */ if (QtAndroidPrivate::androidSdkVersion() < 15) { qCWarning(QT_BT_ANDROID) << "Aborting SDP enquiry due to too low Android API version (requires v15+)"; error = QBluetoothServiceDiscoveryAgent::UnknownError; errorString = QBluetoothServiceDiscoveryAgent::tr("Android API below v15 does not support SDP discovery"); //abort any outstanding discoveries sdpCache.clear(); discoveredDevices.clear(); emit q->error(error); _q_serviceDiscoveryFinished(); return; } QAndroidJniObject inputString = QAndroidJniObject::fromString(address.toString()); QAndroidJniObject remoteDevice = btAdapter.callObjectMethod("getRemoteDevice", "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;", inputString.object<jstring>()); QAndroidJniEnvironment env; if (env->ExceptionCheck()) { env->ExceptionClear(); env->ExceptionDescribe(); //if it was only device then its error -> otherwise go to next device if (singleDevice) { error = QBluetoothServiceDiscoveryAgent::InputOutputError; errorString = QBluetoothServiceDiscoveryAgent::tr("Cannot create Android BluetoothDevice"); qCWarning(QT_BT_ANDROID) << "Cannot start SDP for" << discoveredDevices.at(0).name() << "(" << address.toString() << ")"; emit q->error(error); } _q_serviceDiscoveryFinished(); return; } if (mode == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) { qCDebug(QT_BT_ANDROID) << "Minimal discovery on (" << discoveredDevices.at(0).name() << ")" << address.toString() ; //Minimal discovery uses BluetoothDevice.getUuids() QAndroidJniObject parcelUuidArray = remoteDevice.callObjectMethod( "getUuids", "()[Landroid/os/ParcelUuid;"); if (!parcelUuidArray.isValid()) { if (singleDevice) { error = QBluetoothServiceDiscoveryAgent::InputOutputError; errorString = QBluetoothServiceDiscoveryAgent::tr("Cannot obtain service uuids"); emit q->error(error); } qCWarning(QT_BT_ANDROID) << "Cannot retrieve SDP UUIDs for" << discoveredDevices.at(0).name() << "(" << address.toString() << ")"; _q_serviceDiscoveryFinished(); return; } const QList<QBluetoothUuid> results = ServiceDiscoveryBroadcastReceiver::convertParcelableArray(parcelUuidArray); populateDiscoveredServices(discoveredDevices.at(0), results); _q_serviceDiscoveryFinished(); } else { qCDebug(QT_BT_ANDROID) << "Full discovery on (" << discoveredDevices.at(0).name() << ")" << address.toString(); //Full discovery uses BluetoothDevice.fetchUuidsWithSdp() if (!receiver) { receiver = new ServiceDiscoveryBroadcastReceiver(); QObject::connect(receiver, SIGNAL(uuidFetchFinished(QBluetoothAddress,QList<QBluetoothUuid>)), q, SLOT(_q_processFetchedUuids(QBluetoothAddress,QList<QBluetoothUuid>))); } if (!localDeviceReceiver) { localDeviceReceiver = new LocalDeviceBroadcastReceiver(); QObject::connect(localDeviceReceiver, SIGNAL(hostModeStateChanged(QBluetoothLocalDevice::HostMode)), q, SLOT(_q_hostModeStateChanged(QBluetoothLocalDevice::HostMode))); } jboolean result = remoteDevice.callMethod<jboolean>("fetchUuidsWithSdp"); if (!result) { //kill receiver to limit load of signals receiver->unregisterReceiver(); receiver->deleteLater(); receiver = 0; qCWarning(QT_BT_ANDROID) << "Cannot start dynamic fetch."; _q_serviceDiscoveryFinished(); } } }