javaextensions/bluetooth/omjbluetooth/src.s60/bluetoothservicesearcher.cpp
branchRCL_3
changeset 19 04becd199f91
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/bluetooth/omjbluetooth/src.s60/bluetoothservicesearcher.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,391 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+#include <bluetooth/hci/hcierrors.h>
+
+#include "bluetoothconsts.h"
+#include "bluetoothservicesearcher.h"
+#include "discoveryagent.h"
+
+namespace java
+{
+namespace bluetooth
+{
+
+#define GET_VALID_HCI_ERR_CODE(err_no) (((err_no) < KHCIErrorBase) ? \
+                                        (KHCIErrorBase - (err_no)) : \
+                                        (err_no))
+
+BluetoothServiceSearcher* BluetoothServiceSearcher::New(
+    DiscoveryAgent *aDiscoveryAgent, BluetoothFunctionServer* aServer)
+{
+    JELOG2(EJavaBluetooth);
+    BluetoothServiceSearcher* searcher = new BluetoothServiceSearcher();
+    searcher->Construct(aDiscoveryAgent, aServer);
+    return searcher;
+}
+
+BluetoothServiceSearcher::BluetoothServiceSearcher()
+{
+}
+
+void BluetoothServiceSearcher::Construct(DiscoveryAgent *aDiscoveryAgent,
+        BluetoothFunctionServer* aServer)
+{
+    JELOG2(EJavaBluetooth);
+    mDiscoveryAgent = aDiscoveryAgent;
+    mServer = aServer;
+    mSDPAgent = NULL;
+    mSpat = NULL;
+    mAttributeList = NULL;
+    mSrPopulator = NULL;
+    mFoundServiceRecord = false;
+    mIsPopulateRecordMode = false;
+
+    mJni = mServer->getValidJniEnv();
+    mPeer = mServer->getPeer();
+
+    jclass peerClass = mJni->GetObjectClass(mPeer);
+    mCreateServiceRecordMethod
+    = mJni->GetMethodID(peerClass, "createServiceRecord",
+                        "(J)Lcom/intel/bluetooth/ServiceRecordImpl;");
+
+    mServiceRecordImplClass = mJni->FindClass(
+                                  "com/intel/bluetooth/ServiceRecordImpl");
+
+}
+
+BluetoothServiceSearcher::~BluetoothServiceSearcher()
+{
+    JELOG2(EJavaBluetooth);
+    Cleanup();
+}
+
+void BluetoothServiceSearcher::SearchServicesL(TInt64 aRemoteAddress,
+        TPtrC8 aUuidsDes, TPtrC16 aAttrIdsDes)
+{
+    JELOG2(EJavaBluetooth);
+    LOG1(EJavaBluetooth, EInfo,
+         "+ BluetoothServiceSearcher:: SearchServices:%X",
+         (long) aRemoteAddress);
+
+    mIsPopulateRecordMode = false;
+
+    TBTDevAddr devAddr(aRemoteAddress);
+
+    FillSearchPatternL(aUuidsDes);
+
+    FillAttributeListL(aAttrIdsDes);
+
+    LOG(
+        EJavaBluetooth,
+        EInfo,
+        "  BluetoothServiceSearcher::SearchServicesOnDeviceL: Clearing SDPAgent if any...");
+    // Init new service discovery agent
+    if (mSDPAgent)
+    {
+        delete mSDPAgent;
+        mSDPAgent = NULL;
+    }
+    mSDPAgent = CSdpAgent::NewL(*this, devAddr);
+
+    mSDPAgent->SetRecordFilterL(*mSpat);
+
+    mSDPAgent->NextRecordRequestL();
+
+}
+
+void BluetoothServiceSearcher::cancelServiceSearch()
+{
+    JELOG2(EJavaBluetooth);
+    DiscoveryAgent* tempDiscoveryAgent = mDiscoveryAgent;
+    Cleanup();
+    if (NULL == tempDiscoveryAgent)
+        return;
+    if (!mIsPopulateRecordMode)
+    {
+        tempDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_TERMINATED);
+    }
+    else
+    {
+        tempDiscoveryAgent->PopulateRecordCompleted(SERVICE_SEARCH_TERMINATED);
+    }
+}
+
+void BluetoothServiceSearcher::Cleanup()
+{
+    JELOG2(EJavaBluetooth);
+    if (mSDPAgent)
+    {
+        delete mSDPAgent;
+        mSDPAgent = NULL;
+    }
+    if (mSpat)
+    {
+        mSpat->Reset();
+        delete mSpat;
+        mSpat = NULL;
+    }
+    if (mAttributeList)
+    {
+        delete mAttributeList;
+        mAttributeList = NULL;
+    }
+    if (mSrPopulator)
+    {
+        delete mSrPopulator;
+        mSrPopulator = NULL;
+    }
+
+    mDiscoveryAgent = NULL;
+}
+
+void BluetoothServiceSearcher::NextRecordRequestComplete(TInt aError,
+        TSdpServRecordHandle aHandle, TInt /*aTotalRecordsCount*/)
+{
+    JELOG2(EJavaBluetooth);
+    LOG1(
+        EJavaBluetooth,
+        EInfo,
+        "  BluetoothServiceSearcher::NextRecordRequestComplete aError=%d",
+        aError);
+
+    if (KErrEof == aError && !mFoundServiceRecord)
+    {
+        LOG(
+            EJavaBluetooth,
+            EInfo,
+            "  BluetoothServiceSearcher::NextRecordRequestComplete SERVICE_SEARCH_NO_RECORDS");
+        mDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_NO_RECORDS);
+    }
+    else if (KErrNone == aError)
+    {
+        TInt64 servRecHandle = MAKE_TINT64(0, aHandle);
+        mServiceRecordImpl = (*mJni).CallObjectMethod(mPeer,
+                             mCreateServiceRecordMethod, servRecHandle);
+        if (NULL == mServiceRecordImpl)
+        {
+            LOG(EJavaBluetooth, EInfo,
+                "  BluetoothServiceSearcher::NextRecordRequestComplete SERVICE_SEARCH_ERROR");
+            mDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_ERROR);
+        }
+        else
+        {
+            LOG(EJavaBluetooth, EInfo,
+                "  BluetoothServiceSearcher::NextRecordRequestComplete Populating record");
+            delete mSrPopulator;
+            mSrPopulator = BTServiceRecordPopulator::New(mJni,
+                           mServiceRecordImpl);
+            TRAPD(attrRequestErr, mSDPAgent->AttributeRequestL(mSrPopulator,
+                    aHandle, *mAttributeList));
+            if (KErrNone != attrRequestErr)
+            {
+                delete mSrPopulator;
+                mSrPopulator = NULL;
+                mDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_ERROR);
+            }
+        }
+    }
+    else if (EPageTimedOut == GET_VALID_HCI_ERR_CODE(aError))
+    {
+        LOG(
+            EJavaBluetooth,
+            EInfo,
+            "  BluetoothServiceSearcher::NextRecordRequestComplete SERVICE_SEARCH_DEVICE_NOT_REACHABLE");
+        mDiscoveryAgent->ServiceSearchCompleted(
+            SERVICE_SEARCH_DEVICE_NOT_REACHABLE);
+    }
+    else
+    {
+        LOG1(
+            EJavaBluetooth,
+            EInfo,
+            "  BluetoothServiceSearcher::NextRecordRequestComplete SERVICE_SEARCH_COMPLETED %d",
+            aError);
+        mDiscoveryAgent->ServiceSearchCompleted(SERVICE_SEARCH_COMPLETED);
+    }
+}
+
+void BluetoothServiceSearcher::PopulateServiceRecordsL(TInt64 aRemoteAddress,
+        long aHandle, TPtrC16 aAttrIdsDes, jobject aServiceRecordImpl)
+{
+    JELOG2(EJavaBluetooth);
+
+    mIsPopulateRecordMode = true;
+
+    TBTDevAddr devAddr(aRemoteAddress);
+
+    FillAttributeListL(aAttrIdsDes);
+
+    LOG(
+        EJavaBluetooth,
+        EInfo,
+        "  BluetoothServiceSearcher::PopulateServiceRecords: Clearing SDPAgent if any...");
+
+    if (mSDPAgent)
+    {
+        mSDPAgent->Cancel();
+        delete mSDPAgent;
+        mSDPAgent = NULL;
+    }
+    mSDPAgent = CSdpAgent::NewL(*this, devAddr);
+
+    mServiceRecordImpl = aServiceRecordImpl;
+
+    delete mSrPopulator;
+    mSrPopulator = BTServiceRecordPopulator::New(mJni, mServiceRecordImpl);
+
+    mSDPAgent->AttributeRequestL(mSrPopulator, aHandle, *mAttributeList);
+}
+
+void BluetoothServiceSearcher::AttributeRequestResult(
+    TSdpServRecordHandle /*aHandle*/, TSdpAttributeID /*aAttrID*/,
+    CSdpAttrValue* /*aAttrValue*/)
+{
+    // No implementation required...
+}
+
+void BluetoothServiceSearcher::AttributeRequestComplete(
+    TSdpServRecordHandle /*aHandle*/, TInt aError)
+{
+    JELOG2(EJavaBluetooth);
+    LOG1(EJavaBluetooth, EInfo,
+         "  BluetoothServiceSearcher::AttributeRequestComplete aError=%d",
+         aError);
+
+    int status = 0;
+    bool attributeFound = mSrPopulator->isAttributesFound();
+
+    delete mSrPopulator;
+    mSrPopulator = NULL;
+
+    if (KErrNone == aError && !mIsPopulateRecordMode)
+    {
+        mFoundServiceRecord = true;
+        LOG(
+            EJavaBluetooth,
+            EInfo,
+            "  BluetoothServiceSearcher::AttributeRequestComplete Callback serviceDiscoveredCallback");
+        jclass peerClass = mJni->GetObjectClass(mPeer);
+        jmethodID serviceDiscoveredMethod = mJni->GetMethodID(peerClass,
+                                            "serviceDiscoveredCallback",
+                                            "(Lcom/intel/bluetooth/ServiceRecordImpl;)V");
+        (*mJni).CallVoidMethod(mPeer, serviceDiscoveredMethod,
+                               mServiceRecordImpl);
+
+        LOG(
+            EJavaBluetooth,
+            EInfo,
+            "  BluetoothServiceSearcher::AttributeRequestComplete. Trying for the next record if any");
+
+        // In case of any leave, then this will terminates the search for the next record.
+        TRAP_IGNORE(mSDPAgent->NextRecordRequestL());
+    }
+    else
+    {
+        if (KErrNone == aError)
+        {
+            mFoundServiceRecord = true;
+            status = SERVICE_SEARCH_COMPLETED;
+        }
+        else if (EPageTimedOut == GET_VALID_HCI_ERR_CODE(aError))
+        {
+            LOG(
+                EJavaBluetooth,
+                EInfo,
+                "  BluetoothServiceSearcher::AttributeRequestComplete SERVICE_SEARCH_DEVICE_NOT_REACHABLE");
+            status = SERVICE_SEARCH_DEVICE_NOT_REACHABLE;
+        }
+        else
+        {
+            LOG(EJavaBluetooth, EInfo,
+                "  BluetoothServiceSearcher::AttributeRequestComplete SERVICE_SEARCH_ERROR");
+            status = SERVICE_SEARCH_ERROR;
+        }
+
+        if (!mIsPopulateRecordMode)
+        {
+            mDiscoveryAgent->ServiceSearchCompleted(status);
+        }
+        else
+        {
+            if (false == attributeFound)
+                status = SERVICE_SEARCH_NO_RECORDS;
+            mDiscoveryAgent->PopulateRecordCompleted(status);
+        }
+    }
+}
+
+void BluetoothServiceSearcher::BluetoothServiceSearcher::FillSearchPatternL(
+    TDesC8& uuidsBytes)
+{
+    JELOG2(EJavaBluetooth);
+
+    const TInt numBytes = uuidsBytes.Length();
+    const TInt numberOfUUIDs = numBytes / KSdpUUIDMaxLength;
+
+    TInt uuidsConverted = 0;
+    TInt startByte = 0;
+
+    if (mSpat)
+    {
+        mSpat->Reset();
+        delete mSpat;
+        mSpat = NULL;
+    }
+    mSpat = CSdpSearchPattern::NewL();
+    CleanupStack::PushL(mSpat);
+
+    while (uuidsConverted < numberOfUUIDs)
+    {
+        TUUID uuid;
+        uuid.SetL(uuidsBytes.Mid(startByte, KSdpUUIDMaxLength));
+
+        mSpat->AddL(uuid);
+        startByte += KSdpUUIDMaxLength;
+        uuidsConverted++;
+    }
+    CleanupStack::Pop(mSpat);
+}
+
+void BluetoothServiceSearcher::BluetoothServiceSearcher::FillAttributeListL(
+    TDesC16& attrIds)
+{
+    JELOG2(EJavaBluetooth);
+    delete mAttributeList;
+    mAttributeList = NULL;
+    mAttributeList = CSdpAttrIdMatchList::NewL();
+    CleanupStack::PushL(mAttributeList);
+
+    TInt numElements = attrIds.Length();
+
+    for (TInt attrIndex = 0; attrIndex < numElements; attrIndex += 2)
+    {
+        const TUint16* attrIdStartPtr = (attrIds.Mid(attrIndex, 2)).Ptr();
+        const TInt* attrId = reinterpret_cast<const TInt*>(attrIdStartPtr);
+        const TUint16 attrId16 = static_cast<TUint16>(*attrId);
+        TAttrRange attrRange(static_cast<TSdpAttributeID>(attrId16));
+
+        mAttributeList->AddL(attrRange);
+    }
+    CleanupStack::Pop(mAttributeList);
+
+}
+
+} //end namespace bluetooth
+} //end namespace java