common/tools/ats/smoketest/localisation/apparchitecture/apserv/APSSERV.CPP
changeset 793 0c32c669a39d
child 872 17498133d9ad
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/tools/ats/smoketest/localisation/apparchitecture/apserv/APSSERV.CPP	Fri Nov 27 12:22:12 2009 +0000
@@ -0,0 +1,1162 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Symbian Foundation License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+#include <e32svr.h>
+#include <u32hal.h>
+#include <bautils.h>
+#include "APSSERV.H"
+#include "APFREC.H"
+#include "APSSES.H"
+#include "APSSTD.H"
+#include "../apfile/aprfndr.h"
+#include "APGAPLST.H"
+#include "APSSCAN.H"
+#include "APSSTD.H"
+#include "APASVST.H"
+#include "datastor.h"
+#include "APSRECCACHE.h"
+#include "apsnnapps.h"
+#include "../apfile/apuninstallmonitor.h"
+#include "../apgrfx/apprivate.h"
+#include "apsiconcaptionoverride.h"
+
+_LIT(KAppArcServerSemaphore,"AppArcServerSemaphore");
+_LIT(KAppArcServerThread,"AppArcServerThread");
+_LIT(KAppRegistrationFileImportLocation, "?:\\private\\10003a3f\\import\\apps\\");
+_LIT(KAppResourceAppsLocation, "?:\\resource\\apps\\");
+_LIT(KNonNativeApplicationTypeRegistry, ":\\private\\10003a3f\\NonNativeTypes.dat");
+
+/*
+ * patchable const data values defined in ApsConstData.cpp
+ */
+
+IMPORT_C extern const TInt KApaLoadDataRecognizersOnDemand;
+IMPORT_C extern const TInt KApaUnloadRecognizersTimeout;
+IMPORT_C extern const TInt KApaDrivesToMonitor;
+IMPORT_C extern const TInt KApaLoadMbmIconsOnDemand;
+
+const TUint8 KPolicyElementWriteDeviceData = 0;
+
+//To monitor all drives.
+const TInt KApaMonitorAllDrives = 0x3FFFFFF;
+
+const TUint KRangeCount = 3; 
+
+const TInt KAppListServRanges[KRangeCount] = 
+	{	
+	EFirstUnrestrictedOpcodeInAppListServ,
+	EFirstOpcodeNeedingWriteDeviceDataInAppListServ, 
+	EAppListFirstUnusedOpcode,
+	};
+
+const TUint8 KElementsIndex[KRangeCount] =
+	{
+	CPolicyServer::EAlwaysPass,			//Always passing no capability required [0-99]
+	KPolicyElementWriteDeviceData,		//Requires WriteDeviceData				 [100-(EAppListFirstUnusedOpcode-1)]
+	CPolicyServer::ENotSupported, 		//Not Supported		[EAppListFirstUnusedOpcode-End]
+	};
+
+const CPolicyServer::TPolicyElement KPolicyElements[] = 
+	{ 
+	{_INIT_SECURITY_POLICY_C1(ECapabilityWriteDeviceData), CPolicyServer::EFailClient} 
+	};
+
+const CPolicyServer::TPolicy KApaServPolicy =
+	{
+	CPolicyServer::EAlwaysPass, 
+	KRangeCount,
+	KAppListServRanges,
+	KElementsIndex, 	
+	KPolicyElements 	
+	};
+ 	
+
+
+//////////////////////////////
+// CApaAppListServer
+//////////////////////////////
+
+const TInt KAppListServerPriority=CActive::EPriorityStandard;
+/**
+NameApaServStartSemaphore
+
+@internalTechnology
+*/
+EXPORT_C TPtrC NameApaServStartSemaphore()
+	{
+	TPtrC nameApaServStartSemaphore(KAppArcServerSemaphore);
+	return nameApaServStartSemaphore;
+	}
+
+/**
+NameApaServServerThread
+
+@internalTechnology 
+*/
+EXPORT_C TPtrC NameApaServServerThread()
+	{
+	TPtrC nameApaServServerThread(KAppArcServerThread);
+	return nameApaServServerThread;
+	}
+
+EXPORT_C CApaAppListServer* CApaAppListServer::Self()
+	{ // static
+	return static_cast<CApaAppListServer*>(Dll::Tls());
+	}
+
+EXPORT_C CApaAppListServer* CApaAppListServer::NewL(MApaAppStarter* aAppStarter)
+// Create a new CApaAppListServer which owns it's own resources
+	{
+	CApaAppListServer* self=new(ELeave) CApaAppListServer(KAppListServerPriority);
+	CleanupStack::PushL(self);
+	self->ConstructL(aAppStarter);
+	CleanupStack::Pop();
+	return self;
+	}
+
+CApaAppListServer::CApaAppListServer(TInt aPriority)
+	: CPolicyServer(aPriority,KApaServPolicy),
+	iAppList(0),
+	iTypeStoreModified(0),
+	iLoadRecognizersOnDemand(KApaLoadDataRecognizersOnDemand),
+	iLoadMbmIconsOnDemand(KApaLoadMbmIconsOnDemand)
+	{
+	
+	#ifdef __WINS__
+	// KApaLoadDataRecognizersOnDemand and KApaloadIconsOnDemand are Rom patchable constants,
+	// so need an emulator equivalent
+	// if WINS then read value from epoc.ini
+	// requires licencees to set property in epoc.ini
+
+	TInt halValue = 0;
+	if (UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty, (TAny*)"patchdata_apserv_dll_KApaLoadDataRecognizersOnDemand", &halValue) == KErrNone)
+		{
+		iLoadRecognizersOnDemand = halValue;
+		}
+	if (UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty, (TAny*)"patchdata_apserv_dll_KApaLoadMbmIconsOnDemand", &halValue) == KErrNone)
+		{
+		iLoadMbmIconsOnDemand = halValue;
+		}
+	#endif
+
+	__DECLARE_NAME(_S("CApaAppListServer"));
+	}
+
+void CApaAppListServer::ConstructL(MApaAppStarter* aAppStarter)
+	{
+	StartL(KAppListServerName);
+	User::LeaveIfError(Dll::SetTls(this));
+	User::LeaveIfError(iFs.Connect());
+	
+	iScanningFileRecognizer=CApaScanningFileRecognizer::NewL(iFs,aAppStarter);
+		
+	// Get the idle timeout delay from the commandline if specified. The default is 50000ms
+	const TInt cmdLineLen = User::CommandLineLength();
+	TInt idlePeriodicDelay=50000; //default value
+	if(cmdLineLen)
+		{
+		_LIT(KIdleTimeout,"IDLE_TIMEOUT_PERIODIC_DELAY_");
+		
+		// Extract the command line into a buffer
+		HBufC* cmdLine = HBufC::NewLC(cmdLineLen);
+		TPtr cmdLinePtr = cmdLine->Des();
+		User::CommandLine(cmdLinePtr);
+		cmdLinePtr.UpperCase();
+				
+		// Check if there is an idle timeout value given
+		TInt idleTimeOutArgPos = cmdLinePtr.Find(KIdleTimeout);
+		if(KErrNotFound != idleTimeOutArgPos)
+			{
+			// Extract the value out of the command line argument
+			const TInt idleTimeOutValuePos = idleTimeOutArgPos + KIdleTimeout().Length();
+			TInt i = idleTimeOutValuePos;
+			while (i < cmdLineLen)
+				{
+				TChar c(cmdLinePtr[i]);
+				if (!c.IsDigit())
+					{
+					break;
+					}
+				i++;
+				}
+			TLex idleTimeOutParser(cmdLinePtr.Mid(idleTimeOutValuePos, (i-idleTimeOutValuePos)));
+		  	User::LeaveIfError(idleTimeOutParser.Val(idlePeriodicDelay));	  					  	
+			}
+							
+		// Check if the recognition cache should be used or not. By default the cache is used
+		iRecognitionCache = 0;
+		_LIT(KWithoutRecognitionCache,"WITHOUT_RECOGNITION_CACHE");
+		if(KErrNotFound == cmdLinePtr.Find(KWithoutRecognitionCache))
+			{
+			iRecognitionCache = new (ELeave) CApsRecognitionCache(iFs);
+			}
+			
+		_LIT(KTextShellMode,"TEXT_SHELL_MODE");
+		if (KErrNotFound == cmdLinePtr.Find(KTextShellMode))
+			{
+			// We are NOT running in text shell mode so connect to wserv session
+			User::LeaveIfError(iWsSession.Connect());
+			iRuleBasedPlugIns = CApaScanningRuleBasedPlugIns::NewL();
+			}
+
+		CleanupStack::PopAndDestroy(cmdLine);		
+		}
+	else
+		{
+		// no arguments so cache is used
+		iRecognitionCache = new (ELeave) CApsRecognitionCache(iFs);
+		// and rule based plugins are enabled
+		User::LeaveIfError(iWsSession.Connect());
+		iRuleBasedPlugIns = CApaScanningRuleBasedPlugIns::NewL();
+		}
+	
+	CApaAppRegFinder* appRegFinder=CApaAppRegFinder::NewL(iFs); //non-standard transfer of ownership, no need for CleanupStack
+	iAppList=CApaAppList::NewL(iFs, appRegFinder, iLoadMbmIconsOnDemand, idlePeriodicDelay); // takes ownership of scanner
+
+	// If the phone rebooted halfway through processing updates, there will be a log file left
+	// look for one and recover if neccessary
+	CApsNonNativeApplicationsManager::RecoverFromUpdateLogL(iFs);
+
+	iDataRecognizer=CApaScanningDataRecognizer::NewL(iFs, !iLoadRecognizersOnDemand);
+
+	ConstructPathsToMonitorL();	
+
+	if ( iAppFsMonitor )
+		{
+		iAppFsMonitor->Start(ENotifyFile);
+		iAppFsMonitor->SetBlocked(ETrue);			
+		}
+	TRAP_IGNORE(iAppList->InitListL(this));
+	
+#ifdef USING_ECOM_RECOGS
+	iRecEcomMonitor=CApaEComMonitor::NewL(TCallBack(&PlugInNotifyCallBack,this));
+	iRecEcomMonitor->Start();
+#endif
+	iTypeStoreManager=CTypeStoreManager::NewL(iFs);
+	TRAPD(err,iTypeStoreManager->RestoreL());
+	if(err==KErrNone)
+		{
+		User::LeaveIfError(iFs.Modified(iTypeStoreManager->IniFileName(),iTypeStoreModified));
+		}
+	iTypeStoreMonitor=CApaFsMonitor::NewL(iFs,iTypeStoreManager->IniFileName(),TCallBack(&TypeStoreNotifyCallback,this));
+	iTypeStoreMonitor->Start(ENotifyWrite); // this presumably needs to be ENotifyWrite rather than ENotifyFile (the latter being used or the other CApaFsMonitor objects) because CTypeStoreManager internally uses CDictionaryFileStore::OpenL, which presumably itself uses RFile::Open, which isn't covered by ENotifyFile according to its documentation
+	TypeStoreNotifyCallback(this);
+	iBaBackupSessionWrapper=CBaBackupSessionWrapper::NewL();
+	iBaBackupSessionWrapper->RegisterBackupOperationObserverL(*((MBackupOperationObserver*)this));
+
+	TChar sysDrive = RFs::GetSystemDriveChar();
+	TInt maxSizeofFileName = KNonNativeApplicationTypeRegistry().Length() + 1;
+	iNonNativeApplicationTypeRegistry.CreateL(maxSizeofFileName);
+	iNonNativeApplicationTypeRegistry.Append(sysDrive);
+	iNonNativeApplicationTypeRegistry.Append(KNonNativeApplicationTypeRegistry());
+
+	TRAP_IGNORE(InternalizeNonNativeApplicationTypeArrayL());	// We don't want a corrupt file to prevent from starting
+	if(iLoadRecognizersOnDemand)
+		{
+		iRecognizerUnloadTimer=CPeriodic::NewL(EPriorityNormal);
+		}
+	iAppUnInstallMonitor = CApaAppUnInstallMonitor::NewL(this);
+	iAppUnInstallMonitor->Start();
+
+	iIconCaptionOverrides = new(ELeave) CApaIconCaptionOverrides();
+	iIconCaptionObserver = CApaIconCaptionCenrepObserver::NewL(*iIconCaptionOverrides);
+	iIconCaptionObserver->LoadOverridesL();
+	}
+	
+void CApaAppListServer::ConstructPathsToMonitorL()
+	{
+	TInt drivesToMonitor = KApaDrivesToMonitor;
+	#ifdef __WINS__
+	// KApaDrivesToMonitor is a Rom patchable constant, so need an emulator equivalent
+	// if WINS then read value from epoc.ini requires licencees to set property in epoc.ini
+	// Usage: In epoc.ini patchdata_apserv_dll_KApaDrivesToMonitor 4
+	
+	TInt valueOfKApaDrivesToMonitor = 0;
+	if (UserSvr::HalFunction(EHalGroupEmulator,EEmulatorHalIntProperty,(TAny*)"patchdata_apserv_dll_KApaDrivesToMonitor",&valueOfKApaDrivesToMonitor) == KErrNone)
+		{
+		drivesToMonitor = valueOfKApaDrivesToMonitor;
+		}
+	#endif
+	
+	if ( drivesToMonitor != KApaMonitorAllDrives )
+		{
+		// 1. Create and add CApaFsNotifier for all locations belonging to a drive if the drive is set to monitor.
+		// 2. Do this for all the drives which are required to monitor.
+		TInt maskBit = 1;
+		TChar driveLetter;
+		//Only bits from 0(EDriveA)- 25(EDriveZ) are valid other bits are ignored from 32-bit KApaDrivesToMonitor.
+		for ( TInt i = EDriveA; i <= EDriveZ; i++ )
+			{
+			if ( drivesToMonitor & maskBit )
+				{
+				RFs::DriveToChar(i,driveLetter);
+				RBuf pathToBeMonitored;
+				TBuf<1> drive;
+				drive.Append(driveLetter);
+				
+				//Creating or Adding <driveLetter>:\private\10003a3f\import\apps\ path to monitor.
+				pathToBeMonitored.CreateL(KAppRegistrationFileImportLocation());				
+				CleanupClosePushL(pathToBeMonitored);
+				pathToBeMonitored.Replace(0,1,drive);				
+				if ( iAppFsMonitor == NULL )
+					{
+					iAppFsMonitor=CApaFsMonitor::NewL(iFs, pathToBeMonitored, TCallBack(&AppFsNotifyCallBack, this));
+					}
+				else
+					{
+					iAppFsMonitor->AddLocationL(pathToBeMonitored);		
+					}
+				CleanupStack::PopAndDestroy(&pathToBeMonitored);
+			
+				//Adding <driveLetter>:\resource\apps\ path to monitor.
+				pathToBeMonitored.CreateL(KAppResourceAppsLocation());
+				CleanupClosePushL(pathToBeMonitored);
+				pathToBeMonitored.Replace(0,1,drive);			
+				iAppFsMonitor->AddLocationL(pathToBeMonitored);
+				CleanupStack::PopAndDestroy(&pathToBeMonitored);
+				}
+			maskBit = maskBit << 1;
+			}	
+		}
+	else
+		{
+		iAppFsMonitor=CApaFsMonitor::NewL(iFs, KAppRegistrationFileImportLocation, TCallBack(&AppFsNotifyCallBack, this));
+		iAppFsMonitor->AddLocationL(KAppResourceAppsLocation);
+		}	
+	}
+	
+EXPORT_C CApaAppListServer::~CApaAppListServer()
+	{
+	delete iIconCaptionObserver;
+	delete iIconCaptionOverrides;
+	if(iBaBackupSessionWrapper)
+		iBaBackupSessionWrapper->DeRegisterBackupOperationObserver(*this);
+	delete iAppUnInstallMonitor;
+	delete iScanningFileRecognizer;
+	delete iAppList; // deletes scanners
+	delete iDataRecognizer;
+	delete iTypeStoreManager;
+	delete iAppFsMonitor;	
+	delete iTypeStoreMonitor;
+	delete iBaBackupSessionWrapper;
+	delete iRecognitionCache;
+#ifdef USING_ECOM_RECOGS
+	delete iRecEcomMonitor;
+#else
+	iRecEcomMonitor = NULL;
+#endif
+	iFs.Close();
+	iAppCmdLine=NULL;
+	iWsSession.Close();	
+	delete 	iRuleBasedPlugIns;
+	for (TInt i=iNonNativeApplicationTypeArray.Count()-1; i>=0; --i)
+		{
+		delete iNonNativeApplicationTypeArray[i].iNativeExecutable;
+		}
+	iNonNativeApplicationTypeArray.Close();
+	iCustomAppList.ResetAndDestroy();
+	iCustomAppList.Close();
+	delete iRecognizerUnloadTimer;
+	iNonNativeApplicationTypeRegistry.Close();
+	}
+
+EXPORT_C void CApaAppListServer::HandleStartUninstallEvent()
+	{
+	if ( iAppFsMonitor )
+		{
+		iAppFsMonitor->SetBlocked(ETrue);	
+		}
+	AppList().StopScan();
+	}
+EXPORT_C void CApaAppListServer::HandleEndUninstallEventL()
+	{
+	if ( iAppFsMonitor )
+		{
+		iAppFsMonitor->SetBlocked(EFalse);	
+		}
+	AppList().RestartScanL();
+	}
+
+CSession2* CApaAppListServer::NewSessionL(const TVersion& aVersion,const RMessage2&/* aMessage*/) const
+
+// Create a new server session.
+	{
+	// check we're the right version
+	TVersion v(KAppListServMajorVersionNumber,KAppListServMinorVersionNumber,KAppListServBuildVersionNumber);
+	if (!User::QueryVersionSupported(v,aVersion))
+		User::Leave(KErrNotSupported);
+	// make new session
+	return CApaAppListServSession::NewL(const_cast<CApaAppListServer&>(*this), const_cast<RFs&>(iFs));
+	}
+
+//
+// scanning code here
+//
+
+EXPORT_C TCallBack CApaAppListServer::RescanCallBack()
+	{
+	return TCallBack(&AppFsNotifyWithForcedRegistrationsResetCallBack,this);
+	}
+
+TInt CApaAppListServer::AppFsNotifyWithForcedRegistrationsResetCallBack(TAny* aPtr)
+	{
+	ASSERT(aPtr);
+	reinterpret_cast<CApaAppListServer*>(aPtr)->AppList().ResetForcedRegistrations();
+	return AppFsNotifyCallBack(aPtr);
+	}
+
+TInt CApaAppListServer::AppFsNotifyCallBack(TAny* aObject)
+	{
+	ASSERT(aObject);
+	reinterpret_cast<CApaAppListServer*>(aObject)->UpdateApps();
+	return KErrNone;
+	}
+
+TInt CApaAppListServer::PlugInNotifyCallBack(TAny* aObject)
+	{
+	//update the pre-Platform-security style  recognizers and rule-based plug-ins
+	ASSERT(aObject);
+	reinterpret_cast<CApaAppListServer*>(aObject)->UpdatePlugIns();
+	return KErrNone;
+	}
+
+TInt CApaAppListServer::TypeStoreNotifyCallback(TAny* aObject)
+	{
+	ASSERT(aObject);
+	reinterpret_cast<CApaAppListServer*>(aObject)->UpdateTypeStore();
+	return KErrNone;
+	}
+
+void CApaAppListServer::UpdateApps()
+// update the list
+	{
+	// File system change, rescan
+	TRAP_IGNORE(iAppList->StartIdleUpdateL (this));
+	}
+
+void CApaAppListServer::NotifyUpdate(TInt aReason)
+// tell all sessions to update their clients
+	{
+	// Updates the applist with the icon caption details from the Central Repository.
+	TRAP_IGNORE(UpdateAppListByIconCaptionOverridesL());
+	// The short caption value sets through the API has got the highest precedence over the
+	// values found in either central repository or resource file.
+	TRAP_IGNORE(UpdateAppListByShortCaptionL());
+		
+    //Delete any data mappings in service registry related to uninstalled applications.
+    CArrayFixFlat<TUid>* uninstalledApps=iAppList->UninstalledAppArray();
+    TBool modificationStatus=EFalse;
+    TBool modified;
+    
+    if(uninstalledApps)
+        {
+        TInt count=uninstalledApps->Count();
+        for(int index=0;index<count;index++)
+            {
+            modified=iTypeStoreManager->DeleteApplicationDataMappings((*uninstalledApps)[index]);
+        
+            //Set modificationStatus if any data mapping is removed from the service registry
+            if(modified)
+                modificationStatus=ETrue;
+            }
+        
+        delete uninstalledApps;
+        
+        //If service registry is modified, store it to a file
+        if(modificationStatus)
+            TRAP_IGNORE(iTypeStoreManager->StoreL());
+        }
+    
+	// iterate through sessions
+	iSessionIter.SetToFirst();
+	CApaAppListServSession* ses=static_cast<CApaAppListServSession*>(&(*iSessionIter++));
+	while (ses!=NULL)
+		{
+		ses->NotifyClients(aReason);	
+		ses=static_cast<CApaAppListServSession*>(&(*iSessionIter++));
+		}
+	}
+
+void CApaAppListServer::UpdatePlugIns()
+// update the pre-Platform-security style, ecom style recognizers and rule-based plug-ins
+	{
+	TRAP_IGNORE(iScanningFileRecognizer->ScanForRecognizersL());
+	//we want the recognizers to be loaded either if:
+	// 1) they are not loaded on demand
+	// 2) they are loaded on demand and actively used
+	// 3) they are loaded on demand but waiting for the timer to be unloaded
+	if(!iLoadRecognizersOnDemand || iRecognizerUsageCount > 0 || (iRecognizerUnloadTimer && iRecognizerUnloadTimer->IsActive()))
+		{
+		TRAP_IGNORE(iDataRecognizer->LoadRecognizersL());
+		}
+	if (iRecognitionCache)
+		{	// RecognitionCache is flushed if there are any changes in plugins, i.e.,if:
+			// 1. New ECom Plugin is installed.
+			// 2. Existing ECom Plugin is uninstalled.
+		iRecognitionCache->Flush();
+		}
+
+	TRAP_IGNORE(iRuleBasedPlugIns->ScanForRuleBasedPlugInsL());
+	}
+
+void CApaAppListServer::UpdateTypeStore()
+// Update the internal type store if things have changed
+	{
+	TRAP_IGNORE(DoUpdateTypeStoreL());
+	}
+
+void CApaAppListServer::DoUpdateTypeStoreL()
+	{
+	TTime modified;
+	TInt err=iFs.Modified(iTypeStoreManager->IniFileName(),modified);
+	// check the time stamp to see if we are interested in an update
+	if (modified>iTypeStoreModified && err==KErrNone)
+		{
+		CTypeStoreManager* manager=CTypeStoreManager::NewL(iFs);
+		CleanupStack::PushL(manager);
+		manager->RestoreL();
+		iTypeStoreModified=modified;
+		delete iTypeStoreManager;
+		iTypeStoreManager=manager;
+		CleanupStack::Pop(manager); 
+		}
+	for (iSessionIter.SetToFirst(); ; iSessionIter++) //lint !e1757 prefix operator not defined for TDblQueIter
+		{
+     	CSession2* const session=iSessionIter;
+     	if (session==NULL)
+			{
+  			break;
+			}
+     	static_cast<CApaAppListServSession*>(session)->NotifyClientOfDataMappingChange();
+		}
+	}
+
+void CApaAppListServer::HandleBackupOperationEventL(const TBackupOperationAttributes& aBackupOperationAttributes)
+//
+// Handle a signal from the backup server to indicate that a backup has started or finished.
+//
+	{
+	switch(aBackupOperationAttributes.iOperation)
+		{
+	case MBackupOperationObserver::ENone:
+	case MBackupOperationObserver::EAbort:
+		break;
+	case MBackupOperationObserver::EStart:
+		if ( iAppFsMonitor )
+			{
+			iAppFsMonitor->SetBlocked(ETrue);	
+			}
+		break;
+	case MBackupOperationObserver::EEnd:
+		if ( iAppFsMonitor )
+			{
+			iAppFsMonitor->SetBlocked(EFalse);	
+			}
+		break;
+	default:
+		Panic(EEventFromBackupObserverError);
+		break;
+		}
+	}
+
+void CApaAppListServer::InitialListPopulationComplete()
+	{
+	if ( iAppFsMonitor )
+		{
+		iAppFsMonitor->SetBlocked(EFalse);	
+		}
+	
+	// notify clients (whoever is interested) that initial population of list is completed
+	iSessionIter.SetToFirst();
+	CApaAppListServSession* ses=static_cast<CApaAppListServSession*>(&(*iSessionIter++));
+	// iterate through sessions
+	while (ses!=NULL)
+		{
+		ses->NotifyClientForCompletionOfListPopulation();	
+		ses=static_cast<CApaAppListServSession*>(&(*iSessionIter++));
+		}
+	}
+
+void CApaAppListServer::RegisterNonNativeApplicationTypeL(TUid aApplicationType, const TDesC& aNativeExecutable)
+	{
+	for (TInt i=iNonNativeApplicationTypeArray.Count()-1; i>=0; --i)
+		{
+		if (iNonNativeApplicationTypeArray[i].iTypeUid.iUid==aApplicationType.iUid)
+			{
+			User::Leave(KErrAlreadyExists);
+			}
+		}
+	SNonNativeApplicationType nonNativeApplicationType;
+	nonNativeApplicationType.iTypeUid.iUid=aApplicationType.iUid;
+	nonNativeApplicationType.iNativeExecutable=aNativeExecutable.AllocLC();
+	iNonNativeApplicationTypeArray.AppendL(nonNativeApplicationType);
+	CleanupStack::Pop(nonNativeApplicationType.iNativeExecutable);
+	CleanupStack::PushL(TCleanupItem(DeleteLastNonNativeApplicationType, this));
+	ExternalizeNonNativeApplicationTypeArrayL();
+	CleanupStack::Pop(this); // the TCleanupItem
+	}
+
+void CApaAppListServer::DeregisterNonNativeApplicationTypeL(TUid aApplicationType)
+	{
+	TInt i;
+	for (i=iNonNativeApplicationTypeArray.Count()-1; i>=0; --i)
+		{
+		if (iNonNativeApplicationTypeArray[i].iTypeUid.iUid==aApplicationType.iUid)
+			{
+			break;
+			}
+		}
+	if (i>=0)
+		{
+		ExternalizeNonNativeApplicationTypeArrayL(i);
+		delete iNonNativeApplicationTypeArray[i].iNativeExecutable;
+		iNonNativeApplicationTypeArray[i].iNativeExecutable = NULL;
+		iNonNativeApplicationTypeArray.Remove(i);
+		}
+	}
+
+void CApaAppListServer::InternalizeNonNativeApplicationTypeArrayL()
+	{
+	RFile file;
+	CleanupClosePushL(file);
+	const TInt error=file.Open(iFs, iNonNativeApplicationTypeRegistry, EFileShareReadersOnly|EFileStream|EFileRead);
+	if (error==KErrNone) // don't leave if the file can't be opened (because it doesn't exist, or because the directory we're looking for it in doesn't exist)
+		{
+		RFileReadStream sourceStream;
+		sourceStream.Attach(file); // file gets closed by this call, but that's okay, we don't need it any more (sourceStream has its own copy of this RFile object that it owns)
+		CleanupClosePushL(sourceStream);
+		TCardinality arrayCount;
+		arrayCount.InternalizeL(sourceStream);
+		for (TInt i=0; i<TInt(arrayCount); ++i)
+			{
+			SNonNativeApplicationType nonNativeApplicationType;
+			nonNativeApplicationType.iTypeUid.iUid=sourceStream.ReadUint32L();
+			nonNativeApplicationType.iNativeExecutable=HBufC::NewLC(sourceStream, KMaxFileName);
+			iNonNativeApplicationTypeArray.AppendL(nonNativeApplicationType);
+			CleanupStack::Pop(nonNativeApplicationType.iNativeExecutable);
+			}
+		CleanupStack::PopAndDestroy(&sourceStream);
+		}
+	CleanupStack::PopAndDestroy(&file);
+	}
+
+void CApaAppListServer::ExternalizeNonNativeApplicationTypeArrayL(TInt aIndexToIgnore/*=-1*/) const
+	{
+	RFs& fs=const_cast<RFs&>(iFs);
+	fs.MkDirAll(iNonNativeApplicationTypeRegistry); // ignore any error
+	RFile file;
+	CleanupClosePushL(file);
+	User::LeaveIfError(file.Replace(fs, iNonNativeApplicationTypeRegistry, EFileShareExclusive|EFileStream|EFileWrite));
+	RFileWriteStream targetStream;
+	targetStream.Attach(file); // file gets closed by this call, but that's okay, we don't need it any more (targetStream has its own copy of this RFile object that it owns)
+	CleanupClosePushL(targetStream);
+	const TInt arrayCount(iNonNativeApplicationTypeArray.Count());
+	TInt arrayCountToExternalize=arrayCount;
+	if (aIndexToIgnore>=0)
+		{
+		--arrayCountToExternalize;
+		}
+	TCardinality(arrayCountToExternalize).ExternalizeL(targetStream);
+	for (TInt i=0; i<arrayCount; ++i)
+		{
+		if (i!=aIndexToIgnore)
+			{
+			const SNonNativeApplicationType& nonNativeApplicationType=iNonNativeApplicationTypeArray[i];
+			targetStream.WriteUint32L(nonNativeApplicationType.iTypeUid.iUid);
+			targetStream << *nonNativeApplicationType.iNativeExecutable;
+			}
+		}
+	targetStream.CommitL();
+	CleanupStack::PopAndDestroy(2, &file);
+	}
+
+TPtrC CApaAppListServer::NativeExecutableL(TUid aNonNativeApplicationType) const
+	{
+	for (TInt i=iNonNativeApplicationTypeArray.Count()-1; i>=0; --i)
+		{
+		const SNonNativeApplicationType& nonNativeApplicationType=iNonNativeApplicationTypeArray[i];
+		if (nonNativeApplicationType.iTypeUid.iUid==aNonNativeApplicationType.iUid)
+			{
+			return *nonNativeApplicationType.iNativeExecutable;
+			}
+		}
+	User::Leave(KErrNotSupported); // not KErrNotFound
+	return KNullDesC();
+	}
+
+void CApaAppListServer::DeleteLastNonNativeApplicationType(TAny* aThis)
+	{ // static
+	CApaAppListServer& self=*static_cast<CApaAppListServer*>(aThis);
+	const TInt arrayIndex=self.iNonNativeApplicationTypeArray.Count()-1;
+	delete self.iNonNativeApplicationTypeArray[arrayIndex].iNativeExecutable;
+	self.iNonNativeApplicationTypeArray[arrayIndex].iNativeExecutable = NULL;
+	self.iNonNativeApplicationTypeArray.Remove(arrayIndex);
+	}
+
+void CApaAppListServer::NotifyScanComplete()
+	{
+	// Updates the applist with the icon caption details from the Central Repository.
+	TRAP_IGNORE(UpdateAppListByIconCaptionOverridesL());
+	// The short caption value sets through the API has got the highest precedence over the
+	// values found in either central repository or resource file.		
+	TRAP_IGNORE(UpdateAppListByShortCaptionL());
+
+	// iterate through sessions
+	iSessionIter.SetToFirst();
+	CApaAppListServSession* ses=static_cast<CApaAppListServSession*>(&(*iSessionIter++));
+	while (ses!=NULL)
+		{
+		ses->NotifyScanComplete();	
+		ses=static_cast<CApaAppListServSession*>(&(*iSessionIter++));
+		}
+	}
+
+void CApaAppListServer::AddCustomAppInfoInListL(CCustomAppInfoData* aCustomAppInfo)
+	{
+	TBool replaced=EFalse;
+	for (TInt i=iCustomAppList.Count()-1; i>=0; --i)
+		{
+		if ((aCustomAppInfo->Uid()==iCustomAppList[i]->Uid()) && (aCustomAppInfo->Language()==iCustomAppList[i]->Language()))
+			{
+			CCustomAppInfoData* oldAppInfo = iCustomAppList[i];
+			iCustomAppList[i]=aCustomAppInfo;
+			delete oldAppInfo;
+			replaced=ETrue;
+			break;
+			}
+		}
+	//Add ELangNone items at the end and others at the beginning
+	if(!replaced)
+		{
+		if(aCustomAppInfo->Language()==ELangNone)
+			{
+			iCustomAppList.AppendL(aCustomAppInfo);
+			}
+		else
+			{
+			iCustomAppList.InsertL(aCustomAppInfo,0);
+			}
+		}
+	
+	} //lint !e818 Suppress pointer parameter could be declared as pointing to const - this method takes ownership
+
+
+void CApaAppListServer::UpdateAppListByShortCaptionL()
+	{
+	CApaAppData* app=NULL;
+	//Items with ELangNone are always found at the end and other languages at the beginning
+	//While iterating from end to beginning, we overwrite short caption set by ELangNone if there is any provided for the application language
+	for (TInt i=iCustomAppList.Count()-1; i>=0; --i)
+		{
+		const CCustomAppInfoData* const customAppInfo=iCustomAppList[i];
+		app=iAppList->AppDataByUid(customAppInfo->Uid());
+		if ( app && ((app->ApplicationLanguage()==customAppInfo->Language()) || (customAppInfo->Language()==ELangNone)))
+			{
+			app->SetShortCaptionL(*customAppInfo->ShortCaption());
+			}
+		}
+	}
+
+void CApaAppListServer::UpdateAppListByIconCaptionOverridesL()
+	{
+	// get the language downgrade path, so that most appropriate language can be used
+	RArray<TLanguage> languageDowngradePath;
+	CleanupClosePushL(languageDowngradePath);
+	BaflUtils::GetDowngradePathL(iFs, User::Language(), languageDowngradePath);
+	for (CApaAppData* app = iAppList->FirstApp(); app; app = iAppList->NextApp(app))
+		{
+		CApaIconCaptionOverridesForApp* appOverride = iIconCaptionOverrides->OverrideForApp(app->AppEntry().iUidType[2]);
+		if (appOverride)
+			{
+			TApaIconCaptionOverrideReader overrideReader = appOverride->Reader(languageDowngradePath);
+			const TDesC* shortCaption = overrideReader.ShortCaption();
+			if (shortCaption)
+				app->SetShortCaptionL(*shortCaption);
+			const TDesC* caption = overrideReader.Caption();
+			if (caption)
+				app->SetCaptionL(*caption);
+			const TDesC* iconFileName = overrideReader.IconFileName();
+			if (overrideReader.NumIconsSet() && iconFileName)
+				app->SetIconsL(*iconFileName, overrideReader.NumIcons());
+			}
+		}
+	CleanupStack::PopAndDestroy(&languageDowngradePath);
+	}
+
+CCustomAppInfoData* CCustomAppInfoData::NewL(TUid aAppUid, TLanguage aLanguage, const TDesC& aShortCaption)
+	{
+	CCustomAppInfoData* self=new(ELeave) CCustomAppInfoData(aAppUid, aLanguage);
+    CleanupStack::PushL(self);
+	self->ConstructL(aShortCaption);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CCustomAppInfoData::~CCustomAppInfoData()
+	{
+	delete iShortCaption;
+	}
+
+CCustomAppInfoData::CCustomAppInfoData(TUid aAppUid, TLanguage aLanguage)
+	:iUid(aAppUid),
+	iLanguage(aLanguage)
+	{
+	}
+
+void CCustomAppInfoData::ConstructL(const TDesC& aShortCaption)
+	{
+	iShortCaption=aShortCaption.AllocL();
+	}
+
+/*
+ * Data Recognizer calls
+ */
+ 
+TBool CApaAppListServer::CachedRecognitionResult(const TParseBase& aParser, TDataRecognitionResult& aResult) const
+	{
+	if(iRecognitionCache && aParser.PathPresent() && aParser.NamePresent())
+		{
+		return iRecognitionCache->Get(aParser.DriveAndPath(), aParser.NameAndExt(), aResult);
+		}
+	return EFalse;
+	}
+
+/**
+N.B. The @c CRecognitionResult object is reference counted so it must be closed!
+*/
+CRecognitionResult* CApaAppListServer::CachedRecognitionResult(const RFile& aFile, const TParseBase& aParser) const
+	{
+	if(iRecognitionCache && aParser.PathPresent() && aParser.NamePresent())
+		{
+		return iRecognitionCache->Get(aFile, aParser.DriveAndPath(), aParser.NameAndExt());
+		}
+	return NULL;
+	}
+
+void CApaAppListServer::CacheRecognitionResultL(const TParseBase& aParser, const TDataRecognitionResult& aResult)
+	{
+	if(iRecognitionCache && aParser.PathPresent() && aParser.NamePresent())
+		{
+		iRecognitionCache->AddL(aParser.DriveAndPath(), aParser.NameAndExt(), aResult);
+		}
+	}
+
+void CApaAppListServer::CacheRecognitionResultL(const RFile& aFile, const TParseBase& aParser, const TDataRecognitionResult& aResult)
+	{
+	if(iRecognitionCache && aParser.PathPresent() && aParser.NamePresent())
+		{
+		iRecognitionCache->AddL(aFile, aParser.DriveAndPath(), aParser.NameAndExt(), aResult);
+		}
+	}
+
+TDataRecognitionResult CApaAppListServer::RecognizeDataL(const TDesC& aName, const TDesC8& aBuffer)
+	{
+	TParsePtrC parser(iFs.IsValidName(aName) ? aName : KNullDesC);
+	TDataRecognitionResult result;
+	
+	// check cache	
+	if(!CachedRecognitionResult(parser, result))
+		{
+		// recognize
+		if(iLoadRecognizersOnDemand)
+			{
+			LoadRecognizersLC();
+			}
+		result = iDataRecognizer->RecognizeL(aName, aBuffer);
+		if(iLoadRecognizersOnDemand)
+			{
+			CleanupStack::PopAndDestroy();
+			}
+
+		// add to cache
+		CacheRecognitionResultL(parser, result);
+		}
+	
+	return result;	
+	}
+
+TDataRecognitionResult CApaAppListServer::RecognizeDataL(RFile& aFile, TInt aPreferredBufSize)
+	{
+	CRecognitionResult* result = RecognizeDataAsCRecognitionResultL(aFile, aPreferredBufSize);
+	TDataRecognitionResult ret;
+	result->Get(ret);
+	result->Close();
+	return ret;
+	}
+
+/**
+Same as @c RecognizeDataL(RFile&, TInt) but returns a @c CRecognitionResult 
+instead of a @c TDataRecognitionResult.
+
+N.B. The @c CRecognitionResult object is reference counted so it must be closed!
+*/
+CRecognitionResult* CApaAppListServer::RecognizeDataAsCRecognitionResultL(RFile& aFile, TInt aPreferredBufSize)
+	{
+	CRecognitionResult* result = NULL;
+	
+	TFileName fileName;
+	User::LeaveIfError(aFile.FullName(fileName));
+	TParsePtrC parser(fileName); //fileName is valid since it comes from RFile
+
+	//check cache
+	result = CachedRecognitionResult(aFile,parser);
+	if(!result)
+		{
+		// recognize
+		if(iLoadRecognizersOnDemand)
+			{
+			LoadRecognizersLC();
+			}
+		const TDataRecognitionResult recResult = iDataRecognizer->RecognizeL(aFile, aPreferredBufSize);
+		if(iLoadRecognizersOnDemand)
+			{
+			CleanupStack::PopAndDestroy();
+			}
+		
+		//add to cache
+		CacheRecognitionResultL(aFile, parser, recResult);
+
+		result = CRecognitionResult::NewL(parser.NameAndExt(), recResult);
+		}
+	
+	return result;
+	}
+
+TBool CApaAppListServer::RecognizeDataL(const TDesC& aName, const TDesC8& aBuffer, const TDataType& aDataType)
+	{
+	if(iLoadRecognizersOnDemand)
+		{
+		LoadRecognizersLC();
+		}
+	const TBool ret = iDataRecognizer->RecognizeL(aName,aBuffer,aDataType);
+	if(iLoadRecognizersOnDemand)
+		{
+		CleanupStack::PopAndDestroy();
+		}
+	return ret;
+	}
+
+TBool CApaAppListServer::RecognizeDataL(RFile& aFile, TInt aPreferredBufSize, const TDataType& aDataType)
+	{
+	if(iLoadRecognizersOnDemand)
+		{
+		LoadRecognizersLC();
+		}
+	const TBool ret = iDataRecognizer->RecognizeL(aFile,aPreferredBufSize,aDataType);
+	if(iLoadRecognizersOnDemand)
+		{
+		CleanupStack::PopAndDestroy();
+		}
+	return ret;
+	}
+
+TInt CApaAppListServer::DataRecognizerPreferredBufSizeL()
+	{
+	if(iLoadRecognizersOnDemand)
+		{
+		LoadRecognizersLC();
+		}
+	const TInt ret = iDataRecognizer->PreferredBufSize();
+	if(iLoadRecognizersOnDemand)
+		{
+		CleanupStack::PopAndDestroy();
+		}
+	return ret;
+	}
+
+void CApaAppListServer::DataTypeL(CDataTypeArray& aArray)
+	{
+	if(iLoadRecognizersOnDemand)
+		{
+		LoadRecognizersLC();
+		}
+	iDataRecognizer->DataTypeL(aArray);
+	if(iLoadRecognizersOnDemand)
+		{
+		CleanupStack::PopAndDestroy();
+		}
+	}
+
+/*
+ * Recognizer loading/unloading code
+ */
+
+void CApaAppListServer::LoadRecognizersLC()
+	{
+	ASSERT(iLoadRecognizersOnDemand);
+
+	LoadRecognizersL();
+	TCleanupItem cleanup(CApaAppListServer::RecognizerCleanup, this);
+	CleanupStack::PushL(cleanup);
+	}
+
+void CApaAppListServer::RecognizerCleanup(TAny* aSelf)
+	{
+	if (aSelf)
+		{
+		static_cast<CApaAppListServer*>(aSelf)->UnloadRecognizers();
+		}
+	}
+
+void CApaAppListServer::LoadRecognizersL()
+	{
+	ASSERT(iLoadRecognizersOnDemand);
+
+	if(iRecognizerUnloadTimer->IsActive())
+		{
+		__ASSERT_DEBUG(iRecognizerUsageCount==0,Panic(EReferenceCountingError1));
+		iRecognizerUnloadTimer->Cancel();
+		}
+	else if(iRecognizerUsageCount==0)
+		{
+		iDataRecognizer->LoadRecognizersL();
+		}
+
+	++iRecognizerUsageCount;
+	}
+
+TInt CApaAppListServer::UnloadRecognizers()
+	{
+	ASSERT(iLoadRecognizersOnDemand);
+
+	--iRecognizerUsageCount;
+	__ASSERT_DEBUG(iRecognizerUsageCount>=0,Panic(EReferenceCountingError2));
+	if (iRecognizerUsageCount==0)
+		{
+		iRecognizerUnloadTimer->Start(KApaUnloadRecognizersTimeout,0,TCallBack(CApaAppListServer::DoUnloadRecognizersCallback,this));
+		}
+	return KErrNone;
+	}
+	
+TInt CApaAppListServer::DoUnloadRecognizersCallback(TAny* aSelf)
+	{
+	TInt ret=KErrNone;
+	if (aSelf)
+		{
+		ret = static_cast<CApaAppListServer*>(aSelf)->DoUnloadRecognizers();
+		}
+	return ret;
+	}
+
+TInt CApaAppListServer::DoUnloadRecognizers()
+	{
+	ASSERT(iLoadRecognizersOnDemand);
+
+	// need to cancel the periodic timer since we only want a oneshot timer
+	iRecognizerUnloadTimer->Cancel();
+	iDataRecognizer->UnloadRecognizers();
+	return KErrNone;
+	}
+	
+void CApaAppListServer::GetAppByDataType(const TDataType& aDataType, TUid& aUid) const
+	{
+	iTypeStoreManager->GetAppByDataType(aDataType, aUid);
+	}
+	
+void CApaAppListServer::GetAppByDataType(const TDataType& aDataType, TUid aServiceUid, TUid& aUid) const
+	{
+	iTypeStoreManager->GetAppByDataType(aDataType, aServiceUid, aUid);
+	}
+	
+TBool CApaAppListServer::InsertAndStoreIfHigherL(const TDataType& aDataType, TDataTypePriority aPriority, TUid aUid)
+	{
+	return iTypeStoreManager->InsertAndStoreIfHigherL(aDataType, aPriority, aUid);
+	}
+	
+void CApaAppListServer::InsertAndStoreDataMappingL(const TDataType& aDataType, TDataTypePriority aPriority, TUid aUid, TUid aServiceUid)
+	{
+	iTypeStoreManager->InsertAndStoreDataMappingL(aDataType, aPriority, aUid, aServiceUid);
+	}
+	
+void CApaAppListServer::DeleteAndStoreDataMappingL(const TDataType& aDataType, TUid aServiceUid)
+	{
+	iTypeStoreManager->DeleteAndStoreDataMappingL(aDataType, aServiceUid);
+	}
+	
+CApaFileRecognizer* CApaAppListServer::FileRecognizer()
+	{ 
+	return static_cast<CApaFileRecognizer*>(iScanningFileRecognizer); 
+	}
+
+TBool CApaAppListServer::LoadMbmIconsOnDemand() const
+	{
+	return iLoadMbmIconsOnDemand;
+	}
+
+#ifdef _DEBUG
+
+/**
+Flushes the recognition cache.
+
+Useful for debugging.
+*/
+void CApaAppListServer::FlushRecognitionCache()
+	{
+	if(iRecognitionCache)
+		iRecognitionCache->Flush();
+	}
+
+/**
+Sets whether or not recognizers should be loaded when they are needed.
+
+Useful for debugging.
+*/	
+void CApaAppListServer::SetLoadRecognizersOnDemandL(TBool aLoadRecognizersOnDemand)
+	{
+	if(iLoadRecognizersOnDemand == aLoadRecognizersOnDemand)
+		return;
+	
+	CPeriodic* newUnloadTimer;
+	if(aLoadRecognizersOnDemand)
+		{
+		ASSERT(!iRecognizerUnloadTimer);
+		newUnloadTimer = CPeriodic::NewL(EPriorityNormal);
+		}
+	else
+		{
+		ASSERT(iRecognizerUnloadTimer);
+		newUnloadTimer = NULL;
+		}
+	CleanupStack::PushL(newUnloadTimer);
+	
+	CApaScanningDataRecognizer* newDataRecognizer = CApaScanningDataRecognizer::NewL(iFs,!aLoadRecognizersOnDemand);
+	delete iDataRecognizer;
+	iDataRecognizer = newDataRecognizer;
+	
+	delete iRecognizerUnloadTimer;
+	iRecognizerUnloadTimer = newUnloadTimer;
+	CleanupStack::Pop(newUnloadTimer);
+	
+	iRecognizerUsageCount = 0;
+	iLoadRecognizersOnDemand = aLoadRecognizersOnDemand;	
+	}
+
+/**
+If recognizers are set to be loaded on demand this method can be used to perform
+the unloading synchronously, instead of waiting for the unloading timer to go off.
+
+Useful for debugging.
+*/
+void CApaAppListServer::PerformOutstandingRecognizerUnloading()
+	{
+	if(iLoadRecognizersOnDemand && iRecognizerUnloadTimer->IsActive())
+		{
+		__ASSERT_DEBUG(iRecognizerUsageCount==0,Panic(EReferenceCountingError3));
+		DoUnloadRecognizers();
+		}
+	}
+
+#endif //_DEBUG