serviceproviders/sapi_location/locationservice/src/locationservice.cpp
changeset 22 fc9cf246af83
parent 19 989d2f495d90
child 32 8d692d9f828f
--- a/serviceproviders/sapi_location/locationservice/src/locationservice.cpp	Fri Jul 03 15:51:24 2009 +0100
+++ b/serviceproviders/sapi_location/locationservice/src/locationservice.cpp	Thu Aug 27 07:43:07 2009 +0300
@@ -21,11 +21,6 @@
 #include "locationcoreimp.h"
 #include "locationservice.h"
 
-/**
- * Maximum number of active objects that can be created : at present only each corresponding
- * to location-asynch and trace
- */
-const TInt  KMAXAO = 2;
 
 
 
@@ -60,7 +55,6 @@
                     iRegTable[iter]->Deque() ;
                     }
                 delete iRegTable[iter];
-                iRegTable[iter] = NULL ;
 
                 }
         }
@@ -88,110 +82,154 @@
 /**
  * CLocationService::ConstructL
  * Symbian 2nd phase constructor can leave.
- */
-
-void CLocationService::ConstructL()
-    {
-
-    DoInitialiseL();
-    }
-
-
-
-/**
- * CLocationService::DoInitialiseL
  * Initialises position server and positioner and
  * begins the position request sequence.
  */
 
-EXPORT_C void CLocationService :: DoInitialiseL()
+void CLocationService::ConstructL()
     {
-    TInt error = iPosServer.Connect( );
-    // The connection failed
-  
-    User :: LeaveIfError(error) ;
+    User :: LeaveIfError(iPosServer.Connect());
+    CleanupClosePushL(iPosServer);
     
-    // Open subsession to the position server
-    error = iPositioner.Open(iPosServer);
-
-    // The opening of a subsession failed
-    if ( KErrNone != error )
-        {
-        iPosServer.Close();
-        User :: Leave( error );
-        }
-
+    //Get the module id of the default module available
+    User :: LeaveIfError(iPosServer.GetDefaultModuleId(iModuleId));
 
-    //setting identity for this requestor
-    User::LeaveIfError( iPositioner.SetRequestor( CRequestor::ERequestorService,
-												  CRequestor::EFormatApplication,
-												  KIdentity ) );
-    
-    //Initialise index which means there is no 
-    //active object created yet
-    iIndex = 0 ;
-    //Initialising array pointer to NULL 
-
-    for ( TInt count = 0;count < KMAXAO;count++)
-        {
-        iRegTable.Insert(NULL,count);
-        }
-    
-       
-     //Getthe module id used by location server for sapi location calls.
-    error = iPosServer.GetDefaultModuleId(iModuleId);
-
-    User :: LeaveIfError(error) ;
-
+    CleanupStack::Pop(&iPosServer);
     }
 
+/**
+ * CLocationService::GetHighAccuracyModule
+ * This function returns the module id of highest accuracy 
+ * module that is available on the phone currently.
+ */
+void CLocationService::GetHighAccuracyModuleL(TPositionModuleId* aModId)
+    {
+    TPositionModuleId moduleId;
+    TPositionModuleInfo modInfo;
+    TUint numOfModules = 0;
+
+    //Flags used for indicating if a particular module is found
+    TInt termInternalFlag = 0;   
+    TInt termFlag = 0 ,assisFlag = 0 ,networkFlag = 0,unknownFlag = 0;
+    TInt err;
+    
+    User::LeaveIfError(iPosServer.GetNumModules(numOfModules));
+        
+
+    for( TInt i=0;i< numOfModules;i++ )
+        {
+        iPosServer.GetModuleInfoByIndex(i,modInfo);
+
+				if( modInfo.TechnologyType() == modInfo.ETechnologyAssisted  && 
+                 modInfo.IsAvailable())
+            {
+
+            assisFlag = 1;
+            moduleId = modInfo.ModuleId();
+						break;
+            }
+            
+        if( modInfo.TechnologyType() == modInfo.ETechnologyTerminal  && 
+                !assisFlag && !termInternalFlag && modInfo.IsAvailable() )
+            {
+
+            termFlag = 1;
+            moduleId = modInfo.ModuleId();
+
+            //Internal Module takes higher priority than External module 
+            if(modInfo.DeviceLocation() == modInfo.EDeviceInternal)
+                {
+                termInternalFlag = 1;                
+                }
+
+            }
+
+        if(modInfo.TechnologyType() == modInfo.ETechnologyNetwork && 
+                !assisFlag  && !termFlag && modInfo.IsAvailable())
+            {
+
+            networkFlag = 1;
+            moduleId = modInfo.ModuleId();
+
+            }
+
+        if( modInfo.TechnologyType() == modInfo.ETechnologyUnknown && 
+                !assisFlag  && !termFlag && 
+                !networkFlag && modInfo.IsAvailable() )
+            {
+
+            unknownFlag = 1;
+            moduleId = modInfo.ModuleId();                            
+            }
+        }
+    *aModId =  moduleId;
+    }
 
 /**
  * CLocationService :: GetLocationL with update options, this function gets users current location
  * returns 0 on success and Symbian specific error codes on failure
  */
 
-EXPORT_C TInt  CLocationService :: GetLocationL( TPositionInfoBase* aInfoBase , const TPositionUpdateOptions* aUpdateOpts )
+EXPORT_C void  CLocationService :: GetLocationL( TPositionInfoBase* aInfoBase ,
+        const TPositionUpdateOptions* aUpdateOpts,TBool aEnableHighAcc )
     {
-
-    TRequestStatus status  ;
-
-    if(aUpdateOpts)
+    // Open subsession to the position server
+    TPositionModuleId ModuleId;
+    TInt error;
+    if(aEnableHighAcc)
         {
-        TInt error;
-        error = iPositioner.SetUpdateOptions(*aUpdateOpts);
-        if( error)
-	    	{
-            return error ;
-            }
+        GetHighAccuracyModuleL(&ModuleId);
+       
+        User::LeaveIfError(iPositioner.Open(iPosServer,ModuleId));
         
         }
     else
         {
-        TPositionUpdateOptions updateopts ;
-        
-        // Set update interval to one second to receive one position data per second
-	    updateopts.SetUpdateInterval(TTimeIntervalMicroSeconds(KSUpdateInterval));
+        User::LeaveIfError(iPositioner.Open(iPosServer));
+        }
+
+    
+    CleanupClosePushL(iPositioner);
+
+    //setting identity for this requestor
+    User::LeaveIfError( iPositioner.SetRequestor( CRequestor::ERequestorService,
+            CRequestor::EFormatApplication,
+            KIdentity ) );
+
+    TRequestStatus status;
+
+    if(aUpdateOpts)
+        {
+        User::LeaveIfError(iPositioner.SetUpdateOptions(*aUpdateOpts));
+        }
 
-	    // If position server could not get position
-	    // In two minutes it will terminate the position request
-	    updateopts.SetUpdateTimeOut(TTimeIntervalMicroSeconds(KSUpdateTimeOut));
+    else
+        {
+        TPositionUpdateOptions updateopts ;
+
+        // Set update interval to one second to receive one position data per second
+        updateopts.SetUpdateInterval(TTimeIntervalMicroSeconds(KSUpdateInterval));
 
-	    // Positions which have time stamp below KMaxAge can be reused
-	    updateopts.SetMaxUpdateAge(TTimeIntervalMicroSeconds(KSMaxAge));
+        // If position server could not get position
+        // In two minutes it will terminate the position request
+        updateopts.SetUpdateTimeOut(TTimeIntervalMicroSeconds(KSUpdateTimeOut));
 
-	    // Enables location framework to send partial position data
-	    updateopts.SetAcceptPartialUpdates(FALSE);
+        // Positions which have time stamp below KMaxAge can be reused
+        updateopts.SetMaxUpdateAge(TTimeIntervalMicroSeconds(KSMaxAge));
 
-        
+        // Enables location framework to send partial position data
+        updateopts.SetAcceptPartialUpdates(FALSE);
+
+
         iPositioner.SetUpdateOptions(updateopts) ;
         }
 
 
     iPositioner.NotifyPositionUpdate( *aInfoBase, status );
     User :: WaitForRequest(status) ;
-
-    return status.Int() ;
+    CleanupStack::PopAndDestroy(&iPositioner);
+    
+    User::LeaveIfError(status.Int());
     }
 
 /**
@@ -212,46 +250,44 @@
  * This function gets users current location
  * returns status of job submitted 
  */
-EXPORT_C TInt CLocationService :: GetLocationL( MLocationCallBack* aCallBackObj ,
-													TInt aLocationInfoCategory, 
-													TPositionFieldIdList aFieldList ,
-													const TPositionUpdateOptions* aUpateOptions
-													 )
-    {
-
-    if(iRegTable[KARRAY_INDEX_GETLOCATION])
+EXPORT_C void CLocationService :: GetLocationL( MLocationCallBack* aCallBackObj ,
+        TInt aLocationInfoCategory,
+        TPositionFieldIdList aFieldList ,
+        const TPositionUpdateOptions* aUpateOptions,
+        TBool aEnableHighAcc 
+)
+    {  
+    TPositionModuleId ModuleId;
+    if(aEnableHighAcc)
         {
-        if(iRegTable[KARRAY_INDEX_GETLOCATION]->IsActive())
-            {
-            return KErrInUse ;                //Return Error is Already registred 
-            }
-
-        delete iRegTable[KARRAY_INDEX_GETLOCATION] ;
-        iRegTable[KARRAY_INDEX_GETLOCATION] = NULL ;
-
+        GetHighAccuracyModuleL(&ModuleId);
+        
+        }
+    else
+        {
+        //Indicates that when opening the subsession ,moudleId need not be specified
+        ModuleId.iUid = 0;       
         }
 
-    CGetLoc *activeGetLoc = CGetLoc :: NewL(iPosServer ,
-    									    aFieldList ,	
-                                            KGetLocationRequest,
-                                            aLocationInfoCategory ) ;
-    	//after creation of each active object increment counter by 1
-    
-    TInt err = 	activeGetLoc->GetLocation(aCallBackObj , aUpateOptions) ;
-    	
-    if ( KErrNone == err  )
-        {
+    TInt err = KErrGeneral;
+
+    CGetLoc* activeGetLoc = CGetLoc :: NewL(iPosServer ,
+            aFieldList ,
+            KGetLocationRequest,
+            aLocationInfoCategory,
+            ModuleId) ;
+
+    err = activeGetLoc->GetLocationUpdates(this,aCallBackObj,aUpateOptions);
 
-        iIndex = KARRAY_INDEX_GETLOCATION;  //for getlocation we are storing the pointer in 0th slot
-        iRegTable[KARRAY_INDEX_GETLOCATION] = activeGetLoc ;
+    if ( KErrNone == err )
+        {
+        iRegTable.Append(activeGetLoc);
         }
-        
-    else 
+    else
         {
-        delete activeGetLoc ;	//Clean up
-        }	
-
-    return err;	
+        delete activeGetLoc; //Clean up
+        User::Leave(err);
+        }
     }
 
 
@@ -262,42 +298,46 @@
  * Returns 0 on success and symbian specific error codes on failures
  */
 
-EXPORT_C TInt CLocationService :: TraceL( MLocationCallBack* aCallBackObj ,
-												TInt aLocationInfoCategory, 
-												TPositionFieldIdList aFiledList ,
-												const TPositionUpdateOptions* aUpateOptions )
+EXPORT_C void CLocationService :: TraceL( MLocationCallBack* aCallBackObj ,
+        TInt aLocationInfoCategory,
+        TPositionFieldIdList aFiledList ,
+        const TPositionUpdateOptions* aUpateOptions,
+        TBool aEnableHighAcc )
     {
-
-    if(iRegTable[KARRAY_INDEX_TRACE]) //Return Error to user is the reg table slot is not free
+    TPositionModuleId ModuleId;
+    if(aEnableHighAcc)
+        {
+        GetHighAccuracyModuleL(&ModuleId);
+        if(ModuleId.iUid == NULL)
+            {
+            User::Leave(KErrGeneral);
+            }
+        }
+    else
         {
-        if(iRegTable[KARRAY_INDEX_TRACE]->IsAdded())  
-            {
-            return KErrInUse ;            
-            }
-        //Reuse the existing inactive object
-        delete iRegTable[KARRAY_INDEX_TRACE]  ; //Activate this asynchronous job
-        iRegTable[KARRAY_INDEX_TRACE] = NULL ;
+        //Indicates that when opening the subsession ,moudleId need not be specified
+        ModuleId.iUid = 0;          
+        }
+    
+    CGetLoc* activeTrace = CGetLoc :: NewL(iPosServer ,
+            aFiledList ,
+            KTraceRequest,
+            aLocationInfoCategory,
+            ModuleId) ;
 
+    TInt ret = activeTrace->GetLocationUpdates(this,aCallBackObj , aUpateOptions);
+
+    if (ret == KErrNone)
+        {        
+        iRegTable.Append(activeTrace);
+        }
+    else
+        { 
+        //Cleanup the allocated object
+        delete activeTrace;
+        User::Leave(ret);
         }
 
-    CGetLoc *activeTrace = CGetLoc :: NewL(iPosServer ,
-                                           aFiledList , 
-                                           KTraceRequest,
-                                           aLocationInfoCategory) ;
-
-    TInt ret  = activeTrace->GetLocationUpdates(aCallBackObj , aUpateOptions) ;
-
-    if (ret == KErrNone)  
-        {
-        iIndex = KARRAY_INDEX_TRACE;	
-        iRegTable[KARRAY_INDEX_TRACE] = activeTrace ;
-        }
-    else
-        {         //Cleanup the allocated object
-        delete activeTrace ;
-        }	
-       
-    return ret;
     }
 
 /**
@@ -339,8 +379,29 @@
  * Synchronous function which returns users last known position
  */
 
-TInt CLocationService :: GetLastKnownLoc( TPosition& aResultPos )
+EXPORT_C TInt CLocationService :: GetLastKnownLoc( TPosition& aResultPos )
     {
+    TInt error = iPositioner.Open(iPosServer);
+
+
+    // The opening of a subsession failed
+    if ( KErrNone != error )
+        {
+        iPosServer.Close();
+        return error ;
+        }
+		
+    //setting identity for this requestor
+    error = iPositioner.SetRequestor( CRequestor::ERequestorService,
+            CRequestor::EFormatApplication,
+            KIdentity ) ;
+
+	  if ( KErrNone != error )
+        {
+        iPositioner.Close();
+        return error ;
+        }
+	
     TRequestStatus Status  = KRequestPending ;
     TPositionInfo  posinfo  ;
     TPositionInfoBase *posinfoBase =  &posinfo ;	
@@ -348,7 +409,8 @@
     iPositioner.GetLastKnownPosition(*posinfoBase,Status);
     User::WaitForRequest(Status);
     posinfo.GetPosition(aResultPos) ;
-
+    
+    iPositioner.Close();
     return Status.Int() ;
 
     }
@@ -363,24 +425,79 @@
     {
     if ( (aCancelparam == ECancelGetLocation ) || (aCancelparam == ECancelTrace))
         {
-        CGetLoc* ptr = iRegTable[aCancelparam];
-        if(iRegTable[aCancelparam])
+        TInt i;
+        for( i = 0; i< iRegTable.Count(); i++)
             {
-            if(iRegTable[aCancelparam]->IsAdded())
+            if(iRegTable[i] )
                 {
-                iRegTable[aCancelparam]->Deque() ;
-                }
-            if( ( aCancelparam == ECancelTrace ) )
-            	iRegTable[aCancelparam]->SetStatusComplete();
-            	delete iRegTable[aCancelparam] ;
-            iRegTable[aCancelparam] = NULL ;
-            return KErrNone;
-            }
-        return KErrNotFound ;
+
+                if((((iRegTable[i]->GetCallBackobj())->GetRequestType()) == 
+                KGetLocationReq) && (aCancelparam == ECancelGetLocation ))              
+                    {                  
+                    if(iRegTable[i]->IsAdded())
+                        {         
+                        iRegTable[i]->Deque();
+                        }
+
+
+                    delete iRegTable[i];
+                    iRegTable[i] = NULL;
+                    return KErrNone;
+                    }
 
+                else if ((((iRegTable[i]->GetCallBackobj())->GetRequestType()) == 
+                KTraceReq) &&  (aCancelparam == ECancelTrace ))
+                    {
+                    if(iRegTable[i]->IsAdded())
+                        {
+                        iRegTable[i]->Deque();
+                        }
+
+                    iRegTable[i]->SetStatusComplete();
+
+                    delete iRegTable[i];
+                    iRegTable[i] = NULL;
+                    return KErrNone;
+                    }
+                }  
+            }    
+        return KErrNotFound;
         }
 
     return KErrArgument;
-
     }
 
+/**
+ * CancelService : Cancels Requested asynchronous requests,
+ * Input : TransactionId returned by the Async request,
+ * Returns success(KErrNone) if service canceled or else error if 
+ * input parameter is invalid
+ */
+EXPORT_C TInt CLocationService::CancelService( TInt aTransId)
+    {
+    TInt i;
+    for( i = 0; i< iRegTable.Count(); i++)
+        {
+        if(iRegTable[i])
+            {
+            if(aTransId == 
+            (iRegTable[i]->GetCallBackobj())->GetTransactionId())
+                {
+                if(iRegTable[i]->IsAdded())
+                    {
+                    iRegTable[i]->Deque();
+                    }
+                if(((iRegTable[i]->GetCallBackobj())->GetRequestType()) == 
+                KTraceReq)
+                    {
+                    iRegTable[i]->SetStatusComplete();
+                    }
+                delete iRegTable[i];
+                iRegTable[i] = NULL;
+                return KErrNone;
+                }
+            }
+        }
+
+    return KErrNotFound;
+    }