appfw/apparchitecture/aplist/aplapplist.cpp
changeset 0 2e3d3ce01487
child 29 6a787171e1de
child 62 924385140d98
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // aplapplist.cpp
       
    15 //
       
    16 
       
    17 #include "aplapplist.h"
       
    18 #include "APGAPLST.H"			// KDefaultAppIconMbm
       
    19 #include "aplapplistitem.h"
       
    20 #include "../apgrfx/APGSTD.H"	// EPanicNullPointer
       
    21 #include "APFDEF.H"
       
    22 #include "../apparc/TRACE.H"
       
    23 #include "apgnotif.h"			// MApaAppListServObserver
       
    24 #include "aplappregfinder.h"	// CApaAppRegFinder
       
    25 #include <bautils.h>			// BaflUtils::NearestLanguageFile()
       
    26 #include <s32mem.h>				// RBufWriteStream
       
    27 #include "aplappinforeader.h"
       
    28 #include "apsiconcaptionoverride.h"
       
    29 #ifdef SYMBIAN_BAFL_SYSUTIL
       
    30 #include <bafl/sysutil.h>
       
    31 #endif
       
    32 
       
    33 
       
    34 // Delays in the pseudo idle object that builds the application list
       
    35 //
       
    36 
       
    37 const TInt KIdleStartDelay=0;
       
    38 const TInt KBufferExpansionGranularity = 0x100;
       
    39 const TInt KNumberOfIconsInDefaultMbm = 3;
       
    40 const TInt KAppListToFileStartDelay = 60000000;
       
    41 #ifdef SYMBIAN_BAFL_SYSUTIL
       
    42 const TInt KInfoBufLength=KSysUtilVersionTextLength;
       
    43 //This file is used for storing the rom version. If actual rom version differs from the one stored here the applist is not restored.
       
    44 //This file is versioned to avoid a data compatability break on adding further information to this file.
       
    45 //On adding further info to this file, KROMVersionCacheFileMajorVersion or KROMVersionCacheFileMinorVersion or KROMVersionCacheFileBuildVersion needs to be incremented appropriately.
       
    46 _LIT(KROMVersionStringCacheFileName, "ROMVersionCache.bin");
       
    47 const TInt8 KROMVersionCacheFileMajorVersion=1;
       
    48 const TInt8 KROMVersionCacheFileMinorVersion=0;
       
    49 const TInt16 KROMVersionCacheFileBuildVersion=0;
       
    50 #endif
       
    51 
       
    52 
       
    53 GLDEF_C void Panic(TApgPanic aPanic)
       
    54 	{
       
    55 	_LIT(KApGrfxPanic,"APGRFX");
       
    56 	User::Panic(KApGrfxPanic,aPanic);
       
    57 	}
       
    58 
       
    59 
       
    60 //
       
    61 // Class CApaLangChangeMonitor
       
    62 //
       
    63 
       
    64 /**
       
    65 Utility class used to monitor locale/language change event.
       
    66 @internalComponent
       
    67 */
       
    68 NONSHARABLE_CLASS(CApaAppList::CApaLangChangeMonitor) : public CActive
       
    69 	{
       
    70 public:
       
    71 	static CApaLangChangeMonitor* NewL(CApaAppList& aAppList);
       
    72 	~CApaLangChangeMonitor();
       
    73 	void Start();
       
    74 private:
       
    75 	CApaLangChangeMonitor(CApaAppList& aAppList);
       
    76 	void ConstructL();
       
    77 private:	//from CActive
       
    78 	void RunL();
       
    79 	void DoCancel();
       
    80 	TInt RunError(TInt aError);
       
    81 private:
       
    82 	RChangeNotifier iLangNotifier;
       
    83 	CApaAppList& iAppList;
       
    84 	TLanguage iPrevLanguage;
       
    85 	};
       
    86 
       
    87 		
       
    88 //
       
    89 // Local functions
       
    90 //
       
    91 
       
    92 void CleanupServiceArray(TAny* aServiceArray)
       
    93 	{
       
    94 	__ASSERT_DEBUG(aServiceArray, Panic(EPanicNullPointer));
       
    95 	CArrayFixFlat<TApaAppServiceInfo>* serviceArray = static_cast<CArrayFixFlat<TApaAppServiceInfo>*>(aServiceArray);
       
    96 	const TInt serviceCount = serviceArray->Count();
       
    97 	
       
    98 	for (TInt i = serviceCount - 1; i >= 0; i--)
       
    99 		(*serviceArray)[i].Release();
       
   100 
       
   101 	delete serviceArray;
       
   102 	serviceArray = 0;
       
   103 	}
       
   104 
       
   105 
       
   106 //
       
   107 // Class CApaAppList
       
   108 //
       
   109 
       
   110 EXPORT_C CApaAppList* CApaAppList::NewL(RFs& aFs, TBool aLoadMbmIconsOnDemand, TInt aIdlePeriodicDelay)
       
   111 	{
       
   112 	CApaAppList* self=new (ELeave) CApaAppList(aFs, aLoadMbmIconsOnDemand, aIdlePeriodicDelay);
       
   113 	CleanupStack::PushL(self);
       
   114 	self->ConstructL();
       
   115 	CleanupStack::Pop(self);
       
   116 	return self;
       
   117 	}
       
   118 
       
   119 CApaAppList::CApaAppList(RFs& aFs, TBool aLoadMbmIconsOnDemand, TInt aIdlePeriodicDelay)
       
   120 	:iFs(aFs),
       
   121 	iFlags(0),
       
   122 	iIdlePeriodicDelay(aIdlePeriodicDelay),
       
   123 	iLoadMbmIconsOnDemand(aLoadMbmIconsOnDemand),
       
   124     iUninstalledApps(NULL)	
       
   125 	{
       
   126 	}
       
   127 
       
   128 void CApaAppList::ConstructL()
       
   129 	{
       
   130 	iAppRegFinder = CApaAppRegFinder::NewL(iFs);
       
   131 	
       
   132 	User::LeaveIfError(iFsShareProtected.Connect());
       
   133 	User::LeaveIfError(iFsShareProtected.ShareProtected());
       
   134 	User::LeaveIfError(Dll::SetTls(this));
       
   135 	
       
   136 	//Start language change monitor.
       
   137 	iAppLangMonitor = CApaLangChangeMonitor::NewL(*this);
       
   138 	const TInt KArrayGranularity = 128;
       
   139 	iForcedRegistrations = new (ELeave) CDesCArraySeg(KArrayGranularity);
       
   140 	
       
   141 	// Init the AppsList cache paths
       
   142 	_LIT(KAppsListCacheFileName, ":\\private\\10003a3f\\AppsListCache\\AppsList.bin");
       
   143 	_LIT(KAppsListCacheBackUpFileName, ":\\private\\10003a3f\\AppsListCache\\AppsList_Backup.bin");
       
   144 	_LIT(KAppsListCachePath, ":\\private\\10003a3f\\AppsListCache\\");
       
   145 
       
   146 	const TChar sysDrive = RFs::GetSystemDriveChar();
       
   147 	TInt maxSizeofFileName = KAppsListCacheFileName().Length() + 1;
       
   148 	iAppsListCacheFileName.CreateL(maxSizeofFileName);
       
   149 	iAppsListCacheFileName.Append(sysDrive);
       
   150 	iAppsListCacheFileName.Append(KAppsListCacheFileName());
       
   151 	
       
   152 	maxSizeofFileName = KAppsListCacheBackUpFileName().Length() + 1;
       
   153 	iAppsListCacheBackUpFileName.CreateL(maxSizeofFileName);
       
   154 	iAppsListCacheBackUpFileName.Append(sysDrive);
       
   155 	iAppsListCacheBackUpFileName.Append(KAppsListCacheBackUpFileName());
       
   156 	
       
   157 	maxSizeofFileName = KAppsListCachePath().Length() + 1;
       
   158 	iAppsListCachePath.CreateL(maxSizeofFileName);
       
   159 	iAppsListCachePath.Append(sysDrive);
       
   160 	iAppsListCachePath.Append(KAppsListCachePath());
       
   161 	
       
   162 	iIconCaptionOverrides = new(ELeave) CApaIconCaptionOverrides();
       
   163 	iIconCaptionObserver = CApaIconCaptionCenrepObserver::NewL(*iIconCaptionOverrides);
       
   164 	iIconCaptionObserver->LoadOverridesL();
       
   165 	}
       
   166 	
       
   167 EXPORT_C CApaAppList::~CApaAppList()
       
   168 /** Frees all resources prior to destruction, including the application data list. */
       
   169 	{
       
   170 	iValidFirstAppData = NULL;
       
   171 	DeleteAppData();
       
   172 
       
   173 	iAppData = NULL;
       
   174 	iObserver = NULL;
       
   175 	iFsShareProtected.Close();
       
   176 
       
   177 	delete iDefaultIconArray;
       
   178 	delete iDefaultAppIconMbmFileName;
       
   179 	delete iAppRegFinder;
       
   180 	delete iAppIdler;
       
   181 	delete iAppListStorer;
       
   182 	delete iAppIconLoader;
       
   183 	delete iAppLangMonitor;
       
   184 	delete iForcedRegistrations;
       
   185 	delete iIconCaptionObserver;
       
   186 	delete iIconCaptionOverrides;
       
   187 	iAppsListCacheFileName.Close();
       
   188 	iAppsListCacheBackUpFileName.Close();
       
   189 	iAppsListCachePath.Close();
       
   190 	
       
   191 	iCustomAppList.ResetAndDestroy();
       
   192 	iCustomAppList.Close();
       
   193 	}
       
   194 
       
   195 // Stop scanning applications if installation or uninstallation has started	
       
   196 EXPORT_C void CApaAppList::StopScan(TBool aNNAInstall)
       
   197 	{
       
   198 	if (aNNAInstall)
       
   199 		{
       
   200 		iNNAInstallation = ETrue;
       
   201 		}
       
   202 	if (iAppIdler)
       
   203 		{
       
   204 		delete iAppIdler;
       
   205 		iAppIdler=NULL;
       
   206 		}
       
   207 	UndoSetPending(iAppData);
       
   208 	}
       
   209 	
       
   210 // Allow scanning when installation or uninstallation is complete
       
   211 EXPORT_C void CApaAppList::RestartScanL()
       
   212 	{
       
   213 	TRAP_IGNORE(PurgeL());
       
   214 	StartIdleUpdateL();
       
   215 	}
       
   216 
       
   217 EXPORT_C TBool CApaAppList::AppListUpdatePending()
       
   218 	{
       
   219 	return iNNAInstallation;
       
   220 	}
       
   221 
       
   222 void CApaAppList::UndoSetPending(CApaAppData* aAppData)
       
   223 	// Reset all apps to pevious pending state so they don't get purged
       
   224 	{
       
   225   	for (; aAppData; aAppData = aAppData->iNext)
       
   226 		{
       
   227 		if (aAppData->iIsPresent == CApaAppData::EPresentPendingUpdate)
       
   228 			{
       
   229 			aAppData->iIsPresent = CApaAppData::EIsPresent;
       
   230 			}
       
   231 		}
       
   232 	}
       
   233 
       
   234 EXPORT_C void CApaAppList::StartIdleUpdateL()
       
   235 /** Updates the list asynchronously, using an idle time active object, 
       
   236 and no observer. When the update is finished, the resulting app 
       
   237 list is stored. */
       
   238 	{
       
   239 	// find the default icons (.mbm file) for applications, wrt current locale
       
   240 	CreateDefaultAppIconFileNameL();
       
   241 
       
   242 	// File operation is abandoned if it is in progress.
       
   243 	if (iAppListStorer && iAppListStorer->IsActive())
       
   244 		{
       
   245 		delete iAppListStorer;
       
   246 		iAppListStorer = NULL;
       
   247 		}
       
   248 
       
   249 	// Stops icon loading if it is in progress.
       
   250 	if (iAppIconLoader && iAppIconLoader->IsActive())
       
   251 		{
       
   252 		delete iAppIconLoader;
       
   253 		iAppIconLoader = NULL;
       
   254 		}
       
   255 
       
   256 	// DEF076594 - if changing locale, need to update the default icons here
       
   257 	// If updating the default icons array fails, the array is left in the state
       
   258 	// it was in before the call.
       
   259 	if(iDefaultIconArray)
       
   260 		{
       
   261 		TRAP_IGNORE(UpdateDefaultIconsL());
       
   262 		}
       
   263 
       
   264 	// start to scan.
       
   265 	if (iAppIdler)
       
   266 		{
       
   267 		delete iAppIdler;
       
   268 		iAppIdler=NULL;
       
   269 		}
       
   270 		
       
   271 	// DEF072701
       
   272 	// When performing the update scan let the idle object have lower priority.
       
   273 	if (IsFirstScanComplete())
       
   274 		{
       
   275 		iAppIdler=CPeriodic::NewL(CActive::EPriorityLow);
       
   276 		}
       
   277 	else
       
   278 		{
       
   279 		iAppIdler=CPeriodic::NewL(CActive::EPriorityStandard);
       
   280 		}
       
   281 	SetPending(iAppData);
       
   282 	iAppRegFinder->FindAllAppsL(CApaAppRegFinder::EScanAllDrives);
       
   283  
       
   284  	// DEF072701
       
   285  	// If this is the first scan i.e the boot scan then it may take some time. Thus
       
   286  	// the periodic delay value should be used so that this process will stop periodically 
       
   287  	// to allow time for other processes.
       
   288  	// If this is just a re-scan it should take much less time. Therefore it should just
       
   289  	// be completed in one go rather than periodically delayed. Thus the delay value
       
   290  	// should be set to 0.
       
   291 	iAppIdler->Start(KIdleStartDelay, IsFirstScanComplete()? 0 : iIdlePeriodicDelay, TCallBack(IdleUpdateCallbackL, this));
       
   292 	}
       
   293 
       
   294 EXPORT_C void CApaAppList::StartIdleUpdateL(MApaAppListObserver* aObserver)
       
   295 /** Updates the list asynchronously, using an idle time active object 
       
   296 and an observer. When the update is finished, the resulting app list 
       
   297 is stored and the observer is notified with an MApaAppListServObserver::EAppListChanged 
       
   298 message, if the list changed.
       
   299 @param aObserver Observer to be notified when the update has finished. */
       
   300 	{
       
   301 	iObserver=aObserver;
       
   302 
       
   303 	// Rename Appslist.bin file to AppsList_Backup.bin, so that it can be renamed back, if rescan/update scan does not change applist.
       
   304 	TInt replaceError = iFs.Replace(iAppsListCacheFileName, iAppsListCacheBackUpFileName);
       
   305 	if (replaceError != KErrNone)
       
   306 		{
       
   307 		iFs.Delete(iAppsListCacheFileName);
       
   308 		}
       
   309 	StartIdleUpdateL();
       
   310 	}
       
   311 
       
   312 void CApaAppList::CreateDefaultAppIconFileNameL()
       
   313 	{
       
   314 	TFileName tempFileName(KDefaultAppIconMbm);
       
   315 	TLanguage language;
       
   316 	BaflUtils::NearestLanguageFileV2(iFs, tempFileName, language);
       
   317 	(void)language;
       
   318 	delete iDefaultAppIconMbmFileName;
       
   319 	iDefaultAppIconMbmFileName = NULL;
       
   320 	iDefaultAppIconMbmFileName = tempFileName.AllocL();
       
   321 	}
       
   322 
       
   323 EXPORT_C void CApaAppList::InitListL(MApaAppListObserver* aObserver)
       
   324 /** It Restores the data present in the AppsList.bin file and updates the applist. 
       
   325  * If Restore operation fails then it 
       
   326  * starts updating the list asynchronously, by calling StartIdleUpdateL().
       
   327 
       
   328 @param aObserver Observer to be notified when the update has finished. */
       
   329 	{
       
   330 	DeleteAppsListBackUpAndTempFiles();
       
   331 	TInt ret = KErrGeneral;
       
   332 #ifndef __WINS__ // on the emulator, don't read app list from file, as doing so means apps
       
   333                  // built while the emulator isn't running won't appear in the list
       
   334 	TRAP(ret, RestoreL());
       
   335 #endif
       
   336 	if (ret != KErrNone)
       
   337 		{
       
   338 		// There was an error during restore, so update the list asynchronously.
       
   339 		DeleteAppData();
       
   340 		iFs.Delete(iAppsListCacheFileName);
       
   341 		StartIdleUpdateL(aObserver);
       
   342 		}
       
   343 	else
       
   344 		{
       
   345 		iObserver = aObserver;
       
   346 		if (iLoadMbmIconsOnDemand)
       
   347 			{
       
   348 			InitiateStoringOfAppList();
       
   349 			}
       
   350 		else
       
   351 			{
       
   352 			StartIconLoadingL();
       
   353 			}
       
   354 		}
       
   355 	}
       
   356 
       
   357 void CApaAppList::StartIconLoadingL()
       
   358 	{
       
   359 	iAppIconLoader = new(ELeave) CApaIdleIconLoader(iAppData, iFs, *this);
       
   360 	iAppIconLoader->Start();
       
   361 	}
       
   362 
       
   363 void CApaAppList::ScanRemovableDrivesAndUpdateL()
       
   364 /** Rename Appslist.bin file to AppsList_Backup.bin, so that it can be renamed back, 
       
   365      if the update scan on removable media drives does not change applist. */
       
   366 	{
       
   367 	const TArray<const TDriveUnitInfo> listOfRemovableMediaDrives = iAppRegFinder->DriveList();
       
   368 	const TInt count = listOfRemovableMediaDrives.Count();
       
   369 
       
   370 	// Removable media scan would take place only if removable drives are present.
       
   371 	if (count)
       
   372 		{
       
   373 		CApaAppData* appData = iAppData;
       
   374 		while (appData)
       
   375 			{
       
   376 			for (TInt driveIndex = 0; driveIndex < count; ++driveIndex)
       
   377 				{
       
   378 				if (TParsePtrC(*appData->iRegistrationFile).Drive() == listOfRemovableMediaDrives[driveIndex].iUnit.Name())
       
   379 					{
       
   380 					appData->SetAppPending();
       
   381 					break;
       
   382 					}
       
   383 				}
       
   384 			appData = appData->iNext;
       
   385 			}
       
   386 
       
   387 		while (IdleUpdateL())
       
   388 			{ // It updates the removable media apps present in AppList if it has changed.
       
   389 
       
   390 			};
       
   391 		}
       
   392 	}
       
   393 
       
   394 void CApaAppList::DeleteAppsListBackUpAndTempFiles()
       
   395 /** Deletes all files inside AppsListCache folder except AppsList.bin */
       
   396 	{
       
   397 	_LIT(KTemp, "AppsList.bin");
       
   398 	CDir* cache = NULL;
       
   399 	TInt ret = iFs.GetDir(iAppsListCachePath, KEntryAttNormal, ESortNone, cache);
       
   400 	if (ret == KErrNone)
       
   401 		{
       
   402 		const TInt count = cache->Count();
       
   403 		TBufC<KMaxFileName> cacheFileName;
       
   404 		TEntry entry;
       
   405 		for (TInt i = 0; i < count; ++i)
       
   406 			{
       
   407 			entry=(*cache)[i];
       
   408 			cacheFileName=entry.iName;
       
   409 	#if defined (SYMBIAN_BAFL_SYSUTIL)
       
   410 			if ((cacheFileName.Match(KTemp) == KErrNotFound) && (cacheFileName.Match(KROMVersionStringCacheFileName) == KErrNotFound)) 
       
   411 	#else
       
   412 			if ((cacheFileName.Match(KTemp) == KErrNotFound)) 
       
   413 	#endif
       
   414 				{
       
   415 				TFileName fileNameToDelete;
       
   416 				fileNameToDelete.Append(iAppsListCachePath);
       
   417 				fileNameToDelete.Append(cacheFileName);
       
   418 				iFs.Delete(fileNameToDelete);
       
   419 				}
       
   420 			}
       
   421 		delete cache;
       
   422 		}
       
   423 	}
       
   424 
       
   425 void CApaAppList::RestoreL()
       
   426 /** It restores the data present in the AppsList.bin file */
       
   427 	{
       
   428 	RFileReadStream theReadStream;
       
   429 	User::LeaveIfError(theReadStream.Open(iFs, iAppsListCacheFileName, EFileRead));
       
   430 	CleanupClosePushL(theReadStream);
       
   431 	
       
   432 	TLanguage appListFileLanguage = (TLanguage)theReadStream.ReadInt32L();
       
   433 	if (appListFileLanguage != User::Language())
       
   434 		{
       
   435 		User::Leave(KErrNotSupported);
       
   436 		}
       
   437 	
       
   438 #if defined (SYMBIAN_BAFL_SYSUTIL)
       
   439 	//Build the filename for the cache file
       
   440 	TInt maxSizeofFileName = iAppsListCachePath.Length() + KROMVersionStringCacheFileName().Length();
       
   441 	RBuf romVersionCacheFileName;
       
   442 	romVersionCacheFileName.CreateL(maxSizeofFileName);
       
   443 	romVersionCacheFileName.CleanupClosePushL();
       
   444 	romVersionCacheFileName.Append(iAppsListCachePath);
       
   445 	romVersionCacheFileName.Append(KROMVersionStringCacheFileName());
       
   446 	
       
   447 	RFileReadStream romVerStream;
       
   448 	User::LeaveIfError(romVerStream.Open(iFs,romVersionCacheFileName,EFileRead));
       
   449 	CleanupClosePushL(romVerStream);
       
   450 	
       
   451 	TVersion actualROMVersionCacheFileVersion(KROMVersionCacheFileMajorVersion, KROMVersionCacheFileMinorVersion, KROMVersionCacheFileBuildVersion);
       
   452 	TVersionName actualROMVersionCacheFileVersionName = actualROMVersionCacheFileVersion.Name();
       
   453 	
       
   454 	//read the rom file version
       
   455 	TInt8 romVersionCacheFileMajorVersion = romVerStream.ReadInt8L();
       
   456 	TInt8 romVersionCacheFileMinorVersion = romVerStream.ReadInt8L();
       
   457 	TInt16 romVersionCacheFileBuildVersion = romVerStream.ReadInt16L();
       
   458 	TVersion romVersionCacheFileVersion(romVersionCacheFileMajorVersion, romVersionCacheFileMinorVersion, romVersionCacheFileBuildVersion);
       
   459 	TVersionName romVersionCacheFileVersionName = romVersionCacheFileVersion.Name();
       
   460 	
       
   461 	//If persisted file version differs from what apparc can handle, recreate rom version file and applist.bin
       
   462 	if (romVersionCacheFileVersionName.Compare(actualROMVersionCacheFileVersionName) != 0)
       
   463 		{
       
   464 		User::Leave(KErrGeneral);
       
   465 		}
       
   466 		
       
   467 	//Read the length & value of software version from it.
       
   468 	TBuf<KInfoBufLength> softwareVersion;
       
   469 	TUint32 length = romVerStream.ReadUint32L();
       
   470 	if (length>KInfoBufLength)
       
   471 		{
       
   472 		//File must be corrupt, an attempt to read will panic
       
   473 		User::Leave(KErrCorrupt);
       
   474 		}	
       
   475 	romVerStream.ReadL(softwareVersion, length);
       
   476 
       
   477 	//the persisted version has been successfully read
       
   478 	//read the actual current version string
       
   479 	TBuf<KInfoBufLength> actualSoftwareVersion;
       
   480 	TInt err = SysUtil::GetSWVersion(actualSoftwareVersion); //use the SysUtil implementation
       
   481 	if(err == KErrNone)
       
   482 		{
       
   483 		if (softwareVersion.Compare(actualSoftwareVersion) != 0)
       
   484 			{
       
   485 			//Leave if the current version is different from the previous stored version and recreate applist.
       
   486 #ifdef _DEBUG
       
   487 			RDebug::Print(_L("!!Firmware update detected!! Rebuilding AppList"));
       
   488 #endif
       
   489 			User::Leave(KErrGeneral);
       
   490 			}
       
   491 		}
       
   492 	else
       
   493 		{
       
   494 		//Leave if any error reading the version information, except if file is not present
       
   495 		if (err != KErrPathNotFound && err != KErrNotFound)
       
   496 			{
       
   497 #ifdef _DEBUG
       
   498 			RDebug::Print(_L("!!Error %d reading Firmware version.  Rebuilding AppList"),err);
       
   499 #endif
       
   500 			User::Leave(err);
       
   501 			}
       
   502 		}
       
   503 	CleanupStack::PopAndDestroy(2); //romVerStream, romVersionCacheFileName
       
   504 #endif
       
   505 		
       
   506 	// Create Default Icon File Name
       
   507 	CreateDefaultAppIconFileNameL();
       
   508 	
       
   509 	TInt ret = KErrNone;
       
   510 	while (ret == KErrNone)
       
   511 		{
       
   512 		CApaAppData* const pApp = new (ELeave) CApaAppData(iFs);
       
   513 		CleanupStack::PushL(pApp);
       
   514 
       
   515 		// Restore entries till we leave
       
   516 		TRAP(ret, pApp->InternalizeL(theReadStream));
       
   517 		
       
   518 		if (ret != KErrNone && ret != KErrEof)
       
   519 			{
       
   520 			User::Leave(ret);
       
   521 			}
       
   522 		// Check that the app has not been added to the list twice
       
   523 		if (ret == KErrNone && !AppDataByUid(pApp->iUidType[2]))
       
   524 			{
       
   525 			AddToList(pApp);
       
   526 			CleanupStack::Pop(pApp);
       
   527 			}
       
   528 		else
       
   529 			{ // Delete pApp if an End of File condition is reached or the app has been added to the list twice
       
   530 			CleanupStack::PopAndDestroy(pApp);
       
   531 			}
       
   532 		}	
       
   533 	// Close the stream;
       
   534 	CleanupStack::PopAndDestroy(&theReadStream);
       
   535 
       
   536 	iFs.Rename(iAppsListCacheFileName, iAppsListCacheBackUpFileName);
       
   537 	iAppRegFinder->FindAllAppsL(CApaAppRegFinder::EScanRemovableDrives);	// Builds the Removable Media Drive List
       
   538 
       
   539 	iFlags |= ENotifyUpdateOnFirstScanComplete;
       
   540 
       
   541 	// It runs an update scan on removable media apps.
       
   542 	ScanRemovableDrivesAndUpdateL();
       
   543 	}
       
   544 
       
   545 EXPORT_C TBool CApaAppList::IsLanguageChangePending() const
       
   546 /** Returns ETrue if a language change event is received and a re-scan is in progress otherwise EFalse. */
       
   547 	{
       
   548 	return (iFlags & ELangChangePending);
       
   549 	}
       
   550 
       
   551 
       
   552 TInt CApaAppList::IdleUpdateCallbackL(TAny* aObject)
       
   553 	{
       
   554 	CApaAppList* self=REINTERPRET_CAST(CApaAppList*,aObject);
       
   555 	const TBool moreToCome=self->IdleUpdateL();
       
   556 	if (moreToCome==EFalse)
       
   557 		{
       
   558 		//Reset language change flag if scanning is over.
       
   559 		if (self->IsLanguageChangePending())
       
   560 			self->iFlags &= ~ELangChangePending;
       
   561 
       
   562 		self->StopIdler();
       
   563 		if (self->iLoadMbmIconsOnDemand)
       
   564 			{
       
   565 			self->InitiateStoringOfAppList();
       
   566 			}
       
   567 		else
       
   568 			{
       
   569 			self->StartIconLoadingL();
       
   570 			}
       
   571 		}
       
   572 	return moreToCome;
       
   573 	}
       
   574 
       
   575 void CApaAppList::StoreL()
       
   576 	{
       
   577 	iAppListStorer = CApaAppListStorer::NewL(iAppData, iFs, *this);
       
   578 	iAppListStorer->StartL(KAppListToFileStartDelay);
       
   579 	}
       
   580 
       
   581 void CApaAppList::NotifyObserver()
       
   582 	{
       
   583 	if (iObserver)
       
   584 		{
       
   585 		if (iFlags & EAppListHasChanged || iFlags & ENotifyUpdateOnFirstScanComplete)
       
   586 			iObserver->NotifyUpdate(MApaAppListServObserver::EAppListChanged);	// NotifyUpdate will notify clients for both list update and scan complete.
       
   587 		else
       
   588 			iObserver->NotifyScanComplete();	// NotifyScanComplete will notify clients for scan complete.
       
   589 
       
   590 		iObserver=NULL;
       
   591 		}
       
   592 	}
       
   593 
       
   594 void CApaAppList::StopIdler()
       
   595 	{
       
   596  	delete iAppIdler;
       
   597 	iAppIdler=NULL;
       
   598 	}
       
   599 
       
   600 TInt CApaAppList::IdleUpdateL()
       
   601 // returns ETrue if there is more scanning to be done.
       
   602 	{
       
   603 	TBool more=EFalse;
       
   604 	TApaAppEntry currentApp = TApaAppEntry();
       
   605 	TRAPD(err, more = iAppRegFinder->NextL(currentApp, *iForcedRegistrations));
       
   606 	if (err!=KErrNone)
       
   607 		{
       
   608 		if (iFlags & ENotifyUpdateOnFirstScanComplete)
       
   609 			User::Leave(err);
       
   610 
       
   611 		return more;
       
   612 		}
       
   613 	TBool hasChanged=EFalse;
       
   614 	if (more)
       
   615 		{
       
   616 		TRAPD(err,UpdateNextAppL(currentApp,hasChanged));
       
   617 		if (err!=KErrNone)
       
   618 			{
       
   619 			SetNotFound(iAppData,hasChanged);
       
   620 			if (iFlags & ENotifyUpdateOnFirstScanComplete)
       
   621 				User::Leave(err);
       
   622 
       
   623 			more=EFalse; // abandon ship
       
   624 			}
       
   625 		}
       
   626 	else
       
   627 		{
       
   628 		SetNotFound(iAppData,hasChanged);
       
   629 		PurgeL();
       
   630 		}
       
   631 
       
   632 	if (hasChanged)
       
   633 		iFlags |= EAppListHasChanged;
       
   634 
       
   635 	return more;
       
   636 	}
       
   637 
       
   638 EXPORT_C TBool CApaAppList::IsIdleUpdateComplete() const
       
   639 /** Tests whether an asynchronous update of the list is currently in progress.
       
   640 
       
   641 @return True if no asynchronous update of the list is currently in progress, 
       
   642 otherwise false. */
       
   643 	{
       
   644 	return iAppIdler == NULL;
       
   645 	}
       
   646 
       
   647 void CApaAppList::SetPending(CApaAppData* aAppData)
       
   648 	// set all apps to pending update - we'll find them again as we scan
       
   649 	{
       
   650   	for (; aAppData; aAppData = aAppData->iNext)
       
   651 		aAppData->SetAppPending();
       
   652 	}
       
   653 
       
   654 void CApaAppList::SetNotFound(CApaAppData* aAppData, TBool& aHasChanged)
       
   655 	// mark any unfound apps not present
       
   656 	{
       
   657 	while (aAppData)
       
   658 		{
       
   659 		if (aAppData->IsPending())
       
   660 			{
       
   661 			aAppData->iIsPresent = CApaAppData::ENotPresent;
       
   662 			aHasChanged = ETrue;
       
   663 			}
       
   664 		aAppData = aAppData->iNext;
       
   665 		}
       
   666 	}
       
   667 
       
   668 void CApaAppList::AddToList( CApaAppData* aAppData )
       
   669 	{
       
   670 	__ASSERT_DEBUG(aAppData, Panic(EPanicNullPointer));
       
   671 	aAppData->iNext=iAppData;
       
   672 	iAppData=aAppData;
       
   673 	}
       
   674 
       
   675 void CApaAppList::UpdateNextAppL(const TApaAppEntry& aAppEntry,TBool& aHasChanged)
       
   676 	{
       
   677 	CApaAppData* appData=AppDataByUid(aAppEntry.iUidType[2]);
       
   678 	if (appData==NULL)
       
   679 		{// not in list, so add it at the start
       
   680 		TRAPD(err,appData=CApaAppData::NewL(aAppEntry, iFs));
       
   681 		if (err==KErrNone)
       
   682 			{
       
   683 			AddToList( appData );
       
   684 			aHasChanged=ETrue;
       
   685 			}
       
   686 		}
       
   687 	else if (appData->IsPending())
       
   688 		{ // not found yet during current scan - we may need to override this one
       
   689 		
       
   690 		// On a system which scans for registration .RSC files (V2 apps) first, followed by
       
   691 		// .APP files (V1 apps), it's valid for a V1 app to override a V2 app (if the V2 app
       
   692 		// has just been removed). If this is the case, assume it's ok to compare the V1 .APP filename,
       
   693 		// with the V2 .RSC filename as their filenames will never match (which is what we want in this case).
       
   694 		TPtrC currentFileName;
       
   695 		if (appData->RegistrationFileUsed())
       
   696 			currentFileName.Set(*appData->iRegistrationFile);
       
   697 		else
       
   698 			currentFileName.Set(*appData->iFullName);
       
   699 	
       
   700 		if (aAppEntry.iFullName.CompareF(currentFileName)!=0)
       
   701 			{
       
   702 			delete appData->iSuccessor;
       
   703 			appData->iSuccessor = NULL;
       
   704 			appData->iSuccessor = CApaAppEntry::NewL(aAppEntry);
       
   705 
       
   706 			appData->iIsPresent = CApaAppData::ESuperseded;
       
   707 			aHasChanged=ETrue;
       
   708 			}
       
   709 		else
       
   710 			{
       
   711 			if (appData->Update() || appData->iIsPresent==CApaAppData::ENotPresentPendingUpdate) 
       
   712 				aHasChanged=ETrue; 
       
   713 
       
   714 			appData->iIsPresent = CApaAppData::EIsPresent;
       
   715 			}
       
   716 		}
       
   717 	}
       
   718 
       
   719 /**
       
   720 @internalComponent
       
   721 */
       
   722 EXPORT_C CApaAppData* CApaAppList::FindAndAddSpecificAppL(CApaAppRegFinder* aFinder, TUid aAppUid)
       
   723 	{
       
   724 //Scans and adds the specified application to the app list if found
       
   725 	__ASSERT_DEBUG(aFinder, Panic(EPanicNullPointer));
       
   726 	TBool found = EFalse;
       
   727 	TApaAppEntry appEntry;
       
   728 	aFinder->FindAllAppsL(CApaAppRegFinder::EScanAllDrives);
       
   729 	while (aFinder->NextL(appEntry, *iForcedRegistrations))
       
   730 		{
       
   731 		if (appEntry.iUidType[2] == aAppUid)
       
   732 			{
       
   733 			found = ETrue;
       
   734 			break;
       
   735 			}
       
   736 		}
       
   737 	
       
   738 	CApaAppData* app = NULL;
       
   739 	if (found)
       
   740 		{
       
   741 		// add the app to the list
       
   742 		TBool hasChanged = EFalse;
       
   743 		CApaAppData* prevFirstAppInList = iAppData;
       
   744 		UpdateNextAppL(appEntry, hasChanged);
       
   745 		if (iAppData != prevFirstAppInList)
       
   746 			app = iAppData;		// assume the new app was added to the list
       
   747 
       
   748 		if (hasChanged)
       
   749 			iFlags |= EAppListHasChanged;
       
   750 		}
       
   751 
       
   752 	return app;
       
   753 	}
       
   754 
       
   755 EXPORT_C void CApaAppList::PurgeL()
       
   756 /** Removes any applications from the list if they are no longer present 
       
   757 on the phone. It updates applications that have been 
       
   758 superceded. */
       
   759 	{
       
   760 	CApaAppData* appData=iAppData;
       
   761 	CApaAppData* prev=NULL;
       
   762 	while (appData)
       
   763 		{
       
   764 		CApaAppData* next=appData->iNext;
       
   765 		if (appData->iIsPresent==CApaAppData::ENotPresent)
       
   766 			{
       
   767 			if (prev)
       
   768 				prev->iNext=next;
       
   769 			else
       
   770 				iAppData=next;
       
   771 			
       
   772             //Add uninstalled application UID to a list
       
   773             if(iUninstalledApps==NULL)
       
   774                 iUninstalledApps=new(ELeave) CArrayFixFlat<TUid>(1);
       
   775             
       
   776             iUninstalledApps->AppendL(appData->AppEntry().iUidType[2]);
       
   777 			
       
   778 			delete appData;
       
   779 			}
       
   780 		else if (appData->iIsPresent==CApaAppData::ESuperseded)
       
   781 			{
       
   782 			CApaAppData* newApp=NULL;
       
   783 			TApaAppEntry appEntry;
       
   784 			appData->iSuccessor->Get(appEntry);
       
   785 			TRAPD(err,newApp=CApaAppData::NewL(appEntry, iFs));
       
   786 			if (err==KErrNone)
       
   787 				{
       
   788 				// remove the old one and add the new one in its place
       
   789 				if (prev)
       
   790 					prev->iNext=newApp;
       
   791 				else
       
   792 					iAppData=newApp;
       
   793 		
       
   794 				newApp->iNext = appData->iNext;
       
   795 				delete appData;
       
   796 				// increment the iterator
       
   797 				prev = newApp;
       
   798 				}
       
   799 			}
       
   800 		else
       
   801 			prev=appData;
       
   802 		
       
   803 		appData=next;
       
   804 		}
       
   805 	}
       
   806 
       
   807 EXPORT_C TInt CApaAppList::Count() const
       
   808 /** Gets the count of applications present in the app list.
       
   809 
       
   810 @return The number of applications in the list. */
       
   811 
       
   812 	{
       
   813 	TInt count=0;
       
   814 	CApaAppData* appData=iAppData;
       
   815 	while (appData)
       
   816 		{
       
   817 		count++;
       
   818 		appData=appData->iNext;
       
   819 		}
       
   820 	
       
   821 	return count;
       
   822 	}
       
   823 
       
   824 EXPORT_C CApaAppData* CApaAppList::FirstApp() const
       
   825 /** Gets a pointer to the first application in the list 
       
   826 that can use the default screen mode.
       
   827 
       
   828 @return A pointer to the first application. */
       
   829 	{
       
   830 	return FirstApp(0);
       
   831 	}
       
   832 
       
   833 EXPORT_C CApaAppData* CApaAppList::FirstApp(TInt aScreenMode) const
       
   834 /** Gets a pointer to the first application in the list 
       
   835 that can use the specified screen mode.
       
   836 
       
   837 @param aScreenMode The index of the screen mode. Specifying 
       
   838 KIgnoreScreenMode returns the first application in the list, 
       
   839 regardless of screen mode.
       
   840 @return A pointer to the first application that can use the 
       
   841 specified screen mode. */
       
   842 	{
       
   843 
       
   844 	CApaAppData* appData=iValidFirstAppData;
       
   845 
       
   846 	if(aScreenMode!=KIgnoreScreenMode)
       
   847 		{
       
   848 		while (appData && !appData->CanUseScreenMode(aScreenMode))
       
   849 			appData = appData->iNext;
       
   850 		}
       
   851 
       
   852 	return appData;
       
   853 	}
       
   854 
       
   855 EXPORT_C CApaAppData* CApaAppList::NextApp(const CApaAppData* aApp) const
       
   856 /** Gets a pointer to the next application after aApp in the list 
       
   857 that can use the default screen mode.
       
   858 
       
   859 @param aApp A pointer to an application in the list.
       
   860 @return A pointer to the next application after aApp in the list 
       
   861 that can use the default screen mode.
       
   862 @panic APGRFX 12 aApp is NULL. */
       
   863 	{
       
   864 	return NextApp(aApp,0);
       
   865 	}
       
   866 
       
   867 EXPORT_C CApaAppData* CApaAppList::NextApp(const CApaAppData* aApp, TInt aScreenMode) const
       
   868 /** Gets a pointer to the next application after aApp in the list 
       
   869 that can use the specified screen mode.
       
   870 
       
   871 @param aApp A pointer to an application in the list. 
       
   872 @param aScreenMode The index of the screen mode. Specifying 
       
   873 KIgnoreScreenMode returns the next application in the list, 
       
   874 regardless of screen mode.
       
   875 @return A pointer to the next application after aApp in the list 
       
   876 that can use the specified screen mode.
       
   877 @panic APGRFX 12 aApp is NULL. */
       
   878 
       
   879 	{
       
   880 	__ASSERT_ALWAYS(aApp,Panic(EPanicNoAppDataSupplied));
       
   881 	//
       
   882 	CApaAppData* iApp=aApp->iNext; //lint !e613 Suppress possible use of null pointer - asserted above
       
   883 
       
   884 	if(aScreenMode!=KIgnoreScreenMode)
       
   885 		while (iApp && !iApp->CanUseScreenMode(aScreenMode))
       
   886 			iApp = iApp->iNext;
       
   887 
       
   888 	return iApp;
       
   889 	}
       
   890 
       
   891 EXPORT_C CApaAppData* CApaAppList::AppDataByUid(TUid aAppUid) const
       
   892 /** Gets a pointer to the application in the list whose third 
       
   893 UID matches the specified UID.
       
   894 
       
   895 @param aAppUid An application's third UID. 
       
   896 @return A pointer to the application, if successful. Null, 
       
   897 if no match is found or if KNullUid was specified. */
       
   898 	{
       
   899 	if (aAppUid==KNullUid)
       
   900 		return NULL; // never match null UID as it represents an un-UIDed file
       
   901 	
       
   902 	CApaAppData* appData=iAppData;
       
   903 	while (appData)
       
   904 		{
       
   905 		if (appData->AppEntry().iUidType[2]==aAppUid)
       
   906 			return appData;
       
   907 		appData=appData->iNext;
       
   908 		}
       
   909 	
       
   910 	return NULL;
       
   911 	}
       
   912 
       
   913 EXPORT_C CApaAppData* CApaAppList::AppDataByFileName(const TDesC& aFullFileName) const
       
   914 /** Gets a pointer to the application in the list whose application
       
   915 file name matches the one specified
       
   916 
       
   917 @param aFullFileName a file name. 
       
   918 @return A pointer to the application, if successful. Null, 
       
   919 if no match is found or if KNullDesC was specified.
       
   920 @internalTechnology
       
   921 */
       
   922 	{
       
   923 	if (aFullFileName.Length()==0)
       
   924 		return NULL; // never match null UID as it represents an un-UIDed file
       
   925 
       
   926 	CApaAppData* appData=iAppData;
       
   927 	while (appData)
       
   928 		{
       
   929 		if (appData->AppEntry().iFullName.CompareF(aFullFileName)==0)
       
   930 			return appData;
       
   931 
       
   932 		appData=appData->iNext;
       
   933 		}
       
   934 
       
   935 	return NULL;
       
   936 	}
       
   937 	
       
   938 /**
       
   939 Adds a registration file to the iForcedRegistrations array.
       
   940 
       
   941 @param aRegistrationFile The function takes ownership of the HBufC.
       
   942 @internalComponent
       
   943 */
       
   944 EXPORT_C void CApaAppList::AddForcedRegistrationL(const TDesC& aRegistrationFile)
       
   945 	{
       
   946 	TInt err = iForcedRegistrations->InsertIsqL(aRegistrationFile, ECmpFolded);
       
   947 	if (err != KErrAlreadyExists) // We silently ignore attempts to insert duplicates
       
   948 		User::LeaveIfError(err);
       
   949 	
       
   950 	} //lint !e818 Suppress pointer parameter 'aRegistrationFile' could be declared as pointing to const
       
   951 	
       
   952 EXPORT_C void CApaAppList::ResetForcedRegistrations()
       
   953 	{
       
   954 	if(iForcedRegistrations)
       
   955 		iForcedRegistrations->Reset();
       
   956 	}
       
   957 
       
   958 /** Finds the preferred application to handle the specified data type.
       
   959 
       
   960 @param aDataType The data type of interest.
       
   961 @return The third UID of the application in the list which has the 
       
   962 highest priority for handling the specified data type. A null UID is 
       
   963 returned if no application in the list can handle the specified data type. */
       
   964 EXPORT_C TUid CApaAppList::PreferredDataHandlerL(const TDataType& aDataType) const
       
   965 	{
       
   966 	TInt dummy;
       
   967 	return PreferredDataHandlerL(aDataType, NULL, dummy);
       
   968 	}
       
   969 	
       
   970 /** Finds the preferred application to handle the specified data type.
       
   971 
       
   972 @param aDataType The data type of interest.
       
   973 @param aServiceUid The optional service UID.
       
   974 @param aPriority The priority associated with the returned app.
       
   975 @return The third UID of the application in the list which has the 
       
   976 highest priority for handling a combination of the specified data type
       
   977 and service. A null UID is returned if no application in the list can
       
   978 handle the combination of specified data type and service.
       
   979 @internalComponent
       
   980 */
       
   981 EXPORT_C TUid CApaAppList::PreferredDataHandlerL(const TDataType& aDataType, const TUid* aServiceUid, TInt& aPriority) const
       
   982 	{
       
   983 	// If there is a service UID then first try to use the service specific list
       
   984 	// of datatypes
       
   985 	if (aServiceUid)
       
   986 		{
       
   987 		CApaAppData* appData = iAppData;
       
   988 		aPriority = KDataTypePriorityNotSupported;
       
   989 		TUid uid = KNullUid; 
       
   990 
       
   991 		while (appData)
       
   992 			{
       
   993 			TInt priority = appData->ImplementsServiceWithDataType(*aServiceUid, aDataType);
       
   994 			if (priority > aPriority)
       
   995 				{
       
   996 				aPriority=priority;
       
   997 				uid=appData->AppEntry().iUidType[2];
       
   998 				}
       
   999 
       
  1000 			appData=appData->iNext;
       
  1001 			}
       
  1002 
       
  1003 		if (aPriority != KDataTypePriorityNotSupported)
       
  1004 			return uid;
       
  1005 		}
       
  1006 	
       
  1007 	CApaAppData* appData = iAppData;
       
  1008 	aPriority = KDataTypePriorityNotSupported;
       
  1009 	TUid uid = KNullUid;
       
  1010 
       
  1011 	// Run through all of the linked list of app-data to locate the application 
       
  1012 	// with the highest priority that can handle the given data type
       
  1013 	while (appData)
       
  1014 		{
       
  1015 		const TInt priority = appData->DataType(aDataType);
       
  1016 		if ((priority > aPriority) && (!aServiceUid || (aServiceUid && appData->ImplementsService(*aServiceUid))))
       
  1017 			{
       
  1018 			aPriority = priority;
       
  1019 			uid = appData->AppEntry().iUidType[2];
       
  1020 			}
       
  1021 			
       
  1022 		appData=appData->iNext;
       
  1023 		}
       
  1024 		
       
  1025 	return uid;
       
  1026 	}
       
  1027   
       
  1028 void CApaAppList::DeleteAppData()
       
  1029 	{
       
  1030 	iValidFirstAppData = NULL;
       
  1031 	iFlags &= ~EFirstScanComplete;
       
  1032 	iFlags &= ~EAppListHasChanged;
       
  1033 	iFlags &= ~ELangChangePending;
       
  1034 	
       
  1035 	CApaAppData* next = NULL;
       
  1036 	for (CApaAppData* appData=iAppData; appData; appData = next)
       
  1037 		{
       
  1038 		next = appData->iNext;
       
  1039 		delete appData;
       
  1040 		}
       
  1041 	iAppData = NULL;
       
  1042 	}
       
  1043 
       
  1044 void CApaAppList::ScanComplete()
       
  1045 	{
       
  1046 	if (!(iFlags & EFirstScanComplete) && iObserver)
       
  1047 		iObserver->InitialListPopulationComplete();
       
  1048 	iValidFirstAppData = iAppData;
       
  1049 	iFlags|=EFirstScanComplete;
       
  1050 	iNNAInstallation = EFalse;
       
  1051 	}
       
  1052 
       
  1053 /**
       
  1054  *
       
  1055  * Tests whether the first scan for list of Apps has completed.
       
  1056  *
       
  1057  * @return   "TBool"
       
  1058  *            True, if the first scan for list of Apps has completed; false, otherwise.
       
  1059  * @internalComponent
       
  1060  */
       
  1061 EXPORT_C TBool CApaAppList::IsFirstScanComplete() const
       
  1062 	{
       
  1063 	return iFlags&EFirstScanComplete;
       
  1064 	}
       
  1065 
       
  1066 EXPORT_C TBool CApaAppList::AppScanInProgress() const
       
  1067 /** @internalComponent */
       
  1068 	{
       
  1069 	return (iAppIdler!=NULL) && iAppIdler->IsActive();
       
  1070 	}
       
  1071 
       
  1072 /**
       
  1073 @internalComponent
       
  1074 */
       
  1075 EXPORT_C CBufFlat* CApaAppList::ServiceArrayBufferL(TUid aAppUid) const
       
  1076 	{
       
  1077 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1078 	while (app && app->AppEntry().iUidType[2] != aAppUid)
       
  1079 		app = NextApp(app, KIgnoreScreenMode);
       
  1080 
       
  1081 	if (app)
       
  1082 		{
       
  1083 		if (!app->RegistrationFileUsed())
       
  1084 			User::Leave(KErrNotSupported);
       
  1085 
       
  1086 		if (app->iServiceArray)
       
  1087 			{
       
  1088 			CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1089 			CleanupStack::PushL(buf);
       
  1090 			RBufWriteStream writeStream(*buf);
       
  1091 			writeStream << *(app->iServiceArray);
       
  1092 			writeStream.CommitL();
       
  1093 			writeStream.Release();
       
  1094 			CleanupStack::Pop(buf);
       
  1095 			return buf;
       
  1096 			}
       
  1097 		}
       
  1098 
       
  1099 	User::Leave(KErrNotFound);
       
  1100 	return NULL; // to keep compiler happy
       
  1101 	}
       
  1102 
       
  1103 /**
       
  1104 @internalComponent
       
  1105 */
       
  1106 EXPORT_C CBufFlat* CApaAppList::ServiceUidBufferL(TUid aAppUid) const
       
  1107 	{
       
  1108 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1109 	while (app && app->AppEntry().iUidType[2] != aAppUid)
       
  1110 		app = NextApp(app, KIgnoreScreenMode);
       
  1111 
       
  1112 	if (app)
       
  1113 		{
       
  1114 		if (!app->RegistrationFileUsed())
       
  1115 			User::Leave(KErrNotSupported);
       
  1116 
       
  1117 		if (app->iServiceArray)
       
  1118 			{
       
  1119 			CArrayFixFlat<TApaAppServiceInfo>& serviceArray = *(app->iServiceArray);
       
  1120 			CArrayFixFlat<TUid>* uidArray = new(ELeave) CArrayFixFlat<TUid>(4);
       
  1121 			CleanupStack::PushL(uidArray);
       
  1122 			for (TInt i = serviceArray.Count()-1; i >= 0; i--)
       
  1123 				uidArray->AppendL(serviceArray[i].Uid());
       
  1124 
       
  1125 			CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1126 			CleanupStack::PushL(buf);
       
  1127 			RBufWriteStream writeStream(*buf);
       
  1128 			writeStream << *uidArray;
       
  1129 			writeStream.CommitL();
       
  1130 			writeStream.Release();
       
  1131 			CleanupStack::Pop(buf);
       
  1132 			CleanupStack::PopAndDestroy(uidArray);
       
  1133 			return buf;
       
  1134 			}
       
  1135 		}
       
  1136 
       
  1137 	User::Leave(KErrNotFound);
       
  1138 	return NULL; // to keep compiler happy
       
  1139 	}
       
  1140 
       
  1141 /**
       
  1142 @internalComponent
       
  1143 */
       
  1144 EXPORT_C CBufFlat* CApaAppList::ServiceOpaqueDataBufferL(TUid aAppUid, TUid aServiceUid) const
       
  1145 	{
       
  1146 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1147 	while (app && app->AppEntry().iUidType[2] != aAppUid)
       
  1148 		app = NextApp(app, KIgnoreScreenMode);
       
  1149 
       
  1150 	if (app)
       
  1151 		{
       
  1152 		if (!app->RegistrationFileUsed())
       
  1153 			User::Leave(KErrNotSupported);
       
  1154 
       
  1155 		if (app->iServiceArray)
       
  1156 			{
       
  1157 			CArrayFixFlat<TApaAppServiceInfo>* implArray = NULL;
       
  1158 			CArrayFixFlat<TApaAppServiceInfo>& serviceArray = *(app->iServiceArray);
       
  1159 			for (TInt i = serviceArray.Count()-1; i >= 0; i--)
       
  1160 				{
       
  1161 				const TApaAppServiceInfo& infoRef = serviceArray[i];
       
  1162 				if (infoRef.Uid() == aServiceUid)
       
  1163 					{
       
  1164 					if (!implArray)
       
  1165 						{
       
  1166 						implArray = new(ELeave) CArrayFixFlat<TApaAppServiceInfo>(4);
       
  1167 						CleanupStack::PushL(TCleanupItem(CleanupServiceArray, implArray));
       
  1168 						}
       
  1169 
       
  1170 					CArrayFixFlat<TDataTypeWithPriority>* dummy = new(ELeave) CArrayFixFlat<TDataTypeWithPriority>(1);
       
  1171 					CleanupStack::PushL(dummy);					
       
  1172 					TApaAppServiceInfo info(aServiceUid, dummy, infoRef.OpaqueData().AllocLC());
       
  1173 					implArray->AppendL(info);
       
  1174 					CleanupStack::Pop(CONST_CAST(TDesC8*,&info.OpaqueData()));
       
  1175 					CleanupStack::Pop(dummy);
       
  1176 					}
       
  1177 				}
       
  1178 				
       
  1179 			if (implArray)
       
  1180 				{
       
  1181 				CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1182 				CleanupStack::PushL(buf);
       
  1183 				RBufWriteStream writeStream(*buf);
       
  1184 				writeStream << *implArray;
       
  1185 				writeStream.CommitL();
       
  1186 				writeStream.Release();
       
  1187 				CleanupStack::Pop(buf);
       
  1188 				CleanupStack::PopAndDestroy(implArray);
       
  1189 				return buf;
       
  1190 				}
       
  1191 			}
       
  1192 		}
       
  1193 	User::Leave(KErrNotFound);
       
  1194 	return NULL; // to keep compiler happy
       
  1195 	}
       
  1196 
       
  1197 /**
       
  1198 @internalComponent
       
  1199 */
       
  1200 EXPORT_C CBufFlat* CApaAppList::ServiceImplArrayBufferL(TUid aServiceUid) const
       
  1201 	{
       
  1202 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1203 	// build an array containing all implementations of the service identified by aServiceUid
       
  1204 	CArrayFixFlat<TApaAppServiceInfo>* implArray = NULL;
       
  1205 	while (app)
       
  1206 		{
       
  1207 		if (app->iServiceArray)
       
  1208 			{
       
  1209 			for (TInt i = app->iServiceArray->Count()-1; i >= 0; i--)
       
  1210 				{
       
  1211 				const TApaAppServiceInfo& infoRef = (*app->iServiceArray)[i];
       
  1212 				if (infoRef.Uid() == aServiceUid)
       
  1213 					{
       
  1214 					if (!implArray)
       
  1215 						{
       
  1216 						implArray = new(ELeave) CArrayFixFlat<TApaAppServiceInfo>(4);
       
  1217 						CleanupStack::PushL(TCleanupItem(CleanupServiceArray, implArray));
       
  1218 						}
       
  1219 				
       
  1220 					CArrayFixFlat<TDataTypeWithPriority>* datatypes = DataTypeArrayDeepCopyLC(infoRef.DataTypes());
       
  1221 					HBufC8* data = infoRef.OpaqueData().AllocLC();
       
  1222 					TApaAppServiceInfo info(app->AppEntry().iUidType[2], datatypes, data);
       
  1223 					implArray->AppendL(info);
       
  1224 					CleanupStack::Pop(data);
       
  1225 					CleanupStack::Pop(datatypes);
       
  1226 					}
       
  1227 				}
       
  1228 			}
       
  1229 		app = NextApp(app, KIgnoreScreenMode);
       
  1230 		}
       
  1231 
       
  1232 	if (implArray)
       
  1233 		{
       
  1234 		CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1235 		CleanupStack::PushL(buf);
       
  1236 		RBufWriteStream writeStream(*buf);
       
  1237 		writeStream << *(implArray);
       
  1238 		writeStream.CommitL();
       
  1239 		writeStream.Release();
       
  1240 		CleanupStack::Pop(buf);
       
  1241 		CleanupStack::PopAndDestroy(implArray);
       
  1242 		return buf;
       
  1243 		}
       
  1244 		
       
  1245 	User::Leave(KErrNotFound);
       
  1246 	return NULL; // to keep compiler happy
       
  1247 	}
       
  1248 
       
  1249 EXPORT_C CBufFlat* CApaAppList::ServiceImplArrayBufferL(TUid aServiceUid, const TDataType& aDataType) const
       
  1250 	{
       
  1251 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1252 	// build an array containing all implementations of the service identified by aServiceUid
       
  1253 	CArrayFixFlat<TApaAppServiceInfo>* implArray = NULL;
       
  1254 	while (app)
       
  1255 		{
       
  1256 		if (app->iServiceArray)
       
  1257 			{
       
  1258 			for (TInt i = app->iServiceArray->Count()-1; i >= 0; i--)
       
  1259 				{
       
  1260 				const TApaAppServiceInfo& infoRef = (*app->iServiceArray)[i];
       
  1261 				if (infoRef.Uid() == aServiceUid)
       
  1262 					{
       
  1263 				 	if (KDataTypePriorityNotSupported != app->DataType(aDataType, infoRef.DataTypes()))
       
  1264 						{
       
  1265 						if (!implArray)
       
  1266 							{
       
  1267 							implArray = new(ELeave) CArrayFixFlat<TApaAppServiceInfo>(4);
       
  1268 							CleanupStack::PushL(TCleanupItem(CleanupServiceArray, implArray));
       
  1269 							}
       
  1270 						CArrayFixFlat<TDataTypeWithPriority>* datatypes = DataTypeArrayDeepCopyLC(infoRef.DataTypes());
       
  1271 						HBufC8* data = infoRef.OpaqueData().AllocLC();
       
  1272 						TApaAppServiceInfo info(app->AppEntry().iUidType[2], datatypes, data);
       
  1273 						implArray->AppendL(info);
       
  1274 						CleanupStack::Pop(data);
       
  1275 						CleanupStack::Pop(datatypes);
       
  1276 						}
       
  1277 					}
       
  1278 				}
       
  1279 			}
       
  1280 		app = NextApp(app, KIgnoreScreenMode);
       
  1281 		}
       
  1282 
       
  1283 	if (implArray)
       
  1284 		{
       
  1285 		CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1286 		CleanupStack::PushL(buf);
       
  1287 		RBufWriteStream writeStream(*buf);
       
  1288 		writeStream << *(implArray);
       
  1289 		writeStream.CommitL();
       
  1290 		writeStream.Release();
       
  1291 		CleanupStack::Pop(buf);
       
  1292 		CleanupStack::PopAndDestroy(implArray);
       
  1293 		return buf;
       
  1294 		}
       
  1295 		
       
  1296 	User::Leave(KErrNotFound);
       
  1297 	return NULL; // to keep compiler happy
       
  1298 	}
       
  1299 	
       
  1300 CArrayFixFlat<TDataTypeWithPriority>* CApaAppList::DataTypeArrayDeepCopyLC(const CArrayFixFlat<TDataTypeWithPriority>& aOriginal) const
       
  1301 	{
       
  1302 	CArrayFixFlat<TDataTypeWithPriority>* result = new(ELeave) CArrayFixFlat<TDataTypeWithPriority>(1);
       
  1303 	CleanupStack::PushL(result);
       
  1304 	TInt ii = 0;
       
  1305 	TInt end = aOriginal.Count();
       
  1306 	while (ii < end)
       
  1307 		{
       
  1308 		result->AppendL(aOriginal[ii]);
       
  1309 		ii++;
       
  1310 		}
       
  1311 		
       
  1312 	return result;
       
  1313 	}
       
  1314 	
       
  1315 EXPORT_C CApaAppList* CApaAppList::Self()
       
  1316 	{ // static
       
  1317 	return STATIC_CAST(CApaAppList*,Dll::Tls());
       
  1318 	}
       
  1319 	
       
  1320 /*EXPORT_C*/ RFs& CApaAppList::ShareProtectedFileServer()
       
  1321 	{
       
  1322 	return iFsShareProtected; //lint !e1536 Exposing low access member - need to consider a redesign or design clarification here(iFsShareProtected should be owned be the one that needs it) but postpone for now as that may require large changes
       
  1323 	}
       
  1324 	
       
  1325 CApaAppIconArray* CApaAppList::LoadDefaultIconsL() const
       
  1326 	{
       
  1327 	CApaIconLoader* iconLoader = CApaIconLoader::NewLC(iFs);
       
  1328 	CApaAppIconArray* icons = CApaAppIconArray::NewRealDefaultIconsLC(KNumberOfIconsInDefaultMbm,*iDefaultAppIconMbmFileName, *iconLoader);
       
  1329 	const TBool badMbmEntryInfo = !icons->LoadIconsL();
       
  1330 	if(badMbmEntryInfo)
       
  1331 		{
       
  1332 		CleanupStack::PopAndDestroy(2,iconLoader);
       
  1333 		return CApaAppIconArray::NewL();
       
  1334 		}
       
  1335 	else
       
  1336 		{
       
  1337 		CleanupStack::Pop(icons);
       
  1338 		CleanupStack::PopAndDestroy(iconLoader);
       
  1339 		}
       
  1340 		
       
  1341 	return icons;
       
  1342 	}
       
  1343 
       
  1344 void CApaAppList::AcquireDefaultIconArrayL() const
       
  1345 	{
       
  1346 	ASSERT(iDefaultIconUsageCount >= 0);
       
  1347 	if (iDefaultIconUsageCount == 0)
       
  1348 		iDefaultIconArray = LoadDefaultIconsL();
       
  1349 
       
  1350 	++iDefaultIconUsageCount;
       
  1351 	}
       
  1352 
       
  1353 // Should NEVER be called by an object that does not call AcquireDefaultIconArrayL and
       
  1354 // ReleaseDefaultIconArray at the beginning and end of its lifetime respectively
       
  1355 const CApaAppIconArray& CApaAppList::DefaultIconArray() const
       
  1356 	{
       
  1357 	__ASSERT_ALWAYS(iDefaultIconArray, Panic(EPanicNullPointer));
       
  1358 	return *iDefaultIconArray;
       
  1359 	}
       
  1360 
       
  1361 void CApaAppList::ReleaseDefaultIconArray() const
       
  1362 	{
       
  1363 	ASSERT(iDefaultIconUsageCount > 0);
       
  1364 	if(0 == --iDefaultIconUsageCount)
       
  1365 		{
       
  1366 		delete iDefaultIconArray;
       
  1367 		iDefaultIconArray = NULL;		
       
  1368 		}
       
  1369 	}
       
  1370 	
       
  1371 // DEF077478 - Required to update the default icons that the app list holds.
       
  1372 void CApaAppList::UpdateDefaultIconsL()
       
  1373 	{
       
  1374 	CApaAppIconArray* iconArray = LoadDefaultIconsL();
       
  1375 	if (iconArray)
       
  1376 		{
       
  1377 		delete iDefaultIconArray;
       
  1378 		iDefaultIconArray = iconArray;
       
  1379 		}
       
  1380 	}
       
  1381 
       
  1382 void CApaAppList::DeleteAppListStorer()
       
  1383 	{
       
  1384 	delete iAppListStorer;
       
  1385 	iAppListStorer = NULL;
       
  1386 	}
       
  1387 
       
  1388 void CApaAppList::DeleteAppIconLoader()
       
  1389 	{
       
  1390 	delete iAppIconLoader;
       
  1391 	iAppIconLoader = NULL;
       
  1392 	}
       
  1393 
       
  1394 void CApaAppList::InitiateStoringOfAppList()
       
  1395 	{
       
  1396 	ScanComplete();	
       
  1397 	NotifyObserver();
       
  1398 	iFlags &= ~ENotifyUpdateOnFirstScanComplete;
       
  1399 	// now that the scan is finished, iDefaultAppIconMbmFileName is deleted
       
  1400 	delete iDefaultAppIconMbmFileName;
       
  1401 	iDefaultAppIconMbmFileName=NULL;
       
  1402 	// if applist has not changed and AppsList_Backup.bin file exists then it is replaced back to AppsList.bin
       
  1403 	if (!(iFlags & EAppListHasChanged) && BaflUtils::FileExists(iFs, iAppsListCacheBackUpFileName))
       
  1404 		{
       
  1405 		TInt replaceError = iFs.Replace(iAppsListCacheBackUpFileName, iAppsListCacheFileName);
       
  1406 		if (replaceError == KErrNone)
       
  1407 			return;
       
  1408 		}
       
  1409 
       
  1410     iFlags &= ~EAppListHasChanged;
       
  1411 	iFs.Delete(iAppsListCacheBackUpFileName);
       
  1412 	TInt err = iFs.MkDir(iAppsListCachePath);
       
  1413 	if (err == KErrNone || err == KErrAlreadyExists)
       
  1414 		{
       
  1415 		TRAP(err, StoreL());
       
  1416 		if (err)
       
  1417 			DeleteAppListStorer();
       
  1418 		}
       
  1419 	}
       
  1420 
       
  1421 
       
  1422 EXPORT_C void CApaAppList::AddCustomAppInfoInListL(TUid aAppUid, TLanguage aLanguage, const TDesC& aShortCaption)
       
  1423 	{
       
  1424 	TBool replaced=EFalse;
       
  1425 	for (TInt i=iCustomAppList.Count()-1; i>=0; --i)
       
  1426 		{
       
  1427 		if (aAppUid == iCustomAppList[i]->Uid() && aLanguage == iCustomAppList[i]->Language())
       
  1428 			{
       
  1429 			CCustomAppInfoData* oldAppInfo = iCustomAppList[i];
       
  1430 			iCustomAppList[i] = CCustomAppInfoData::NewL(aAppUid, aLanguage, aShortCaption);;
       
  1431 			delete oldAppInfo;
       
  1432 			replaced=ETrue;
       
  1433 			break;
       
  1434 			}
       
  1435 		}
       
  1436 	//Add ELangNone items at the end and others at the beginning
       
  1437 	if(!replaced)
       
  1438 		{
       
  1439 		CCustomAppInfoData* appInfo = CCustomAppInfoData::NewL(aAppUid, aLanguage, aShortCaption);
       
  1440 		CleanupStack::PushL(appInfo);
       
  1441 		
       
  1442 		if(aLanguage == ELangNone)
       
  1443 			iCustomAppList.AppendL(appInfo);
       
  1444 		else
       
  1445 			iCustomAppList.InsertL(appInfo,0);
       
  1446 		
       
  1447 		CleanupStack::Pop(appInfo);
       
  1448 		}
       
  1449 	
       
  1450 	} //lint !e818 Suppress pointer parameter could be declared as pointing to const - this method takes ownership
       
  1451 
       
  1452 
       
  1453 EXPORT_C void CApaAppList::UpdateAppListByShortCaptionL()
       
  1454 	{
       
  1455 	//Items with ELangNone are always found at the end and other languages at the beginning
       
  1456 	//While iterating from end to beginning, we overwrite short caption set by ELangNone if there is any provided for the application language
       
  1457 	for (TInt i=iCustomAppList.Count()-1; i>=0; --i)
       
  1458 		{
       
  1459 		const CCustomAppInfoData* const customAppInfo=iCustomAppList[i];
       
  1460 		CApaAppData* app = AppDataByUid(customAppInfo->Uid());
       
  1461 		
       
  1462 		if ( app && (app->ApplicationLanguage()==customAppInfo->Language() || customAppInfo->Language()==ELangNone))
       
  1463 			app->SetShortCaptionL(*customAppInfo->ShortCaption());
       
  1464 		}
       
  1465 	}
       
  1466 
       
  1467 EXPORT_C void CApaAppList::UpdateAppListByIconCaptionOverridesL()
       
  1468 	{
       
  1469 	// get the language downgrade path, so that most appropriate language can be used
       
  1470 	RArray<TLanguage> languageDowngradePath;
       
  1471 	CleanupClosePushL(languageDowngradePath);
       
  1472 	BaflUtils::GetDowngradePathL(iFs, User::Language(), languageDowngradePath);
       
  1473 	for (CApaAppData* app = FirstApp(); app; app = NextApp(app))
       
  1474 		{
       
  1475 		CApaIconCaptionOverridesForApp* appOverride = iIconCaptionOverrides->OverrideForApp(app->AppEntry().iUidType[2]);
       
  1476 		if (appOverride)
       
  1477 			{
       
  1478 			TApaIconCaptionOverrideReader overrideReader = appOverride->Reader(languageDowngradePath);
       
  1479 			const TDesC* shortCaption = overrideReader.ShortCaption();
       
  1480 			if (shortCaption)
       
  1481 				app->SetShortCaptionL(*shortCaption);
       
  1482 			const TDesC* caption = overrideReader.Caption();
       
  1483 			if (caption)
       
  1484 				app->SetCaptionL(*caption);
       
  1485 			const TDesC* iconFileName = overrideReader.IconFileName();
       
  1486 			if (overrideReader.NumIconsSet() && iconFileName)
       
  1487 				app->SetIconsL(*iconFileName, overrideReader.NumIcons());
       
  1488 			}
       
  1489 		}
       
  1490 	CleanupStack::PopAndDestroy(&languageDowngradePath);
       
  1491 	}
       
  1492 
       
  1493 //
       
  1494 // Class CApaAppListStorer
       
  1495 //
       
  1496 
       
  1497 CApaAppList::CApaAppListStorer::CApaAppListStorer(CApaAppData* aFirstAppData, RFs& aFs, CApaAppList& aAppList) : CActive(EPriorityIdle), iCurrentAppData(aFirstAppData), iFs(aFs), iAppList(aAppList)
       
  1498 	{
       
  1499 	}
       
  1500 
       
  1501 CApaAppList::CApaAppListStorer::~CApaAppListStorer()
       
  1502 	{
       
  1503 	Cancel();
       
  1504 	iWriteStream.Close();
       
  1505 	iFs.Delete(iTempFilename);
       
  1506 	iTimer.Close();
       
  1507 	iCurrentAppData = NULL;
       
  1508 	}
       
  1509 
       
  1510 CApaAppList::CApaAppListStorer* CApaAppList::CApaAppListStorer::NewL(CApaAppData* aFirstAppData, RFs& aFs, CApaAppList& aAppList)
       
  1511 	{
       
  1512 	CApaAppListStorer* self = new(ELeave) CApaAppListStorer(aFirstAppData, aFs, aAppList);
       
  1513 	CleanupStack::PushL(self);
       
  1514 	self->ConstructL();
       
  1515 	CleanupStack::Pop(self);
       
  1516 	return self;
       
  1517 	}
       
  1518 
       
  1519 void CApaAppList::CApaAppListStorer::ConstructL()
       
  1520 	{
       
  1521 	User::LeaveIfError(iTimer.CreateLocal());
       
  1522 	CActiveScheduler::Add(this);
       
  1523 	}
       
  1524 
       
  1525 void CApaAppList::CApaAppListStorer::StartL(const TTimeIntervalMicroSeconds32& aDelay)
       
  1526 	{
       
  1527 	User::LeaveIfError(iWriteStream.Temp(iFs, iAppList.iAppsListCachePath, iTempFilename, EFileWrite));
       
  1528 	iWriteStream.WriteInt32L(User::Language());
       
  1529 	
       
  1530 #if defined (SYMBIAN_BAFL_SYSUTIL)
       
  1531 	//Write a cache of the ROM version to a separate stream
       
  1532 	//Build the filename for the cache file
       
  1533 	TInt maxSizeofFileName = iAppList.iAppsListCachePath.Length() + KROMVersionStringCacheFileName().Length();
       
  1534 	RBuf romVersionCacheFileName;
       
  1535 	romVersionCacheFileName.CreateL(maxSizeofFileName);
       
  1536 	romVersionCacheFileName.CleanupClosePushL();
       
  1537 	romVersionCacheFileName.Append(iAppList.iAppsListCachePath);
       
  1538 	romVersionCacheFileName.Append(KROMVersionStringCacheFileName());
       
  1539 	
       
  1540 	RFileWriteStream romVerStream;
       
  1541 	User::LeaveIfError(romVerStream.Replace(iFs,romVersionCacheFileName,EFileWrite));
       
  1542 	CleanupClosePushL(romVerStream);
       
  1543 	
       
  1544 	// Write the file version that apparc can handle.
       
  1545 	romVerStream.WriteInt8L(KROMVersionCacheFileMajorVersion);
       
  1546 	romVerStream.WriteInt8L(KROMVersionCacheFileMinorVersion);
       
  1547 	romVerStream.WriteInt16L(KROMVersionCacheFileBuildVersion);
       
  1548 		
       
  1549 	TBuf<KInfoBufLength> version;
       
  1550 	SysUtil::GetSWVersion(version);
       
  1551 	
       
  1552 	// Write the software version even if SysUtil returns err since all conditions are taken care during restore.
       
  1553 	romVerStream.WriteUint32L(version.Length());
       
  1554 	romVerStream.WriteL(version, version.Length());
       
  1555 	CleanupStack::PopAndDestroy(2); //romVerStream, romVersionCacheFileName
       
  1556 #endif //(SYMBIAN_BAFL_SYSUTIL)
       
  1557 	
       
  1558 	iTimer.After(iStatus, aDelay);
       
  1559 	SetActive();
       
  1560 	}
       
  1561 
       
  1562 void CApaAppList::CApaAppListStorer::RunL()
       
  1563 	{ 
       
  1564 	// iStatus could be KErrNone or negative when timer completes, irrespective of its status we need to re-queue the request.
       
  1565 	if (iCurrentAppData)
       
  1566 		{
       
  1567 		StoreEntryL(iWriteStream, *iCurrentAppData);
       
  1568 		iCurrentAppData = iCurrentAppData->Next();
       
  1569 		SetActive();
       
  1570 		TRequestStatus* status = &iStatus;
       
  1571 		User::RequestComplete(status, KErrNone);
       
  1572 		}
       
  1573 	else
       
  1574 		{
       
  1575 		iWriteStream.CommitL();
       
  1576 		iWriteStream.Close();
       
  1577 
       
  1578 		TInt err = iFs.Replace(iTempFilename, iAppList.iAppsListCacheFileName);
       
  1579 		if (err != KErrNone)
       
  1580 			iFs.Delete(iTempFilename);
       
  1581 
       
  1582 		iAppList.DeleteAppListStorer();
       
  1583 		}
       
  1584 	}
       
  1585 
       
  1586 void CApaAppList::CApaAppListStorer::StoreEntryL(RWriteStream& aWriteStream, const CApaAppData& aApp)
       
  1587 	{
       
  1588 	aWriteStream << aApp;
       
  1589 	}
       
  1590 
       
  1591 void CApaAppList::CApaAppListStorer::DoCancel()
       
  1592 	{
       
  1593 	iTimer.Cancel();
       
  1594 	}
       
  1595 
       
  1596 TInt CApaAppList::CApaAppListStorer::RunError(TInt /*aError*/)
       
  1597 	{
       
  1598 	iAppList.DeleteAppListStorer();
       
  1599 	return KErrNone;
       
  1600 	}
       
  1601 
       
  1602 //
       
  1603 // Class CApaIdleIconLoader
       
  1604 //
       
  1605 
       
  1606 CApaAppList::CApaIdleIconLoader::CApaIdleIconLoader(CApaAppData* aFirstAppData, RFs& aFs, CApaAppList& aAppList) : CActive(EPriorityLow), iCurrentAppData(aFirstAppData), iFs(aFs), iAppList(aAppList)
       
  1607 	{ // Priority is less than KAppListServerPriority, to maintain server responsiveness.
       
  1608 	CActiveScheduler::Add(this);
       
  1609 	}
       
  1610 
       
  1611 CApaAppList::CApaIdleIconLoader::~CApaIdleIconLoader()
       
  1612 	{
       
  1613 	Cancel();
       
  1614 	iCurrentAppData = NULL;
       
  1615 	}
       
  1616 
       
  1617 void CApaAppList::CApaIdleIconLoader::Start()
       
  1618 	{
       
  1619 	SetActive();
       
  1620 	TRequestStatus* status = &iStatus;
       
  1621 	User::RequestComplete(status, KErrNone);
       
  1622 	}
       
  1623 
       
  1624 void CApaAppList::CApaIdleIconLoader::RunL()
       
  1625 /** if the icons are not already loaded on demand then it would be loaded here. */
       
  1626 	{
       
  1627 	while (iCurrentAppData && !iCurrentAppData->MbmIconsRequireLoading())
       
  1628 		iCurrentAppData = iCurrentAppData->Next();
       
  1629 
       
  1630 	if(iCurrentAppData)
       
  1631 		{
       
  1632 		Start();
       
  1633 		CApaAppData* const appData = iCurrentAppData;
       
  1634 		iCurrentAppData = iCurrentAppData->Next();
       
  1635 		appData->LoadIconsL();
       
  1636 		}
       
  1637 	else
       
  1638 		{
       
  1639 		iAppList.InitiateStoringOfAppList();
       
  1640 		iAppList.DeleteAppIconLoader();
       
  1641 		}
       
  1642 	}
       
  1643 
       
  1644 void CApaAppList::CApaIdleIconLoader::DoCancel()
       
  1645 	{
       
  1646 	}
       
  1647 
       
  1648 TInt CApaAppList::CApaIdleIconLoader::RunError(TInt /*aError*/)
       
  1649 	{
       
  1650 	return KErrNone;
       
  1651 	}
       
  1652 
       
  1653 
       
  1654 //
       
  1655 // Class CApaLangChangeMonitor
       
  1656 //
       
  1657 
       
  1658 CApaAppList::CApaLangChangeMonitor::~CApaLangChangeMonitor()
       
  1659 	{	
       
  1660 	Cancel();
       
  1661 	iLangNotifier.Close();
       
  1662 	}
       
  1663 
       
  1664 CApaAppList::CApaLangChangeMonitor* CApaAppList::CApaLangChangeMonitor::NewL(CApaAppList& aAppList)
       
  1665 	{ // static	
       
  1666 	CApaLangChangeMonitor* self=new(ELeave) CApaLangChangeMonitor(aAppList);
       
  1667 	self->ConstructL();
       
  1668 	return self;
       
  1669 	}
       
  1670 
       
  1671 CApaAppList::CApaLangChangeMonitor::CApaLangChangeMonitor(CApaAppList& aAppList)
       
  1672 	: CActive(EPriorityNormal),
       
  1673 	iAppList(aAppList)
       
  1674 	{	
       
  1675 	iPrevLanguage = User::Language();
       
  1676 	CActiveScheduler::Add(this);
       
  1677 	}
       
  1678 
       
  1679 void CApaAppList::CApaLangChangeMonitor::ConstructL()
       
  1680 	{
       
  1681 	User::LeaveIfError(iLangNotifier.Create());
       
  1682 	Start();
       
  1683 	}
       
  1684  
       
  1685 void CApaAppList::CApaLangChangeMonitor::Start()
       
  1686 	{
       
  1687 	iLangNotifier.Logon(iStatus);
       
  1688 	SetActive();
       
  1689 	}
       
  1690 
       
  1691 void CApaAppList::CApaLangChangeMonitor::DoCancel()
       
  1692 	{
       
  1693 	iLangNotifier.LogonCancel();
       
  1694 	}
       
  1695 
       
  1696 void CApaAppList::CApaLangChangeMonitor::RunL()
       
  1697 	{
       
  1698 	// Logon to get further events before handling current request.
       
  1699 	TRequestStatus status = iStatus;
       
  1700 	Start();
       
  1701 	
       
  1702 	// if it is a language change event, start a rescan on app-list.
       
  1703 	if (status.Int() == EChangesLocale && iPrevLanguage != User::Language())
       
  1704 		{		
       
  1705 		iPrevLanguage = User::Language();
       
  1706 		iAppList.iFlags |= CApaAppList::ELangChangePending;
       
  1707 		iAppList.StartIdleUpdateL(iAppList.iObserver);
       
  1708 		}
       
  1709 	}
       
  1710 
       
  1711 TInt CApaAppList::CApaLangChangeMonitor::RunError(TInt /*aError*/)
       
  1712 	{
       
  1713 	// Reset ELangChangePending flag if RunL leaves.
       
  1714 	iAppList.iFlags &= ~CApaAppList::ELangChangePending;
       
  1715 	// Reset iPrevLanguage to ELangNone if RunL leaves.
       
  1716 	iPrevLanguage = ELangNone;
       
  1717 	return KErrNone;
       
  1718 	}
       
  1719 
       
  1720 //
       
  1721 // CCustomAppInfoData
       
  1722 //
       
  1723 
       
  1724 CApaAppList::CCustomAppInfoData* CApaAppList::CCustomAppInfoData::NewL(TUid aAppUid, TLanguage aLanguage, const TDesC& aShortCaption)
       
  1725 	{
       
  1726 	CCustomAppInfoData* self=new(ELeave) CCustomAppInfoData(aAppUid, aLanguage);
       
  1727     CleanupStack::PushL(self);
       
  1728 	self->ConstructL(aShortCaption);
       
  1729 	CleanupStack::Pop(self);
       
  1730 	return self;
       
  1731 	}
       
  1732 
       
  1733 CApaAppList::CCustomAppInfoData::~CCustomAppInfoData()
       
  1734 	{
       
  1735 	delete iShortCaption;
       
  1736 	}
       
  1737 
       
  1738 CApaAppList::CCustomAppInfoData::CCustomAppInfoData(TUid aAppUid, TLanguage aLanguage)
       
  1739 	:iUid(aAppUid),
       
  1740 	iLanguage(aLanguage)
       
  1741 	{
       
  1742 	}
       
  1743 
       
  1744 void CApaAppList::CCustomAppInfoData::ConstructL(const TDesC& aShortCaption)
       
  1745 	{
       
  1746 	iShortCaption=aShortCaption.AllocL();
       
  1747 	}
       
  1748 
       
  1749 TUid CApaAppList::CCustomAppInfoData::Uid() const
       
  1750 	{ return iUid; }
       
  1751 	
       
  1752 TLanguage CApaAppList::CCustomAppInfoData::Language() const
       
  1753 	{ return iLanguage; }
       
  1754 	
       
  1755 HBufC* CApaAppList::CCustomAppInfoData::ShortCaption() const
       
  1756 	{ return iShortCaption; }
       
  1757 
       
  1758 // The function transfers ownership of the pointer owned by a CApaAppList to the caller
       
  1759 // to avoid copying the array.
       
  1760 
       
  1761 EXPORT_C CArrayFixFlat<TUid>* CApaAppList::UninstalledAppArray()
       
  1762     {
       
  1763     CArrayFixFlat<TUid>* uninstalledApps=iUninstalledApps;
       
  1764     iUninstalledApps=NULL;
       
  1765     return uninstalledApps;
       
  1766     }
       
  1767