qthighway/xqserviceutil/src/xqservicemanager.cpp
branchRCL_3
changeset 9 5d007b20cfd0
equal deleted inserted replaced
8:885c2596c964 9:5d007b20cfd0
       
     1 /*
       
     2 * Copyright (c) 2009 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:                                                         
       
    19 *
       
    20 */
       
    21 
       
    22 #include <e32std.h>
       
    23 #include <w32std.h>
       
    24 #include <apaidpartner.h>
       
    25 #include <apparc.h>
       
    26 #include <apgcli.h>
       
    27 #include <apacln.h>
       
    28 #include <apgtask.h>
       
    29 #include <barsread2.h>
       
    30 #include <apacmdln.h>
       
    31 #include <coemain.h>
       
    32 
       
    33 #include <QBuffer>
       
    34 #include <QString>
       
    35 #include <QCoreApplication>
       
    36 #include <QHash>
       
    37 
       
    38 #include "xqservicelog.h"
       
    39 #include <xqserviceglobal.h>
       
    40 #include "xqrequestutil.h"
       
    41 #include "xqservicemanager.h"
       
    42 #include "xqserviceipcconst.h"
       
    43 
       
    44 #include "xqservicemetadata/xqservicemetadata_p.h"
       
    45 #include <xqservicemetadata/xqaiwinterfacedescriptor.h>
       
    46 #include "xqconversions.h"
       
    47 
       
    48 
       
    49 #define TIMER_DELAY 3000
       
    50 
       
    51 class CProcessInfo : public CActive
       
    52     {
       
    53     public:
       
    54         static void AddProcessL(const TUid& appUid, RProcess& appProcess);
       
    55         static void EnsureProcessCanStartL(const TUid& appUid);
       
    56         
       
    57     protected:
       
    58         CProcessInfo(const TUid& appUid);
       
    59         ~CProcessInfo();
       
    60         void ConstructL(RProcess& appProcess);
       
    61         void DoCancel();
       
    62         void RunL();
       
    63         
       
    64     protected:
       
    65         class ProcessInfoMap
       
    66         {
       
    67         public:
       
    68             ~ProcessInfoMap()
       
    69             {
       
    70                 foreach (CProcessInfo* info, map.values())
       
    71                     delete info;
       
    72             }
       
    73             QHash<TInt32, CProcessInfo*> map;
       
    74         };
       
    75         
       
    76         static ProcessInfoMap iProcessInfoMap;
       
    77         const TUid iAppUid;
       
    78     };
       
    79 
       
    80 
       
    81 
       
    82 CProcessInfo::ProcessInfoMap CProcessInfo::iProcessInfoMap;
       
    83 
       
    84 CProcessInfo::CProcessInfo(const TUid& appUid):
       
    85         CActive(CActive::EPriorityStandard), 
       
    86         iAppUid(appUid)
       
    87 {
       
    88     XQSERVICE_DEBUG_PRINT("CProcessInfo::CProcessInfo");
       
    89     
       
    90     CActiveScheduler::Add(this);
       
    91 }
       
    92 
       
    93 CProcessInfo::~CProcessInfo()
       
    94 {
       
    95     XQSERVICE_DEBUG_PRINT("CProcessInfo::~CProcessInfo");
       
    96     
       
    97     // Cancel asynch request, normally it should be done in DoCancel() 
       
    98     // but we dont wont to cancel request when we cancel active object
       
    99     User::CancelMiscNotifier(iStatus);
       
   100     
       
   101     Cancel();
       
   102 }
       
   103 
       
   104 void CProcessInfo::AddProcessL(const TUid& appUid, RProcess& appProcess)
       
   105 {
       
   106     XQSERVICE_DEBUG_PRINT("CProcessInfo::AddProcessL");
       
   107     
       
   108     CProcessInfo* self = new(ELeave) CProcessInfo(appUid);
       
   109     CleanupStack::PushL(self);
       
   110     self->ConstructL(appProcess);
       
   111     CleanupStack::Pop(self);
       
   112 }
       
   113 
       
   114 void CProcessInfo::EnsureProcessCanStartL(const TUid& appUid)
       
   115 {
       
   116     XQSERVICE_DEBUG_PRINT("CProcessInfo::EnsureProcessCanStartL");
       
   117     
       
   118     CProcessInfo* previousProcess = iProcessInfoMap.map[appUid.iUid];
       
   119     if (previousProcess) {
       
   120         previousProcess->Cancel();
       
   121         
       
   122         // Timer is for ensure that wait will end. 
       
   123         // Maybe there is possibility that destroing process notification could be lost.
       
   124         RTimer securityTimer;
       
   125         securityTimer.CreateLocal();
       
   126         CleanupClosePushL(securityTimer);
       
   127         
       
   128         TRequestStatus timerStatus;
       
   129         securityTimer.After(timerStatus, TIMER_DELAY);
       
   130         User::WaitForRequest(previousProcess->iStatus, timerStatus);
       
   131         
       
   132         CleanupStack::PopAndDestroy();
       
   133         delete previousProcess;
       
   134         iProcessInfoMap.map.remove(appUid.iUid);
       
   135     }
       
   136 }
       
   137 
       
   138 void CProcessInfo::RunL()
       
   139 {
       
   140     XQSERVICE_DEBUG_PRINT("CProcessInfo::RunL");
       
   141     
       
   142     iProcessInfoMap.map.remove(iAppUid.iUid);
       
   143     delete this;
       
   144 }
       
   145 
       
   146 void CProcessInfo::ConstructL(RProcess& appProcess)
       
   147 {
       
   148     XQSERVICE_DEBUG_PRINT("CProcessInfo::ConstructL");
       
   149     
       
   150     SetActive();
       
   151     
       
   152     EnsureProcessCanStartL(iAppUid);
       
   153     iProcessInfoMap.map.insert(iAppUid.iUid, this);
       
   154     appProcess.NotifyDestruction(iStatus);
       
   155 }
       
   156 
       
   157 void CProcessInfo::DoCancel()
       
   158 {
       
   159     XQSERVICE_DEBUG_PRINT("CProcessInfo::DoCancel");
       
   160     
       
   161     // Cancel asynch request, normally it should be done in DoCancel() 
       
   162     // but we dont wont to cancel request when we cancel active object.
       
   163     // Cancel asynch request is in ~CProcessInfo().
       
   164 }
       
   165 
       
   166 /*!
       
   167     \class XQServiceManagerPrivate
       
   168     \brief Private implementation of the XQServiceManager.
       
   169 */
       
   170 class XQServiceManagerPrivate 
       
   171     {
       
   172     public:
       
   173         XQServiceManagerPrivate();
       
   174         ~XQServiceManagerPrivate();
       
   175 
       
   176         enum matchMode
       
   177         {
       
   178             MatchInterfaceName,
       
   179             MatchServiceAndInterfaceName
       
   180         };
       
   181         
       
   182         int StartServer(const QString& aService,  bool embedded, int& applicationUid, quint64& processId,
       
   183                        XQRequestUtil *util);
       
   184         TInt Discover(const QString& aService,TUid& aAppUid, QList<XQAiwInterfaceDescriptor>& interfaces, int matchMode,
       
   185                       bool findFirst=false);
       
   186         int  LatestError() const {return iLatestError;};
       
   187         bool IsRunning(const XQAiwInterfaceDescriptor& implementation) const;
       
   188         
       
   189     private:
       
   190         void StartServerL(const TUid& uid, bool embedded, TUint64& processId, XQRequestUtil *util);
       
   191         TInt Discover(const TDesC& aService,TUid& aAppUid, QList<XQAiwInterfaceDescriptor>& interfaces, int matchMode,
       
   192                       bool findFirst=false);
       
   193         TInt Discover1(const TDesC& aService,TUid& aAppUid, QList<XQAiwInterfaceDescriptor>& interfaces, int matchMode,
       
   194                        bool findFirst=false);
       
   195         TInt Discover2(const TDesC& aService,TUid& aAppUid, QList<XQAiwInterfaceDescriptor>& interfaces, int matchMode,
       
   196                        bool findFirst=false);
       
   197         CApaAppServiceInfoArray* AvailableServiceImplementations1L();
       
   198         CApaAppServiceInfoArray* AvailableServiceImplementations2L();
       
   199         TUint64 getAppPid(const TUid& aAppUid);   
       
   200         int doMapErrors(TInt aError);
       
   201         
       
   202         TVersion iVersion;
       
   203         TApaAppInfo  iAppInfo;
       
   204         int iLatestError;
       
   205         RApaLsSession iApaSession;
       
   206         XQAiwInterfaceDescriptor iImplDescriptor; 
       
   207     };
       
   208 
       
   209 /*!
       
   210     \class XQServiceManager
       
   211     \brief Discovery and service startup. 
       
   212 */
       
   213 
       
   214 /*!
       
   215     Constructor.
       
   216 */
       
   217 XQServiceManager::XQServiceManager()
       
   218 {
       
   219     XQSERVICE_DEBUG_PRINT("XQServiceManager::XQServiceManager");
       
   220     d = new XQServiceManagerPrivate();
       
   221 }
       
   222 
       
   223 /*!
       
   224     Destructor.
       
   225 */
       
   226 XQServiceManager::~XQServiceManager()
       
   227 {
       
   228     XQSERVICE_DEBUG_PRINT("XQServiceManager::~XQServiceManager");
       
   229     delete d;
       
   230 }
       
   231 
       
   232 /*!
       
   233     Starts service
       
   234     \param service The full name of service (servicename + interfacename).
       
   235     \param embedded Start in embedded mode.
       
   236     \param applicationUid Returned applicatiion.
       
   237     \param threadId Returned process id of the application.
       
   238     \return Error code if error occured, 0 otherwise.
       
   239 */
       
   240 int XQServiceManager::startServer(const QString& service, bool embedded, int& applicationUid, quint64& threadId)
       
   241 {
       
   242     XQSERVICE_DEBUG_PRINT("XQServiceManager::startServer(1)");
       
   243     return startServer(service,embedded,applicationUid,threadId,NULL);
       
   244 }
       
   245 
       
   246 /*!
       
   247     Starts service
       
   248     \param service The full name of service (servicename + interfacename).
       
   249     \param embedded Start in embedded mode.
       
   250     \param applicationUid Returned applicatiion.
       
   251     \param threadId Returned process id of the application.
       
   252     \param userData Additional user data.
       
   253     \return Error code if error occured, 0 otherwise.
       
   254 */
       
   255 int XQServiceManager::startServer(const QString& service, bool embedded, int& applicationUid, quint64& threadId,
       
   256                                  const void *userData)
       
   257 {
       
   258     XQSERVICE_DEBUG_PRINT("XQServiceManager::startServer(2)");
       
   259 
       
   260     // The "XQServiceRequest::send(QVariant& retData)" function passed the utility as user data
       
   261     // the IPC layer. Could be NULL if no descriptor was given upon creating the request.
       
   262     // The util data is known to be writeable (though passed as const userData)
       
   263     XQRequestUtil *util = static_cast<XQRequestUtil*>((void *)userData);
       
   264     if (util == 0)
       
   265     {
       
   266         // Something is badly wrong as this should be always avaible
       
   267         return XQService::EMgrInternalError;
       
   268     }
       
   269     
       
   270     return d->StartServer(service,embedded,applicationUid,threadId, util);
       
   271 }
       
   272 
       
   273 
       
   274 /*!
       
   275     Finds implementations for the given interface.
       
   276     \param interfaceName Interfacename to match.
       
   277     \return List of implementations.
       
   278 */
       
   279 QList<XQAiwInterfaceDescriptor>  XQServiceManager::findInterfaces ( const QString &interfaceName ) const
       
   280     {
       
   281     XQSERVICE_DEBUG_PRINT("XQServiceManager::findInterfaces 1");
       
   282     QList<XQAiwInterfaceDescriptor> interfaces;
       
   283     TUid appUid;
       
   284     interfaces.clear();
       
   285     TInt error=d->Discover(interfaceName, appUid, interfaces, XQServiceManagerPrivate::MatchInterfaceName);
       
   286     return interfaces;
       
   287     }
       
   288 
       
   289 /*!
       
   290     Finds implementations for the given interface implemented by given service.
       
   291     \param serviceName Service name.
       
   292     \param interfaceName Interfacename to match.
       
   293     \return List of implementations.
       
   294 */
       
   295 QList<XQAiwInterfaceDescriptor>  XQServiceManager::findInterfaces ( const QString &serviceName, const QString &interfaceName ) const
       
   296 {
       
   297     XQSERVICE_DEBUG_PRINT("XQServiceManager::findInterfaces 2");
       
   298     QList<XQAiwInterfaceDescriptor> interfaces;
       
   299     TUid appUid;
       
   300     interfaces.clear(); 
       
   301     TInt error=d->Discover(serviceName + "." + interfaceName, appUid, interfaces,
       
   302                            XQServiceManagerPrivate::MatchServiceAndInterfaceName);
       
   303     return interfaces;
       
   304 }
       
   305 
       
   306 
       
   307 /*!
       
   308     Finds the first implementation for the given interface name.
       
   309     \param interfaceName Interfacename to match.
       
   310     \return List of implementations.
       
   311 */
       
   312 QList<XQAiwInterfaceDescriptor>  XQServiceManager::findFirstInterface ( const QString &interfaceName ) const
       
   313 {
       
   314     XQSERVICE_DEBUG_PRINT("XQServiceManager::findFirstInterface 1");
       
   315     QList<XQAiwInterfaceDescriptor> interfaces;
       
   316     TUid appUid;
       
   317     interfaces.clear();
       
   318     TInt error=d->Discover(interfaceName, appUid, interfaces, XQServiceManagerPrivate::MatchInterfaceName, true);
       
   319     return interfaces;
       
   320 }
       
   321 
       
   322 /*!
       
   323     Finds the first implementation for the given service + interface names.
       
   324     \param serviceName Service name.
       
   325     \param interfaceName Interfacename to match.
       
   326     \return List of implementations.
       
   327 */
       
   328 QList<XQAiwInterfaceDescriptor>  XQServiceManager::findFirstInterface ( const QString &serviceName, const QString &interfaceName ) const
       
   329 {
       
   330     XQSERVICE_DEBUG_PRINT("XQServiceManager::findFirstInterface 2");
       
   331     QList<XQAiwInterfaceDescriptor> interfaces;
       
   332     TUid appUid;
       
   333     interfaces.clear(); 
       
   334     // Catenate to get full name
       
   335     TInt error=d->Discover(serviceName + "." + interfaceName, appUid, interfaces,
       
   336                            XQServiceManagerPrivate::MatchServiceAndInterfaceName, true);
       
   337     return interfaces;
       
   338 }
       
   339 
       
   340 
       
   341 /*!
       
   342     Gets the latest error occured.
       
   343     \return Latest error code as integer value.
       
   344 */
       
   345 int XQServiceManager::latestError() const
       
   346 {
       
   347     return d->LatestError();
       
   348 }
       
   349 
       
   350 /*!
       
   351     Checks if the given \a implmentation is running.
       
   352     \param implementation Implementation to be checked.
       
   353     \return true if given \a implementation is running, false otherwise.
       
   354 */
       
   355 bool XQServiceManager::isRunning(const XQAiwInterfaceDescriptor& implementation) const
       
   356 {
       
   357     XQSERVICE_DEBUG_PRINT("XQServiceManager::isRunning");
       
   358     return d->IsRunning(implementation);
       
   359 }
       
   360 
       
   361 // ====== Private part ==============
       
   362 
       
   363 XQServiceManagerPrivate::XQServiceManagerPrivate()
       
   364 {
       
   365     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::XQServiceManagerPrivate");
       
   366     iLatestError = 0;
       
   367     iApaSession.Connect();    
       
   368 }
       
   369 
       
   370 XQServiceManagerPrivate::~XQServiceManagerPrivate()
       
   371 {
       
   372     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::~XQServiceManagerPrivate");
       
   373     iApaSession.Close();
       
   374 };
       
   375 
       
   376 // aService is here the full name (service + interface)
       
   377 int XQServiceManagerPrivate::StartServer(const QString& aService,  bool embedded, int& applicationUid, quint64& processId,
       
   378                                         XQRequestUtil *util)
       
   379 {
       
   380     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::startServer(2)");
       
   381     XQSERVICE_DEBUG_PRINT("aService: %s", qPrintable(aService));
       
   382     
       
   383     TUid appUid;
       
   384     appUid.iUid=0;
       
   385     
       
   386     TInt error = KErrNone;
       
   387     QList<XQAiwInterfaceDescriptor> interfaces;
       
   388     TPtrC serverName( reinterpret_cast<const TUint16*>(aService.utf16()) );
       
   389     if (util->mDescriptor.isValid()) 
       
   390     {
       
   391         iImplDescriptor=util->mDescriptor;  // Descriptor given by caller
       
   392         appUid.iUid = util->mDescriptor.property(XQAiwInterfaceDescriptor::ImplementationId).toInt();
       
   393         XQSERVICE_DEBUG_PRINT("ApplicationUid from descriptor: %x", appUid.iUid);
       
   394     }
       
   395     
       
   396     // Need to discover service first if descriptor did not contained valid UID
       
   397     // Otherwise, go directly starting the service server
       
   398     if (appUid.iUid == 0)
       
   399     {
       
   400         // Find the first implementation
       
   401         error = Discover(serverName,appUid,interfaces, XQServiceManagerPrivate::MatchServiceAndInterfaceName, true);
       
   402         if (interfaces.count())
       
   403         {
       
   404             iImplDescriptor=interfaces[0];  // Descriptor search upon start
       
   405         }
       
   406     }
       
   407     if (error)
       
   408         {
       
   409         return doMapErrors(error);
       
   410         }
       
   411 
       
   412     TRAP(error, StartServerL(appUid,embedded,processId, util));
       
   413     applicationUid = appUid.iUid ;
       
   414 
       
   415     XQSERVICE_DEBUG_PRINT("ApplicationUid: %x, processId: %d", applicationUid, processId);
       
   416     XQSERVICE_DEBUG_PRINT("error: %d", error);
       
   417     return doMapErrors(error);
       
   418 }
       
   419 
       
   420 void XQServiceManagerPrivate::StartServerL(const TUid& uid, bool embedded, TUint64& processId,
       
   421                                            XQRequestUtil *util)
       
   422 {
       
   423     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::StartServerL");
       
   424     Q_UNUSED(embedded);  // Not used any more. XQRequestUtil applied instead
       
   425     
       
   426     bool toBackground = false;
       
   427     // Apply the utility's option for embedding  instead
       
   428     bool embed = util->mInfo.isEmbedded();
       
   429     toBackground = util->mInfo.isBackground();
       
   430     
       
   431     XQSERVICE_DEBUG_PRINT("\tembedded got from utility=%d", embed);
       
   432     XQSERVICE_DEBUG_PRINT("\tbackground got from utility=%d", toBackground);
       
   433 
       
   434     // retrieve application information
       
   435     User::LeaveIfError( iApaSession.GetAppInfo( iAppInfo, uid ) );
       
   436 
       
   437     TApaAppCapabilityBuf caps;
       
   438     User::LeaveIfError(iApaSession.GetAppCapability(caps, uid));
       
   439     if (!toBackground)
       
   440     {
       
   441         // If service wants to be launched to background.. respect it
       
   442         toBackground = caps().iLaunchInBackground;
       
   443         XQSERVICE_DEBUG_PRINT("\tbackground from apparch=%d", toBackground);
       
   444     }
       
   445 
       
   446     // Consistency check
       
   447     if (embed && toBackground)
       
   448     {
       
   449         User::Leave(KErrArgument);
       
   450     }
       
   451 
       
   452     /*
       
   453     // Using the "iAppInfo.iCaption" is wrong as the channel name (full servicename) shall be used:
       
   454     // e.g. tester's "com.nokia.servicesd.serviceapp.Dialer" or
       
   455     //       "com.nokia.servicesd.serviceapp.Dialer.PROCESS-ID" in case of embedded launch
       
   456     // Anyway, this is not needed as the "XQServiceIpcClient::connectToServer()" takes care of the checking logic
       
   457     // earlier (the "startServer" logic will be applied only when needed)
       
   458     TFindServer find( iAppInfo.iCaption );
       
   459     TFullName fullName;
       
   460     TInt err = find.Next( fullName );
       
   461     XQSERVICE_DEBUG_PRINT("err: %d", err);
       
   462     */
       
   463     TInt err = KErrNotFound;  // Assume not found
       
   464     if ( err != KErrNone )
       
   465         {
       
   466         CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
       
   467         cmdLine->SetExecutableNameL( iAppInfo.iFullName );
       
   468         TApaCommand  aLaunchCommand = toBackground ? EApaCommandBackground : EApaCommandRun;
       
   469         cmdLine->SetCommandL(aLaunchCommand);
       
   470 
       
   471         // just use the Secure ID as server differentiator
       
   472         //cmdLine->SetServerRequiredL( uid.iUid );
       
   473         RProcess client;
       
   474         cmdLine->SetServerRequiredL(client.Id().Id());
       
   475         if (embed) {
       
   476             CCoeEnv* env= CCoeEnv::Static();
       
   477             if (env)  // Could be NULL 
       
   478             {
       
   479                 RWindowGroup& wg = env->RootWin();
       
   480                 wg.AllowProcessToCreateChildWindowGroups(iAppInfo.iUid);
       
   481                 TInt parentId = wg.Identifier();
       
   482                 if (parentId)
       
   483                 {
       
   484                     // pass our window group ID to the embedded child process
       
   485                     cmdLine->SetParentWindowGroupID(parentId);
       
   486                     XQSERVICE_DEBUG_PRINT("\tParent ID %x set for %x (%x)", (int)parentId, iAppInfo.iUid, uid.iUid);
       
   487                 }
       
   488             }
       
   489             else
       
   490             {
       
   491                 // Can not be embedded (non GUI client)
       
   492                 embed = false;
       
   493             }
       
   494         }
       
   495         else {
       
   496             CProcessInfo::EnsureProcessCanStartL(uid);
       
   497         }
       
   498         TRequestStatus requestStatusForRendezvous;
       
   499         
       
   500         // start application with command line parameters
       
   501         //User::LeaveIfError( iApaSession.StartApp( *cmdLine, threadId, &requestStatusForRendezvous) );
       
   502         QString startupArgs = QString::fromLatin1(XQServiceUtils::StartupArgService);
       
   503         if (embed)
       
   504         {
       
   505             startupArgs += (" " + QString::fromLatin1(XQServiceUtils::StartupArgEmbedded));
       
   506         }
       
   507 
       
   508         //
       
   509         // Add interface name and operation (message) name to the command line as startup args.
       
   510         // Usable in practise only for the embedded launch
       
   511         // Can be used  by service application to prepare the UI to the coming call.
       
   512         //
       
   513         QStringList l = util->mOperation.split("("); 
       
   514         QString oper = l.value(0); //  // Pick only the function name and ignore parameters
       
   515         
       
   516         startupArgs += (" " + QString::fromLatin1(XQServiceUtils::StartupArgInterfaceName) + iImplDescriptor.interfaceName() );
       
   517         startupArgs += (" " + QString::fromLatin1(XQServiceUtils::StartupArgServiceName) + iImplDescriptor.serviceName() );
       
   518         startupArgs += (" " + QString::fromLatin1(XQServiceUtils::StartupArgOperationName) + oper);
       
   519         
       
   520         XQSERVICE_DEBUG_PRINT("\tStartupArgs:%s", qPrintable(startupArgs));
       
   521         TPtrC cmdLineArgs( reinterpret_cast<const TUint16*>(startupArgs.utf16()) );
       
   522         
       
   523         RProcess newApp;
       
   524         XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Creating process");
       
   525         User::LeaveIfError(newApp.Create(iAppInfo.iFullName, cmdLineArgs));
       
   526         CleanupClosePushL(newApp);
       
   527         
       
   528         XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Created process");
       
   529         cmdLine->SetProcessEnvironmentL(newApp);
       
   530         TProcessId newAppId = newApp.Id();
       
   531         processId = newAppId.Id();
       
   532         XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Rendezvous for %x", processId);
       
   533         newApp.Rendezvous(requestStatusForRendezvous);  // Asynchronous
       
   534         newApp.Resume();
       
   535         
       
   536         User::WaitForRequest( requestStatusForRendezvous ); // Make the  rendezvouz
       
   537         XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Rendezvous done %d", requestStatusForRendezvous.Int());
       
   538 
       
   539         if (!embed) {
       
   540             CProcessInfo::AddProcessL(uid, newApp);
       
   541         }
       
   542         
       
   543         User::LeaveIfError( requestStatusForRendezvous.Int()); 
       
   544         CleanupStack::PopAndDestroy(2,cmdLine); // newApp, cmdLine
       
   545         
       
   546         XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Done"); 
       
   547         }
       
   548     
       
   549 }
       
   550 
       
   551 
       
   552 TUint64 XQServiceManagerPrivate::getAppPid(const TUid& aAppUid)
       
   553 {
       
   554     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::getAppPid");
       
   555     TUint64 pid = 0;
       
   556     // Get the current task
       
   557     RWsSession ws;
       
   558     if (ws.Connect()==KErrNone) {
       
   559         XQSERVICE_DEBUG_PRINT("Connected to window server");
       
   560         TApaTaskList tasklist( ws );
       
   561         TApaTask task = tasklist.FindApp( aAppUid );        
       
   562         if (task.Exists()) {
       
   563             XQSERVICE_DEBUG_PRINT("Application found");
       
   564             pid=task.ThreadId().Id();
       
   565         }
       
   566     }
       
   567     return pid;
       
   568 }
       
   569 
       
   570 CApaAppServiceInfoArray* XQServiceManagerPrivate::AvailableServiceImplementations1L()
       
   571 {
       
   572     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::AvailableServiceImplementations1L");
       
   573     // retrieve list of available services implementations from apparc
       
   574     CApaAppServiceInfoArray* apaInfo = 
       
   575                     iApaSession.GetServiceImplementationsLC(TUid::Uid(KXQServiceUid));
       
   576     CleanupStack::Pop( apaInfo );
       
   577     return apaInfo;
       
   578 }
       
   579 
       
   580 CApaAppServiceInfoArray* XQServiceManagerPrivate::AvailableServiceImplementations2L()
       
   581 {
       
   582     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::AvailableServiceImplementations2L");
       
   583     // retrieve list of available services implementations from apparc
       
   584     CApaAppServiceInfoArray* apaInfo = 
       
   585                     iApaSession.GetServiceImplementationsLC(TUid::Uid(KXQServiceUid2));
       
   586     CleanupStack::Pop( apaInfo );
       
   587     return apaInfo;
       
   588 }
       
   589 
       
   590 TInt XQServiceManagerPrivate::Discover(const QString& aService,TUid& aAppUid, QList<XQAiwInterfaceDescriptor>& interfaces,
       
   591                                       int matchMode, bool findFirst)
       
   592     {
       
   593     TPtrC serverName( reinterpret_cast<const TUint16*>(aService.utf16()) );
       
   594     TInt error=Discover(serverName, aAppUid, interfaces, matchMode, findFirst);
       
   595     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Discover (1)");
       
   596     return error;
       
   597     }
       
   598 
       
   599 TInt XQServiceManagerPrivate::Discover( const TDesC& aService,
       
   600                                       TUid& aAppUid, QList<XQAiwInterfaceDescriptor>& interfaces,
       
   601                                       int matchMode, bool findFirst)
       
   602     {
       
   603     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Discover (2)");
       
   604     TInt discoverResult1 = KErrNotFound;
       
   605     TInt discoverResult2 = KErrNotFound;
       
   606 
       
   607     // Discover first possible reg files with old format
       
   608     discoverResult1 = Discover1(aService, aAppUid, interfaces, matchMode, findFirst);
       
   609     // Discover then  reg files with new format (add results)
       
   610     discoverResult2 = Discover2(aService, aAppUid, interfaces, matchMode, findFirst);
       
   611     
       
   612     if (discoverResult1 == KErrNone || discoverResult2 == KErrNone)
       
   613         {
       
   614         // Results merged
       
   615         return KErrNone;
       
   616         }
       
   617     else
       
   618         {
       
   619         return KErrNotFound;
       
   620         }
       
   621     }
       
   622 
       
   623 TInt XQServiceManagerPrivate::Discover1( const TDesC& aService,
       
   624                                       TUid& aAppUid, QList<XQAiwInterfaceDescriptor>& interfaces,
       
   625                                       int matchMode, bool findFirst)
       
   626     {
       
   627     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Discover1");
       
   628         
       
   629     CApaAppServiceInfoArray* apaInfo = NULL;
       
   630     TInt error = KErrNone;
       
   631     TRAP(error, apaInfo = AvailableServiceImplementations1L());
       
   632     XQSERVICE_DEBUG_PRINT("Discover status=%d", error);
       
   633     if (error)
       
   634         {
       
   635         return error;  // This is fatal as nothing found
       
   636         }
       
   637     TArray<TApaAppServiceInfo> implArray( apaInfo->Array() );
       
   638     XQSERVICE_DEBUG_PRINT("implArray.Count(): %d", implArray.Count());
       
   639     if ( !implArray.Count() )
       
   640         {
       
   641         delete apaInfo;
       
   642         return KErrNotFound;   // No services found
       
   643         }
       
   644     
       
   645     TBool found( EFalse );
       
   646     QString serviceName = QString::fromUtf16(aService.Ptr(),aService.Length());
       
   647     XQSERVICE_DEBUG_PRINT("serviceName: %s", qPrintable(serviceName));
       
   648     TBool firstUidPicked(EFalse);
       
   649     
       
   650     for ( TInt ii = 0; ii < implArray.Count(); ii++ )  
       
   651         {
       
   652 
       
   653         //
       
   654         // Reset error for each check round
       
   655         //
       
   656         error = KErrNone;
       
   657             
       
   658         TUid uid = implArray[ii].Uid();
       
   659         XQSERVICE_DEBUG_PRINT("implArray[%d].UID=%x", ii, uid);
       
   660             
       
   661         RResourceReader res;
       
   662         // read opaque data
       
   663         TRAP(error,res.OpenL( implArray[ii].OpaqueData() ) )
       
   664         if ( error )
       
   665             {
       
   666             XQSERVICE_DEBUG_PRINT("OpaqueData error: %d", error);
       
   667             delete apaInfo;
       
   668             apaInfo = NULL;
       
   669             continue;  // Next could be OK
       
   670             }
       
   671         
       
   672         //the first WORD contains the number of elements in the resource
       
   673         int count = 0;
       
   674         TRAP(error,count = res.ReadInt16L());
       
   675         if ( error )
       
   676             {
       
   677             XQSERVICE_DEBUG_PRINT("resource error1: %d", error);
       
   678             res.Close();
       
   679             delete apaInfo;
       
   680             apaInfo = NULL;
       
   681             continue;  // Next could be OK
       
   682             }      
       
   683         QByteArray xmlConf ;
       
   684         XQSERVICE_DEBUG_PRINT("resource line count: %d", count);
       
   685         for (int i=0; i < count ; i++) 
       
   686             {
       
   687             TPtrC16 xmlBuf;
       
   688             TRAP(error, xmlBuf.Set( res.ReadTPtrC16L() ));
       
   689             if (error)
       
   690                 {
       
   691                 XQSERVICE_DEBUG_PRINT("resource error2: %d", error);
       
   692                 res.Close();
       
   693                 delete apaInfo;
       
   694                 apaInfo = NULL;
       
   695                 break;
       
   696                 }
       
   697             else
       
   698                 {
       
   699                 QString str=QString::fromUtf16(xmlBuf.Ptr(),xmlBuf.Length());
       
   700                 XQSERVICE_DEBUG_PRINT("resource str: %s", qPrintable(str));
       
   701                 xmlConf.append(str.toAscii());
       
   702                 }
       
   703             }
       
   704 
       
   705         // If we stop loop for the first resource error,
       
   706         // it will hit cases where same interface has been implemented by multiple services
       
   707         // So go on checking all the resource files
       
   708         if (error)
       
   709         {
       
   710             continue; // Next could be OK
       
   711         }
       
   712         
       
   713         XQSERVICE_DEBUG_PRINT("resource data: %s", xmlConf.constData());
       
   714         QBuffer buf(&xmlConf);
       
   715         ServiceMetaData* metaData = new ServiceMetaData(&buf);
       
   716         if (metaData->extractMetadata()) 
       
   717             {
       
   718             ServiceMetaDataResults results=metaData->parseResults();
       
   719             // interfaces = results.interfaces;  // return value set here ???!!
       
   720 
       
   721             // Go through all interfaces and pick the UI for the first matching one.
       
   722             // THIS NEED TO BE FIXED IF SOMEONE WANTS DEDICATED IMPLEMENTATION
       
   723             // Fill in the implementationId for all interfaces
       
   724             foreach (XQAiwInterfaceDescriptor interface,results.interfaces)
       
   725                 {
       
   726                 QString sn;
       
   727                 QString snDeprecated;
       
   728                 if (results.version == ServiceMetaDataResults::VERSION_1)
       
   729                     {
       
   730                     // Old version of the XML format. The parser took care of adaptation
       
   731                     // discovery-name = service-name + interface name
       
   732                     XQSERVICE_DEBUG_PRINT("version 1");
       
   733                     }
       
   734                 else
       
   735                     {
       
   736                     // discovery-name = interface name
       
   737                    XQSERVICE_DEBUG_PRINT("version 2");
       
   738                     }
       
   739 
       
   740                 // Deprecated service name, if any
       
   741                 QString deprecatedServiceName = interface.customProperty("deprecatedsn");
       
   742                 bool deprNameExists = !deprecatedServiceName.isEmpty();
       
   743                 if (deprNameExists)
       
   744                 {
       
   745                     XQSERVICE_DEBUG_PRINT("deprecatedServiceName: %s", qPrintable(deprecatedServiceName));
       
   746                 }
       
   747                 
       
   748                 // This is the name used in match
       
   749                 // TODO: Version handling support: Take the latest version if multiple matches
       
   750                 switch (matchMode)
       
   751                 {
       
   752                     case MatchInterfaceName :
       
   753                         sn = interface.interfaceName();
       
   754                         break;
       
   755                     case MatchServiceAndInterfaceName :
       
   756                         sn =interface.serviceName() + "." + interface.interfaceName();
       
   757                         snDeprecated = deprecatedServiceName + "." + interface.interfaceName();
       
   758                         break;
       
   759                     default:
       
   760                         sn = interface.interfaceName();
       
   761                        break;
       
   762                 }
       
   763 
       
   764                 XQSERVICE_DEBUG_PRINT("compare name is: %s", qPrintable(sn));
       
   765                 XQSERVICE_DEBUG_PRINT("requested name: %s", qPrintable(serviceName));
       
   766                 if ((!serviceName.compare(sn,Qt::CaseInsensitive)) ||
       
   767                     (deprNameExists && !serviceName.compare(snDeprecated,Qt::CaseInsensitive)))
       
   768                     {
       
   769                     TUid appUid = implArray[ii].Uid();
       
   770                     if (!firstUidPicked)
       
   771                         {
       
   772                         aAppUid = appUid;
       
   773                         firstUidPicked = ETrue;
       
   774                         XQSERVICE_DEBUG_PRINT("First service found UID3=%x", appUid.iUid);
       
   775                         }
       
   776                     XQSERVICE_DEBUG_PRINT("Service found UID3=%x", appUid.iUid);
       
   777                     //  Add impl. UID to interface
       
   778                     interface.setProperty(XQAiwInterfaceDescriptor::ImplementationId, (int)appUid.iUid);
       
   779                     found = ETrue;
       
   780 
       
   781                     // Add the matched interface to result set
       
   782                     interfaces.append(interface);
       
   783                     
       
   784                     }
       
   785                 } // forearch interface
       
   786             } 
       
   787         else
       
   788             {
       
   789              error = metaData->getLatestError();
       
   790              iLatestError = error;
       
   791              XQSERVICE_DEBUG_PRINT("metadata error: %d", error); 
       
   792             }  
       
   793         
       
   794         delete metaData;
       
   795         metaData = NULL;
       
   796         res.Close();
       
   797 
       
   798 
       
   799         // If only first found needed, quit the loop.
       
   800         if (findFirst && firstUidPicked)
       
   801             {
       
   802             XQSERVICE_DEBUG_PRINT("First service returned UID3=%x", aAppUid.iUid);
       
   803             break;
       
   804             }
       
   805         
       
   806         } // for implArray ...
       
   807     
       
   808     delete apaInfo;
       
   809     if (!found)
       
   810         {
       
   811         error = KErrNotFound;
       
   812         }
       
   813     if (found)
       
   814         {
       
   815         error = KErrNone;
       
   816         }
       
   817     
       
   818     XQSERVICE_DEBUG_PRINT("Discover error: %d", error);
       
   819     
       
   820     return error;
       
   821     }
       
   822 
       
   823 
       
   824 TInt XQServiceManagerPrivate::Discover2( const TDesC& aService,
       
   825                                       TUid& aAppUid, QList<XQAiwInterfaceDescriptor>& interfaces,
       
   826                                       int matchMode, bool findFirst)
       
   827     {
       
   828     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::Discover2");
       
   829         
       
   830     CApaAppServiceInfoArray* apaInfo = NULL;
       
   831     TInt error = KErrNone;
       
   832     
       
   833     TRAP(error, apaInfo = AvailableServiceImplementations2L());
       
   834     XQSERVICE_DEBUG_PRINT("Discover status=%d", error);
       
   835     
       
   836     if (error)
       
   837         {
       
   838         return error;  // This is fatal as nothing found
       
   839         }
       
   840     TArray<TApaAppServiceInfo> implArray( apaInfo->Array() );
       
   841     XQSERVICE_DEBUG_PRINT("implArray.Count(): %d", implArray.Count());
       
   842     
       
   843     if ( !implArray.Count() )
       
   844         {
       
   845         delete apaInfo;
       
   846         return KErrNotFound;   // No services found
       
   847         }
       
   848     
       
   849     TBool found( EFalse );
       
   850     
       
   851     QString serviceName = QString::fromUtf16(aService.Ptr(),aService.Length());
       
   852     XQSERVICE_DEBUG_PRINT("serviceName: %s", qPrintable(serviceName));
       
   853     TBool firstUidPicked(EFalse);
       
   854 
       
   855     for ( TInt ii = 0; ii < implArray.Count(); ii++ )  
       
   856         {
       
   857         TUid uid = implArray[ii].Uid();
       
   858         XQSERVICE_DEBUG_PRINT("implArray[%d].UID=%x", ii, uid);
       
   859 
       
   860         QByteArray xmlConf ;
       
   861 
       
   862         TPtrC8 opaque = implArray[ii].OpaqueData();
       
   863         const TPtrC16 tmpXml((TText16*) opaque.Ptr(),(opaque.Length()+1)>>1);
       
   864         QString strXml = XQConversions:: s60DescToQString( tmpXml ) ;
       
   865         // XQSERVICE_DEBUG_PRINT("XML conf: %s", qPrintable(strXml));
       
   866         XQSERVICE_DEBUG_PRINT("size of xml conf.: %d characters", strXml.size());
       
   867         xmlConf.append(strXml.toAscii());
       
   868         
       
   869         XQSERVICE_DEBUG_PRINT("resource data: %s", xmlConf.constData());
       
   870         QBuffer buf(&xmlConf);
       
   871         ServiceMetaData* metaData = new ServiceMetaData(&buf);
       
   872         if (metaData->extractMetadata()) 
       
   873             {
       
   874             ServiceMetaDataResults results=metaData->parseResults();
       
   875 
       
   876             // Go through all interfaces and pick the UI for the first matching one.
       
   877             // THIS NEED TO BE FIXED IF SOMEONE WANTS DEDICATED IMPLEMENTATION
       
   878             // Fill in the implementationId for all interfaces
       
   879             foreach (XQAiwInterfaceDescriptor interface,results.interfaces)
       
   880                 {
       
   881                 QString sn;
       
   882                 QString snDeprecated;
       
   883                 if (results.version == ServiceMetaDataResults::VERSION_1)
       
   884                     {
       
   885                     // Old version of the XML format. The parser took care of adaptation
       
   886                     // discovery-name = service-name + interface name
       
   887                     XQSERVICE_DEBUG_PRINT("version 1");
       
   888                     }
       
   889                 else
       
   890                     {
       
   891                     // discovery-name = interface name
       
   892                    XQSERVICE_DEBUG_PRINT("version 2");
       
   893                     }
       
   894 
       
   895                 // Deprecated service name, if any
       
   896                 QString deprecatedServiceName = interface.customProperty("deprecatedsn");
       
   897                 bool deprNameExists = !deprecatedServiceName.isEmpty();
       
   898                 if (deprNameExists)
       
   899                 {
       
   900                     XQSERVICE_DEBUG_PRINT("deprecatedServiceName: %s", qPrintable(deprecatedServiceName));
       
   901                 }
       
   902                 // This is the name used in match
       
   903                 // TODO: Version handling support: Take the latest version if multiple matches
       
   904                 switch (matchMode)
       
   905                 {
       
   906                     case MatchInterfaceName :
       
   907                         sn = interface.interfaceName();
       
   908                         break;
       
   909                     case MatchServiceAndInterfaceName :
       
   910                         sn =interface.serviceName() + "." + interface.interfaceName();
       
   911                         snDeprecated = deprecatedServiceName + "." + interface.interfaceName();
       
   912                         break;
       
   913                     default:
       
   914                         sn = interface.interfaceName();
       
   915                         break;
       
   916                 }
       
   917 
       
   918                 XQSERVICE_DEBUG_PRINT("compare name is: %s", qPrintable(sn));
       
   919                 XQSERVICE_DEBUG_PRINT("requested name: %s", qPrintable(serviceName));
       
   920                 if ((!serviceName.compare(sn,Qt::CaseInsensitive)) ||
       
   921                     (deprNameExists && !serviceName.compare(snDeprecated,Qt::CaseInsensitive)))
       
   922                     {
       
   923                     TUid appUid = implArray[ii].Uid();
       
   924                     if (!firstUidPicked)
       
   925                         {
       
   926                         aAppUid = appUid;
       
   927                         firstUidPicked = ETrue;
       
   928                         XQSERVICE_DEBUG_PRINT("First service found UID3=%x", appUid.iUid);
       
   929                         }
       
   930                     XQSERVICE_DEBUG_PRINT("Service found UID3=%x", appUid.iUid);
       
   931                     //  Add impl. UID to interface
       
   932                     interface.setProperty(XQAiwInterfaceDescriptor::ImplementationId, (int)appUid.iUid);
       
   933                     found = ETrue;
       
   934 
       
   935                     // Add the matched interface to result set
       
   936                     interfaces.append(interface);
       
   937                     }
       
   938 
       
   939                     if (found)
       
   940                     {
       
   941                         error = KErrNone;
       
   942                     }
       
   943                 } // forearch interface
       
   944             }
       
   945         else
       
   946             {
       
   947              error = metaData->getLatestError();
       
   948              iLatestError = error;
       
   949              XQSERVICE_DEBUG_PRINT("metadata error: %d", error); 
       
   950             }  
       
   951         
       
   952         delete metaData;
       
   953         metaData = NULL;
       
   954 
       
   955         // If only first found needed, quit the loop.
       
   956         if (findFirst && firstUidPicked)
       
   957             {
       
   958             XQSERVICE_DEBUG_PRINT("First service returned UID3=%x", aAppUid.iUid);
       
   959             break;
       
   960             }
       
   961         } // for implArray ...
       
   962     
       
   963     delete apaInfo;
       
   964     if (!found)
       
   965         {
       
   966         error = KErrNotFound;
       
   967         }
       
   968     
       
   969     if (found)
       
   970         {
       
   971         error = KErrNone;
       
   972         }
       
   973     
       
   974     XQSERVICE_DEBUG_PRINT("Discover error: %d", error);
       
   975     
       
   976     return error;
       
   977 }
       
   978 
       
   979 bool XQServiceManagerPrivate::IsRunning(const XQAiwInterfaceDescriptor& implementation) const
       
   980 {
       
   981     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::IsRunning");
       
   982     QString fullServiceName = implementation.serviceName() + "." +  implementation.interfaceName();
       
   983     TPtrC serverName( reinterpret_cast<const TUint16*>(fullServiceName.utf16()) );
       
   984     
       
   985     TFindServer findServer(serverName);
       
   986     TFullName name;
       
   987     bool b = findServer.Next(name) == KErrNone;
       
   988     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::IsRunning=%d",b);
       
   989     return b;
       
   990 }
       
   991 
       
   992     
       
   993 int XQServiceManagerPrivate::doMapErrors(TInt aError)
       
   994 {
       
   995     XQSERVICE_DEBUG_PRINT("XQServiceManagerPrivate::doMapErrors");
       
   996     XQSERVICE_DEBUG_PRINT("aError: %d", aError);
       
   997     int error(XQService::ENoError);
       
   998     
       
   999     switch (aError)
       
  1000     {
       
  1001     case KErrNone: {
       
  1002         error = XQService::ENoError;
       
  1003         break;
       
  1004     }
       
  1005     case KErrPermissionDenied:
       
  1006     case KErrServerTerminated: {
       
  1007         error = XQService::EConnectionClosed;
       
  1008         break;
       
  1009     }
       
  1010     case KErrServerBusy: {
       
  1011         error = XQService::EConnectionError;
       
  1012         break;
       
  1013     }
       
  1014     case KErrArgument:
       
  1015     {
       
  1016         error = XQService::EArgumentError;
       
  1017         break;
       
  1018     }
       
  1019         
       
  1020     case KErrNoMemory: {
       
  1021         error = XQService::EIPCError;
       
  1022         break;
       
  1023     }
       
  1024     case KErrNotFound: {
       
  1025         error = XQService::EServerNotFound;
       
  1026         break;
       
  1027     }
       
  1028 
       
  1029     default:
       
  1030     {
       
  1031 
       
  1032         if (aError >= XQService::EMetaNoService && aError <= XQService::EMetaDuplicatedCustomKey)
       
  1033         {
       
  1034             iLatestError = error;
       
  1035             return error;  // Already real error
       
  1036         }
       
  1037         
       
  1038         error = XQService::EUnknownError;
       
  1039         break;
       
  1040     }
       
  1041     }
       
  1042 
       
  1043     // Save error
       
  1044     iLatestError = error;
       
  1045     
       
  1046     XQSERVICE_DEBUG_PRINT("error: %d", error);
       
  1047     return error;
       
  1048 }
       
  1049 
       
  1050 
       
  1051