javaextensions/bluetooth/bluetoothcommons/src.s60/servicerecord.cpp
changeset 21 2a9601315dfc
child 47 f40128debb5d
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <errno.h>
       
    20 #include <sys/types.h>
       
    21 #include <sys/stat.h>
       
    22 #include <dirent.h>
       
    23 #include <sys/uio.h>
       
    24 #include <unistd.h>
       
    25 #include <fcntl.h>
       
    26 
       
    27 #include "fs_methodcall.h"
       
    28 #include "javajniutils.h"
       
    29 #include "servicerecord.h"
       
    30 #include "logger.h"
       
    31 #include "javasymbianoslayer.h"
       
    32 #include "bluetoothconsts.h"
       
    33 #include "applicationinfo.h"
       
    34 #include "fileutilities.h"
       
    35 #include "javaoslayer.h"
       
    36 #include "javacommonutils.h"
       
    37 #include "btservicerecordpopulator.h"
       
    38 #include "serviceclasshandler.h"
       
    39 #include "fileutilities.h"
       
    40 #include "exceptionbase.h"
       
    41 
       
    42 using namespace java::util;
       
    43 using namespace java::fileutils;
       
    44 
       
    45 namespace java
       
    46 {
       
    47 namespace bluetooth
       
    48 {
       
    49 
       
    50 #define SERVICE_AVAILABLE 0xFF
       
    51 #define KGOEP 0x0008    // This is the fixed Id. Should not be modified at any time.
       
    52 #define SERVICE_CLASSES_BITS_POS    13
       
    53 
       
    54 // Permission: Read,Write,Execute for both Owner & Group
       
    55 #define BT_DIR_PERM 0777
       
    56 
       
    57 /**
       
    58  * Returns the new ServiceRecord object.
       
    59  */
       
    60 OS_EXPORT ServiceRecord* ServiceRecord::NewL(BluetoothFunctionServer* aServer)
       
    61 {
       
    62     JELOG2(EJavaBluetooth);
       
    63     ServiceRecord* servRec = new ServiceRecord(aServer);
       
    64     CleanupStack::PushL(servRec);
       
    65 
       
    66     servRec->ConstructL();
       
    67 
       
    68     CleanupStack::Pop(servRec);
       
    69 
       
    70     return servRec;
       
    71 }
       
    72 
       
    73 OS_EXPORT void ServiceRecord::cleanup(ServiceRecord*& aServer)
       
    74 {
       
    75     JELOG2(EJavaBluetooth);
       
    76     if (aServer)
       
    77     {
       
    78         aServer->cleanUp();
       
    79         delete aServer;
       
    80         aServer = NULL;
       
    81     }
       
    82 }
       
    83 
       
    84 void ServiceRecord::ConstructL()
       
    85 {
       
    86     JELOG2(EJavaBluetooth);
       
    87 
       
    88     mInitializedByPush = false;
       
    89     mRestoredFromPersistentFile = false;
       
    90 
       
    91     // Open sdp session
       
    92     User::LeaveIfError(mSdp.Connect());
       
    93 
       
    94     // Open sdp database session
       
    95     User::LeaveIfError(mSdpDB.Open(mSdp));
       
    96 
       
    97     mRecordState = 0;
       
    98 }
       
    99 
       
   100 ServiceRecord::ServiceRecord(BluetoothFunctionServer* aServer)
       
   101 {
       
   102     JELOG2(EJavaBluetooth);
       
   103     mFunctionServer = aServer;
       
   104     mRecord = 0;
       
   105     mSrvRecFd = 0;
       
   106 }
       
   107 
       
   108 ServiceRecord::~ServiceRecord()
       
   109 {
       
   110     JELOG2(EJavaBluetooth);
       
   111     mFunctionServer = NULL;
       
   112 }
       
   113 
       
   114 void ServiceRecord::cleanUp()
       
   115 {
       
   116     JELOG2(EJavaBluetooth);
       
   117     if (mRecord)
       
   118     {
       
   119         TRAP_IGNORE(mSdpDB.DeleteRecordL(mRecord));
       
   120         mRecord = 0;
       
   121     }
       
   122     mSdpDB.Close();
       
   123     mSdp.Close();
       
   124 }
       
   125 
       
   126 /**
       
   127  * Used in case there is no persistence storage of service record
       
   128  * On success returns 0; otherwise err number.
       
   129  *
       
   130  * Creates and initializes the Service record.
       
   131  * aProtocol: One among the PROTOCOL_L2CAP, PROTOCOL_RFCOMM, PROTOCOL_GOEP
       
   132  * aPSMValue: In case of L2CAP it should be PSM Value;
       
   133  *            In case of RFComm it should be channel number.
       
   134  * aUuid: UUID string of the current service
       
   135  * aServiceName: Name of the current service.
       
   136  */
       
   137 
       
   138 OS_EXPORT int ServiceRecord::initializeRecord(int aProtocol, int aPSMValue,
       
   139         std::wstring aUuid, std::wstring aServiceName)
       
   140 {
       
   141     JELOG2(EJavaBluetooth);
       
   142 
       
   143     int uuidByteLength = 0;
       
   144     TUint8* uuidBytes = uuidToByteArray(aUuid, uuidByteLength);
       
   145 
       
   146     TUUID uuid;
       
   147 
       
   148     TPtrC8 uuidDes(uuidBytes, uuidByteLength);
       
   149     TRAPD(err, uuid.SetL(uuidDes));
       
   150 
       
   151     delete uuidBytes;
       
   152     uuidBytes = NULL;
       
   153 
       
   154     if (KErrNone != err)
       
   155     {
       
   156         LOG2(EJavaBluetooth, EInfo,
       
   157              "- ServiceRecord::initializeRecord Error SetL:%d [UUID:%S]",
       
   158              err, aUuid.c_str());
       
   159         return err;
       
   160     }
       
   161 
       
   162     HBufC* nameString = wstringToBuf(aServiceName);
       
   163     TPtrC nameBufPointer(nameString->Des());
       
   164 
       
   165     HBufC8* utf8NameBuffer = HBufC8::NewMax(aServiceName.length() + 1);
       
   166     TPtr8 utf8NameBufferPtr(utf8NameBuffer->Des());
       
   167 
       
   168     utf8NameBufferPtr.Copy(nameBufPointer);
       
   169 
       
   170     TRAP(err, initializeRecordL(aProtocol, aPSMValue, uuid, utf8NameBufferPtr));
       
   171 
       
   172     return err;
       
   173 }
       
   174 
       
   175 /**
       
   176  * Used in case of persistence storage of updated service record
       
   177  */
       
   178 OS_EXPORT int ServiceRecord::restorePersistentRecord()
       
   179 {
       
   180     JELOG2(EJavaBluetooth);
       
   181     int ret = 0;
       
   182 
       
   183     CallMethod(ret, this, &ServiceRecord::restorePersistentRecordFs,
       
   184                mFunctionServer);
       
   185     return ret;
       
   186 }
       
   187 
       
   188 int ServiceRecord::restorePersistentRecordFs()
       
   189 {
       
   190     JELOG2(EJavaBluetooth);
       
   191 
       
   192     // Can set this flag as this function will get called
       
   193     // only in case of push invocation
       
   194     mInitializedByPush = true;
       
   195 
       
   196     std::wstring persistentFileName = getPersistentFileName();
       
   197     int persistentRecFd = -1;
       
   198     int ret = 0;
       
   199     int err = 0;
       
   200 
       
   201     if (persistentFileName.length() > 0)
       
   202     {
       
   203         try
       
   204         {
       
   205             char *fileName = java::util::JavaCommonUtils::wstringToUtf8(
       
   206                                  persistentFileName);
       
   207             persistentRecFd = open(fileName, O_RDONLY);
       
   208             delete fileName;
       
   209         }
       
   210         catch (ExceptionBase ex)
       
   211         {
       
   212             ELOG1(
       
   213                 EJavaBluetooth,
       
   214                 "- ServiceRecord::restorePersistentRecordFs exception Caught: %S",
       
   215                 ex.toString().c_str());
       
   216         }
       
   217     }
       
   218 
       
   219     if (persistentRecFd < 0)
       
   220         return errno;
       
   221 
       
   222     // Reading and restoring the DeviceServiceClasses bits
       
   223     int devServClass = 0;
       
   224     ret = read(persistentRecFd, &devServClass, sizeof(devServClass));
       
   225 
       
   226     if (ret <= 0)
       
   227         return errno;
       
   228 
       
   229     if (devServClass != 0)
       
   230     {
       
   231         LOG1(EJavaBluetooth, EInfo,
       
   232              "  ServiceRecord::restorePersistentRecordFs Setting COD:0x%X",
       
   233              devServClass);
       
   234         ret = ServiceClassHandler::setDeviceServiceClass(devServClass, true);
       
   235         LOG1(EJavaBluetooth, EInfo,
       
   236              "  ServiceRecord::restorePersistentRecordFs Set COD Return:%d",
       
   237              ret);
       
   238     }
       
   239 
       
   240     // Restoring all other service record data
       
   241     int attrId = 0;
       
   242     while ((ret = read(persistentRecFd, &attrId, sizeof(attrId))) > 0)
       
   243     {
       
   244         int dataType = 0;
       
   245 
       
   246         ret = read(persistentRecFd, &dataType, sizeof(dataType));
       
   247         if (ret <= 0)
       
   248             break;
       
   249 
       
   250         LOG2(EJavaBluetooth, EInfo, "  ServiceRecord reading %X, %X", attrId,
       
   251              dataType);
       
   252 
       
   253         switch (dataType)
       
   254         {
       
   255         case DataElement_DATSEQ:
       
   256         case DataElement_DATALT:
       
   257         {
       
   258             err = attributeListStartFs(attrId, dataType, EFalse);
       
   259             break;
       
   260         }
       
   261         case DataElement_EndList:
       
   262         {
       
   263             err = attributeListEndFs(attrId, EFalse);
       
   264             break;
       
   265         }
       
   266         case DataElement_NULL:
       
   267         {
       
   268             err = setAttributeNilFs(attrId, EFalse);
       
   269             break;
       
   270         }
       
   271         case DataElement_BOOL:
       
   272         {
       
   273             TUint8 val = 0;
       
   274             ret = read(persistentRecFd, &val, sizeof(val));
       
   275             if (ret <= 0)
       
   276                 break;
       
   277 
       
   278             LOG1(EJavaBluetooth, EInfo, "  ServiceRecord reading Bool %X", val);
       
   279             err = setAttributeBoolFs(attrId, (val) ? ETrue : EFalse, EFalse);
       
   280             break;
       
   281         }
       
   282         case DataElement_INT_1:
       
   283         case DataElement_INT_2:
       
   284         case DataElement_INT_4:
       
   285         {
       
   286             int len = 0;
       
   287             ret = read(persistentRecFd, &len, sizeof(len));
       
   288             if (ret <= 0)
       
   289                 break;
       
   290 
       
   291             TUint8 buf[20] = { 0 };
       
   292             ret = read(persistentRecFd, buf, len);
       
   293             if (ret <= 0)
       
   294                 break;
       
   295             std::auto_ptr<HBufC8> val(convertIntToDesC(buf, dataType));
       
   296             err = setAttributeIntFs(attrId, dataType, *val, EFalse);
       
   297             break;
       
   298         }
       
   299         case DataElement_INT_8:
       
   300         case DataElement_INT_16:
       
   301         {
       
   302             int len = 0;
       
   303             ret = read(persistentRecFd, &len, sizeof(len));
       
   304             if (ret <= 0)
       
   305                 break;
       
   306 
       
   307             TUint8 buf[20] = { 0 };
       
   308             ret = read(persistentRecFd, buf, len);
       
   309             if (ret <= 0)
       
   310                 break;
       
   311             TPtrC8 val(buf, len);
       
   312             err = setAttributeIntFs(attrId, dataType, val, EFalse);
       
   313             break;
       
   314         }
       
   315         case DataElement_U_INT_1:
       
   316         case DataElement_U_INT_2:
       
   317         case DataElement_U_INT_4:
       
   318         {
       
   319             int len = 0;
       
   320             ret = read(persistentRecFd, &len, sizeof(len));
       
   321             if (ret <= 0)
       
   322                 break;
       
   323 
       
   324             TUint8 buf[20] = { 0 };
       
   325             ret = read(persistentRecFd, buf, len);
       
   326             if (ret <= 0)
       
   327                 break;
       
   328 
       
   329             LOG2(EJavaBluetooth, EInfo, "  ServiceRecord reading INT8 %X, %S",
       
   330                  len, buf);
       
   331 
       
   332             std::auto_ptr<HBufC8> val(convertIntToDesC(buf, dataType));
       
   333             err = setAttributeUintFs(attrId, dataType, *val, EFalse);
       
   334             break;
       
   335         }
       
   336         case DataElement_U_INT_8:
       
   337         case DataElement_U_INT_16:
       
   338         {
       
   339             int len = 0;
       
   340             ret = read(persistentRecFd, &len, sizeof(len));
       
   341             if (ret <= 0)
       
   342                 break;
       
   343 
       
   344             TUint8 buf[20] = { 0 };
       
   345             ret = read(persistentRecFd, buf, len);
       
   346             if (ret <= 0)
       
   347                 break;
       
   348 
       
   349             LOG2(EJavaBluetooth, EInfo, "  ServiceRecord reading INT16 %X, %S",
       
   350                  len, buf);
       
   351 
       
   352             TPtrC8 val(buf, len);
       
   353             err = setAttributeUintFs(attrId, dataType, val, EFalse);
       
   354             break;
       
   355         }
       
   356         case DataElement_UUID:
       
   357         {
       
   358             int len = 0;
       
   359             ret = read(persistentRecFd, &len, sizeof(len));
       
   360             if (ret <= 0)
       
   361                 break;
       
   362 
       
   363             TUint8 buf[256] = { 0 };
       
   364             ret = read(persistentRecFd, buf, len);
       
   365             if (ret <= 0)
       
   366                 break;
       
   367 
       
   368             LOG2(EJavaBluetooth, EInfo, "  ServiceRecord reading UUID %X, %S",
       
   369                  len, buf);
       
   370 
       
   371             TPtrC8 uuidDes(buf, len);
       
   372 
       
   373             TUUID val;
       
   374             TRAP(err, val.SetL(uuidDes));
       
   375 
       
   376             if (KErrNone == err)
       
   377             {
       
   378                 err = setAttributeUUIDFs(attrId, val, EFalse);
       
   379             }
       
   380             break;
       
   381         }
       
   382         case DataElement_STRING:
       
   383         {
       
   384             int len = 0;
       
   385             ret = read(persistentRecFd, &len, sizeof(len));
       
   386             if (ret <= 0)
       
   387                 break;
       
   388 
       
   389             TUint8 buf[1024] = {0};
       
   390             ret = read(persistentRecFd, buf, len);
       
   391             if (ret <= 0)
       
   392                 break;
       
   393 
       
   394             LOG1(EJavaBluetooth, EInfo, "  ServiceRecord reading STRING %X",
       
   395                  len);
       
   396 
       
   397             TPtrC8 val(buf, len);
       
   398             err = setAttributeStringFs(attrId, val, EFalse);
       
   399             break;
       
   400         }
       
   401         case DataElement_URL:
       
   402         {
       
   403             int len = 0;
       
   404             ret = read(persistentRecFd, &len, sizeof(len));
       
   405             if (ret <= 0)
       
   406                 break;
       
   407 
       
   408             TUint8 buf[1024] = {0};
       
   409             ret = read(persistentRecFd, buf, len);
       
   410             if (ret <= 0)
       
   411                 break;
       
   412 
       
   413             LOG2(EJavaBluetooth, EInfo, "  ServiceRecord reading URL %X, %S",
       
   414                  len, buf);
       
   415 
       
   416             TPtrC8 val(buf, len);
       
   417             err = setAttributeUrlFs(attrId, val, EFalse);
       
   418             break;
       
   419         }
       
   420         default:
       
   421             break;
       
   422         }
       
   423 
       
   424         // Treated as EOF reached.
       
   425         if (ret <= 0)
       
   426             break;
       
   427     }
       
   428 
       
   429     // Indicates a successful retrieval
       
   430     // of the service record from the persistent file
       
   431     mRestoredFromPersistentFile = true;
       
   432 
       
   433     return ret;
       
   434 }
       
   435 
       
   436 /**
       
   437  * Creates and initializes the Service record.
       
   438  * aProtocol: One among the PROTOCOL_L2CAP, PROTOCOL_RFCOMM, PROTOCOL_GOEP
       
   439  * aPSMValue: In case of L2CAP it should be PSM Value;
       
   440  *            In case of RFComm it should be channel number.
       
   441  * aServiceUUID: UUID of the current service
       
   442  * aServiceName: Name of the current service.
       
   443  */
       
   444 OS_EXPORT void ServiceRecord::initializeRecordL(TInt aProtocol, TInt aPsmValue,
       
   445         TUUID &aServiceUUID, TDesC8 &aServiceName)
       
   446 {
       
   447     JELOG2(EJavaBluetooth);
       
   448     CallMethodL(this, &ServiceRecord::initializeRecordFsL, aProtocol,
       
   449                 aPsmValue, aServiceUUID, aServiceName, mFunctionServer);
       
   450 }
       
   451 
       
   452 /**
       
   453  * Returns the service record handle.
       
   454  */
       
   455 OS_EXPORT int ServiceRecord::getServiceRecordID()
       
   456 {
       
   457     return mRecord;
       
   458 }
       
   459 
       
   460 void ServiceRecord::initializeRecordFsL(TInt aProtocol, TInt aPsmValue,
       
   461                                         TUUID &aServiceUUID, TDesC8 &aServiceName)
       
   462 {
       
   463     JELOG2(EJavaBluetooth);
       
   464     // Open sdp session
       
   465     User::LeaveIfError(mSdp.Connect());
       
   466     // Open sdp database session
       
   467     User::LeaveIfError(mSdpDB.Open(mSdp));
       
   468 
       
   469     LOG1(
       
   470         EJavaBluetooth,
       
   471         EInfo,
       
   472         "  ServiceRecord::initializeRecordFsL: After registering to SDPDB: %S",
       
   473         aServiceUUID.Des().Ptr());
       
   474 
       
   475     // Creating proper ServiceClassID list
       
   476     CSdpAttrValueDES *serviceClassIds = CSdpAttrValueDES::NewDESL(NULL);
       
   477     serviceClassIds->BuildUUIDL(aServiceUUID);
       
   478     if (PROTOCOL_RFCOMM == aProtocol)
       
   479     {
       
   480         LOG(EJavaBluetooth, EInfo,
       
   481             "  ServiceRecord::initializeRecordFsL: Adding KSerialPortUUID");
       
   482 
       
   483         serviceClassIds->BuildUUIDL(TUUID(KSerialPortUUID));
       
   484     }
       
   485 
       
   486     // Create a record of the correct service class
       
   487     mSdpDB.CreateServiceRecordL(*serviceClassIds, mRecord);
       
   488 
       
   489     // Add a protocol to the record
       
   490     mSdpAttrValueList = CSdpAttrValueDES::NewDESL(NULL);
       
   491     mLastSdpAttr = mSdpAttrValueList;
       
   492     CleanupStack::PushL(mSdpAttrValueList);
       
   493 
       
   494     // Getting port number
       
   495     TSdpIntBuf<TUint> portBuf(aPsmValue);
       
   496     LOG1(EJavaBluetooth, EInfo,
       
   497          "  ServiceRecord::initializeRecordFsL: port value : %d", aPsmValue);
       
   498 
       
   499     LOG(EJavaBluetooth, EInfo,
       
   500         "  ServiceRecord::initializeRecordFsL: Creating protocol list");
       
   501 
       
   502     // Create protocol list for our service
       
   503 
       
   504     switch (aProtocol)
       
   505     {
       
   506     case PROTOCOL_L2CAP:
       
   507         LOG(EJavaBluetooth, EInfo,
       
   508             "  ServiceRecord::initializeRecordFsL: PROTOCOL_L2CAP");
       
   509         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   510         mLastSdpAttr = mLastSdpAttr -> BuildDESL();
       
   511         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   512         mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KL2CAP);
       
   513         mLastSdpAttr = mLastSdpAttr -> BuildUintL(portBuf);
       
   514         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   515         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   516         break;
       
   517     case PROTOCOL_RFCOMM:
       
   518         LOG(EJavaBluetooth, EInfo,
       
   519             "  ServiceRecord::initializeRecordFsL: PROTOCOL_RFCOMM");
       
   520         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   521         mLastSdpAttr = mLastSdpAttr -> BuildDESL();
       
   522         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   523         mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KL2CAP);
       
   524         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   525         mLastSdpAttr = mLastSdpAttr -> BuildDESL();
       
   526         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   527         mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KRFCOMM);
       
   528         mLastSdpAttr = mLastSdpAttr -> BuildUintL(portBuf);
       
   529         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   530         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   531         break;
       
   532     case PROTOCOL_GOEP:
       
   533         LOG(EJavaBluetooth, EInfo,
       
   534             "  ServiceRecord::initializeRecordFsL: PROTOCOL_GOEP");
       
   535         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   536         mLastSdpAttr = mLastSdpAttr -> BuildDESL();
       
   537         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   538         mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KL2CAP);
       
   539         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   540         mLastSdpAttr = mLastSdpAttr -> BuildDESL();
       
   541         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   542         mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KRFCOMM);
       
   543         mLastSdpAttr = mLastSdpAttr -> BuildUintL(portBuf);
       
   544         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   545         mLastSdpAttr = mLastSdpAttr -> BuildDESL();
       
   546         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   547         mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(KGOEP);
       
   548         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   549         mLastSdpAttr = mLastSdpAttr -> EndListL();
       
   550         break;
       
   551     }
       
   552 
       
   553     LOG(EJavaBluetooth, EInfo,
       
   554         "  ServiceRecord::initializeRecordFsL: Set protocol list to the record");
       
   555     // Set protocol list to the record
       
   556     mSdpDB.UpdateAttributeL(mRecord, KSdpAttrIdProtocolDescriptorList,
       
   557                             *mSdpAttrValueList);
       
   558     CleanupStack::PopAndDestroy(mSdpAttrValueList);
       
   559 
       
   560     mSdpAttrValueList = NULL;
       
   561     mLastSdpAttr = NULL;
       
   562 
       
   563     LOG(EJavaBluetooth, EInfo,
       
   564         "  ServiceRecord::initializeRecordFsL: Update attribute");
       
   565 
       
   566     if (aServiceName.Size() > 0)
       
   567     {
       
   568         // Add a name to the record
       
   569         mSdpDB.UpdateAttributeL(mRecord, KSdpAttrIdBasePrimaryLanguage
       
   570                                 + KSdpAttrIdOffsetServiceName, aServiceName);
       
   571         LOG1(EJavaBluetooth, EInfo,
       
   572              "  ServiceRecord::initializeRecordFsL: Update Name: %d",
       
   573              KSdpAttrIdBasePrimaryLanguage + KSdpAttrIdOffsetServiceName);
       
   574     }
       
   575 
       
   576     mOrigUuid = uuidToWstring(aServiceUUID);
       
   577 
       
   578     LOG1(EJavaBluetooth, EInfo,
       
   579          "  ServiceRecord::initializeRecordFsL mOrigUuid = %S",
       
   580          mOrigUuid.c_str());
       
   581 
       
   582     mProtocol = aProtocol;
       
   583 }
       
   584 
       
   585 /**
       
   586  * Opens the persistent file. Called when Update Record triggered.
       
   587  * And stores the DeviceServiceClasses bits (32 bit) in the persistent file
       
   588  * While retrieving the service record back from the file, it is must to read first
       
   589  * one integer which depicts this DeviceServiceClasses. If the service classes is not
       
   590  * set for the corresponding service, then the value 0(32 bits) is stored in place of the
       
   591  * DeviceServiceClasses bits.
       
   592  *
       
   593  */
       
   594 OS_EXPORT void ServiceRecord::initializeUpdateRecord(int aDeviceServiceClasses)
       
   595 {
       
   596     JELOG2(EJavaBluetooth);
       
   597     std::wstring persistentFileName;
       
   598 
       
   599     persistentFileName = getPersistentFileName();
       
   600 
       
   601     if (persistentFileName.length() > 0)
       
   602     {
       
   603         try
       
   604         {
       
   605             char *fileName = java::util::JavaCommonUtils::wstringToUtf8(
       
   606                                  persistentFileName);
       
   607             mSrvRecFd = open(fileName, O_CREAT | O_WRONLY | O_TRUNC, 0666);
       
   608 
       
   609             if (mSrvRecFd < 0)
       
   610             {
       
   611                 ELOG1(
       
   612                     EJavaBluetooth,
       
   613                     "- ServiceRecord::initializeUpdateRecord Err while file open. %d",
       
   614                     errno);
       
   615                 return;
       
   616             }
       
   617             // Storing the Current DeviceClass (32 bits)
       
   618             write(mSrvRecFd, (char *) &aDeviceServiceClasses,
       
   619                   sizeof(aDeviceServiceClasses));
       
   620 
       
   621             delete fileName;
       
   622         }
       
   623         catch (ExceptionBase ex)
       
   624         {
       
   625             ELOG1(
       
   626                 EJavaBluetooth,
       
   627                 "- ServiceRecord::initializeUpdateRecord exception Caught: %S",
       
   628                 ex.toString().c_str());
       
   629         }
       
   630     }
       
   631 }
       
   632 
       
   633 /**
       
   634  * Closes the persistent file.
       
   635  */
       
   636 OS_EXPORT void ServiceRecord::completesUpdateRecord()
       
   637 {
       
   638     JELOG2(EJavaBluetooth);
       
   639     if (0 != mSrvRecFd)
       
   640     {
       
   641         close(mSrvRecFd);
       
   642         mSrvRecFd = 0;
       
   643     }
       
   644 }
       
   645 
       
   646 /**
       
   647  * Gets the persistent file name. This function returns the file name pattern
       
   648  * srv_rec_<uuid>_<protocol>.txt And also, the srv_rec_XXX.txt
       
   649  * file name will be prepended with midlet's private directory for
       
   650  * bluetooth. That is, the final outcome of this function may be something
       
   651  * like, <midlet_private_dir>/bt/srv_rec_XXX.txt
       
   652  *
       
   653  * @param aUuid
       
   654  *            uuid string
       
   655  * @param aProtocol
       
   656  *            protocol name
       
   657  * @return Null when connection not registered for push;
       
   658  *         otherwise srv_rec_XXX file name
       
   659  */
       
   660 std::wstring ServiceRecord::getPersistentFileName()
       
   661 {
       
   662     JELOG2(EJavaBluetooth);
       
   663     std::wstring noFileName;
       
   664     std::wstring srvRecFile;
       
   665 
       
   666     LOG1(EJavaBluetooth, EInfo, "+ ServiceRecord:getPersistentFileName %d",
       
   667          mProtocol);
       
   668 
       
   669     const java::runtime::ApplicationInfo& appInf =
       
   670         java::runtime::ApplicationInfo::getInstance();
       
   671     const std::wstring btFilesPath = appInf.getRootPath() + L"bt\\";
       
   672 
       
   673     if (false == FileUtilities::exists(btFilesPath))
       
   674     {
       
   675         try
       
   676         {
       
   677             LOG1(EJavaBluetooth, EInfo,
       
   678                  "  ServiceRecord:getPersistentFileName mkdir:%S",
       
   679                  btFilesPath.c_str());
       
   680 
       
   681             char *dirName = JavaCommonUtils::wstringToUtf8(btFilesPath);
       
   682             if (mkdir(dirName, BT_DIR_PERM) < 0)
       
   683             {
       
   684                 ELOG1(EJavaBluetooth,
       
   685                       "- ServiceRecord:getPersistentFileName Err, mkdir:%d",errno);
       
   686                 delete[] dirName;
       
   687                 return noFileName;
       
   688             }
       
   689             delete[] dirName;
       
   690         }
       
   691         catch (ExceptionBase ex)
       
   692         {
       
   693             ELOG1(EJavaBluetooth,
       
   694                   "- ServiceRecord::getPersistentFileName exception Caught: %S",
       
   695                   ex.toString().c_str());
       
   696             return noFileName;
       
   697         }
       
   698     }
       
   699 
       
   700     srvRecFile = btFilesPath + L"srv_rec_";
       
   701 
       
   702     switch (mProtocol)
       
   703     {
       
   704     case PROTOCOL_L2CAP:
       
   705         srvRecFile += mOrigUuid + L"_btl2cap.txt";
       
   706         break;
       
   707     case PROTOCOL_RFCOMM:
       
   708         srvRecFile += mOrigUuid + L"_btspp.txt";
       
   709         break;
       
   710     case PROTOCOL_GOEP:
       
   711         srvRecFile += mOrigUuid + L"_btgoep.txt";
       
   712         break;
       
   713     }
       
   714 
       
   715     LOG1(EJavaBluetooth, EInfo,
       
   716          "- ServiceRecord:getPersistentFileName %S", srvRecFile.c_str());
       
   717     return srvRecFile;
       
   718 }
       
   719 
       
   720 /**
       
   721  * Exporting this function only for the use of ServerConnection::AcceptL
       
   722  * and ServerConnection::HandleAcceptL methods. In rest of the cases,
       
   723  * this method should be called via setAdvertise()
       
   724  */
       
   725 OS_EXPORT int ServiceRecord::setAdvertiseFs(TBool aAvailable)
       
   726 {
       
   727     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::setAdvertise %s",
       
   728          (aAvailable)?"True":"False");
       
   729     int err = 0;
       
   730 
       
   731     TInt state = aAvailable ? SERVICE_AVAILABLE : !SERVICE_AVAILABLE;
       
   732 
       
   733     // Set availability
       
   734     TRAP(err,
       
   735     {
       
   736         mSdpDB.UpdateAttributeL(mRecord,
       
   737         KSdpAttrIdServiceAvailability, state);
       
   738 
       
   739         mSdpDB.UpdateAttributeL(mRecord,
       
   740                                 KSdpAttrIdServiceRecordState, ++mRecordState);
       
   741     }
       
   742         );
       
   743     return err;
       
   744 }
       
   745 
       
   746 /**
       
   747  * Creates and starts the new list (DEA/DES)
       
   748  * On success returns 0; otherwise err number.
       
   749  */
       
   750 OS_EXPORT int ServiceRecord::attributeListStart(int aAttrId, int aAttrType)
       
   751 {
       
   752     JELOG2(EJavaBluetooth);
       
   753     int ret = 0;
       
   754     TBool persistentReq = ETrue;
       
   755 
       
   756     CallMethod(ret, this, &ServiceRecord::attributeListStartFs,
       
   757                aAttrId, aAttrType, persistentReq, mFunctionServer);
       
   758     return ret;
       
   759 }
       
   760 
       
   761 int ServiceRecord::attributeListStartFs(int aAttrId, int aAttrType, TBool isPersistenceRequired)
       
   762 {
       
   763     JELOG2(EJavaBluetooth);
       
   764     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::attributeListStart %d", aAttrId);
       
   765 
       
   766     TRAPD(err,
       
   767     {
       
   768         if (aAttrId >= 0)
       
   769         {
       
   770             switch (aAttrType)
       
   771             {
       
   772             case DataElement_DATSEQ:
       
   773                 mSdpAttrValueList = CSdpAttrValueDES::NewDESL(NULL);
       
   774                 break;
       
   775             case DataElement_DATALT:
       
   776                 mSdpAttrValueList = CSdpAttrValueDEA::NewDEAL(NULL);
       
   777                 break;
       
   778             default:
       
   779                 break;
       
   780             }
       
   781             mLastSdpAttr = mSdpAttrValueList;
       
   782         }
       
   783         else
       
   784         {
       
   785             switch (aAttrType)
       
   786             {
       
   787             case DataElement_DATSEQ:
       
   788                 if (mLastSdpAttr)
       
   789                     mLastSdpAttr = mLastSdpAttr -> BuildDESL();
       
   790                 break;
       
   791             case DataElement_DATALT:
       
   792                 if (mLastSdpAttr)
       
   793                     mLastSdpAttr = mLastSdpAttr -> BuildDESL();
       
   794                 break;
       
   795             default:
       
   796                 break;
       
   797             }
       
   798         }
       
   799         mLastSdpAttr = mLastSdpAttr -> StartListL();
       
   800     }
       
   801          );
       
   802 
       
   803     // Writing into persistent file for further usage
       
   804     if (0 != mSrvRecFd && isPersistenceRequired)
       
   805     {
       
   806         LOG2(EJavaBluetooth, EInfo,  "  ServiceRecord Writing %d, %d",
       
   807              aAttrId, aAttrType);
       
   808         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
   809         write(mSrvRecFd, (char *)&aAttrType, sizeof(aAttrType));
       
   810     }
       
   811     return err;
       
   812 }
       
   813 
       
   814 /**
       
   815  * Ends the list (DEA/DES), and update the attribute list of SDP database
       
   816  * On success returns 0; otherwise err number.
       
   817  */
       
   818 OS_EXPORT int ServiceRecord::attributeListEnd(int aAttrId)
       
   819 {
       
   820     JELOG2(EJavaBluetooth);
       
   821     int ret = 0;
       
   822     TBool persistentReq = ETrue;
       
   823 
       
   824     CallMethod(ret, this, &ServiceRecord::attributeListEndFs,
       
   825                aAttrId, persistentReq, mFunctionServer);
       
   826     return ret;
       
   827 }
       
   828 
       
   829 int ServiceRecord::attributeListEndFs(int aAttrId, TBool isPersistenceRequired)
       
   830 {
       
   831     JELOG2(EJavaBluetooth);
       
   832     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::attributeListEnd %d", aAttrId);
       
   833     int err = 0;
       
   834 
       
   835     if (mLastSdpAttr)
       
   836         TRAP(err, mLastSdpAttr = mLastSdpAttr -> EndListL());
       
   837     if (KErrNone == err && aAttrId >= 0)
       
   838     {
       
   839         LOG1(EJavaBluetooth, EInfo,  "*  ServiceRecord::attributeListEnd %d", aAttrId);
       
   840         TRAP(err, mSdpDB.UpdateAttributeL(mRecord, aAttrId, *mSdpAttrValueList));
       
   841         LOG1(EJavaBluetooth, EInfo,  "x  ServiceRecord::attributeListEnd %d", aAttrId);
       
   842         delete mSdpAttrValueList;
       
   843         mSdpAttrValueList = NULL;
       
   844         mLastSdpAttr = NULL;
       
   845     }
       
   846 
       
   847     // Writing into persistent file for further usage
       
   848     if (0 != mSrvRecFd && isPersistenceRequired)
       
   849     {
       
   850         int type = DataElement_EndList;
       
   851         LOG2(EJavaBluetooth, EInfo,  "  ServiceRecord Writing %d, %d",
       
   852              aAttrId, type);
       
   853         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
   854         write(mSrvRecFd, (char *)&type, sizeof(type));
       
   855     }
       
   856     return err;
       
   857 }
       
   858 
       
   859 /**
       
   860  * Adds unsigned integer to the list (DEA/DES),
       
   861  * or update the attribute list of SDP database
       
   862  * On success returns 0; otherwise err number.
       
   863  */
       
   864 OS_EXPORT int ServiceRecord::setAttributeUint(int aAttrId, int aAttrType, TDesC8 &aNumVal)
       
   865 {
       
   866     JELOG2(EJavaBluetooth);
       
   867     int ret = 0;
       
   868     TBool persistentReq = ETrue;
       
   869 
       
   870     CallMethod(ret, this, &ServiceRecord::setAttributeUintFs,
       
   871                aAttrId, aAttrType, aNumVal, persistentReq, mFunctionServer);
       
   872     return ret;
       
   873 }
       
   874 
       
   875 int ServiceRecord::setAttributeUintFs(int aAttrId, int aAttrType, TDesC8 &aNumVal, TBool isPersistenceRequired)
       
   876 {
       
   877     JELOG2(EJavaBluetooth);
       
   878     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::setAttributeUint %d", aAttrId);
       
   879 
       
   880     TRAPD(err,
       
   881     {
       
   882         if (aAttrId < 0)
       
   883         {
       
   884             if (mLastSdpAttr)
       
   885                 mLastSdpAttr = mLastSdpAttr -> BuildUintL(aNumVal);
       
   886         }
       
   887         else
       
   888         {
       
   889             CSdpAttrValueUint *val = NULL;
       
   890             val = CSdpAttrValueUint::NewUintL(aNumVal);
       
   891             mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
       
   892             delete val;
       
   893         }
       
   894     }
       
   895          );
       
   896 
       
   897     // Writing into persistent file for further usage
       
   898     if (0 != mSrvRecFd && isPersistenceRequired)
       
   899     {
       
   900         int size = aNumVal.Size();
       
   901         const TUint8 *ptr = aNumVal.Ptr();
       
   902 
       
   903         LOG4(EJavaBluetooth, EInfo,"  ServiceRecord Writing %d, %d, %d, [%S]",
       
   904              aAttrId, aAttrType, size, ptr);
       
   905 
       
   906         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
   907         write(mSrvRecFd, (char *)&aAttrType, sizeof(aAttrType));
       
   908         write(mSrvRecFd, (char *)&size, sizeof(size));
       
   909         write(mSrvRecFd, (char *)ptr, size);
       
   910     }
       
   911     return err;
       
   912 }
       
   913 
       
   914 /**
       
   915  * Adds integer to the list (DEA/DES),
       
   916  * or update the attribute list of SDP database
       
   917  * On success returns 0; otherwise err number.
       
   918  */
       
   919 OS_EXPORT int ServiceRecord::setAttributeInt(int aAttrId, int aAttrType, TDesC8 &aNumVal)
       
   920 {
       
   921     JELOG2(EJavaBluetooth);
       
   922     int ret = 0;
       
   923     TBool persistentReq = ETrue;
       
   924 
       
   925     CallMethod(ret, this, &ServiceRecord::setAttributeIntFs,
       
   926                aAttrId, aAttrType, aNumVal, persistentReq, mFunctionServer);
       
   927     return ret;
       
   928 }
       
   929 
       
   930 int ServiceRecord::setAttributeIntFs(int aAttrId, int aAttrType, TDesC8 &aNumVal, TBool isPersistenceRequired)
       
   931 {
       
   932     JELOG2(EJavaBluetooth);
       
   933     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::setAttributeInt %d", aAttrId);
       
   934 
       
   935     TRAPD(err,
       
   936     {
       
   937         if (aAttrId < 0)
       
   938         {
       
   939             if (mLastSdpAttr)
       
   940                 mLastSdpAttr = mLastSdpAttr -> BuildIntL(aNumVal);
       
   941         }
       
   942         else
       
   943         {
       
   944             CSdpAttrValueInt *val = NULL;
       
   945             val = CSdpAttrValueInt::NewIntL(aNumVal);
       
   946             mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
       
   947             delete val;
       
   948         }
       
   949     }
       
   950          );
       
   951 
       
   952     // Writing into persistent file for further usage
       
   953     if (0 != mSrvRecFd && isPersistenceRequired)
       
   954     {
       
   955         int size = aNumVal.Size();
       
   956         const TUint8 *ptr = aNumVal.Ptr();
       
   957 
       
   958         LOG4(EJavaBluetooth, EInfo,"  ServiceRecord Writing %d, %d, %d, [%S]",
       
   959              aAttrId, aAttrType, size, ptr);
       
   960 
       
   961         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
   962         write(mSrvRecFd, (char *)&aAttrType, sizeof(aAttrType));
       
   963         write(mSrvRecFd, (char *)&size, sizeof(size));
       
   964         write(mSrvRecFd, (char *)ptr, size);
       
   965     }
       
   966     return err;
       
   967 }
       
   968 
       
   969 /**
       
   970  * Adds boolean value to the list (DEA/DES),
       
   971  * or update the attribute list of SDP database
       
   972  * On success returns 0; otherwise err number.
       
   973  */
       
   974 OS_EXPORT int ServiceRecord::setAttributeBool(int aAttrId, TBool aBoolVal)
       
   975 {
       
   976     JELOG2(EJavaBluetooth);
       
   977     int ret = 0;
       
   978     TBool persistentReq = ETrue;
       
   979 
       
   980     CallMethod(ret, this, &ServiceRecord::setAttributeBoolFs,
       
   981                aAttrId, aBoolVal, persistentReq, mFunctionServer);
       
   982     return ret;
       
   983 }
       
   984 
       
   985 int ServiceRecord::setAttributeBoolFs(int aAttrId, TBool aBoolVal, TBool isPersistenceRequired)
       
   986 {
       
   987     JELOG2(EJavaBluetooth);
       
   988     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::setAttributeBool %d", aAttrId);
       
   989 
       
   990     TRAPD(err,
       
   991     {
       
   992         if (aAttrId < 0)
       
   993         {
       
   994             if (mLastSdpAttr)
       
   995                 mLastSdpAttr = mLastSdpAttr -> BuildBooleanL(aBoolVal);
       
   996         }
       
   997         else
       
   998         {
       
   999             CSdpAttrValueBoolean  *val = NULL;
       
  1000             val =  CSdpAttrValueBoolean::NewBoolL(aBoolVal);
       
  1001             mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
       
  1002             delete val;
       
  1003         }
       
  1004     }
       
  1005          );
       
  1006 
       
  1007     // Writing into persistent file for further usage
       
  1008     if (0 != mSrvRecFd && isPersistenceRequired)
       
  1009     {
       
  1010         // Taking largest type for storage
       
  1011         int type = DataElement_BOOL;
       
  1012         TUint8 val = (aBoolVal) ? 1 : 0;
       
  1013 
       
  1014         LOG3(EJavaBluetooth, EInfo,"  ServiceRecord Writing %d, %d, %d",
       
  1015              aAttrId, type, val);
       
  1016 
       
  1017         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
  1018         write(mSrvRecFd, (char *)&type, sizeof(type));
       
  1019         write(mSrvRecFd, (char *)&val, 1);
       
  1020     }
       
  1021     return err;
       
  1022 }
       
  1023 
       
  1024 /**
       
  1025  * Adds UUID to the list (DEA/DES),
       
  1026  * or update the attribute list of SDP database
       
  1027  * On success returns 0; otherwise err number.
       
  1028  */
       
  1029 OS_EXPORT int ServiceRecord::setAttributeUUID(int aAttrId, TUUID &aUUIDVal)
       
  1030 {
       
  1031     JELOG2(EJavaBluetooth);
       
  1032     int ret = 0;
       
  1033     TBool persistentReq = ETrue;
       
  1034 
       
  1035     CallMethod(ret, this, &ServiceRecord::setAttributeUUIDFs,
       
  1036                aAttrId, aUUIDVal, persistentReq, mFunctionServer);
       
  1037     return ret;
       
  1038 }
       
  1039 
       
  1040 int ServiceRecord::setAttributeUUIDFs(int aAttrId, TUUID &aUUIDVal, TBool isPersistenceRequired)
       
  1041 {
       
  1042     JELOG2(EJavaBluetooth);
       
  1043     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::setAttributeUUID %d", aAttrId);
       
  1044 
       
  1045     TRAPD(err,
       
  1046     {
       
  1047         if (aAttrId < 0)
       
  1048         {
       
  1049             if (mLastSdpAttr)
       
  1050                 mLastSdpAttr = mLastSdpAttr -> BuildUUIDL(aUUIDVal);
       
  1051         }
       
  1052         else
       
  1053         {
       
  1054             CSdpAttrValueUUID  *val = NULL;
       
  1055             val = CSdpAttrValueUUID::NewUUIDL(aUUIDVal);
       
  1056             mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
       
  1057             delete val;
       
  1058         }
       
  1059     }
       
  1060          );
       
  1061 
       
  1062     // Writing into persistent file for further usage
       
  1063     if (0 != mSrvRecFd && isPersistenceRequired)
       
  1064     {
       
  1065         int type = DataElement_UUID;
       
  1066         int size = aUUIDVal.Des().Size();
       
  1067         const TUint8 *ptr = aUUIDVal.Des().Ptr();
       
  1068 
       
  1069         LOG4(EJavaBluetooth, EInfo,"  ServiceRecord Writing %d, %d, %d, [%S]",
       
  1070              aAttrId, type, size, ptr);
       
  1071 
       
  1072         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
  1073         write(mSrvRecFd, (char *)&type, sizeof(type));
       
  1074         write(mSrvRecFd, (char *)&size, sizeof(size));
       
  1075         write(mSrvRecFd, (char *)ptr, size);
       
  1076     }
       
  1077     return err;
       
  1078 }
       
  1079 
       
  1080 /**
       
  1081  * Adds string to the list (DEA/DES),
       
  1082  * or update the attribute list of SDP database
       
  1083  * On success returns 0; otherwise err number.
       
  1084  */
       
  1085 OS_EXPORT int ServiceRecord::setAttributeString(int aAttrId, TDesC8 &aStrVal)
       
  1086 {
       
  1087     JELOG2(EJavaBluetooth);
       
  1088     int ret = 0;
       
  1089     TBool persistentReq = ETrue;
       
  1090 
       
  1091     CallMethod(ret, this, &ServiceRecord::setAttributeStringFs,
       
  1092                aAttrId, aStrVal, persistentReq, mFunctionServer);
       
  1093     return ret;
       
  1094 }
       
  1095 
       
  1096 int ServiceRecord::setAttributeStringFs(int aAttrId, TDesC8 &aStrVal, TBool isPersistenceRequired)
       
  1097 {
       
  1098     JELOG2(EJavaBluetooth);
       
  1099     LOG1(EJavaBluetooth, EInfo,
       
  1100          "+ ServiceRecord::setAttributeString %d", aAttrId);
       
  1101 
       
  1102     TRAPD(err,
       
  1103     {
       
  1104         if (aAttrId < 0)
       
  1105         {
       
  1106             if (mLastSdpAttr)
       
  1107                 mLastSdpAttr = mLastSdpAttr -> BuildStringL(aStrVal);
       
  1108         }
       
  1109         else
       
  1110         {
       
  1111             CSdpAttrValueString   *val = NULL;
       
  1112             val = CSdpAttrValueString::NewStringL(aStrVal);
       
  1113             mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
       
  1114             delete val;
       
  1115         }
       
  1116     }
       
  1117          );
       
  1118 
       
  1119     // Writing into persistent file for further usage
       
  1120     if (0 != mSrvRecFd && isPersistenceRequired)
       
  1121     {
       
  1122         int type = DataElement_STRING;
       
  1123         int size = aStrVal.Size();
       
  1124         const TUint8 *ptr = aStrVal.Ptr();
       
  1125 
       
  1126         LOG3(EJavaBluetooth, EInfo,"  ServiceRecord Writing %d, %d, %d",
       
  1127              aAttrId, type, size);
       
  1128 
       
  1129         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
  1130         write(mSrvRecFd, (char *)&type, sizeof(type));
       
  1131         write(mSrvRecFd, (char *)&size, sizeof(size));
       
  1132         write(mSrvRecFd, (char *)ptr, size);
       
  1133     }
       
  1134     return err;
       
  1135 }
       
  1136 
       
  1137 /**
       
  1138  * Adds URL to the list (DEA/DES),
       
  1139  * or update the attribute list of SDP database
       
  1140  * On success returns 0; otherwise err number.
       
  1141  */
       
  1142 OS_EXPORT int ServiceRecord::setAttributeUrl(int aAttrId, TDesC8 &aUrlVal)
       
  1143 {
       
  1144     JELOG2(EJavaBluetooth);
       
  1145     int ret = 0;
       
  1146     TBool persistentReq = ETrue;
       
  1147 
       
  1148     CallMethod(ret, this, &ServiceRecord::setAttributeUrlFs,
       
  1149                aAttrId, aUrlVal, persistentReq, mFunctionServer);
       
  1150     return ret;
       
  1151 }
       
  1152 
       
  1153 int ServiceRecord::setAttributeUrlFs(int aAttrId, TDesC8 &aUrlVal, TBool isPersistenceRequired)
       
  1154 {
       
  1155     JELOG2(EJavaBluetooth);
       
  1156     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::setAttributeUrl %d", aAttrId);
       
  1157 
       
  1158     TRAPD(err,
       
  1159     {
       
  1160         if (aAttrId < 0)
       
  1161         {
       
  1162             if (mLastSdpAttr)
       
  1163                 mLastSdpAttr = mLastSdpAttr -> BuildURLL(aUrlVal);
       
  1164         }
       
  1165         else
       
  1166         {
       
  1167             CSdpAttrValueURL *val = NULL;
       
  1168             val = CSdpAttrValueURL::NewURLL(aUrlVal);
       
  1169             mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
       
  1170             delete val;
       
  1171         }
       
  1172     }
       
  1173          );
       
  1174     // Writing into persistent file for further usage
       
  1175     if (0 != mSrvRecFd && isPersistenceRequired)
       
  1176     {
       
  1177         int type = DataElement_URL;
       
  1178         int size = aUrlVal.Size();
       
  1179         const TUint8 *ptr = aUrlVal.Ptr();
       
  1180 
       
  1181         LOG4(EJavaBluetooth, EInfo,"  ServiceRecord Writing %d, %d, %d, [%S]",
       
  1182              aAttrId, type, size, ptr);
       
  1183 
       
  1184         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
  1185         write(mSrvRecFd, (char *)&type, sizeof(type));
       
  1186         write(mSrvRecFd, (char *)&size, sizeof(size));
       
  1187         write(mSrvRecFd, (char *)ptr, size);
       
  1188     }
       
  1189     return err;
       
  1190 }
       
  1191 
       
  1192 /**
       
  1193  * Adds NIL to the list (DEA/DES),
       
  1194  * or update the attribute list of SDP database
       
  1195  * On success returns 0; otherwise err number.
       
  1196  */
       
  1197 OS_EXPORT int ServiceRecord::setAttributeNil(int aAttrId)
       
  1198 {
       
  1199     JELOG2(EJavaBluetooth);
       
  1200     int ret = 0;
       
  1201     TBool persistentReq = ETrue;
       
  1202 
       
  1203     CallMethod(ret, this, &ServiceRecord::setAttributeNilFs,
       
  1204                aAttrId, persistentReq, mFunctionServer);
       
  1205     return ret;
       
  1206 }
       
  1207 
       
  1208 int ServiceRecord::setAttributeNilFs(int aAttrId, TBool isPersistenceRequired)
       
  1209 {
       
  1210     JELOG2(EJavaBluetooth);
       
  1211     LOG1(EJavaBluetooth, EInfo,  "+ ServiceRecord::setAttributeNil %d", aAttrId);
       
  1212 
       
  1213     TRAPD(err,
       
  1214     {
       
  1215         if (aAttrId < 0)
       
  1216         {
       
  1217             if (mLastSdpAttr)
       
  1218                 mLastSdpAttr = mLastSdpAttr -> BuildNilL();
       
  1219         }
       
  1220         else
       
  1221         {
       
  1222             CSdpAttrValueNil *val = NULL;
       
  1223             val = CSdpAttrValueNil::NewNilL();
       
  1224             mSdpDB.UpdateAttributeL(mRecord, aAttrId, *val);
       
  1225             delete val;
       
  1226         }
       
  1227     }
       
  1228          );
       
  1229 
       
  1230     // Writing into persistent file for further usage
       
  1231     if (0 != mSrvRecFd && isPersistenceRequired)
       
  1232     {
       
  1233         // Taking largest type for storage
       
  1234         int type = DataElement_NULL;
       
  1235 
       
  1236         LOG2(EJavaBluetooth, EInfo,  "  ServiceRecord Writing %d, %d",
       
  1237              aAttrId, type);
       
  1238 
       
  1239         write(mSrvRecFd, (char *)&aAttrId, sizeof(aAttrId));
       
  1240         write(mSrvRecFd, (char *)&type, sizeof(type));
       
  1241     }
       
  1242     return err;
       
  1243 }
       
  1244 
       
  1245 /*
       
  1246  * This function is used to restore the Java Service Record by reading the
       
  1247  * persistent file. This function will work only once after midlet took
       
  1248  * the server connection handle from the Push framework.
       
  1249  * This function tries to populate Java Service record only when there is a
       
  1250  * successful retrieval of persistent storage exists.
       
  1251  */
       
  1252 
       
  1253 OS_EXPORT void ServiceRecord::restoreJavaServiceRecordL(
       
  1254     JNIEnv *aJni, jobject aServiceRecordImpl)
       
  1255 {
       
  1256     JELOG2(EJavaBluetooth);
       
  1257 
       
  1258     if (false == mInitializedByPush)
       
  1259     {
       
  1260         // No need of restoring anything since it is not a push service
       
  1261         return;
       
  1262     }
       
  1263 
       
  1264     // Setting service record handle.
       
  1265     BTServiceRecordPopulator* srvRecPopulator =
       
  1266         BTServiceRecordPopulator::New(aJni, aServiceRecordImpl);
       
  1267 
       
  1268     srvRecPopulator->SetServiceRecordHandle(mRecord);
       
  1269 
       
  1270     if (false == mRestoredFromPersistentFile)
       
  1271     {
       
  1272         // No need of restoring anything from persistent file.
       
  1273         delete srvRecPopulator;
       
  1274         return;
       
  1275     }
       
  1276 
       
  1277     std::wstring persistentFileName = getPersistentFileName();
       
  1278 
       
  1279     int persistentRecFd = -1;
       
  1280     int ret = 0;
       
  1281 
       
  1282     if (persistentFileName.length()> 0)
       
  1283     {
       
  1284         try
       
  1285         {
       
  1286             char *fileName =
       
  1287                 java::util::JavaCommonUtils::wstringToUtf8(persistentFileName);
       
  1288             persistentRecFd = open(fileName, O_RDONLY);
       
  1289             delete fileName;
       
  1290         }
       
  1291         catch (ExceptionBase ex)
       
  1292         {
       
  1293             ELOG1(EJavaBluetooth,
       
  1294                   "- ServiceRecord::restoreJavaServiceRecord exception caught: %S",
       
  1295                   ex.toString().c_str());
       
  1296         }
       
  1297     }
       
  1298 
       
  1299     if (persistentRecFd < 0)
       
  1300     {
       
  1301         // Nothing else to be done, as persistent file can not be opened or
       
  1302         // it is empty.
       
  1303         delete srvRecPopulator;
       
  1304         return;
       
  1305     }
       
  1306 
       
  1307     MSdpElementBuilder* elementBuilder = (MSdpElementBuilder*) srvRecPopulator;
       
  1308 
       
  1309     // Reading and restoring the DeviceServiceClasses bits (If any)
       
  1310     unsigned int devServClass = 0;
       
  1311     ret = read(persistentRecFd, &devServClass, sizeof(devServClass));
       
  1312     if (ret <= 0)
       
  1313         return;
       
  1314 
       
  1315     elementBuilder = srvRecPopulator->SetDeviceServiceClass(devServClass);
       
  1316 
       
  1317 
       
  1318     // Calling first BuildDESL, is mandatory
       
  1319     elementBuilder = elementBuilder->BuildDESL();
       
  1320     elementBuilder = elementBuilder->StartListL();
       
  1321 
       
  1322     int attrId = 0;
       
  1323     while ((ret = read(persistentRecFd, &attrId, sizeof(attrId))) > 0)
       
  1324     {
       
  1325         int dataType = 0;
       
  1326 
       
  1327         ret = read(persistentRecFd, &dataType, sizeof(dataType));
       
  1328         if (ret <= 0)
       
  1329             break;
       
  1330 
       
  1331         if (attrId > 0 && DataElement_EndList != dataType)
       
  1332         {
       
  1333             TSdpIntBuf<TUint> attrIdBuf(attrId);
       
  1334             elementBuilder = elementBuilder->BuildUintL(attrIdBuf);
       
  1335         }
       
  1336 
       
  1337         LOG2(EJavaBluetooth, EInfo,
       
  1338              "  ServiceRecord reading %X, %X", attrId, dataType);
       
  1339 
       
  1340         switch (dataType)
       
  1341         {
       
  1342         case DataElement_DATSEQ:
       
  1343         {
       
  1344             elementBuilder = elementBuilder->BuildDESL();
       
  1345             elementBuilder = elementBuilder->StartListL();
       
  1346             break;
       
  1347         }
       
  1348         case DataElement_DATALT:
       
  1349         {
       
  1350             elementBuilder = elementBuilder->BuildDEAL();
       
  1351             elementBuilder = elementBuilder->StartListL();
       
  1352             break;
       
  1353         }
       
  1354         case DataElement_EndList:
       
  1355         {
       
  1356             elementBuilder = elementBuilder->EndListL();
       
  1357             break;
       
  1358         }
       
  1359         case DataElement_NULL:
       
  1360         {
       
  1361             elementBuilder = elementBuilder->BuildNilL();
       
  1362             break;
       
  1363         }
       
  1364         case DataElement_BOOL:
       
  1365         {
       
  1366             TUint8 val = 0;
       
  1367             ret = read(persistentRecFd, &val, sizeof(val));
       
  1368             if (ret <= 0)
       
  1369                 break;
       
  1370 
       
  1371             LOG1(EJavaBluetooth, EInfo,
       
  1372                  "  ServiceRecord reading Bool %X", val);
       
  1373             elementBuilder =
       
  1374                 elementBuilder->BuildBooleanL((val) ? ETrue : EFalse);
       
  1375             break;
       
  1376         }
       
  1377         case DataElement_U_INT_1:
       
  1378         case DataElement_U_INT_2:
       
  1379         case DataElement_U_INT_4:
       
  1380         {
       
  1381             int len = 0;
       
  1382             ret = read(persistentRecFd, &len, sizeof(len));
       
  1383             if (ret <= 0)
       
  1384                 break;
       
  1385 
       
  1386             TUint8 bytes[20] = {0};
       
  1387             ret = read(persistentRecFd, bytes, len);
       
  1388             if (ret <= 0)
       
  1389                 break;
       
  1390 
       
  1391             LOG2(EJavaBluetooth, EInfo,  "  ServiceRecord reading INT 0x%X, 0x%X", len, bytes);
       
  1392 
       
  1393             std::auto_ptr<HBufC8> buf(convertIntToDesC(bytes, dataType));
       
  1394             elementBuilder = elementBuilder->BuildUintL(*buf);
       
  1395             break;
       
  1396         }
       
  1397         case DataElement_U_INT_8:
       
  1398         case DataElement_U_INT_16:
       
  1399         {
       
  1400             int len = 0;
       
  1401             ret = read(persistentRecFd, &len, sizeof(len));
       
  1402             if (ret <= 0)
       
  1403                 break;
       
  1404 
       
  1405             TUint8 buf[20] = {0};
       
  1406             ret = read(persistentRecFd, buf, len);
       
  1407             if (ret <= 0)
       
  1408                 break;
       
  1409 
       
  1410             LOG2(EJavaBluetooth, EInfo,  "  ServiceRecord reading INT 0x%X, %S", len, buf);
       
  1411 
       
  1412             TPtrC8 val(buf, len);
       
  1413             elementBuilder = elementBuilder->BuildUintL(val);
       
  1414             break;
       
  1415         }
       
  1416         case DataElement_INT_1:
       
  1417         case DataElement_INT_2:
       
  1418         case DataElement_INT_4:
       
  1419         {
       
  1420             int len = 0;
       
  1421             ret = read(persistentRecFd, &len, sizeof(len));
       
  1422             if (ret <= 0)
       
  1423                 break;
       
  1424 
       
  1425             TUint8 bytes[20] = {0};
       
  1426             ret = read(persistentRecFd, bytes, len);
       
  1427             if (ret <= 0)
       
  1428                 break;
       
  1429 
       
  1430             LOG2(EJavaBluetooth, EInfo,  "  ServiceRecord reading INT 0x%X, %S", len, bytes);
       
  1431 
       
  1432             std::auto_ptr<HBufC8> buf(convertIntToDesC(bytes, dataType));
       
  1433             elementBuilder = elementBuilder->BuildIntL(*buf);
       
  1434             break;
       
  1435         }
       
  1436         case DataElement_INT_8:
       
  1437         case DataElement_INT_16:
       
  1438         {
       
  1439             int len = 0;
       
  1440             ret = read(persistentRecFd, &len, sizeof(len));
       
  1441             if (ret <= 0)
       
  1442                 break;
       
  1443 
       
  1444             TUint8 buf[20] = {0};
       
  1445             ret = read(persistentRecFd, buf, len);
       
  1446             if (ret <= 0)
       
  1447                 break;
       
  1448 
       
  1449             LOG2(EJavaBluetooth, EInfo,  "  ServiceRecord reading INT %X, %S", len, buf);
       
  1450 
       
  1451             TPtrC8 val(buf, len);
       
  1452             elementBuilder = elementBuilder->BuildIntL(val);
       
  1453             break;
       
  1454         }
       
  1455         case DataElement_UUID:
       
  1456         {
       
  1457             int len = 0;
       
  1458             ret = read(persistentRecFd, &len, sizeof(len));
       
  1459             if (ret <= 0)
       
  1460                 break;
       
  1461 
       
  1462             TUint8 buf[256] = {0};
       
  1463             ret = read(persistentRecFd, buf, len);
       
  1464             if (ret <= 0)
       
  1465                 break;
       
  1466 
       
  1467             LOG2(EJavaBluetooth, EInfo,  "  ServiceRecord reading UUID %X, %S", len, buf);
       
  1468 
       
  1469             TPtrC8 uuidDes(buf, len);
       
  1470 
       
  1471             TUUID val;
       
  1472             val.SetL(uuidDes);
       
  1473 
       
  1474             elementBuilder = elementBuilder->BuildUUIDL(val);
       
  1475             break;
       
  1476         }
       
  1477         case DataElement_STRING:
       
  1478         {
       
  1479             int len = 0;
       
  1480             ret = read(persistentRecFd, &len, sizeof(len));
       
  1481             if (ret <= 0)
       
  1482                 break;
       
  1483 
       
  1484             TUint8 buf[1024] = {0};
       
  1485             ret = read(persistentRecFd, buf, len);
       
  1486             if (ret <= 0)
       
  1487                 break;
       
  1488 
       
  1489             LOG1(EJavaBluetooth, EInfo,
       
  1490                  "  ServiceRecord reading STRING %X", len);
       
  1491 
       
  1492             TPtrC8 val(buf, len);
       
  1493             LOG(EJavaBluetooth, EInfo,
       
  1494                 "  ServiceRecord::RestoreJavaServiceRecord BuildStringL");
       
  1495             elementBuilder = elementBuilder->BuildStringL(val);
       
  1496             break;
       
  1497         }
       
  1498         case DataElement_URL:
       
  1499         {
       
  1500             int len = 0;
       
  1501             ret = read(persistentRecFd, &len, sizeof(len));
       
  1502             if (ret <= 0)
       
  1503                 break;
       
  1504 
       
  1505             TUint8 buf[1024] = {0};
       
  1506             ret = read(persistentRecFd, buf, len);
       
  1507             if (ret <= 0)
       
  1508                 break;
       
  1509 
       
  1510             LOG2(EJavaBluetooth, EInfo,
       
  1511                  "  ServiceRecord reading URL %X, %S", len, buf);
       
  1512 
       
  1513             TPtrC8 val(buf, len);
       
  1514             elementBuilder = elementBuilder->BuildURLL(val);
       
  1515             break;
       
  1516         }
       
  1517         default:
       
  1518             break;
       
  1519         }
       
  1520         if (0 == ret)
       
  1521             break;
       
  1522     }
       
  1523 
       
  1524     delete srvRecPopulator;
       
  1525 
       
  1526     return;
       
  1527 }
       
  1528 
       
  1529 // Helper function
       
  1530 HBufC8* ServiceRecord::convertIntToDesC(TUint8 *aBytes, int aDataType)
       
  1531 {
       
  1532     JELOG2(EJavaBluetooth);
       
  1533     HBufC8* descBytes = NULL;
       
  1534     switch (aDataType)
       
  1535     {
       
  1536     case DataElement_INT_1:
       
  1537     case DataElement_U_INT_1:
       
  1538     {
       
  1539         descBytes = HBufC8::New(sizeof(TUint8) + 1);
       
  1540         TPtr8 ptr = descBytes->Des();
       
  1541         TUint value = *(TUint *)aBytes;
       
  1542         value=ByteOrder::Swap32(value);
       
  1543 
       
  1544         TSdpIntBuf<TUint8> buf(value);
       
  1545         ptr.Copy(buf);
       
  1546         break;
       
  1547     }
       
  1548     case DataElement_INT_2:
       
  1549     case DataElement_U_INT_2:
       
  1550     {
       
  1551         descBytes = HBufC8::New(sizeof(TUint16) + 1);
       
  1552         TPtr8 ptr = descBytes->Des();
       
  1553         TUint value = *(TUint *)aBytes;
       
  1554         value=ByteOrder::Swap32(value);
       
  1555 
       
  1556         TSdpIntBuf<TUint16> buf(value);
       
  1557         ptr.Copy(buf);
       
  1558         break;
       
  1559     }
       
  1560     case DataElement_INT_4:
       
  1561     case DataElement_U_INT_4:
       
  1562     {
       
  1563         descBytes = HBufC8::New(sizeof(TUint32) + 1);
       
  1564         TPtr8 ptr = descBytes->Des();
       
  1565         TUint value = *(TUint *)aBytes;
       
  1566         value=ByteOrder::Swap32(value);
       
  1567 
       
  1568         TSdpIntBuf<TUint32> buf(value);
       
  1569         ptr.Copy(buf);
       
  1570         break;
       
  1571     }
       
  1572     default:
       
  1573     {
       
  1574         descBytes = HBufC8::New(sizeof(TUint64) + 1);
       
  1575         TPtr8 ptr = descBytes->Des();
       
  1576 
       
  1577         TSdpIntBuf<TUint64> buf(*(TUint64 *)aBytes);
       
  1578         ptr.Copy(buf);
       
  1579         break;
       
  1580     }
       
  1581     }
       
  1582 
       
  1583     return descBytes;
       
  1584 }
       
  1585 
       
  1586 TUint8 *ServiceRecord::uuidToByteArray(std::wstring aUuid,
       
  1587                                        int &aUuidByteLength)
       
  1588 {
       
  1589     JELOG2(EJavaBluetooth);
       
  1590 
       
  1591     int len = aUuid.length();
       
  1592     int resultLen = (len/2) + 1;
       
  1593     TUint8 *result = new TUint8[resultLen];
       
  1594     int index = 0;
       
  1595     int byteIndex = 0;
       
  1596 
       
  1597     LOG1(EJavaBluetooth, EInfo, "  ServiceRecord::uuidToByteArray Length:%d", len);
       
  1598 
       
  1599     if ((len % 2) != 0)
       
  1600     {
       
  1601         int charPos = charToInt(aUuid[index]);
       
  1602         index += 1;
       
  1603         result[byteIndex ++] = charPos;
       
  1604     }
       
  1605 
       
  1606     while (index < len)
       
  1607     {
       
  1608         result[byteIndex ++] = (charToInt(aUuid[index]) << 4) |
       
  1609                                charToInt(aUuid[index + 1]);
       
  1610         index += 2;
       
  1611     }
       
  1612     aUuidByteLength = (len /2) + (len %2);
       
  1613 
       
  1614     return result;
       
  1615 }
       
  1616 
       
  1617 TInt8 ServiceRecord::charToInt(wchar_t ch)
       
  1618 {
       
  1619     std::wstring validUpperChars(L"0123456789ABCDEF"); // Never change this.
       
  1620     std::wstring validLowerChars(L"0123456789abcdef"); // Never change this.
       
  1621     TInt8 result = -1;
       
  1622     if ((result = validUpperChars.find(ch)) == std::wstring::npos)
       
  1623     {
       
  1624         result = validLowerChars.find(ch);
       
  1625     }
       
  1626     return result;
       
  1627 }
       
  1628 
       
  1629 std::wstring ServiceRecord::uuidToWstring(TUUID aUuid)
       
  1630 {
       
  1631     JELOG2(EJavaBluetooth);
       
  1632 
       
  1633     std::wstring validChars(L"0123456789ABCDEF"); // Never change this.
       
  1634     std::wstring result;
       
  1635 
       
  1636     int len = aUuid.Des().Size();
       
  1637     const TUint8 *ptr = aUuid.Des().Ptr();
       
  1638 
       
  1639     for (int i = 0; i < len; i ++, ptr ++)
       
  1640     {
       
  1641         result += validChars[((*ptr) >> 4)];
       
  1642         result += validChars[((*ptr) & 0x0F)];
       
  1643         LOG1(EJavaBluetooth, EInfo,
       
  1644              "  ServiceRecord::uuidToWstring %S",  result.c_str());
       
  1645     }
       
  1646 
       
  1647     return result;
       
  1648 }
       
  1649 
       
  1650 }  //end namespace bluetooth
       
  1651 }  //end namespace java