javaextensions/bluetooth/omjbluetooth/src.s60/discoveryagent.cpp
changeset 21 2a9601315dfc
child 72 1f0034e370aa
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaextensions/bluetooth/omjbluetooth/src.s60/discoveryagent.cpp	Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,450 @@
+/*
+* 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 "discoveryagent.h"
+#include "bluetoothdevicediscoverer.h"
+#include "fs_methodcall.h"
+#include "javajniutils.h"
+#include "exceptionbase.h"
+
+using namespace java::util;
+
+namespace java
+{
+namespace bluetooth
+{
+
+DiscoveryAgent::DiscoveryAgent(BluetoothFunctionServer* aServer)
+{
+    JELOG2(EJavaBluetooth);
+    // Initializing discovery agent data
+    mFunctionServer = aServer;
+    mSocketServerStatus = SOCKETSERVER_DISCONNECTED;
+
+    // Initializing device discovery data
+    mDeviceDiscoverer = NULL;
+}
+
+DiscoveryAgent::~DiscoveryAgent()
+{
+    JELOG2(EJavaBluetooth);
+    cleanupDeviceDiscoverer();
+}
+
+/**
+ * Starts the device inquiry. After starts the inquiry, call made to the java
+ * indicates that inquiry started.
+ *
+ * @param aJni
+ * @param aPeer
+ * @param aAccessCode Inquiry code
+ * @param aMonitor    Monitor which waits for this operation to complete
+ */
+int DiscoveryAgent::startDeviceDiscovery(JNIEnv* aJni, jobject& aPeer,
+        int aAccessCode)
+{
+    JELOG2(EJavaBluetooth);
+
+    jclass peerClass = (*aJni).GetObjectClass(aPeer);
+
+    //Get Method ID of Device Discovered Callback
+    mDeviceDiscoveredMethod = aJni->GetMethodID(peerClass,
+                              "deviceDiscoveredCallBack",
+                              "(Ljava/lang/String;Ljava/lang/String;I)V");
+
+    //We call Device Inquiry Started Callback in BluetoothStackS60 itself
+    mDeviceDiscoveryStartedMethod = aJni->GetMethodID(peerClass,
+                                    "deviceInquiryStartedCallback", "()V");
+
+    //Check if all the JNI inits have succeeded
+    if (NULL == mDeviceDiscoveredMethod || NULL
+            == mDeviceDiscoveryStartedMethod)
+    {
+        //Error in initialization
+        ELOG(EJavaBluetooth,
+             "- DiscoveryAgent::startDeviceDiscovery Error in JNIInit");
+        return -1;
+    }
+
+    TRAPD(err, CallMethodL(this,
+                           &java::bluetooth::DiscoveryAgent::discoverDevicesFsL, aAccessCode,
+                           mFunctionServer));
+
+    if (KErrNone != err)
+    {
+        cleanupDeviceDiscoverer();
+
+        ELOG1(EJavaBluetooth,
+              "- DiscoveryAgent::startDeviceDiscovery Error %d", err);
+        return err;
+    }
+
+    LOG(EJavaBluetooth, EInfo,
+        " DiscoveryAgent::startDeviceDiscovery Started Callback");
+
+    startedDeviceDiscovery(aJni, aPeer);
+
+    return err;
+}
+
+void DiscoveryAgent::discoverDevicesFsL(int aAccessCode)
+{
+    mDeviceDiscoverer = BluetoothDeviceDiscoverer::NewL(mFunctionServer);
+    CleanupStack::PushL(mDeviceDiscoverer);
+    mDeviceDiscoverer->DiscoverDevicesL(aAccessCode);
+    CleanupStack::Pop(mDeviceDiscoverer);
+}
+
+/**
+ * Cancels the device inquiry
+ */
+bool DiscoveryAgent::cancelDeviceDiscovery()
+{
+    JELOG2(EJavaBluetooth);
+
+    if (mDeviceDiscoverer)
+    {
+        mDeviceDiscoverer->cancel();
+    }
+    return true;
+}
+
+/**
+ * Makes callback to Java indicates that the inquiry started.
+ */
+void DiscoveryAgent::startedDeviceDiscovery(JNIEnv* aJni, jobject& aPeer)
+{
+    JELOG2(EJavaBluetooth);
+    //Call method in Java here to notify that device discovery has been started
+    //This too happens in Function Server Context.
+
+    (*aJni).CallVoidMethod(aPeer, mDeviceDiscoveryStartedMethod);
+
+}
+
+/**
+ * Searching for the next device.
+ * Returns immediately, if already any device discovered;
+ * otherwise waits for the new device.
+ */
+int DiscoveryAgent::getNextDevice(DiscoveredDevice &aDiscoveredDevice)
+{
+    JELOG2(EJavaBluetooth);
+    int status = mDeviceDiscoverer->getNextDevice(aDiscoveredDevice);
+    if (STATUS_DEVICE_FOUND != status)
+    {
+        cleanupDeviceDiscoverer();
+    }
+    return status;
+}
+
+/**
+ * Makes callback to the Java only when new device found.
+ * Returns the inquiry status.
+ */
+int DiscoveryAgent::doDeviceDiscoveryCallback(JNIEnv* aJni, jobject& aPeer,
+        DiscoveredDevice &aDiscoveredDevice)
+{
+    JELOG2(EJavaBluetooth);
+
+    jstring devAddr = NULL;
+    jstring devName = NULL;
+    int deviceClass = 0;
+
+    if (STATUS_DEVICE_FOUND == aDiscoveredDevice.mInquiryStatus)
+    {
+        LOG(EJavaBluetooth, EInfo,
+            "  DiscoveryAgent::doDeviceDiscoveryCallback: Device discovered callback");
+
+        if (NULL != aDiscoveredDevice.mDeviceAddr)
+        {
+            try
+            {
+                devAddr = java::util::JniUtils::wstringToJstring(aJni,
+                          *(aDiscoveredDevice.mDeviceAddr));
+            }
+            catch (ExceptionBase ex)
+            {
+                // Nothing to handle
+            }
+        }
+        else
+        {
+            ELOG(EJavaBluetooth,
+                 "  DiscoveryAgent Really Serious Error: Address is NULL !!");
+        }
+
+        if (NULL != aDiscoveredDevice.mDeviceName)
+        {
+            try
+            {
+                devName = java::util::JniUtils::wstringToJstring(aJni,
+                          *(aDiscoveredDevice.mDeviceName));
+            }
+            catch (ExceptionBase ex)
+            {
+                // Nothing to handle
+            }
+        }
+        else
+        {
+            ELOG(EJavaBluetooth,
+                 "  DiscoveryAgent::doDeviceDiscoveryCallback: Device Name is NULL");
+        }
+
+        deviceClass = aDiscoveredDevice.mDeviceClass;
+
+        (*aJni).CallVoidMethod(aPeer, mDeviceDiscoveredMethod, devAddr,
+                               devName, deviceClass);
+    }
+
+    LOG1(EJavaBluetooth, EInfo,
+         "- DiscoveryAgent::doDeviceDiscoveryCallback: %d",
+         aDiscoveredDevice.mInquiryStatus);
+    return aDiscoveredDevice.mInquiryStatus;
+}
+
+/**
+ * Deletes the BluetoothDeviceDiscoverer
+ */
+void DiscoveryAgent::cleanupDeviceDiscoverer()
+{
+    JELOG2(EJavaBluetooth);
+    delete mDeviceDiscoverer;
+    mDeviceDiscoverer = NULL;
+}
+
+/**
+ * Starts lookup for the friendly name of the device
+ * On success, returns the friendly name of the device
+ * Otherwise NULL
+ *
+ * Note: Must free resultant friendly name, whenever not required.
+ */
+std::wstring* DiscoveryAgent::lookupFriendlyNameL(long long aDevAddr)
+{
+    JELOG2(EJavaBluetooth);
+    LOG1(EJavaBluetooth, EInfo,
+         "+ DiscoveryAgent::lookupFriendlyName DeviceAddress:%x", aDevAddr);
+
+    TInt64 devAddr = (TInt64) aDevAddr;
+    std::wstring* result = NULL;
+
+    CallMethodL(result, this, &java::bluetooth::DiscoveryAgent::nameLookupL,
+                devAddr, mFunctionServer);
+
+    return result;
+}
+
+/**
+ * Creates the BluetoothNameLookup object
+ */
+std::wstring* DiscoveryAgent::nameLookupL(TInt64 aDevAddr)
+{
+    JELOG2(EJavaBluetooth);
+    std::wstring* result = NULL;
+    BluetoothNameLookup * nameLookup = BluetoothNameLookup::NewL();
+    CleanupStack::PushL(nameLookup);
+    result = nameLookup->doDeviceNameLookupL(aDevAddr);
+    CleanupStack::Pop(nameLookup);
+    delete nameLookup;
+    return result;
+}
+
+/*
+ *   ------- Service Search Methods --------
+ */
+int DiscoveryAgent::StartSearchServices(JNIEnv* aJni, jobject& aPeer,
+                                        TInt64 aRemoteAddress, TPtrC8 aUuidsDes, TPtrC16 aAttrIdsDes,
+                                        java::util::Monitor* aMonitor)
+{
+    JELOG2(EJavaBluetooth);
+
+    mServiceSearchMonitor = aMonitor;
+    mServiceSearchStatus = -1;
+
+    jclass peerClass = (*aJni).GetObjectClass(aPeer);
+
+    //Get Method ID of Service Search Started Callback
+    mServiceSearchStartedMethod = aJni->GetMethodID(peerClass,
+                                  "serviceSearchStartedCallback", "()V");
+
+    //Check if all the JNI inits have succeeded
+    if (NULL == mServiceSearchStartedMethod)
+    {
+        //Error in initialization
+        ELOG(EJavaBluetooth,
+             "- DiscoveryAgent::StartSearchServices: Error in JNIInit ");
+        return -1;
+    }
+
+    LOG(EJavaBluetooth, EInfo,
+        "  DiscoveryAgent::StartSearchServices: Starting service search ");
+
+    TRAPD(err, CallMethodL(this,
+                           &java::bluetooth::DiscoveryAgent::searchServiceFsL, aRemoteAddress,
+                           aUuidsDes, aAttrIdsDes, mFunctionServer));
+
+    if (KErrNone == err)
+    {
+        StartedServiceSearch(aJni, aPeer);
+    }
+
+    return err;
+}
+
+void DiscoveryAgent::searchServiceFsL(TInt64 aRemoteAddress, TPtrC8 aUuidsDes,
+                                      TPtrC16 aAttrIdsDes)
+{
+    mServiceSearcher = BluetoothServiceSearcher::New(this, mFunctionServer);
+
+    TRAPD(err, mServiceSearcher->SearchServicesL(aRemoteAddress, aUuidsDes,
+            aAttrIdsDes));
+    if (KErrNone != err)
+    {
+        ELOG(EJavaBluetooth,
+             "  DiscoveryAgent::SearchServiceFsL: Error occured!! ");
+        CleanupServiceSearcher();
+        User::LeaveIfError(err);
+    }
+}
+
+void DiscoveryAgent::StartedServiceSearch(JNIEnv* aJni, jobject& aPeer)
+{
+    JELOG2(EJavaBluetooth);
+    mIsServiceSearchOn = true;
+
+    (*aJni).CallVoidMethod(aPeer, mServiceSearchStartedMethod);
+
+}
+
+void DiscoveryAgent::ServiceSearchCompleted(int aStatus)
+{
+    JELOG2(EJavaBluetooth);
+    mIsServiceSearchOn = false;
+    mServiceSearchStatus = aStatus;
+    mServiceSearchMonitor->notify();
+    CleanupServiceSearcher();
+}
+
+bool DiscoveryAgent::CancelServiceSearch()
+{
+    JELOG2(EJavaBluetooth);
+    if (NULL != mServiceSearcher)
+    {
+        CallMethod(
+            this,
+            &java::bluetooth::DiscoveryAgent::cancelAndCleanupServiceSearchFs,
+            mFunctionServer);
+    }
+    CleanupAllServiceSearcherInfo();
+    mIsServiceSearchOn = false;
+    return true;
+}
+
+void DiscoveryAgent::cancelAndCleanupServiceSearchFs()
+{
+    mServiceSearcher->cancelServiceSearch();
+    CleanupServiceSearcher();
+}
+
+int DiscoveryAgent::getStatusOfCompletion()
+{
+    JELOG2(EJavaBluetooth);
+    LOG1(EJavaBluetooth, EInfo, "+ DiscoveryAgent::getStatusOfCompletion: %d",
+         mServiceSearchStatus);
+    return mServiceSearchStatus;
+}
+
+int DiscoveryAgent::PopulateServiceRecordAttrValue(JNIEnv* aJni,
+        jobject& aPeer, TInt64 aRemoteAddress, long aHandle,
+        TPtrC16 aAttrIdsDes, jobject aServiceRecordImpl,
+        java::util::Monitor* aMonitor)
+{
+    JELOG2(EJavaBluetooth);
+
+    mServiceSearchMonitor = aMonitor;
+
+    jclass peerClass = (*aJni).GetObjectClass(aPeer);
+
+    LOG(EJavaBluetooth, EInfo,
+        "  DiscoveryAgent::PopulateServiceRecord: Starting populating service records ");
+    TRAPD(err, CallMethodL(this,
+                           &java::bluetooth::DiscoveryAgent::populateServiceRecordAttrValueFs,
+                           aRemoteAddress, aHandle, aAttrIdsDes, aServiceRecordImpl,
+                           mFunctionServer));
+
+    return err;
+}
+
+void DiscoveryAgent::populateServiceRecordAttrValueFs(TInt64 aRemoteAddress,
+        long aHandle, TPtrC16 aAttrIdsDes, jobject aServiceRecordImpl)
+{
+    mServiceSearcher = BluetoothServiceSearcher::New(this, mFunctionServer);
+    mServiceSearcher->PopulateServiceRecordsL(aRemoteAddress, aHandle,
+            aAttrIdsDes, aServiceRecordImpl);
+}
+
+void DiscoveryAgent::PopulateRecordCompleted(int aStatus)
+{
+    JELOG2(EJavaBluetooth);
+    mPopulateRecordStatus = aStatus;
+    mServiceSearchMonitor->notify();
+    CleanupServiceSearcher();
+}
+
+int DiscoveryAgent::GetPopulateServiceRecordStatus()
+{
+    JELOG2(EJavaBluetooth);
+    return mPopulateRecordStatus;
+}
+
+bool DiscoveryAgent::CancelPopulateServiceRecordAttrValue()
+{
+    JELOG2(EJavaBluetooth);
+    mIsServiceSearchOn = false;
+    TRAP_IGNORE(CallMethodL(mServiceSearcher,
+                            &java::bluetooth::BluetoothServiceSearcher::cancelServiceSearch,
+                            mFunctionServer));
+
+    return true;
+}
+
+void DiscoveryAgent::CleanupServiceSearcher()
+{
+    JELOG2(EJavaBluetooth);
+    //Delete all contained objects
+    if (mServiceSearcher)
+    {
+        delete mServiceSearcher;
+        mServiceSearcher = NULL;
+    }
+}
+
+void DiscoveryAgent::CleanupAllServiceSearcherInfo()
+{
+    JELOG2(EJavaBluetooth);
+    // Clear all realted data
+    mServiceSearchStartedMethod = NULL;
+    mIsServiceSearchOn = false;
+    mPopulateRecordStatus = KErrNone;
+    mServiceSearchMonitor = NULL;
+}
+
+} //end namespace bluetooth
+} //end namespace java