qthighway/xqserviceipc/xqserviceipc/xqserviceipc_apasymbian.cpp
branchRCL_3
changeset 9 5d007b20cfd0
equal deleted inserted replaced
8:885c2596c964 9:5d007b20cfd0
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 *
       
     5 * This program is free software: you can redistribute it and/or modify
       
     6 * it under the terms of the GNU Lesser General Public License as published by
       
     7 * the Free Software Foundation, version 2.1 of the License.
       
     8 * 
       
     9 * This program is distributed in the hope that it will be useful,
       
    10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12 * GNU Lesser General Public License for more details.
       
    13 *
       
    14 * You should have received a copy of the GNU Lesser General Public License
       
    15 * along with this program.  If not, 
       
    16 * see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
       
    17 *
       
    18 * Description:  Implementation for a Symbian APA SERVER IPC Client
       
    19 *
       
    20 */
       
    21 
       
    22 #include "xqservicelog.h"
       
    23 
       
    24 #include <QtCore/qobject.h>
       
    25 #include <e32base.h>
       
    26 #include <e32cmn.h>
       
    27 #include <apaserverapp.h>
       
    28 #include <coemain.h>
       
    29 #include "xqserviceipc_apasymbian.h"
       
    30 #include "xqrequestutil.h"
       
    31 
       
    32 #include <xqservicemanager.h>
       
    33 
       
    34 namespace QtService
       
    35 {
       
    36 const TInt KIPCOperation = RApaAppServiceBase::KServiceCmdBase;
       
    37 const TInt KIPCGetBuffer = KIPCOperation+1;
       
    38 const TInt KIPCOperationWithSharableFile = KIPCOperation+2;  // Sharable file support
       
    39 
       
    40 const TInt KServerMajorVersionNumber = 1;
       
    41 const TInt KServerMinorVersionNumber = 0;
       
    42 const TInt KServerBuildVersionNumber = 0;
       
    43 
       
    44 
       
    45 /*!
       
    46     \class CApaSymbianIPC
       
    47     \brief Symbian Client backend for the service IPC
       
    48 */
       
    49 
       
    50 /*!
       
    51     Constructor.
       
    52 */
       
    53 CApaSymbianIPC::CApaSymbianIPC() :
       
    54     CActive(CActive::EPriorityStandard), iDataSize(0)
       
    55 {
       
    56     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::CApaSymbianIPC");
       
    57     CActiveScheduler::Add(this);
       
    58 }
       
    59 
       
    60 /*!
       
    61     Destructor.
       
    62 */
       
    63 CApaSymbianIPC::~CApaSymbianIPC()
       
    64 {
       
    65     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::~CApaSymbianIPC");
       
    66     Cancel();
       
    67     delete iAsyncData;
       
    68     delete iRequestData;
       
    69 }
       
    70 
       
    71 /*!
       
    72     2nd phased constructor.
       
    73 */
       
    74 void CApaSymbianIPC::ConstructL()
       
    75 {
       
    76     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::ConstructL");
       
    77 	iServerExitMonitor = NULL;
       
    78 }
       
    79 
       
    80 /*!
       
    81     Two Phased Constructor.
       
    82 */
       
    83 CApaSymbianIPC* CApaSymbianIPC::NewL()
       
    84 {
       
    85     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::NewL");
       
    86     CApaSymbianIPC* self = new(ELeave) CApaSymbianIPC();
       
    87     CleanupStack::PushL(self);
       
    88     self->ConstructL();
       
    89     CleanupStack::Pop(self);
       
    90     return self;
       
    91 }
       
    92 
       
    93 /*!
       
    94     Connect to the server.
       
    95     \param aServerName Name of the server to connect to.
       
    96     \return true if connected, false if not.
       
    97 */
       
    98 bool CApaSymbianIPC::connect( const QString& aServerName )
       
    99 {
       
   100     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::connect");
       
   101     // Version informaton
       
   102     TVersion version(KServerMajorVersionNumber, 
       
   103                      KServerMinorVersionNumber, 
       
   104                      KServerBuildVersionNumber);
       
   105     TPtrC serverName(reinterpret_cast<const TUint16*> (aServerName.utf16()));
       
   106     TInt err = iSession.Connect(serverName, version);
       
   107 
       
   108     if (!err) {
       
   109         StartExitMonitor();
       
   110     }
       
   111     
       
   112     return (err == KErrNone);
       
   113 }
       
   114 
       
   115 /*!
       
   116     Disconnect from the server.
       
   117 */
       
   118 void CApaSymbianIPC::disconnect()
       
   119 {
       
   120     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::disconnect");
       
   121     // Note !
       
   122     // iServerExitMonitor->Cancel will cause request cancellation 
       
   123     // in CApaServerSymbianSession::ServiceL() with error code KErrCancel
       
   124     if (iServerExitMonitor) {
       
   125         iServerExitMonitor->Cancel();
       
   126         delete iServerExitMonitor;
       
   127         iServerExitMonitor = NULL;
       
   128     }
       
   129     iSession.Close();
       
   130 }
       
   131 
       
   132 /*!
       
   133     Starts the service.
       
   134     \param aServerName Server name.
       
   135     \param aExeName Server executable name.
       
   136     \return true if start was successful.
       
   137 */
       
   138 bool CApaSymbianIPC::startServer( const QString& aServerName, 
       
   139                                   const QString& /*aExeName*/, 
       
   140                                   quint64& processId,
       
   141                                   int options)
       
   142 {
       
   143     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::startServer");
       
   144     XQServiceManager mng;
       
   145     bool embedded = (options == ServiceFwIPC::EStartInEmbeddedMode) ? true : false;
       
   146     int appUid = 0;
       
   147     int ret=0;
       
   148     if (userData == NULL)
       
   149     {
       
   150         XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::No user data in start");
       
   151         ret = mng.startServer(aServerName,embedded,appUid,processId);
       
   152     }
       
   153     else
       
   154     {
       
   155         XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::Apply user data in start");
       
   156         ret = mng.startServer(aServerName,embedded,appUid,processId, userData);
       
   157     }
       
   158     
       
   159     if (ret)
       
   160         {
       
   161         emitError(ret);
       
   162         }
       
   163     iSession.setServiceUid(appUid);
       
   164     return (ret == KErrNone);
       
   165 }
       
   166 
       
   167 /*!
       
   168     Send a request synchronously.
       
   169     \param aRequestType Type of request to send to the server.
       
   170     \param aData Data to send to the server.
       
   171     \return true if send was successful.
       
   172 */
       
   173 bool CApaSymbianIPC::sendSync( const QString& aRequestType, const QByteArray& aData )
       
   174 {
       
   175     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::sendSync");
       
   176     // Convert from QString to TPtr
       
   177     TPtrC request(reinterpret_cast<const TUint16*> (aRequestType.utf16()));
       
   178     TPtrC8 data(reinterpret_cast<const TUint8*> (aData.constData()), aData.length());
       
   179 
       
   180     // Send data, 0 is new op
       
   181     TInt err=KErrNone;
       
   182     TInt dataSize=0;
       
   183     TIpcArgs args(&request, &data);
       
   184     TInt cmd = KIPCOperation;
       
   185     if (userData != 0)
       
   186     {
       
   187         XQRequestUtil *util = (XQRequestUtil *)userData;
       
   188         // Only the first transferred
       
   189         if (TransferSharableFile(&args, util->getSharableFile(0)))
       
   190         {
       
   191             cmd = KIPCOperationWithSharableFile;
       
   192         }
       
   193     }
       
   194     
       
   195     TRAP( err, dataSize = iSession.SendReceiveL(cmd,args) );
       
   196 
       
   197     // map return value
       
   198     if (err == KErrNone) {
       
   199         iDataSize = dataSize;
       
   200     }
       
   201     
       
   202     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::sendSync status=%s", err);
       
   203     
       
   204     return (err == KErrNone);
       
   205 }
       
   206 
       
   207 
       
   208 /*!
       
   209     Read sync.
       
   210     \return Result of read as QByteArray.
       
   211 */
       
   212 QByteArray CApaSymbianIPC::readAll()
       
   213 {
       
   214     // this is sync operation
       
   215     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::readAll");
       
   216     QByteArray rtn;
       
   217     TInt err(KErrNone);
       
   218     TRAP( err, rtn = doReadAllL() );
       
   219     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::readAll status=%d",err);
       
   220     if ( err )
       
   221         {
       
   222         emitError(err);
       
   223         }
       
   224     return rtn;
       
   225 }
       
   226 
       
   227 /**
       
   228 * read sync
       
   229 */
       
   230 QByteArray CApaSymbianIPC::doReadAllL()
       
   231 {
       
   232     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::doReadAllL");
       
   233     // Read the data via IPC
       
   234     CBufBase* buf = CBufFlat::NewL(iDataSize);
       
   235     CleanupStack::PushL(buf);
       
   236     buf->ResizeL(iDataSize);
       
   237     TPtr8 ptr(buf->Ptr(0));
       
   238     iSession.SendReceiveL(KIPCGetBuffer, TIpcArgs(&ptr));
       
   239 
       
   240     QByteArray retData((char*) ptr.Ptr(), ptr.Length());
       
   241 
       
   242     CleanupStack::PopAndDestroy(buf);
       
   243 
       
   244     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::doReadAllL DONE");
       
   245     
       
   246     // Deep copy, return variable is implicitly shared
       
   247     return retData;
       
   248 }
       
   249 
       
   250 
       
   251 
       
   252 /*!
       
   253     Send a request asynchronously.
       
   254     \param aRequestType Type of request to send to the server.
       
   255     \param aData Data to send to the server.
       
   256 */
       
   257 void CApaSymbianIPC::sendAsync(const QString& aRequestType,
       
   258 							   const QByteArray& aData )
       
   259 {
       
   260     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::sendAsync");
       
   261     delete iRequestData;
       
   262     iRequestData = NULL;
       
   263     TPtrC request(reinterpret_cast<const TUint16*> (aRequestType.utf16()));
       
   264     iRequestData = request.Alloc();
       
   265     delete iAsyncData;
       
   266     iAsyncData = NULL;
       
   267     TPtrC8 data(reinterpret_cast<const TUint8*> (aData.constData()), aData.length());
       
   268     iAsyncData = data.Alloc();
       
   269 
       
   270     // Send data
       
   271     iRequestDataPtr.Set(*iRequestData);
       
   272     iAsyncDataPtr.Set(*iAsyncData);
       
   273     TIpcArgs args(&iRequestDataPtr, &iAsyncDataPtr);
       
   274 
       
   275     TInt cmd = KIPCOperation;
       
   276     if (userData != 0)
       
   277     {
       
   278         XQRequestUtil *util = (XQRequestUtil *)userData;
       
   279         // Only the first transferred
       
   280         if (TransferSharableFile(&args, util->getSharableFile(0)))
       
   281         {
       
   282             cmd = KIPCOperationWithSharableFile;
       
   283         }
       
   284     }
       
   285     
       
   286     iSession.SendReceive(cmd, args, iStatus);
       
   287     iState = ESend;
       
   288     SetActive();
       
   289 }
       
   290 
       
   291 /*
       
   292  * read async
       
   293  */
       
   294 void CApaSymbianIPC::readAll(QByteArray& aArray)
       
   295 {
       
   296     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::readAll");
       
   297 
       
   298 	// this is async operation
       
   299     TInt err(KErrNone);
       
   300     TRAP(err, doReadAllL(aArray ));
       
   301     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::readAll status=%d",err);
       
   302     if (err)
       
   303         {
       
   304         emitError(err);
       
   305         }
       
   306     
       
   307 }
       
   308 
       
   309 /*!
       
   310     Reads all data pending in the buffer, leaves if an error occured
       
   311     \return QByteArray Containing the result data.
       
   312 */
       
   313 void CApaSymbianIPC::doReadAllL(QByteArray& aArray)
       
   314 {
       
   315     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::doReadAllL");
       
   316     
       
   317 	//shouldn't be active when this is called
       
   318     if (IsActive())
       
   319         {
       
   320         User::LeaveIfError(KErrGeneral);
       
   321         }
       
   322 	
       
   323     iArray = &aArray;
       
   324           
       
   325     
       
   326     iBuf.CreateL(iDataSize);
       
   327     
       
   328     iSession.SendReceive(KIPCGetBuffer, TIpcArgs(&iBuf), iStatus);
       
   329     
       
   330     iState = ERead;
       
   331     SetActive();
       
   332 }
       
   333 
       
   334 
       
   335 /*!
       
   336     Maps error codes from Symbian error codes to Service IPC error codes
       
   337     \param aError Symbian error code.
       
   338     \return Mapped error code.
       
   339 */
       
   340 int CApaSymbianIPC::doMapErrors(TInt aError)
       
   341 {
       
   342     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::doMapErrors");
       
   343     int error(ERROR_NoError);
       
   344     switch (aError) {
       
   345     case KErrNone: {
       
   346         error = ERROR_NoError;
       
   347         break;
       
   348     }
       
   349     case KErrPermissionDenied:
       
   350     case KErrServerTerminated: {
       
   351         error = ServiceFwIPC::EConnectionClosed;
       
   352         break;
       
   353     }
       
   354                                
       
   355     case KErrServerBusy:
       
   356     case KErrCouldNotConnect:
       
   357     {
       
   358         error = ServiceFwIPC::EConnectionError;
       
   359         break;
       
   360     }
       
   361     case KErrArgument:
       
   362     {
       
   363         error = ServiceFwIPC::EArgumentError;
       
   364         break;
       
   365     }
       
   366         
       
   367     case KErrNoMemory: {
       
   368         error = ServiceFwIPC::EIPCError;
       
   369         break;
       
   370     }
       
   371     case KErrNotFound: {
       
   372         error = ServiceFwIPC::EServerNotFound;
       
   373         break;
       
   374     }
       
   375     default: {
       
   376         error = ServiceFwIPC::EUnknownError;
       
   377         break;
       
   378     }
       
   379     }
       
   380     return error;
       
   381 }
       
   382 /*!
       
   383     Waits until data is available for reading.
       
   384     \return bool always true, no need to wait.
       
   385 */
       
   386 bool CApaSymbianIPC::waitForRead()
       
   387 {
       
   388     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::waitForRead");
       
   389     // Symbian Client-server is blocking, so no need to wait for read
       
   390     return true;
       
   391 }
       
   392 
       
   393 /*!
       
   394     Active object callback
       
   395 */
       
   396 TInt CApaSymbianIPC::RunError(TInt err)
       
   397 {
       
   398     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::error %d", err);
       
   399     emitError(doMapErrors(err));
       
   400     
       
   401     return KErrNone;
       
   402 }
       
   403 
       
   404 /*!
       
   405     Active object RunL function.
       
   406 */
       
   407 void CApaSymbianIPC::RunL()
       
   408 {
       
   409     int err = iStatus.Int();
       
   410     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::RunL %d", err);
       
   411     User::LeaveIfError( err );
       
   412     //todo: here the err is used to return le lenght of the data i would change this
       
   413     // Callback to observers
       
   414     //
       
   415     switch (iState)
       
   416         {
       
   417         case ESend:
       
   418             {
       
   419             //here the err variable contains the length of retdata
       
   420             if (err >= KErrNone)
       
   421                 {
       
   422                 iDataSize = err;
       
   423                 emitReadyRead();
       
   424                 }
       
   425             
       
   426             break;
       
   427             }
       
   428         case ERead:
       
   429             {
       
   430             QByteArray retData((char*) iBuf.Ptr(), iBuf.Length());
       
   431             //pass the value back to upper layer
       
   432             *iArray = retData;
       
   433 
       
   434             delete iRequestData;
       
   435             iRequestData = NULL;
       
   436             delete iAsyncData;
       
   437             iAsyncData = NULL;
       
   438             iRequestDataPtr.Set(KNullDesC);
       
   439             iAsyncDataPtr.Set(KNullDesC8);
       
   440 
       
   441             emitReadDone();
       
   442 
       
   443             break;
       
   444             }
       
   445         }
       
   446 }
       
   447 
       
   448 /*!
       
   449     Active object cancel
       
   450 */
       
   451 void CApaSymbianIPC::DoCancel()
       
   452 {
       
   453     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::DoCancel");
       
   454     // We can't cancel in the IPC design.
       
   455  
       
   456 }
       
   457 
       
   458 void CApaSymbianIPC::StartExitMonitor()
       
   459 {
       
   460     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::StartExitMonitor");
       
   461     if (iServerExitMonitor == NULL)
       
   462         {
       
   463         TInt err(KErrNone);
       
   464         TRAP( err, iServerExitMonitor = CApaServerAppExitMonitor::NewL(iSession,
       
   465                                                                         *this,
       
   466                                                                         CActive::EPriorityStandard ));    
       
   467         XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::StartExitMonitor status=%d",err);
       
   468         }
       
   469 }
       
   470 
       
   471 /*!
       
   472     HandleServerAppExit
       
   473 */
       
   474 void CApaSymbianIPC::HandleServerAppExit(int aReason)
       
   475 {
       
   476     XQSERVICE_DEBUG_PRINT("CApaSymbianIPC::HandleServerAppExit");
       
   477     if (iServerExitMonitor) {
       
   478         iServerExitMonitor->Cancel();
       
   479         delete iServerExitMonitor;
       
   480         iServerExitMonitor = NULL;
       
   481     }
       
   482     emitError(doMapErrors(aReason));
       
   483 }
       
   484 
       
   485 
       
   486 
       
   487 } // namespace QtService
       
   488 // END OF FILE