localisation/apparchitecture/apgrfx/APGAPLST.CPP
branchSymbian2
changeset 1 8758140453c0
child 6 c108117318cb
equal deleted inserted replaced
0:e8c1ea2c6496 1:8758140453c0
       
     1 // Copyright (c) 1997-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 the License "Symbian Foundation License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "apgaplst.h"
       
    17 #include "apgstd.h" 
       
    18 #include "apfdef.h"
       
    19 #include "..\apparc\trace.h"
       
    20 #include "apgnotif.h"
       
    21 #include "..\apfile\aprfndr.h"
       
    22 #include <e32math.h>
       
    23 #include <bautils.h>
       
    24 #include <s32mem.h>
       
    25 #include "apgpriv.h"
       
    26 #include "apgair.h"
       
    27 #include "apgicnfl.h"
       
    28 #include "apprivate.h"
       
    29 #include <e32uid.h>
       
    30 
       
    31 
       
    32 // Delays in the pseudo idle object that builds the application list
       
    33 //
       
    34 
       
    35 const TInt KIdleStartDelay=0;
       
    36 const TInt KMaxOpaqueDataLength = 0x1000; // maximum length of opaque data that can be passed between client and apparc server via a TApaAppServiceInfo object - this can be increased in future if needed
       
    37 const TInt KBufferExpansionGranularity = 0x100;
       
    38 const TInt KNumberOfIconsInDefaultMbm = 3;
       
    39 const TInt KAppListToFileStartDelay = 60000000;
       
    40 
       
    41 
       
    42 //
       
    43 // Class CApaLangChangeMonitor
       
    44 //
       
    45 
       
    46 NONSHARABLE_CLASS(CApaAppList::CApaLangChangeMonitor) : public CActive
       
    47  		{
       
    48  	/**
       
    49  	Utility class used to monitor locale/language change event.
       
    50  	@internalComponent
       
    51  	*/
       
    52  	public:
       
    53  		static CApaLangChangeMonitor* NewL(CApaAppList& aAppList);
       
    54  		~CApaLangChangeMonitor();
       
    55  		void Start();
       
    56  		
       
    57  	private:
       
    58  		CApaLangChangeMonitor(CApaAppList& aAppList);
       
    59  		void ConstructL();
       
    60  		
       
    61  	private:	//from CActive
       
    62  		void RunL();
       
    63  		void DoCancel();
       
    64  		TInt RunError(TInt aError);
       
    65  		
       
    66  	private:
       
    67  		RChangeNotifier iLangNotifier;
       
    68  		CApaAppList& iAppList;
       
    69  		TLanguage iPrevLanguage;
       
    70  		};
       
    71  
       
    72  		
       
    73  
       
    74 //
       
    75 // Local functions
       
    76 //
       
    77 
       
    78 void CleanupServiceArray(TAny* aServiceArray)
       
    79 	{
       
    80 	__ASSERT_DEBUG(aServiceArray, Panic(EPanicNullPointer));
       
    81 	CArrayFixFlat<TApaAppServiceInfo>* serviceArray = static_cast<CArrayFixFlat<TApaAppServiceInfo>*>(aServiceArray);
       
    82 	TInt serviceCount = serviceArray->Count();
       
    83 	if (serviceCount > 0)
       
    84 		{
       
    85 		for (TInt i = serviceCount - 1; i >= 0; i--)
       
    86 			{
       
    87 			(*serviceArray)[i].Release();
       
    88 			}
       
    89 		}
       
    90 	delete serviceArray;
       
    91 	serviceArray = 0;
       
    92 	}
       
    93 
       
    94 
       
    95 //
       
    96 // Class CApaAppViewData
       
    97 //
       
    98 
       
    99 CApaAppViewData::~CApaAppViewData()
       
   100 	{
       
   101 	delete iIcons;
       
   102 	delete iCaption;
       
   103 	delete iIconFileName;
       
   104 	}
       
   105 
       
   106 CApaAppViewData::CApaAppViewData()
       
   107 	: iNonMbmIconFile(EFalse)
       
   108 	{
       
   109 	}
       
   110 
       
   111 void CApaAppViewData::ConstructL()
       
   112 	{
       
   113 	iIcons=CApaAppIconArray::NewL();
       
   114 	}
       
   115 
       
   116 CApaAppViewData* CApaAppViewData::NewLC()
       
   117 	{
       
   118 	CApaAppViewData* self=new(ELeave) CApaAppViewData();
       
   119 	CleanupStack::PushL(self);
       
   120 	self->ConstructL();
       
   121 	return self;	
       
   122 	}
       
   123 
       
   124 void CApaAppViewData::SetUid(TUid aUid)
       
   125 	{
       
   126 	iUid=aUid;
       
   127 	}
       
   128 
       
   129 void CApaAppViewData::SetScreenMode(TInt aScreenMode)
       
   130 	{
       
   131 	iScreenMode=aScreenMode;
       
   132 	}
       
   133 
       
   134 EXPORT_C TInt CApaAppViewData::ScreenMode() const
       
   135 	{
       
   136 	return iScreenMode;
       
   137 	}
       
   138 
       
   139 void CApaAppViewData::SetCaptionL(const TDesC& aCaption)
       
   140 	{
       
   141 	HBufC* newCaption=aCaption.AllocL();
       
   142 	delete(iCaption); // after the AllocL succeeds
       
   143 	iCaption=newCaption;
       
   144 	}
       
   145 
       
   146 void CApaAppViewData::SetIconArray(CApaAppIconArray* aIcons)
       
   147 	{
       
   148 	delete iIcons;
       
   149 	iIcons = aIcons;
       
   150 	}
       
   151 
       
   152 void CApaAppViewData::SetIconFileNameL(const TDesC& aFileName)
       
   153 	{
       
   154 	HBufC* fileName = aFileName.AllocL();
       
   155 	delete iIconFileName; // after the AllocL succeeds
       
   156 	iIconFileName = fileName;
       
   157 	}
       
   158 
       
   159 void CApaAppViewData::SetNonMbmIconFile(TBool aNonMbmIconFile)
       
   160 	{
       
   161 	iNonMbmIconFile = aNonMbmIconFile;
       
   162 	}
       
   163 
       
   164 EXPORT_C TUid CApaAppViewData::Uid() const
       
   165 	{
       
   166 	return iUid;
       
   167 	}
       
   168 
       
   169 EXPORT_C CApaMaskedBitmap* CApaAppViewData::Icon(const TSize& aSize) const
       
   170 	{
       
   171 	__ASSERT_ALWAYS(iIcons, Panic(EPanicNullPointer));
       
   172 	return iIcons->IconBySize(aSize);
       
   173 	}
       
   174 
       
   175 EXPORT_C CArrayFixFlat<TSize>* CApaAppViewData::IconSizesL() const
       
   176 	{
       
   177 	__ASSERT_ALWAYS(iIcons, Panic(EPanicNullPointer));
       
   178 	return iIcons->IconSizesL();
       
   179 	}
       
   180 
       
   181 EXPORT_C TPtrC CApaAppViewData::IconFileName() const
       
   182 	{
       
   183 	if (iIconFileName)
       
   184 		{
       
   185 		return *iIconFileName;
       
   186 		}
       
   187 	else
       
   188 		{
       
   189 		return TPtrC(KNullDesC);
       
   190 		}
       
   191 	}
       
   192 
       
   193 EXPORT_C TBool CApaAppViewData::NonMbmIconFile() const
       
   194 	{
       
   195 	return iNonMbmIconFile;
       
   196 	}
       
   197 
       
   198 
       
   199 //
       
   200 // class CApaAppEntry
       
   201 //
       
   202 
       
   203 CApaAppEntry* CApaAppEntry::NewL(const TApaAppEntry& aAppEntry)
       
   204 	{ // static
       
   205 	CApaAppEntry* self=new(ELeave) CApaAppEntry(aAppEntry.iUidType);
       
   206 	CleanupStack::PushL(self);
       
   207 	self->ConstructL(aAppEntry.iFullName);
       
   208 	CleanupStack::Pop(self);
       
   209 	return self;
       
   210 	}
       
   211 
       
   212 CApaAppEntry::~CApaAppEntry()
       
   213 	{
       
   214 	delete iFullName;
       
   215 	}
       
   216 
       
   217 void CApaAppEntry::Get(TApaAppEntry& aAppEntry) const
       
   218 	{
       
   219 	aAppEntry.iFullName=*iFullName;
       
   220 	aAppEntry.iUidType=iUidType;
       
   221 	}
       
   222 
       
   223 CApaAppEntry::CApaAppEntry(const TUidType& aUidType)
       
   224 	: iUidType(aUidType)
       
   225 	{
       
   226 	}
       
   227 
       
   228 void CApaAppEntry::ConstructL(const TDesC& aFileName)
       
   229 	{
       
   230 	iFullName=aFileName.AllocL();
       
   231 	}
       
   232 
       
   233 
       
   234 //
       
   235 // class TApaAppServiceInfo
       
   236 //
       
   237 
       
   238 TApaAppServiceInfo::TApaAppServiceInfo()
       
   239 	: iUid(KNullUid),
       
   240 	  iDataTypes(0),
       
   241 	  iOpaqueData(NULL)
       
   242 	{
       
   243 	}
       
   244 
       
   245 TApaAppServiceInfo::TApaAppServiceInfo(TUid aUid, 
       
   246 	CArrayFixFlat<TDataTypeWithPriority>* aDataTypes, HBufC8* aOpaqueData)
       
   247 	: iUid(aUid),
       
   248 	  iDataTypes(aDataTypes),
       
   249 	  iOpaqueData(aOpaqueData)
       
   250 	{
       
   251 	__ASSERT_DEBUG(iDataTypes, Panic(EPanicNullPointer));
       
   252 	__ASSERT_DEBUG(iOpaqueData, Panic(EPanicNullPointer));
       
   253 	}
       
   254 
       
   255 void TApaAppServiceInfo::ExternalizeL(RWriteStream& aStream) const
       
   256 	{
       
   257 	__ASSERT_DEBUG(iDataTypes, User::Invariant());
       
   258 	__ASSERT_DEBUG(iDataTypes, Panic(EPanicNullPointer));
       
   259 	__ASSERT_DEBUG(iOpaqueData, Panic(EPanicNullPointer));
       
   260 	aStream << iUid;
       
   261 	aStream << *iDataTypes; //lint !e613 Possible use of null pointer - Asserted above
       
   262 	aStream << *iOpaqueData;//lint !e613 Possible use of null pointer - Asserted above
       
   263 	}
       
   264 
       
   265 void TApaAppServiceInfo::InternalizeL(RReadStream& aStream)
       
   266 	{
       
   267 	aStream >> iUid;
       
   268 	iDataTypes = new(ELeave) CArrayFixFlat<TDataTypeWithPriority>(1);
       
   269 	aStream >> *iDataTypes;
       
   270 	iOpaqueData = HBufC8::NewL(aStream, KMaxOpaqueDataLength);
       
   271 	}
       
   272 
       
   273 void TApaAppServiceInfo::Release()
       
   274 	{
       
   275 	if (iDataTypes)
       
   276 		{
       
   277 		iDataTypes->Reset();
       
   278 		delete iDataTypes;		
       
   279 		iDataTypes = NULL;
       
   280 		}
       
   281 	if (iOpaqueData)
       
   282 		{
       
   283 		delete iOpaqueData;
       
   284 		iOpaqueData = NULL;
       
   285 		}
       
   286 	}
       
   287 
       
   288 CArrayFixFlat<TDataTypeWithPriority>& TApaAppServiceInfo::DataTypes()
       
   289 	{
       
   290 	__ASSERT_DEBUG(iDataTypes, Panic(EPanicNullPointer));
       
   291 	return *iDataTypes; //lint !e613 Possible use of null pointer - Asserted above
       
   292 	}
       
   293 
       
   294 /** Returns the service UID.
       
   295 
       
   296 Note that some APIs may store a UID other than a service UID
       
   297 in a TApaAppServiceInfo object. Such APIs clearly state what
       
   298 the UID represents.
       
   299 
       
   300 @return the service UID.
       
   301 */
       
   302 EXPORT_C TUid TApaAppServiceInfo::Uid() const
       
   303 	{
       
   304 	return iUid;
       
   305 	}
       
   306 	
       
   307 EXPORT_C const CArrayFixFlat<TDataTypeWithPriority>& TApaAppServiceInfo::DataTypes() const
       
   308 	{
       
   309 	__ASSERT_DEBUG(iDataTypes, Panic(EPanicNullPointer));	
       
   310 	return *iDataTypes; //lint !e613 Possible use of null pointer - Asserted above
       
   311 	}
       
   312 
       
   313 /** Returns the service implementation's opaque data.
       
   314 
       
   315 For each service UID registered by an application, the associated
       
   316 opaque data indicates how the service is implemented by that application.
       
   317 
       
   318 The meaning of the opaque data is not known to the framework, it will vary
       
   319 according to the service.
       
   320 
       
   321 For some services the opaque data may be a name intended for user display,
       
   322 for others it may be structured data that the service's client-side code can interpret.
       
   323 
       
   324 @return the service implementation's opaque data.
       
   325 */
       
   326 EXPORT_C const TDesC8& TApaAppServiceInfo::OpaqueData() const
       
   327 	{
       
   328 	if (iOpaqueData)
       
   329 		{
       
   330 		return *iOpaqueData;
       
   331 		}
       
   332 	return KNullDesC8;
       
   333 	}
       
   334 
       
   335 //
       
   336 // class CApaAppServiceInfoArray
       
   337 //
       
   338 
       
   339 CApaAppServiceInfoArray::CApaAppServiceInfoArray()
       
   340 	{
       
   341 	}
       
   342 
       
   343 //
       
   344 // class CApaAppServiceInfoArrayWrapper
       
   345 //
       
   346 
       
   347 CApaAppServiceInfoArrayWrapper* CApaAppServiceInfoArrayWrapper::NewL(CArrayFix<TApaAppServiceInfo>* aServiceInfoArray)
       
   348 	{
       
   349 	CApaAppServiceInfoArrayWrapper* self = new CApaAppServiceInfoArrayWrapper(aServiceInfoArray);
       
   350 	if (!self)
       
   351 		{
       
   352 		CleanupServiceArray(aServiceInfoArray);
       
   353 		User::LeaveNoMemory();
       
   354 		}
       
   355 	return self;
       
   356 	}
       
   357 
       
   358 CApaAppServiceInfoArrayWrapper::CApaAppServiceInfoArrayWrapper(CArrayFix<TApaAppServiceInfo>* aServiceInfoArray)
       
   359 	: iServiceInfoArray(aServiceInfoArray)
       
   360 	{
       
   361 	}
       
   362 
       
   363 CApaAppServiceInfoArrayWrapper::~CApaAppServiceInfoArrayWrapper()
       
   364 	{
       
   365 	CleanupServiceArray(iServiceInfoArray);
       
   366 	iServiceInfoArray = NULL;
       
   367 	}
       
   368 
       
   369 TArray<TApaAppServiceInfo> CApaAppServiceInfoArrayWrapper::Array()
       
   370 	{
       
   371 	__ASSERT_ALWAYS(iServiceInfoArray, Panic(EPanicNullPointer));
       
   372 	return iServiceInfoArray->Array();
       
   373 	}
       
   374 
       
   375 
       
   376 //
       
   377 // Class CApaAppData
       
   378 //
       
   379 
       
   380 EXPORT_C CApaAppData* CApaAppData::NewL(const TApaAppEntry& aAppEntry, RFs& aFs, const TDesC& aDefaultAppIconFileName)
       
   381 	{
       
   382 	CApaAppData* self=new(ELeave) CApaAppData(aFs);
       
   383 	CleanupStack::PushL(self);
       
   384 	self->ConstructL(aAppEntry, aDefaultAppIconFileName);
       
   385 	CleanupStack::Pop(); // self
       
   386 	return self;
       
   387 	}
       
   388 
       
   389 CApaAppData::CApaAppData(RFs& aFs)
       
   390 	:iCaption(NULL), iShortCaption(NULL), 
       
   391 	iIsPresent(CApaAppData::EIsPresent), iFs(aFs),
       
   392 	iNonMbmIconFile(EFalse),
       
   393 	iApplicationLanguage(ELangNone), iIndexOfFirstOpenService(-1),
       
   394 	iNonNativeApplicationType(TUid::Null())
       
   395 	{
       
   396 	}
       
   397 
       
   398 void CApaAppData::ConstructL(const TApaAppEntry& aAppEntry, const TDesC& aDefaultAppIconFileName)
       
   399 	{
       
   400 	iUidType = aAppEntry.iUidType; // if the 2nd UID is KUidAppRegistrationFile, iUidType will be updated in StoreApplicationInformation to reflect the TUidType for the application binary
       
   401 	if (ApaUtils::HandleAsRegistrationFile(aAppEntry.iUidType))
       
   402 		{
       
   403 		iRegistrationFile = aAppEntry.iFullName.AllocL();
       
   404 		}
       
   405 	else
       
   406 		{
       
   407 		iFullName = aAppEntry.iFullName.AllocL();
       
   408 		}
       
   409 
       
   410 	iCapabilityBuf.FillZ(iCapabilityBuf.MaxLength());
       
   411 	iIcons = CApaAppIconArray::NewL();
       
   412 	iViewDataArray=new(ELeave) CArrayPtrFlat<CApaAppViewData>(1);
       
   413 	iOwnedFileArray=new(ELeave) CDesCArraySeg(1);
       
   414 	User::LeaveIfError(StoreApplicationInformation(aDefaultAppIconFileName));
       
   415 	}
       
   416 
       
   417 
       
   418 
       
   419 // Return a standard error code
       
   420 // The value returned only reflect the caption status
       
   421 // If there is errors setting up captions the old values are retained
       
   422 // All other errors are silently ignored
       
   423 // General notes:
       
   424 // 1. This method is deliberately very similar to the old CApaAppData::GetAifData
       
   425 //    in order to maintain behavioural compatibility for V1 apps
       
   426 // 2. Be very careful in this method, because it can be called on a newly constructed object,
       
   427 //    or on an existing object, so don't assume member data pointers will be NULL
       
   428 TInt CApaAppData::StoreApplicationInformation(const TDesC& aDefaultAppIconFileName)
       
   429 	{
       
   430 	HBufC* caption = NULL;
       
   431 	HBufC* shortCaption = NULL;
       
   432 
       
   433 	iTimeStamp = TTime(0); // cannot init in constructor because this function can be called on an existing CApaAppData object
       
   434 
       
   435 	CApaAppInfoReader* appInfoReader = NULL;
       
   436 	TBool readSuccessful = EFalse;
       
   437 	TBool isNonNativeApp = EFalse;
       
   438 	if (iRegistrationFile != NULL)
       
   439 		{
       
   440 		if (TParsePtrC(*iRegistrationFile).Path().CompareF(KLitPathForNonNativeResourceAndIconFiles)==0)
       
   441 			{
       
   442 			isNonNativeApp = ETrue;
       
   443 			}
       
   444 		__ASSERT_ALWAYS(&aDefaultAppIconFileName,Panic(EPanicNullDefaultAppIconFileName));
       
   445 
       
   446 		TRAPD(err,appInfoReader = CApaAppInfoReaderV2::NewL(iFs, *iRegistrationFile, iUidType[2], aDefaultAppIconFileName));
       
   447 		if(err != KErrNone)
       
   448 			{
       
   449 			appInfoReader = NULL;
       
   450 			}
       
   451 
       
   452 		if (appInfoReader == NULL)
       
   453 			{
       
   454 			if (iFullName == NULL)
       
   455 				{
       
   456 				// assume that if iFullName is NULL, this method has been called as part
       
   457 				// of constructing a new app data object. The CApaAppInfoReader derived object
       
   458 				// could not be created, therefore we have no way to determine the full filename
       
   459 				// of the app binary, so give up
       
   460 				return KErrNoMemory;
       
   461 				}
       
   462 			}
       
   463 		else
       
   464 			{
       
   465 			readSuccessful = appInfoReader->Read();
       
   466 			HBufC* appBinaryFullName=appInfoReader->AppBinaryFullName();
       
   467 			if (appBinaryFullName)
       
   468 				{
       
   469 				delete iFullName;
       
   470 				iFullName = appBinaryFullName;
       
   471 				}
       
   472 			if (iFullName == NULL)
       
   473 				{
       
   474 				delete appInfoReader;
       
   475 				return KErrNoMemory;
       
   476 				}
       
   477 			// if this object has just been constructed, iUidType is currently the TUidType
       
   478 			// of the registration file, it should be the TUidType of the app binary file
       
   479 			TUidType uidType = appInfoReader->AppBinaryUidType();
       
   480 			if (uidType[1].iUid != KNullUid.iUid)
       
   481 				{
       
   482 				iUidType = uidType;
       
   483 				}
       
   484 			}
       
   485 		}
       
   486 
       
   487 	if (appInfoReader != NULL)
       
   488 		{
       
   489 		// must get captions and icons regardless of value of readSuccessful,
       
   490 		// because the V1 reader might have read captions
       
   491 		// and default icons from a caption file/default AIF, even if other info wasn't read
       
   492 		// from an application specific AIF file (!readSuccessful)
       
   493 		// this is done to maintain behavioural compatibility with V1
       
   494 		caption = appInfoReader->Caption();
       
   495 		shortCaption = appInfoReader->ShortCaption();
       
   496 
       
   497 		CApaAppIconArray* icons = appInfoReader->Icons();
       
   498 		if(icons)
       
   499 			{
       
   500 			delete iIcons;
       
   501 			iIcons = icons;
       
   502 			}
       
   503 		else
       
   504 			{
       
   505 			TRAPD(err,icons = CApaAppIconArray::NewL());
       
   506 			if(err == KErrNone)
       
   507 				{
       
   508 				delete iIcons;
       
   509 				iIcons = icons;
       
   510 				}
       
   511 			}
       
   512 			
       
   513 		iTimeStamp = appInfoReader->TimeStamp();
       
   514 		delete iLocalisableResourceFileName;
       
   515 		iLocalisableResourceFileName = appInfoReader->LocalisableResourceFileName();
       
   516 		iLocalisableResourceFileTimeStamp = appInfoReader->LocalisableResourceFileTimeStamp();
       
   517 
       
   518 		if (isNonNativeApp)
       
   519 			{
       
   520 			// In the case of a non-native app, the resource file has been prefixed with a
       
   521 			// TCheckedUid, the second of whose UIDs is the non-native application type uid.
       
   522 			TEntry entry;
       
   523 			__ASSERT_ALWAYS(iRegistrationFile, Panic(EPanicNullPointer));
       
   524 			const TInt error=iFs.Entry(*iRegistrationFile, entry);
       
   525 			if (error!=KErrNone)
       
   526 				{
       
   527 				delete appInfoReader;
       
   528 				return error;
       
   529 				}
       
   530 			__ASSERT_DEBUG(entry.iType[0].iUid==KUidPrefixedNonNativeRegistrationResourceFile, Panic(EPanicUnexpectedUid));
       
   531 			iNonNativeApplicationType=entry.iType[1];
       
   532 			}
       
   533 
       
   534 		delete iOpaqueData;
       
   535 		iOpaqueData = appInfoReader->OpaqueData();
       
   536 
       
   537 		if (readSuccessful)
       
   538 			{
       
   539 			appInfoReader->Capability(iCapabilityBuf);
       
   540 
       
   541 			iDefaultScreenNumber = appInfoReader->DefaultScreenNumber();
       
   542 
       
   543 			delete iIconFileName;
       
   544 			iIconFileName = appInfoReader->IconFileName();
       
   545 			iNonMbmIconFile = appInfoReader->NonMbmIconFile();
       
   546 			iApplicationLanguage = appInfoReader->AppLanguage();
       
   547 					
       
   548 			// views
       
   549 			iViewDataArray->ResetAndDestroy();
       
   550 			CArrayPtrFlat<CApaAppViewData>* viewDataArray = appInfoReader->Views();
       
   551 			if (viewDataArray)
       
   552 				{
       
   553 				delete iViewDataArray;
       
   554 				iViewDataArray = viewDataArray;
       
   555 				}
       
   556 
       
   557 			// owned files
       
   558 			iOwnedFileArray->Reset();
       
   559 			CDesCArray* ownedFileArray = appInfoReader->OwnedFiles();
       
   560 			if (ownedFileArray)
       
   561 				{
       
   562 				delete iOwnedFileArray;
       
   563 				iOwnedFileArray = ownedFileArray;
       
   564 				}
       
   565 			
       
   566 			UpdateServiceArray(appInfoReader->ServiceArray(iIndexOfFirstOpenService));
       
   567 			}
       
   568 		delete appInfoReader;
       
   569 		}
       
   570 
       
   571 	if (!caption)
       
   572 		{
       
   573 		TParsePtrC parse (*iFullName);
       
   574 		caption = parse.Name().Alloc();
       
   575 		}
       
   576 
       
   577 	// Put the captions into place
       
   578 	if (caption)
       
   579 		{
       
   580 		if (!shortCaption)
       
   581 			{
       
   582 			shortCaption = caption->Alloc();
       
   583 			if (!shortCaption)
       
   584 				{
       
   585 				delete caption;
       
   586 				caption = NULL;
       
   587 				}
       
   588 			}
       
   589 		}
       
   590 	if (caption)
       
   591 		{
       
   592 		delete iCaption;
       
   593 		iCaption = caption;
       
   594 		delete iShortCaption;
       
   595 		iShortCaption = shortCaption;
       
   596 		}
       
   597 
       
   598 	return caption ? KErrNone : KErrNoMemory;
       
   599 	}
       
   600 
       
   601 EXPORT_C CApaAppData::~CApaAppData()
       
   602 // Just delete components, NOT iNext (next CApaAppData in the list).
       
   603 	{
       
   604 	delete iSuccessor;
       
   605 	delete iCaption;
       
   606 	delete iShortCaption;
       
   607 	delete iFullName;
       
   608 	delete iIcons;
       
   609 
       
   610 	if(iViewDataArray)
       
   611 		{
       
   612 		iViewDataArray->ResetAndDestroy();
       
   613 		delete iViewDataArray;
       
   614 		}
       
   615 	delete iOwnedFileArray;
       
   616 	delete iIconFileName;
       
   617 	delete iLocalisableResourceFileName;
       
   618 	if (iServiceArray)
       
   619 		{
       
   620 		CleanupServiceArray(iServiceArray);
       
   621 		iServiceArray = NULL;
       
   622 		}
       
   623 	delete iOpaqueData;
       
   624 	delete iRegistrationFile;
       
   625 	iNext = NULL;
       
   626 	}
       
   627 
       
   628 void CApaAppData::UpdateServiceArray(CArrayFixFlat<TApaAppServiceInfo>* aNewServiceArray)
       
   629 	{
       
   630 	// clear out any existing service info
       
   631 	if (iServiceArray)
       
   632 		{
       
   633 		CleanupServiceArray(iServiceArray);
       
   634 		iServiceArray = NULL;
       
   635 		}
       
   636 	// store new service array
       
   637 	iServiceArray = aNewServiceArray;
       
   638 	}
       
   639 	
       
   640 TDataTypePriority CApaAppData::DataType(const TDataType& aDataType, const CArrayFixFlat<TDataTypeWithPriority>& aDataTypeArray) const
       
   641 	{
       
   642 	TInt count=aDataTypeArray.Count();
       
   643 	for (TInt ii=0;ii<count;ii++)
       
   644 		{
       
   645 		const TDataTypeWithPriority& type=aDataTypeArray[ii];
       
   646 		if (type.iDataType==aDataType)
       
   647 			{
       
   648 			return type.iPriority;
       
   649 			}
       
   650 		else
       
   651 			{
       
   652 			TPtrC8 src=type.iDataType.Des8();
       
   653 			TPtrC8 trg=aDataType.Des8();
       
   654 			if (src.Match(trg)==0 || trg.Match(src)==0)
       
   655 				{
       
   656 				if (type.iPriority == KDataTypePrioritySystem)
       
   657 					{
       
   658 					// This is more or less a magic number so don't decrement
       
   659 					return KDataTypePrioritySystem;
       
   660 					}
       
   661 				else
       
   662 					{
       
   663 					return (TInt16)(type.iPriority-1);
       
   664 					}
       
   665 				}
       
   666 			}
       
   667 		}
       
   668 	return KDataTypePriorityNotSupported;
       
   669 	}
       
   670 
       
   671 /**
       
   672  * Returns the CApaMaskedBitmap of size aSize for the application associated
       
   673  * with this CApaAppData. If there is not a bitmap of exact size aSize then 
       
   674  * the icon closest to but smaller than the one asked for is returned, or NULL if
       
   675  * none is smaller.
       
   676  * 
       
   677  * @since Uikon1.2
       
   678  */
       
   679 EXPORT_C CApaMaskedBitmap* CApaAppData::Icon(TSize aSize) const
       
   680 	{
       
   681 	__ASSERT_ALWAYS(iIcons, Panic(EPanicNullPointer));
       
   682 	return iIcons->IconBySize(aSize);
       
   683 	}
       
   684 
       
   685 /**
       
   686  * Returns a pointer to the small, medium or large application icon for aIconIndex equal to 0, 1 or 2 respectively.
       
   687  * Panics if aIconIndex is not one of these three values.
       
   688  *
       
   689  * This method is superseded by an overload which returns the icon by finding the closest match to a specified size.
       
   690  *
       
   691  * @deprecated
       
   692  */
       
   693 EXPORT_C CApaMaskedBitmap* CApaAppData::Icon(TInt aIconIndex) const
       
   694 	{
       
   695 	__ASSERT_DEBUG(aIconIndex>-1 && aIconIndex<3, Panic(EDPanicBadIconSize)); //only support old behaviour
       
   696 	TSize sizeExpected;
       
   697 	switch(aIconIndex)
       
   698 		{
       
   699 	case KApaIconIndexSmall:
       
   700 		sizeExpected=TSize(24,24);
       
   701 		break;
       
   702 	case KApaIconIndexMedium:
       
   703 		sizeExpected=TSize(32,32);
       
   704 		break;
       
   705 	case KApaIconIndexLarge:
       
   706 		sizeExpected=TSize(48,48);
       
   707 		break;
       
   708 	default:
       
   709 		break;
       
   710 		}
       
   711 	return Icon(sizeExpected);
       
   712 	}
       
   713 
       
   714 EXPORT_C CArrayFixFlat<TSize>* CApaAppData::IconSizesL() const
       
   715 /** Gets the sizes of icons available for the application. 
       
   716 
       
   717 @return A pointer to an array of the icon sizes. The caller takes ownership. */
       
   718 	{
       
   719 	__ASSERT_ALWAYS(iIcons, Panic(EPanicNullPointer));;
       
   720 	return iIcons->IconSizesL();
       
   721 	}
       
   722 
       
   723 EXPORT_C TApaAppEntry CApaAppData::AppEntry() const
       
   724 /** Constructs an application entry based on this object.
       
   725 
       
   726 @return The application entry. */
       
   727 	{
       
   728 	return TApaAppEntry(iUidType,*iFullName);
       
   729 	}
       
   730 
       
   731 
       
   732 EXPORT_C void CApaAppData::Capability(TDes8& aCapabilityBuf)const
       
   733 /** Gets the application's capabilities.
       
   734 
       
   735 @param aCapabilityBuf On return, contains the application's capabilities, 
       
   736 specified as a TApaAppCapabilityBuf object. */
       
   737 	{
       
   738 	TApaAppCapability::CopyCapability(aCapabilityBuf,iCapabilityBuf);
       
   739 	}
       
   740 
       
   741 /**
       
   742  * Returns a pointer to the array of view data objects current for this application. Does not imply transfer of ownership.
       
   743  *
       
   744  * @since App-Framework_6.1
       
   745  */
       
   746 EXPORT_C CArrayPtrFlat<CApaAppViewData>* CApaAppData::Views() const
       
   747 	{
       
   748 	return iViewDataArray;
       
   749 	}
       
   750 
       
   751 /**
       
   752  * Returns a pointer to the array of files for which this application claims ownership. Does not imply transfer of ownership.
       
   753  *
       
   754  * @since App-Framework_6.1
       
   755  */
       
   756 EXPORT_C CDesCArray* CApaAppData::OwnedFiles() const
       
   757 	{
       
   758 	return iOwnedFileArray;
       
   759 	}
       
   760 
       
   761 TBool CApaAppData::Update(const TDesC& aDefaultAppIconFileName)
       
   762 // returns true if changes were made to the cached data
       
   763 	{
       
   764 	__APA_PROFILE_START(17);
       
   765 	TBool changed=EFalse;
       
   766 
       
   767 	// Get app info file entry
       
   768 	TEntry entry;
       
   769 	TInt ret;
       
   770 	if (iRegistrationFile != NULL)
       
   771 		{
       
   772 		ret = iFs.Entry(*iRegistrationFile, entry);
       
   773 		if (ret==KErrNone && entry.iModified!=iTimeStamp)
       
   774 			{
       
   775 			// assume registration file may have changed
       
   776 			changed = ETrue;
       
   777 			}
       
   778 		else
       
   779 			{
       
   780 			if (iLocalisableResourceFileName)
       
   781 				{
       
   782 				// see if localisable resource information might have changed
       
   783 				TParse parse;
       
   784 				ret = parse.SetNoWild(KAppResourceFileExtension, iLocalisableResourceFileName, NULL);
       
   785 				if (ret == KErrNone)
       
   786 					{
       
   787 					TFileName resourceFileName(parse.FullName());
       
   788 					BaflUtils::NearestLanguageFile(iFs, resourceFileName);
       
   789 					if (resourceFileName.CompareF(*iLocalisableResourceFileName)!=0)
       
   790 						{
       
   791 						changed = ETrue;
       
   792 						}
       
   793 					else
       
   794 						{
       
   795 						ret = iFs.Entry(*iLocalisableResourceFileName, entry);
       
   796 						if ((ret==KErrNotFound && iLocalisableResourceFileTimeStamp!=TTime(0)) ||
       
   797 							(ret==KErrNone && entry.iModified!=iLocalisableResourceFileTimeStamp))
       
   798 							{
       
   799 							changed = ETrue;
       
   800 							}
       
   801 						}
       
   802 					}
       
   803 				}
       
   804 			}
       
   805 		}
       
   806 	if (changed)
       
   807 		{
       
   808 		// Ignore result, nothing we can do in case failure
       
   809 		// and the old values should be preserved
       
   810         const TInt ignore = StoreApplicationInformation(aDefaultAppIconFileName);
       
   811 		} //lint !e529 Suppress symbol 'ignore' not subsequently referenced
       
   812 		
       
   813 	__APA_PROFILE_END(17);
       
   814 	return changed;
       
   815 	}
       
   816 
       
   817 EXPORT_C TDataTypePriority CApaAppData::DataType(const TDataType& aDataType) const
       
   818 // returns the priority of the data type
       
   819 /** If the application supports the specified data type, the function returns 
       
   820 the priority with which it should be selected for handling it.
       
   821 
       
   822 If the application does not support the specified data type, 
       
   823 KDataTypePriorityNotSupported is returned.
       
   824 
       
   825 Note that the function supports wildcard matching, using "*" and "?". In the case 
       
   826 of a wildcard match, the priority value returned is reduced by 1, so that in this 
       
   827 case, the application could never have the maximum priority 
       
   828 (KDataTypePriorityUserSpecified).
       
   829 
       
   830 @param aDataType The data type of interest.
       
   831 @return The priority with which the application should be selected for handling 
       
   832 the specified data type, or KDataTypePriorityNotSupported if the data type is 
       
   833 not supported. */
       
   834 	{
       
   835 	if (iIndexOfFirstOpenService >= 0)
       
   836 		{
       
   837 		__ASSERT_ALWAYS(iServiceArray, Panic(EPanicNullPointer));
       
   838 		const CArrayFixFlat<TDataTypeWithPriority>& dataTypeArray = 
       
   839 			(*iServiceArray)[iIndexOfFirstOpenService].DataTypes();
       
   840 		return DataType(aDataType, dataTypeArray);
       
   841 		}
       
   842 	return KDataTypePriorityNotSupported;
       
   843 	}
       
   844 
       
   845 
       
   846 EXPORT_C TBool CApaAppData::IsPending() const
       
   847 	{
       
   848 	return (iIsPresent==CApaAppData::EPresentPendingUpdate 
       
   849 		|| iIsPresent==CApaAppData::ENotPresentPendingUpdate);
       
   850 	}
       
   851 
       
   852 EXPORT_C TBool CApaAppData::CanUseScreenMode(TInt aScreenMode)
       
   853 /** Tests whether the specified screen mode is valid for any of 
       
   854 this application's views. If the app has no views, the function 
       
   855 assumes that only the default screen mode (at screen mode index 
       
   856 zero) is allowed. This function is used by CApaAppList to create 
       
   857 a list of valid applications.
       
   858 
       
   859 @param aScreenMode The index of the screen mode.
       
   860 @return True if screen mode is valid, otherwise false. */
       
   861 	{
       
   862 	const TInt count=iViewDataArray->Count();
       
   863 	// If there are no views, assume only the default screen mode is allowed
       
   864 	TBool ret=(count==0 && aScreenMode==0);
       
   865 	for(TInt ii=0;ii<count;ii++)
       
   866 		{
       
   867 		const CApaAppViewData* data=(*iViewDataArray)[ii];
       
   868 		if(data->ScreenMode()==aScreenMode)
       
   869 			{
       
   870 			ret=ETrue;
       
   871 			break;
       
   872 			}
       
   873 		}
       
   874 	return ret;
       
   875 	}
       
   876 
       
   877 EXPORT_C void CApaAppData::GetIconInfo(TInt& aIconCount, TInt& aDefaultIconsUsed) const
       
   878 /** Gets icon information for the app
       
   879 
       
   880 @param aIconCount On return, this contains the number of app icons
       
   881 @param aDefaultIconsUsed On return, this indicates whether the default icons have been used
       
   882 */
       
   883 	{
       
   884 	__ASSERT_ALWAYS(iIcons, Panic(EPanicNullPointer));;
       
   885 	aIconCount = iIcons->Count();
       
   886 	aDefaultIconsUsed = iIcons->DefaultIconsUsed();
       
   887 	}
       
   888 
       
   889 /** Gets the default screen number used by the application.
       
   890 
       
   891 A device may have more than once screen. This function
       
   892 returns the number associated with the screen which will
       
   893 be the default screen used by the application.
       
   894 
       
   895 @return The default screen number
       
   896 */
       
   897 EXPORT_C TUint CApaAppData::DefaultScreenNumber() const
       
   898 	{
       
   899 	return iDefaultScreenNumber;
       
   900 	}
       
   901 
       
   902 /** Returns true if app info was provided by a registration file
       
   903 
       
   904 @return true if app info was provided by a registration file
       
   905 */
       
   906 EXPORT_C TBool CApaAppData::RegistrationFileUsed() const
       
   907 	{
       
   908 	return iRegistrationFile != NULL;
       
   909 	}
       
   910 
       
   911 /** Returns the full filename of the registration resource file
       
   912 
       
   913 @return The full path and filename of the registration resource file.
       
   914 @internalTechnology
       
   915 */
       
   916 EXPORT_C TPtrC CApaAppData::RegistrationFileName() const
       
   917 	{
       
   918 	if (iRegistrationFile)
       
   919 		{
       
   920 		return *iRegistrationFile;
       
   921 		}
       
   922 	else
       
   923 		{
       
   924 		return TPtrC(KNullDesC);
       
   925 		}
       
   926 	}
       
   927 
       
   928 
       
   929 /** Returns the full filename of the localisable resource file
       
   930 
       
   931 @return The full path and filename of the localisable resource file.
       
   932 @internalTechnology
       
   933 */
       
   934 EXPORT_C TPtrC CApaAppData::LocalisableResourceFileName() const
       
   935 	{
       
   936 	if (iLocalisableResourceFileName)
       
   937 		{
       
   938 		return *iLocalisableResourceFileName;
       
   939 		}
       
   940 	else
       
   941 		{
       
   942 		return TPtrC(KNullDesC);
       
   943 		}
       
   944 	}
       
   945 
       
   946 
       
   947 /** Returns the non-native application opaque data
       
   948 
       
   949 @return The non-native application opaque data.
       
   950 @internalComponent
       
   951 */
       
   952 EXPORT_C TPtrC8 CApaAppData::OpaqueData() const
       
   953 	{
       
   954 	if (iOpaqueData)
       
   955 		{
       
   956 		return *iOpaqueData;
       
   957 		}
       
   958 	else
       
   959 		{
       
   960 		return TPtrC8(KNullDesC8);
       
   961 		}
       
   962 	}
       
   963 
       
   964 EXPORT_C TUid CApaAppData::NonNativeApplicationType() const
       
   965 /** @internalComponent */
       
   966 	{
       
   967 	return iNonNativeApplicationType;
       
   968 	}
       
   969 
       
   970 /** Returns the full filename of the file containing application icons
       
   971 
       
   972 @return The full path and filename of the icon file.
       
   973 */
       
   974 EXPORT_C TPtrC CApaAppData::IconFileName() const
       
   975 	{
       
   976 	if (iIconFileName)
       
   977 		{
       
   978 		return *iIconFileName;
       
   979 		}
       
   980 	else
       
   981 		{
       
   982 		return TPtrC(KNullDesC);
       
   983 		}
       
   984 	}
       
   985 
       
   986 /** Returns true if the application provides a non-MBM icon filename.
       
   987 
       
   988 If this function returns false, this does not necessarily mean
       
   989 an MBM icon filename is provided.
       
   990 
       
   991 @return true if the application provides a non-MBM icon filename.
       
   992 */
       
   993 EXPORT_C TBool CApaAppData::NonMbmIconFile() const
       
   994 	{
       
   995 	return iNonMbmIconFile;
       
   996 	}
       
   997 
       
   998 
       
   999 /** Determines the current language the application is using to display its
       
  1000 user interface.
       
  1001 @return The current language.
       
  1002 */	
       
  1003 EXPORT_C TLanguage CApaAppData::ApplicationLanguage() const
       
  1004 	{
       
  1005 	return iApplicationLanguage;
       
  1006 	}
       
  1007 
       
  1008 /** Returns true if the application implements the specified service.
       
  1009 @param aServiceUid The service UID.
       
  1010 @return true if the application implements the specified service.
       
  1011 @internalComponent
       
  1012 */
       
  1013 EXPORT_C TBool CApaAppData::ImplementsService(TUid aServiceUid) const
       
  1014 	{
       
  1015 	if (iServiceArray)
       
  1016 		{
       
  1017 		TInt count = iServiceArray->Count();
       
  1018 		for (TInt i = count-1; i >= 0; i--)
       
  1019 			{
       
  1020 			if ((*iServiceArray)[i].Uid() == aServiceUid)
       
  1021 				{
       
  1022 				return ETrue;
       
  1023 				}
       
  1024 			}
       
  1025 		}
       
  1026 	return EFalse;
       
  1027 	}
       
  1028 	
       
  1029 /** Checks if the application implements the specified service and if the 
       
  1030 service explicitly supports the datatype. Explicitly means that the datatype is
       
  1031 listed in the service's list of datatype in the registration file and is
       
  1032 not the general datatype associated with the application (aka the Open service).
       
  1033 @param aServiceUid The service UID.
       
  1034 @param aDataType The datattype
       
  1035 @return The priority. KDataTypePriorityNotSupported if the app doesn't support
       
  1036 this service with this datatype.
       
  1037 @internalComponent
       
  1038 */
       
  1039 TInt CApaAppData::ImplementsServiceWithDataType(TUid aServiceUid, const TDataType& aDataType) const
       
  1040 	{
       
  1041 	TInt result = KDataTypePriorityNotSupported;
       
  1042 	if (iServiceArray)
       
  1043 		{
       
  1044 		TInt count = iServiceArray->Count();
       
  1045 		for (TInt i = count-1; i >= 0; i--)
       
  1046 			{
       
  1047 			// There can be more than one instance of a given service so we iterate
       
  1048 			// through the whole service list even if we have already found a suitable
       
  1049 			// service.
       
  1050 			if ((*iServiceArray)[i].Uid() == aServiceUid)
       
  1051 				{
       
  1052 				const CArrayFixFlat<TDataTypeWithPriority>& datatypes =
       
  1053 					(*iServiceArray)[i].DataTypes();
       
  1054 				TInt priority = DataType(aDataType, datatypes);
       
  1055 				if (priority > result)
       
  1056 					{
       
  1057 					result = priority;
       
  1058 					}
       
  1059 				}
       
  1060 			}
       
  1061 		}
       
  1062 	return result;
       
  1063 	}
       
  1064 
       
  1065 EXPORT_C void CApaAppData::SetShortCaptionL(const TDesC& aShortCaption)
       
  1066 	{
       
  1067 	__ASSERT_ALWAYS(iShortCaption, Panic(EPanicNullPointer));
       
  1068 	if(iShortCaption->Compare(aShortCaption) != 0)
       
  1069 		{
       
  1070 		HBufC* newShortCaption=aShortCaption.AllocL();
       
  1071 		delete iShortCaption; // after the AllocL succeeds
       
  1072 		iShortCaption = newShortCaption;
       
  1073 		}
       
  1074 	}
       
  1075 
       
  1076 //
       
  1077 // Class CApaAppList
       
  1078 //
       
  1079 
       
  1080 EXPORT_C CApaAppList* CApaAppList::NewL(RFs& aFs,CApaAppRegFinder* aAppRegFinder,TBool aLoadMbmIconsOnDemand, TInt aIdlePeriodicDelay)
       
  1081 	{
       
  1082 	CApaAppList* self=new CApaAppList(aFs, aAppRegFinder,aLoadMbmIconsOnDemand, aIdlePeriodicDelay);
       
  1083 	if (!self)
       
  1084 		{
       
  1085 		delete aAppRegFinder;
       
  1086 		User::LeaveNoMemory();
       
  1087 		}
       
  1088 	else
       
  1089 		{
       
  1090 		CleanupStack::PushL(self);
       
  1091 		self->ConstructL();
       
  1092 		CleanupStack::Pop(self);
       
  1093 		}
       
  1094 	return self;
       
  1095 	}
       
  1096 
       
  1097 CApaAppList::CApaAppList(RFs& aFs, CApaAppRegFinder* aAppRegFinder,TBool aLoadMbmIconsOnDemand, TInt aIdlePeriodicDelay)
       
  1098 	:iFs(aFs),
       
  1099 	iFlags(0),
       
  1100 	iAppRegFinder(aAppRegFinder),
       
  1101 	iIdlePeriodicDelay(aIdlePeriodicDelay),
       
  1102 	iLoadMbmIconsOnDemand(aLoadMbmIconsOnDemand)
       
  1103 	{
       
  1104 	}
       
  1105 	
       
  1106 void CApaAppList::ConstructL()
       
  1107 	{
       
  1108 	User::LeaveIfError(iFsShareProtected.Connect());
       
  1109 	User::LeaveIfError(iFsShareProtected.ShareProtected());
       
  1110 	User::LeaveIfError(Dll::SetTls(this));
       
  1111 	
       
  1112 	//Start language change monitor.
       
  1113 	iAppLangMonitor = CApaLangChangeMonitor::NewL(*this);
       
  1114 	}
       
  1115 	
       
  1116 EXPORT_C CApaAppList::~CApaAppList()
       
  1117 /** Frees all resources prior to destruction, including the application data list. */
       
  1118 	{
       
  1119 	iValidFirstAppData = NULL;
       
  1120 	iFlags&=~EFirstScanComplete;
       
  1121 	CApaAppData* next = NULL;
       
  1122 	for (CApaAppData* appData=iAppData; appData; appData = next)
       
  1123 		{
       
  1124 		next = appData->iNext;
       
  1125 		delete appData;
       
  1126 		}
       
  1127 	iAppData = NULL;
       
  1128 	iObserver = NULL;
       
  1129 	
       
  1130 	iFsShareProtected.Close();
       
  1131 	
       
  1132 	delete iDefaultIconArray;
       
  1133 	delete iDefaultAppIcon;
       
  1134 	delete iAppRegFinder;
       
  1135 	delete iAppIdler;
       
  1136 	}
       
  1137 
       
  1138 EXPORT_C void CApaAppList::StartIdleUpdateL()
       
  1139 /** Updates the list asynchronously, using an idle time active object, 
       
  1140 and no observer. When the update is finished, the resulting app 
       
  1141 list is stored. */
       
  1142 	{
       
  1143 
       
  1144 	// find the default icons (.mbm file) for applications, wrt current locale
       
  1145 	TFileName* tempFileName = new(ELeave) TFileName;
       
  1146 	CleanupStack::PushL(tempFileName);
       
  1147 	tempFileName->Append(KDefaultAppIconMbm);
       
  1148 	BaflUtils::NearestLanguageFile(iFs, *tempFileName); 
       
  1149 	delete iDefaultAppIcon;
       
  1150 	iDefaultAppIcon = NULL;	
       
  1151 	iDefaultAppIcon = HBufC::NewL(tempFileName->Size());
       
  1152 	
       
  1153 	TPtr iconptr = iDefaultAppIcon->Des();
       
  1154 	iconptr.Append(*tempFileName);
       
  1155 	CleanupStack::PopAndDestroy(tempFileName); 
       
  1156 	
       
  1157 	// DEF076594 - if changing locale, need to update the default icons here
       
  1158 	// If updating the default icons array fails, the array is left in the state
       
  1159 	// it was in before the call.	
       
  1160 	if(iDefaultIconArray)
       
  1161 		{
       
  1162 		TRAP_IGNORE(UpdateDefaultIconsL());
       
  1163 		}
       
  1164 	
       
  1165 	// start to scan.
       
  1166 	if (iAppIdler)
       
  1167 		{
       
  1168 		delete iAppIdler;
       
  1169 		iAppIdler=NULL;
       
  1170 		}
       
  1171 
       
  1172 	// DEF072701
       
  1173 	// When performing the update scan let the idle object have lower priority.
       
  1174 	if (IsFirstScanComplete())
       
  1175 		{
       
  1176 		iAppIdler=CPeriodic::NewL(CActive::EPriorityLow);
       
  1177 		}
       
  1178 	else
       
  1179 		{
       
  1180 		iAppIdler=CPeriodic::NewL(CActive::EPriorityStandard);
       
  1181 		}
       
  1182 	SetPending(iAppData);
       
  1183 	iCurrentApp=TApaAppEntry();
       
  1184 	iScanStage=EFirstStageScan;
       
  1185 	__ASSERT_ALWAYS(iAppRegFinder, Panic(EPanicNullPointer));
       
  1186 	iAppRegFinder->FindAllAppsL();
       
  1187  
       
  1188  	// DEF072701
       
  1189  	// If this is the first scan i.e the boot scan then it may take some time. Thus
       
  1190  	// the periodic delay value should be used so that this process will stop periodically 
       
  1191  	// to allow time for other processes.
       
  1192  	// If this is just a re-scan it should take much less time. Therefore it should just
       
  1193  	// be completed in one go rather than periodically delayed. Thus the delay value
       
  1194  	// should be set to 0.
       
  1195 	iAppIdler->Start(KIdleStartDelay, IsFirstScanComplete()? 0 : iIdlePeriodicDelay, TCallBack(IdleUpdateCallbackL, this));
       
  1196 	}
       
  1197 
       
  1198 EXPORT_C void CApaAppList::StartIdleUpdateL(MApaAppListObserver* aObserver)
       
  1199 /** Updates the list asynchronously, using an idle time active object 
       
  1200 and an observer. When the update is finished, the resulting app list 
       
  1201 is stored and the observer is notified with an MApaAppListServObserver::EAppListChanged 
       
  1202 message, if the list changed.
       
  1203 @param aObserver Observer to be notified when the update has finished. */
       
  1204 	{
       
  1205 	iObserver=aObserver;
       
  1206 	if (iAppIdler==NULL)
       
  1207 		{
       
  1208 		// if iAppIdler exists then we're already in the middle of an update and
       
  1209 		// may have changed iUpdateCounter without yet reporting the changes
       
  1210 		iOldUpdateCounter=iUpdateCounter;
       
  1211 		}
       
  1212 	
       
  1213 	StartIdleUpdateL();
       
  1214 	}
       
  1215 
       
  1216 // Stop scanning applications if and uninstallation has started	
       
  1217 EXPORT_C void CApaAppList::StopScan()
       
  1218 	{
       
  1219 	if (iAppIdler)
       
  1220 		{
       
  1221 		delete iAppIdler;
       
  1222 		iAppIdler=NULL;
       
  1223 		}
       
  1224 	UndoSetPending(iAppData);
       
  1225 	}
       
  1226 	
       
  1227 // Allow scanning when uninstallation is complete
       
  1228 EXPORT_C void CApaAppList::RestartScanL()
       
  1229 	{
       
  1230 	TRAP_IGNORE(PurgeL());
       
  1231 	StartIdleUpdateL();
       
  1232 	}
       
  1233 
       
  1234 EXPORT_C void CApaAppList::InitListL(MApaAppListObserver* aObserver)
       
  1235 /** Starts updating the list asynchronously, by calling StartIdleUpdateL().
       
  1236 
       
  1237 @param aObserver Observer to be notified when the update has finished. */
       
  1238 	{
       
  1239 	StartIdleUpdateL(aObserver);
       
  1240 	}
       
  1241 	
       
  1242 TInt CApaAppList::IdleUpdateCallbackL(TAny* aObject)
       
  1243 	{
       
  1244 	CApaAppList* self=reinterpret_cast<CApaAppList*>(aObject);
       
  1245 	const TBool moreToCome=self->IdleUpdateL();
       
  1246 	if (moreToCome==EFalse)
       
  1247 		{
       
  1248 		if(self->iScanStage==EFirstStageScan)
       
  1249 			{
       
  1250 			self->iScanStage=EScanFinished;
       
  1251 			self->StopIdlerL();	
       
  1252 			}
       
  1253 		}
       
  1254 	return moreToCome;
       
  1255 	}
       
  1256 
       
  1257 void CApaAppList::StopIdlerL()
       
  1258 	{
       
  1259  
       
  1260 	delete iAppIdler;
       
  1261 	iAppIdler=NULL;
       
  1262 		
       
  1263 	// now that the scan is finished, iDefaultAppIcon is deleted
       
  1264 	delete iDefaultAppIcon;
       
  1265 	iDefaultAppIcon=NULL;
       
  1266 			
       
  1267 	if (iObserver)
       
  1268 		{
       
  1269 		if (iOldUpdateCounter!=iUpdateCounter)
       
  1270 			{
       
  1271 			//NotifyUpdate will notify clients for both list update and scan complete.
       
  1272 			iObserver->NotifyUpdate(MApaAppListServObserver::EAppListChanged);
       
  1273 			}
       
  1274 		else
       
  1275 			{
       
  1276 			//NotifyScanComplete will notify clients for scan complete.
       
  1277 			iObserver->NotifyScanComplete();
       
  1278 			}
       
  1279 			
       
  1280 		iObserver=NULL;
       
  1281 		}
       
  1282 	}
       
  1283 
       
  1284 TInt CApaAppList::IdleUpdateL()
       
  1285 // returns ETrue if there is more scanning to be done.
       
  1286 	{
       
  1287 	TBool more=EFalse;
       
  1288 	__ASSERT_ALWAYS(iAppRegFinder, Panic(EPanicNullPointer));
       
  1289 	TRAPD(err,more=iAppRegFinder->NextL(iCurrentApp, iForcedRegistrations));
       
  1290 	if (err!=KErrNone)
       
  1291 		return more;
       
  1292 	TBool hasChanged=EFalse;
       
  1293 	if (more)
       
  1294 		{
       
  1295 		TRAPD(err,UpdateNextAppL(iCurrentApp,hasChanged));
       
  1296 		if (err!=KErrNone)
       
  1297 			{
       
  1298 			SetNotFound(iAppData,hasChanged);
       
  1299 			more=EFalse; // abandon ship
       
  1300 			}
       
  1301 		}
       
  1302 	else
       
  1303 		{
       
  1304 		SetNotFound(iAppData,hasChanged);
       
  1305 		PurgeL();
       
  1306 		}
       
  1307 	//
       
  1308 	if (hasChanged)
       
  1309 		iUpdateCounter++;
       
  1310 	return more;
       
  1311 	}
       
  1312 
       
  1313 EXPORT_C TBool CApaAppList::IsIdleUpdateComplete() const
       
  1314 /** Tests whether an asynchronous update of the list is currently in progress.
       
  1315 
       
  1316 @return True if no asynchronous update of the list is currently in progress, 
       
  1317 otherwise false. */
       
  1318 	{
       
  1319 	return iAppIdler == NULL;
       
  1320 	}
       
  1321 
       
  1322 void CApaAppList::SetPending(CApaAppData* aAppData)
       
  1323 	// set all apps to pending update - we'll find them again as we scan
       
  1324 	{
       
  1325   	for (; aAppData; aAppData = aAppData->iNext)
       
  1326 		{
       
  1327 		if (aAppData->iIsPresent==CApaAppData::ENotPresent 
       
  1328 			|| aAppData->iIsPresent==CApaAppData::ENotPresentPendingUpdate)
       
  1329 			{
       
  1330 			aAppData->iIsPresent = CApaAppData::ENotPresentPendingUpdate;
       
  1331 			}
       
  1332 		else
       
  1333 			{
       
  1334 			aAppData->iIsPresent = CApaAppData::EPresentPendingUpdate;
       
  1335 			}
       
  1336 		}
       
  1337 	}
       
  1338 
       
  1339 void CApaAppList::UndoSetPending(CApaAppData* aAppData)
       
  1340 	// Reset all apps to pevious pending state so they don't get purged
       
  1341 	{
       
  1342   	for (; aAppData; aAppData = aAppData->iNext)
       
  1343 		{
       
  1344 		if (aAppData->iIsPresent == CApaAppData::EPresentPendingUpdate)
       
  1345 			{
       
  1346 			aAppData->iIsPresent = CApaAppData::EIsPresent;
       
  1347 			}
       
  1348 		}
       
  1349 	}
       
  1350 
       
  1351 void CApaAppList::SetNotFound(CApaAppData* aAppData, TBool& aHasChanged)
       
  1352 	// mark any unfound apps not present
       
  1353 	{
       
  1354 	while (aAppData)
       
  1355 		{
       
  1356 		if (aAppData->IsPending())
       
  1357 			{
       
  1358 			aAppData->iIsPresent = CApaAppData::ENotPresent;
       
  1359 			aHasChanged = ETrue;
       
  1360 			}
       
  1361 		aAppData = aAppData->iNext;
       
  1362 		}
       
  1363 	}
       
  1364 
       
  1365 void CApaAppList::AddToList( CApaAppData* aAppData )
       
  1366 {
       
  1367 	__ASSERT_DEBUG(aAppData, Panic(EPanicNullPointer));
       
  1368 	aAppData->iNext=iAppData;
       
  1369 	iAppData=aAppData;
       
  1370 }
       
  1371 
       
  1372 void CApaAppList::UpdateNextAppL(const TApaAppEntry& aAppEntry,TBool& aHasChanged)
       
  1373 	{
       
  1374 	CApaAppData* appData=AppDataByUid(aAppEntry.iUidType[2]);
       
  1375 	if (appData==NULL)
       
  1376 		{// not in list, so add it at the start
       
  1377 		TRAPD(err,appData=CApaAppData::NewL(aAppEntry, iFs, *iDefaultAppIcon));
       
  1378 		if (err==KErrNone)
       
  1379 			{
       
  1380 			AddToList( appData );
       
  1381 			aHasChanged=ETrue;
       
  1382 			}
       
  1383 		}
       
  1384 	else if (appData->IsPending())
       
  1385 		{ // not found yet during current scan - we may need to override this one
       
  1386 		
       
  1387 		// On a system which scans for registration .RSC files (V2 apps) first, followed by
       
  1388 		// .APP files (V1 apps), it's valid for a V1 app to override a V2 app (if the V2 app
       
  1389 		// has just been removed). If this is the case, assume it's ok to compare the V1 .APP filename,
       
  1390 		// with the V2 .RSC filename as their filenames will never match (which is what we want in this case).
       
  1391 		TPtrC currentFileName;
       
  1392 		if (appData->RegistrationFileUsed())
       
  1393 			{
       
  1394 			currentFileName.Set(*appData->iRegistrationFile);
       
  1395 			}
       
  1396 		else
       
  1397 			{
       
  1398 			currentFileName.Set(*appData->iFullName);
       
  1399 			}
       
  1400 		if (aAppEntry.iFullName.CompareF(currentFileName)!=0)
       
  1401 			{
       
  1402 			delete appData->iSuccessor;
       
  1403 			appData->iSuccessor = NULL;
       
  1404 			appData->iSuccessor = CApaAppEntry::NewL(aAppEntry);
       
  1405 
       
  1406 
       
  1407 			appData->iIsPresent = CApaAppData::ESuperseded;
       
  1408 			aHasChanged=ETrue;
       
  1409 			}
       
  1410 		else
       
  1411 			{
       
  1412 			if (appData->Update(*iDefaultAppIcon)
       
  1413 				|| appData->iIsPresent==CApaAppData::ENotPresentPendingUpdate) 
       
  1414 				{
       
  1415 				aHasChanged=ETrue; 
       
  1416 				}
       
  1417 			appData->iIsPresent = CApaAppData::EIsPresent;
       
  1418 			}
       
  1419 		}
       
  1420 	
       
  1421 	}
       
  1422 
       
  1423 /**
       
  1424 @internalComponent
       
  1425 */
       
  1426 EXPORT_C CApaAppData* CApaAppList::FindAndAddSpecificAppL(CApaAppRegFinder* aFinder, TUid aAppUid)
       
  1427 	{
       
  1428 //Scans and adds the specified application to the app list if found
       
  1429 	__ASSERT_DEBUG(aFinder, Panic(EPanicNullPointer));
       
  1430 	TBool found = EFalse;
       
  1431 	TApaAppEntry appEntry;
       
  1432 	aFinder->FindAllAppsL();
       
  1433 	while (aFinder->NextL(appEntry, iForcedRegistrations))
       
  1434 		{
       
  1435 		if (appEntry.iUidType[2] == aAppUid)
       
  1436 			{
       
  1437 			found = ETrue;
       
  1438 			break;
       
  1439 			}
       
  1440 		}
       
  1441 	
       
  1442 	CApaAppData* app = NULL;
       
  1443 	if (found)
       
  1444 		{
       
  1445 		// add the app to the list
       
  1446 		TBool hasChanged = EFalse;
       
  1447 		CApaAppData* prevFirstAppInList = iAppData;
       
  1448 		UpdateNextAppL(appEntry, hasChanged);
       
  1449 		if (iAppData != prevFirstAppInList)
       
  1450 			{
       
  1451 			// assume the new app was added to the list
       
  1452 			app = iAppData;
       
  1453 			}
       
  1454 		if (hasChanged)
       
  1455 			iUpdateCounter++;
       
  1456 		}
       
  1457 	return app;
       
  1458 	}
       
  1459 
       
  1460 EXPORT_C void CApaAppList::PurgeL()
       
  1461 /** Removes any applications from the list if they are no longer present 
       
  1462 on the phone. It updates applications that have been 
       
  1463 superceded. */
       
  1464 	{
       
  1465 	CApaAppData* appData=iAppData;
       
  1466 	CApaAppData* prev=NULL;
       
  1467 	while (appData)
       
  1468 		{
       
  1469 		CApaAppData* next=appData->iNext;
       
  1470 		if (appData->iIsPresent==CApaAppData::ENotPresent)
       
  1471 			{
       
  1472 			if (prev)
       
  1473 				prev->iNext=next;
       
  1474 			else
       
  1475 				iAppData=next;
       
  1476 			delete appData;
       
  1477 			}
       
  1478 		else if (appData->iIsPresent==CApaAppData::ESuperseded)
       
  1479 			{
       
  1480 			CApaAppData* newApp=NULL;
       
  1481 			TApaAppEntry appEntry;
       
  1482 			appData->iSuccessor->Get(appEntry);
       
  1483 			TRAPD(err,newApp=CApaAppData::NewL(appEntry, iFs,*iDefaultAppIcon));
       
  1484 			if (err==KErrNone)
       
  1485 				{
       
  1486 				// remove the old one and add the new one in its place
       
  1487 				if (prev)
       
  1488 					prev->iNext=newApp;
       
  1489 				else
       
  1490 					iAppData=newApp;
       
  1491 				newApp->iNext = appData->iNext;
       
  1492 				delete appData;
       
  1493 				// increment the iterator
       
  1494 				prev = newApp;
       
  1495 				}
       
  1496 			}
       
  1497 		else
       
  1498 			prev=appData;
       
  1499 		appData=next;
       
  1500 		}
       
  1501  
       
  1502 	ScanComplete();
       
  1503 	}
       
  1504 
       
  1505 EXPORT_C TInt CApaAppList::Count() const
       
  1506 /** Gets the count of applications present in the app list.
       
  1507 
       
  1508 @return The number of applications in the list. */
       
  1509 
       
  1510 	{
       
  1511 	TInt count=0;
       
  1512 	CApaAppData* appData=iAppData;
       
  1513 	while (appData)
       
  1514 		{
       
  1515 		count++;
       
  1516 		appData=appData->iNext;
       
  1517 		}
       
  1518 	return count;
       
  1519 	}
       
  1520 
       
  1521 EXPORT_C CApaAppData* CApaAppList::FirstApp() const
       
  1522 /** Gets a pointer to the first application in the list 
       
  1523 that can use the default screen mode.
       
  1524 
       
  1525 @return A pointer to the first application. */
       
  1526 	{
       
  1527 	return FirstApp(0);
       
  1528 	}
       
  1529 
       
  1530 EXPORT_C CApaAppData* CApaAppList::FirstApp(TInt aScreenMode) const
       
  1531 /** Gets a pointer to the first application in the list 
       
  1532 that can use the specified screen mode.
       
  1533 
       
  1534 @param aScreenMode The index of the screen mode. Specifying 
       
  1535 KIgnoreScreenMode returns the first application in the list, 
       
  1536 regardless of screen mode.
       
  1537 @return A pointer to the first application that can use the 
       
  1538 specified screen mode. */
       
  1539 	{
       
  1540 
       
  1541 	CApaAppData* appData=iValidFirstAppData;
       
  1542 
       
  1543 	if(aScreenMode!=KIgnoreScreenMode)
       
  1544 		{
       
  1545 		while (appData && !appData->CanUseScreenMode(aScreenMode))
       
  1546 			appData = appData->iNext;
       
  1547 		}
       
  1548 
       
  1549 	return appData;
       
  1550 	}
       
  1551 
       
  1552 EXPORT_C CApaAppData* CApaAppList::NextApp(const CApaAppData* aApp) const
       
  1553 /** Gets a pointer to the next application after aApp in the list 
       
  1554 that can use the default screen mode.
       
  1555 
       
  1556 @param aApp A pointer to an application in the list.
       
  1557 @return A pointer to the next application after aApp in the list 
       
  1558 that can use the default screen mode.
       
  1559 @panic APGRFX 12 aApp is NULL. */
       
  1560 	{
       
  1561 	return NextApp(aApp,0);
       
  1562 	}
       
  1563 
       
  1564 EXPORT_C CApaAppData* CApaAppList::NextApp(const CApaAppData* aApp, TInt aScreenMode) const
       
  1565 /** Gets a pointer to the next application after aApp in the list 
       
  1566 that can use the specified screen mode.
       
  1567 
       
  1568 @param aApp A pointer to an application in the list. 
       
  1569 @param aScreenMode The index of the screen mode. Specifying 
       
  1570 KIgnoreScreenMode returns the next application in the list, 
       
  1571 regardless of screen mode.
       
  1572 @return A pointer to the next application after aApp in the list 
       
  1573 that can use the specified screen mode.
       
  1574 @panic APGRFX 12 aApp is NULL. */
       
  1575 
       
  1576 	{
       
  1577 	__ASSERT_ALWAYS(aApp,Panic(EPanicNoAppDataSupplied));
       
  1578 	//
       
  1579 	CApaAppData* iApp=aApp->iNext; //lint !e613 Possible use of null pointer - Asserted above
       
  1580 
       
  1581 	if(aScreenMode!=KIgnoreScreenMode)
       
  1582 		while (iApp && !iApp->CanUseScreenMode(aScreenMode))
       
  1583 			iApp = iApp->iNext;
       
  1584 
       
  1585 	return iApp;
       
  1586 	}
       
  1587 
       
  1588 EXPORT_C CApaAppData* CApaAppList::AppDataByUid(TUid aAppUid) const
       
  1589 /** Gets a pointer to the application in the list whose third 
       
  1590 UID matches the specified UID.
       
  1591 
       
  1592 @param aAppUid An application's third UID. 
       
  1593 @return A pointer to the application, if successful. Null, 
       
  1594 if no match is found or if KNullUid was specified. */
       
  1595 	{
       
  1596 	if (aAppUid==KNullUid)
       
  1597 		return NULL; // never match null UID as it represents an un-UIDed file
       
  1598 	CApaAppData* appData=iAppData;
       
  1599 	while (appData)
       
  1600 		{
       
  1601 		if (appData->AppEntry().iUidType[2]==aAppUid)
       
  1602 			return appData;
       
  1603 		appData=appData->iNext;
       
  1604 		}
       
  1605 	return NULL;
       
  1606 	}
       
  1607 
       
  1608 EXPORT_C CApaAppData* CApaAppList::AppDataByFileName(const TDesC& aFullFileName) const
       
  1609 /** Gets a pointer to the application in the list whose application
       
  1610 file name matches the one specified
       
  1611 
       
  1612 @param aFullFileName a file name. 
       
  1613 @return A pointer to the application, if successful. Null, 
       
  1614 if no match is found or if KNullDesC was specified.
       
  1615 @internalTechnology
       
  1616 */
       
  1617 	{
       
  1618 	if (aFullFileName.Length()==0)
       
  1619 		{
       
  1620 		return NULL; // never match null UID as it represents an un-UIDed file
       
  1621 		}
       
  1622 	CApaAppData* appData=iAppData;
       
  1623 	while (appData)
       
  1624 		{
       
  1625 		if (appData->AppEntry().iFullName.CompareF(aFullFileName)==0)
       
  1626 			{
       
  1627 			return appData;
       
  1628 			}
       
  1629 		appData=appData->iNext;
       
  1630 		}
       
  1631 	return NULL;
       
  1632 	}
       
  1633 	
       
  1634 /**
       
  1635 Adds a registration file to the iForcedRegistrations array.
       
  1636 
       
  1637 @param aRegistrationFile The function takes ownership of the HBufC.
       
  1638 @internalComponent
       
  1639 */
       
  1640 EXPORT_C void CApaAppList::AddForcedRegistrationL(HBufC* aRegistrationFile)
       
  1641 	{
       
  1642 	TInt err = iForcedRegistrations.InsertInOrder(aRegistrationFile, TLinearOrder<HBufC>(CompareStrings));
       
  1643 	if (err == KErrAlreadyExists) // We silently ignore attempts to insert duplicates
       
  1644 		{
       
  1645 		delete aRegistrationFile;
       
  1646 		}
       
  1647 	else
       
  1648 		{
       
  1649 		User::LeaveIfError(err);
       
  1650 		}
       
  1651 	} //lint !e818 Suppress pointer parameter 'aRegistrationFile' could be declared as pointing to const
       
  1652 	
       
  1653 EXPORT_C void CApaAppList::ResetForcedRegistrations()
       
  1654 	{
       
  1655 	iForcedRegistrations.ResetAndDestroy();
       
  1656 	}
       
  1657 
       
  1658 EXPORT_C TInt CApaAppList::UpdateCounter() const
       
  1659 /** Gets the number of times the application list has been updated. 
       
  1660 It returns zero for a newly created empty list.
       
  1661 
       
  1662 @return The number of times the list has been changed since it was 
       
  1663 created. */
       
  1664 	{
       
  1665 	return iUpdateCounter;
       
  1666 	}
       
  1667 
       
  1668 EXPORT_C TUid CApaAppList::PreferredDataHandlerL(const TDataType& aDataType) const
       
  1669 /** Finds the preferred application to handle the specified data type.
       
  1670 
       
  1671 @param aDataType The data type of interest.
       
  1672 @return The third UID of the application in the list which has the 
       
  1673 highest priority for handling the specified data type. A null UID is 
       
  1674 returned if no application in the list can handle the specified data type. */
       
  1675 	{
       
  1676 	TInt dummy;
       
  1677 	return PreferredDataHandlerL(aDataType, NULL, dummy);
       
  1678 	}
       
  1679 	
       
  1680 EXPORT_C TUid CApaAppList::PreferredDataHandlerL(const TDataType& aDataType, const TUid* aServiceUid, TInt& aPriority) const
       
  1681 /** Finds the preferred application to handle the specified data type.
       
  1682 
       
  1683 @param aDataType The data type of interest.
       
  1684 @param aServiceUid The optional service UID.
       
  1685 @param aPriority The priority associated with the returned app.
       
  1686 @return The third UID of the application in the list which has the 
       
  1687 highest priority for handling a combination of the specified data type
       
  1688 and service. A null UID is returned if no application in the list can
       
  1689 handle the combination of specified data type and service.
       
  1690 @internalComponent
       
  1691 */
       
  1692 	{
       
  1693 	// If there is a service uid we first try to use the service specific list
       
  1694 	// of datatypes
       
  1695 	if (aServiceUid)
       
  1696 		{
       
  1697 		CApaAppData* appData=iAppData;
       
  1698 		aPriority=KDataTypePriorityNotSupported;
       
  1699 		TUid uid={0};
       
  1700 		while (appData)
       
  1701 			{
       
  1702 			TInt priority = appData->ImplementsServiceWithDataType(*aServiceUid, aDataType);
       
  1703 			if (priority > aPriority)
       
  1704 				{
       
  1705 				aPriority=priority;
       
  1706 				uid=appData->AppEntry().iUidType[2];
       
  1707 				}
       
  1708 			appData=appData->iNext;
       
  1709 			}
       
  1710 		if (aPriority != KDataTypePriorityNotSupported)
       
  1711 			{
       
  1712 			return uid;
       
  1713 			}
       
  1714 		}
       
  1715 	
       
  1716 	CApaAppData* appData=iAppData;
       
  1717 	aPriority=KDataTypePriorityNotSupported;
       
  1718 	TUid uid={0};
       
  1719 	while (appData)
       
  1720 		{
       
  1721 		TInt priority=appData->DataType(aDataType);
       
  1722 		if ((priority > aPriority) &&
       
  1723 			(!aServiceUid || (aServiceUid && appData->ImplementsService(*aServiceUid))))
       
  1724 			{
       
  1725 			aPriority=priority;
       
  1726 			uid=appData->AppEntry().iUidType[2];
       
  1727 			}
       
  1728 		appData=appData->iNext;
       
  1729 		}
       
  1730 	return uid;
       
  1731 	}
       
  1732 
       
  1733 void CApaAppList::ScanComplete()
       
  1734 	{
       
  1735 	if(!IsFirstScanComplete() && iObserver)
       
  1736 		iObserver->InitialListPopulationComplete();
       
  1737 	iValidFirstAppData = iAppData;
       
  1738 	iFlags|=EFirstScanComplete;
       
  1739 	}
       
  1740 
       
  1741 /**
       
  1742  *
       
  1743  * Tests whether the first scan for list of Apps has completed.
       
  1744  *
       
  1745  * @return   "TBool"
       
  1746  *            True, if the first scan for list of Apps has completed; false, otherwise.
       
  1747  * @internalComponent
       
  1748  */
       
  1749 EXPORT_C TBool CApaAppList::IsFirstScanComplete() const
       
  1750 	{
       
  1751 	return iFlags&EFirstScanComplete;
       
  1752 	}
       
  1753 
       
  1754 EXPORT_C TBool CApaAppList::AppScanInProgress() const
       
  1755 /** @internalComponent */
       
  1756 	{
       
  1757 	return (iAppIdler!=NULL) && iAppIdler->IsActive();
       
  1758 	}
       
  1759 
       
  1760 /**
       
  1761 @internalComponent
       
  1762 */
       
  1763 EXPORT_C CBufFlat* CApaAppList::ServiceArrayBufferL(TUid aAppUid) const
       
  1764 	{
       
  1765 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1766 	while (app && app->AppEntry().iUidType[2] != aAppUid)
       
  1767 		{
       
  1768 		app = NextApp(app, KIgnoreScreenMode);
       
  1769 		}
       
  1770 
       
  1771 	if (app)
       
  1772 		{
       
  1773 		if (!app->RegistrationFileUsed())
       
  1774 			{
       
  1775 			User::Leave(KErrNotSupported);
       
  1776 			}
       
  1777 		if (app->iServiceArray)
       
  1778 			{
       
  1779 			CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1780 			CleanupStack::PushL(buf);
       
  1781 			RBufWriteStream writeStream(*buf);
       
  1782 			writeStream << *(app->iServiceArray);
       
  1783 			writeStream.CommitL();
       
  1784 			writeStream.Release();
       
  1785 			CleanupStack::Pop(buf);
       
  1786 			return buf;
       
  1787 			}
       
  1788 		}
       
  1789 	User::Leave(KErrNotFound);
       
  1790 	return NULL; // to keep compiler happy
       
  1791 	}
       
  1792 
       
  1793 /**
       
  1794 @internalComponent
       
  1795 */
       
  1796 EXPORT_C CBufFlat* CApaAppList::ServiceUidBufferL(TUid aAppUid) const
       
  1797 	{
       
  1798 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1799 	while (app && app->AppEntry().iUidType[2] != aAppUid)
       
  1800 		{
       
  1801 		app = NextApp(app, KIgnoreScreenMode);
       
  1802 		}
       
  1803 
       
  1804 	if (app)
       
  1805 		{
       
  1806 		if (!app->RegistrationFileUsed())
       
  1807 			{
       
  1808 			User::Leave(KErrNotSupported);
       
  1809 			}
       
  1810 		if (app->iServiceArray)
       
  1811 			{
       
  1812 			CArrayFixFlat<TApaAppServiceInfo>& serviceArray = *(app->iServiceArray);
       
  1813 			CArrayFixFlat<TUid>* uidArray = new(ELeave) CArrayFixFlat<TUid>(4);
       
  1814 			CleanupStack::PushL(uidArray);
       
  1815 			for (TInt i = serviceArray.Count()-1; i >= 0; i--)
       
  1816 				{
       
  1817 				uidArray->AppendL(serviceArray[i].Uid());
       
  1818 				}
       
  1819 			CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1820 			CleanupStack::PushL(buf);
       
  1821 			RBufWriteStream writeStream(*buf);
       
  1822 			writeStream << *uidArray;
       
  1823 			writeStream.CommitL();
       
  1824 			writeStream.Release();
       
  1825 			CleanupStack::Pop(buf);
       
  1826 			CleanupStack::PopAndDestroy(uidArray);
       
  1827 			return buf;
       
  1828 			}
       
  1829 		}
       
  1830 	User::Leave(KErrNotFound);
       
  1831 	return NULL; // to keep compiler happy
       
  1832 	}
       
  1833 
       
  1834 /**
       
  1835 @internalComponent
       
  1836 */
       
  1837 EXPORT_C CBufFlat* CApaAppList::ServiceOpaqueDataBufferL(TUid aAppUid, TUid aServiceUid) const
       
  1838 	{
       
  1839 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1840 	while (app && app->AppEntry().iUidType[2] != aAppUid)
       
  1841 		{
       
  1842 		app = NextApp(app, KIgnoreScreenMode);
       
  1843 		}
       
  1844 
       
  1845 	if (app)
       
  1846 		{
       
  1847 		if (!app->RegistrationFileUsed())
       
  1848 			{
       
  1849 			User::Leave(KErrNotSupported);
       
  1850 			}
       
  1851 		if (app->iServiceArray)
       
  1852 			{
       
  1853 			CArrayFixFlat<TApaAppServiceInfo>* implArray = NULL;
       
  1854 			CArrayFixFlat<TApaAppServiceInfo>& serviceArray = *(app->iServiceArray);
       
  1855 			for (TInt i = serviceArray.Count()-1; i >= 0; i--)
       
  1856 				{
       
  1857 				const TApaAppServiceInfo& infoRef = serviceArray[i];
       
  1858 				if (infoRef.Uid() == aServiceUid)
       
  1859 					{
       
  1860 					if (!implArray)
       
  1861 						{
       
  1862 						implArray = new(ELeave) CArrayFixFlat<TApaAppServiceInfo>(4);
       
  1863 						CleanupStack::PushL(TCleanupItem(CleanupServiceArray, implArray));
       
  1864 						}
       
  1865 					CArrayFixFlat<TDataTypeWithPriority>* dummy =
       
  1866 						new(ELeave) CArrayFixFlat<TDataTypeWithPriority>(1);
       
  1867 					CleanupStack::PushL(dummy);					
       
  1868 					TApaAppServiceInfo info(aServiceUid, dummy, infoRef.OpaqueData().AllocLC());
       
  1869 					implArray->AppendL(info);
       
  1870 					CleanupStack::Pop(const_cast<TDesC8*>(&info.OpaqueData()));
       
  1871 					CleanupStack::Pop(dummy);
       
  1872 					}
       
  1873 				}
       
  1874 			if (implArray)
       
  1875 				{
       
  1876 				CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1877 				CleanupStack::PushL(buf);
       
  1878 				RBufWriteStream writeStream(*buf);
       
  1879 				writeStream << *implArray;
       
  1880 				writeStream.CommitL();
       
  1881 				writeStream.Release();
       
  1882 				CleanupStack::Pop(buf);
       
  1883 				CleanupStack::PopAndDestroy(implArray);
       
  1884 				return buf;
       
  1885 				}
       
  1886 			}
       
  1887 		}
       
  1888 	User::Leave(KErrNotFound);
       
  1889 	return NULL; // to keep compiler happy
       
  1890 	}
       
  1891 
       
  1892 /**
       
  1893 @internalComponent
       
  1894 */
       
  1895 EXPORT_C CBufFlat* CApaAppList::ServiceImplArrayBufferL(TUid aServiceUid) const
       
  1896 	{
       
  1897 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1898 	// build an array containing all implementations of the service identified by aServiceUid
       
  1899 	CArrayFixFlat<TApaAppServiceInfo>* implArray = NULL;
       
  1900 	while (app)
       
  1901 		{
       
  1902 		if (app->iServiceArray)
       
  1903 			{
       
  1904 			for (TInt i = app->iServiceArray->Count()-1; i >= 0; i--)
       
  1905 				{
       
  1906 				const TApaAppServiceInfo& infoRef = (*app->iServiceArray)[i];
       
  1907 				if (infoRef.Uid() == aServiceUid)
       
  1908 					{
       
  1909 					if (!implArray)
       
  1910 						{
       
  1911 						implArray = new(ELeave) CArrayFixFlat<TApaAppServiceInfo>(4);
       
  1912 						CleanupStack::PushL(TCleanupItem(CleanupServiceArray, implArray));
       
  1913 						}
       
  1914 					CArrayFixFlat<TDataTypeWithPriority>* datatypes = DataTypeArrayDeepCopyLC(infoRef.DataTypes());
       
  1915 					HBufC8* data = infoRef.OpaqueData().AllocLC();
       
  1916 					TApaAppServiceInfo info(app->AppEntry().iUidType[2], datatypes, data);
       
  1917 					implArray->AppendL(info);
       
  1918 					CleanupStack::Pop(data);
       
  1919 					CleanupStack::Pop(datatypes);
       
  1920 					}
       
  1921 				}
       
  1922 			}
       
  1923 		app = NextApp(app, KIgnoreScreenMode);
       
  1924 		}
       
  1925 
       
  1926 	if (implArray)
       
  1927 		{
       
  1928 		CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1929 		CleanupStack::PushL(buf);
       
  1930 		RBufWriteStream writeStream(*buf);
       
  1931 		writeStream << *(implArray);
       
  1932 		writeStream.CommitL();
       
  1933 		writeStream.Release();
       
  1934 		CleanupStack::Pop(buf);
       
  1935 		CleanupStack::PopAndDestroy(implArray);
       
  1936 		return buf;
       
  1937 		}
       
  1938 	User::Leave(KErrNotFound);
       
  1939 	return NULL; // to keep compiler happy
       
  1940 	}
       
  1941 
       
  1942 EXPORT_C CBufFlat* CApaAppList::ServiceImplArrayBufferL(TUid aServiceUid, const TDataType& aDataType) const
       
  1943 	{
       
  1944 	CApaAppData* app = FirstApp(KIgnoreScreenMode);
       
  1945 	// build an array containing all implementations of the service identified by aServiceUid
       
  1946 	CArrayFixFlat<TApaAppServiceInfo>* implArray = NULL;
       
  1947 	while (app)
       
  1948 		{
       
  1949 		if (app->iServiceArray)
       
  1950 			{
       
  1951 			for (TInt i = app->iServiceArray->Count()-1; i >= 0; i--)
       
  1952 				{
       
  1953 				const TApaAppServiceInfo& infoRef = (*app->iServiceArray)[i];
       
  1954 				if (infoRef.Uid() == aServiceUid)
       
  1955 					{
       
  1956 				 	if (KDataTypePriorityNotSupported != app->DataType(aDataType, infoRef.DataTypes()))
       
  1957 						{
       
  1958 						if (!implArray)
       
  1959 							{
       
  1960 							implArray = new(ELeave) CArrayFixFlat<TApaAppServiceInfo>(4);
       
  1961 							CleanupStack::PushL(TCleanupItem(CleanupServiceArray, implArray));
       
  1962 							}
       
  1963 						CArrayFixFlat<TDataTypeWithPriority>* datatypes = DataTypeArrayDeepCopyLC(infoRef.DataTypes());
       
  1964 						HBufC8* data = infoRef.OpaqueData().AllocLC();
       
  1965 						TApaAppServiceInfo info(app->AppEntry().iUidType[2], datatypes, data);
       
  1966 						implArray->AppendL(info);
       
  1967 						CleanupStack::Pop(data);
       
  1968 						CleanupStack::Pop(datatypes);
       
  1969 						}
       
  1970 					}
       
  1971 				}
       
  1972 			}
       
  1973 		app = NextApp(app, KIgnoreScreenMode);
       
  1974 		}
       
  1975 
       
  1976 	if (implArray)
       
  1977 		{
       
  1978 		CBufFlat* const buf = CBufFlat::NewL(KBufferExpansionGranularity);
       
  1979 		CleanupStack::PushL(buf);
       
  1980 		RBufWriteStream writeStream(*buf);
       
  1981 		writeStream << *(implArray);
       
  1982 		writeStream.CommitL();
       
  1983 		writeStream.Release();
       
  1984 		CleanupStack::Pop(buf);
       
  1985 		CleanupStack::PopAndDestroy(implArray);
       
  1986 		return buf;
       
  1987 		}
       
  1988 	User::Leave(KErrNotFound);
       
  1989 	return NULL; // to keep compiler happy
       
  1990 	}
       
  1991 	
       
  1992 CArrayFixFlat<TDataTypeWithPriority>* CApaAppList::DataTypeArrayDeepCopyLC(const CArrayFixFlat<TDataTypeWithPriority>& aOriginal) const
       
  1993 	{
       
  1994 	CArrayFixFlat<TDataTypeWithPriority>* result = new(ELeave) CArrayFixFlat<TDataTypeWithPriority>(1);
       
  1995 	CleanupStack::PushL(result);
       
  1996 	TInt ii = 0;
       
  1997 	TInt end = aOriginal.Count();
       
  1998 	while (ii < end)
       
  1999 		{
       
  2000 		result->AppendL(aOriginal[ii]);
       
  2001 		ii++;
       
  2002 		}
       
  2003 	return result;
       
  2004 	}
       
  2005 	
       
  2006 EXPORT_C TInt CApaAppList::CompareStrings(const HBufC& aFirst, const HBufC& aSecond)
       
  2007 	{
       
  2008 	return aFirst.CompareF(aSecond);
       
  2009 	}
       
  2010 
       
  2011 EXPORT_C CApaAppList* CApaAppList::Self()
       
  2012 	{ // static
       
  2013 	return static_cast<CApaAppList*>(Dll::Tls());
       
  2014 	}
       
  2015 	
       
  2016 /*EXPORT_C*/ RFs& CApaAppList::ShareProtectedFileServer()
       
  2017 	{
       
  2018 	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
       
  2019 	}
       
  2020 	
       
  2021 CApaAppIconArray* CApaAppList::LoadDefaultIconsL() const
       
  2022 	{
       
  2023 	__ASSERT_ALWAYS(iDefaultAppIcon, Panic(EPanicNullPointer));
       
  2024 	CApaIconLoader* iconLoader = CApaIconLoader::NewLC(iFs);
       
  2025 	CApaAppIconArray* icons = CApaAppIconArray::NewRealDefaultIconsLC(KNumberOfIconsInDefaultMbm,*iDefaultAppIcon, *iconLoader);
       
  2026 	const TBool badMbmEntryInfo = !icons->LoadIconsL();
       
  2027 	if(badMbmEntryInfo)
       
  2028 		{
       
  2029 		CleanupStack::PopAndDestroy(2,iconLoader);
       
  2030 		return CApaAppIconArray::NewL();
       
  2031 		}
       
  2032 	else
       
  2033 		{
       
  2034 		CleanupStack::Pop(icons);
       
  2035 		CleanupStack::PopAndDestroy(iconLoader);
       
  2036 		}
       
  2037 	return icons;
       
  2038 	}
       
  2039 
       
  2040 void CApaAppList::AcquireDefaultIconArrayL() const
       
  2041 	{
       
  2042 	ASSERT(iDefaultIconUsageCount >= 0);
       
  2043 	if (iDefaultIconUsageCount == 0)
       
  2044 		{
       
  2045 		iDefaultIconArray = LoadDefaultIconsL();
       
  2046 		}
       
  2047 	++iDefaultIconUsageCount;
       
  2048 	}
       
  2049 
       
  2050 // Should NEVER be called by an object that does not call AcquireDefaultIconArrayL and
       
  2051 // ReleaseDefaultIconArray at the beginning and end of its lifetime respectively
       
  2052 const CApaAppIconArray& CApaAppList::DefaultIconArray() const
       
  2053 	{
       
  2054 	__ASSERT_ALWAYS(iDefaultIconArray, Panic(EPanicNullPointer));
       
  2055 	return *iDefaultIconArray;
       
  2056 	}
       
  2057 
       
  2058 void CApaAppList::ReleaseDefaultIconArray() const
       
  2059 	{
       
  2060 	ASSERT(iDefaultIconUsageCount > 0);
       
  2061 	if(0 == --iDefaultIconUsageCount)
       
  2062 		{
       
  2063 		delete iDefaultIconArray;
       
  2064 		iDefaultIconArray = NULL;		
       
  2065 		}
       
  2066 	}
       
  2067 	
       
  2068 // DEF077478 - Required to update the default icons that the app list holds.
       
  2069 void CApaAppList::UpdateDefaultIconsL()
       
  2070 	{
       
  2071 	CApaAppIconArray* iconArray = LoadDefaultIconsL();
       
  2072 	if (iconArray)
       
  2073 		{
       
  2074 		delete iDefaultIconArray;
       
  2075 		iDefaultIconArray = iconArray;
       
  2076 		}
       
  2077 	}
       
  2078 
       
  2079 
       
  2080 // ApaUtils
       
  2081 
       
  2082 EXPORT_C TBool ApaUtils::HandleAsRegistrationFile(const TUidType& aUidType)
       
  2083 	{ // static
       
  2084 	return (aUidType[1].iUid==KUidAppRegistrationFile.iUid ||
       
  2085 		   aUidType[0].iUid==KUidPrefixedNonNativeRegistrationResourceFile);
       
  2086 	}
       
  2087 	
       
  2088 // Returns ETrue if a language change event is received and a re-scan is in progress otherwise EFalse. 
       
  2089 EXPORT_C TBool CApaAppList::IsLanguageChangePending() const
       
  2090 	{
       
  2091 	return (iFlags & ELangChangePending);
       
  2092 	}
       
  2093 //
       
  2094 // Class CApaLangChangeMonitor
       
  2095 //
       
  2096 
       
  2097 CApaAppList::CApaLangChangeMonitor::~CApaLangChangeMonitor()
       
  2098 	{	
       
  2099 	Cancel();
       
  2100 	iLangNotifier.Close();
       
  2101 	}
       
  2102 
       
  2103 CApaAppList::CApaLangChangeMonitor* CApaAppList::CApaLangChangeMonitor::NewL(CApaAppList& aAppList)
       
  2104 	{ // static	
       
  2105 	CApaLangChangeMonitor* self=new(ELeave) CApaLangChangeMonitor(aAppList);
       
  2106 	self->ConstructL();
       
  2107 	return self;
       
  2108 	}
       
  2109 
       
  2110 CApaAppList::CApaLangChangeMonitor::CApaLangChangeMonitor(CApaAppList& aAppList)
       
  2111 	: CActive(EPriorityNormal),
       
  2112 	iAppList(aAppList)
       
  2113 	{	
       
  2114 	iPrevLanguage = User::Language();
       
  2115 	CActiveScheduler::Add(this);
       
  2116 	}
       
  2117 
       
  2118 void CApaAppList::CApaLangChangeMonitor::ConstructL()
       
  2119 	{
       
  2120 	User::LeaveIfError(iLangNotifier.Create());
       
  2121 	Start();
       
  2122 	}
       
  2123  
       
  2124 void CApaAppList::CApaLangChangeMonitor::Start()
       
  2125 	{
       
  2126 	iLangNotifier.Logon(iStatus);
       
  2127 	SetActive();
       
  2128  	}
       
  2129  
       
  2130 void CApaAppList::CApaLangChangeMonitor::DoCancel()
       
  2131 	{
       
  2132  	iLangNotifier.LogonCancel();
       
  2133 	}
       
  2134  
       
  2135 void CApaAppList::CApaLangChangeMonitor::RunL()
       
  2136 	{
       
  2137 	// Logon to get further events before handling current request.
       
  2138 	TRequestStatus status = iStatus;
       
  2139 	Start();
       
  2140 	
       
  2141 	// if it is a language change event, start a rescan on app-list.
       
  2142  	if (status.Int() == EChangesLocale && iPrevLanguage != User::Language())
       
  2143 		{		
       
  2144 		iPrevLanguage = User::Language();
       
  2145 		iAppList.iFlags |= CApaAppList::ELangChangePending;
       
  2146 		iAppList.StartIdleUpdateL(iAppList.iObserver);
       
  2147 		}
       
  2148 	}
       
  2149 
       
  2150 TInt CApaAppList::CApaLangChangeMonitor::RunError(TInt /*aError*/)
       
  2151 	{
       
  2152 	// Reset ELangChangePending flag if RunL leaves.
       
  2153 	iAppList.iFlags &= ~CApaAppList::ELangChangePending;
       
  2154 	// Reset iPrevLanguage to ELangNone if RunL leaves.
       
  2155 	iPrevLanguage = ELangNone;
       
  2156 	return KErrNone;
       
  2157 	}