--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/phoneapp/phoneuiview/src/cphoneapplicationexit.cpp Mon Jan 18 20:18:27 2010 +0200
@@ -0,0 +1,864 @@
+/*
+* Copyright (c) 2004-2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of the CPhoneApplicationExit class.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "cphoneapplicationexit.h"
+#include "cphonecenrepproxy.h"
+#include "cphoneviewcontroller.h"
+#include "telephonyvariant.hrh"
+#include "telprivatecrkeys.h"
+#include "phonelogger.h"
+
+#include <w32std.h>
+#include <e32hal.h>
+#include <apgwgnam.h>
+#include <apgtask.h>
+#include <apgcli.h>
+#include <avkon.hrh>
+#include <telephonyvariant.hrh>
+#include <gfxtranseffect/gfxtranseffect.h>
+#include <akntranseffect.h>
+
+// CONSTANTS
+
+// MODULE DATA STRUCTURES
+
+/**
+* Abstract base class to handle rules when certain application should be
+* closed.
+* @since 2.6
+*/
+class CPhoneApplicationExit::CElement : public CBase
+ {
+ public: // New functions
+
+ /**
+ * Checks if this application should be accepted to be closed.
+ * @param aUid uid of the application.
+ * @return ETrue if should be closed, otherwise EFalse.
+ */
+ virtual TBool AcceptL( const TUid& aUid ) const = 0;
+ };
+
+/**
+* Element to handle any application and low memory cases.
+* @since 2.6
+*/
+class CPhoneApplicationExit::CElementBasic :
+ public CPhoneApplicationExit::CElement
+ {
+ public: // Constructors
+
+ /**
+ * Enumerates types.
+ */
+ enum TTypeOfElement
+ {
+ // Any application.
+ EExitAnyApp,
+ // Only when low memory.
+ EExitWhenLowMemory
+ };
+
+ /**
+ * Constructor.
+ * @param aType type of element.
+ */
+ CElementBasic( TTypeOfElement aType );
+
+ public: // New functions
+
+ /**
+ * Checks if system is low in memory.
+ * @return ETrue if system is low in memory.
+ */
+ static TBool IsLowMemory();
+
+ public: // Functions from base classes
+
+ /**
+ * @see CPhoneApplicationExit::CElement::AcceptL.
+ */
+ virtual TBool AcceptL( const TUid& aUid ) const;
+
+ private:
+
+ // Type of element.
+ TTypeOfElement iType;
+
+ };
+
+/**
+* Element to handle applications UID of which are included in UID range.
+* @since 2.6
+*/
+class CPhoneApplicationExit::CElementUid :
+ public CPhoneApplicationExit::CElement
+ {
+ public: // Constructors
+
+ /**
+ * Constructor.
+ * @param aStart start of range.
+ * @param aEnd end of range.
+ */
+ CElementUid( const TUid& aStart, const TUid& aEnd );
+
+ public: // Functions from base classes
+
+ /**
+ * @see CPhoneApplicationExit::CElement::AcceptL.
+ */
+ virtual TBool AcceptL( const TUid& aUid ) const;
+
+ private:
+
+ // Start of the range.
+ TUid iStart;
+
+ // End of the range.
+ TUid iEnd;
+
+ };
+
+/**
+* Element to handle applications on specific drive.
+* @since 2.6
+*/
+class CPhoneApplicationExit::CElementDrive :
+ public CPhoneApplicationExit::CElement
+ {
+ public: // Constructors
+
+ /**
+ * Constructor.
+ * @param aDrive drive.
+ */
+ CElementDrive( const TChar& aDrive );
+
+ public: // Functions from base classes
+
+ /**
+ * @see CPhoneApplicationExit::CElement::AcceptL.
+ */
+ virtual TBool AcceptL( const TUid& aUid ) const;
+
+ private:
+
+ /**
+ * Checks if application has been installed on specified drive.
+ * @param aUid application UID.
+ * @return ETrue if application has been installed on specified drive.
+ */
+ TBool CheckApplicationDriveL(
+ const TUid& aUid ) const;
+
+ private:
+
+ // Drive.
+ TChar iDrive;
+
+ };
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CPhoneApplicationExit
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CPhoneApplicationExit::CPhoneApplicationExit(
+ CPhoneViewController* aViewController,
+ RWsSession& aWsSession,
+ const TInt aUikonWgId ) :
+ iViewController( aViewController ),
+ iWsSession( aWsSession ),
+ iUikonWgId( aUikonWgId )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CPhoneApplicationExit* CPhoneApplicationExit::NewL(
+ CPhoneViewController* aViewController,
+ RWsSession& aWsSession,
+ const TInt aUikonWgId )
+ {
+ CPhoneApplicationExit* self =
+ new ( ELeave ) CPhoneApplicationExit(
+ aViewController,
+ aWsSession,
+ aUikonWgId );
+
+ return self;
+ }
+
+// Destructor
+CPhoneApplicationExit::~CPhoneApplicationExit()
+ {
+ iCloseList.ResetAndDestroy();
+ iCloseList.Close();
+
+ iDontCloseList.ResetAndDestroy();
+ iDontCloseList.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::ExitApplication
+// -----------------------------------------------------------------------------
+//
+TInt CPhoneApplicationExit::ExitApplication()
+ {
+ TRAPD( err, ExitApplicationL() );
+#ifdef __PHENG_DEBUG_INFO__
+ if ( err != KErrNone )
+ {
+ __PHONELOG1( EBasic, EPhoneUIView, "CPhoneApplicationExit::ExitApplication err=%d", err );
+ }
+#endif
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::ExitApplicationL
+// -----------------------------------------------------------------------------
+//
+void CPhoneApplicationExit::ExitApplicationL()
+ {
+ __LOGMETHODSTARTEND( EPhoneUIView, "CPhoneApplicationExit::ExitApplicationL()" );
+ TInt foregroundWindowGroupId = iWsSession.GetFocusWindowGroup();
+ if ( foregroundWindowGroupId == iUikonWgId )
+ {
+ foregroundWindowGroupId =
+ iViewController->ForegroundApplicationWindowGroupId();
+ }
+ if ( foregroundWindowGroupId ==
+ iViewController->ApplicationWindowGroupId() )
+ {
+ // No need to send event to itself.
+ __PHONELOG( EBasic, EPhoneUIView, "CPhoneApplicationExit::ExitApplicationL Phone is foreground application so don't close it" );
+ if ( IsApplicationClosingEnabled() )
+ {
+ ReadListsL();
+ }
+ return;
+ }
+ __PHONELOG1( EBasic, EPhoneUIView, "CPhoneApplicationExit::ExitApplicationL foregroundWindowGroupId=%d", foregroundWindowGroupId );
+
+ CApaWindowGroupName* wgName =
+ CApaWindowGroupName::NewLC(
+ iWsSession,
+ foregroundWindowGroupId );
+
+ if ( IsApplicationClosingEnabled() )
+ {
+ __PHONELOG1( EBasic, EPhoneUIView, "CPhoneApplicationExit::ExitApplicationL Application closing is enabled wgName->AppUid().iUid=%d", wgName->AppUid().iUid );
+
+ if ( CheckApplicationClosingL( wgName->AppUid() ) )
+ {
+ // Transition effects end key handling
+ // This call makes it possible to show application exit effect
+ // whenever exiting application with the end key
+ GfxTransEffect::BeginFullScreen(
+ AknTransEffect::EApplicationExit,
+ TRect(),
+ AknTransEffect::EParameterType,
+ AknTransEffect::GfxTransParam( wgName->AppUid(),
+ AknTransEffect::TParameter::EActivateExplicitCancel |
+ AknTransEffect::TParameter::EEndCheck ) );
+
+ __PHONELOG( EBasic, EPhoneUIView, "CPhoneApplicationExit::ExitApplicationL Send exit event" );
+ TWsEvent event;
+ event.SetType( KAknUidValueEndKeyCloseEvent );
+ event.SetTimeNow();
+
+ iWsSession.SendEventToWindowGroup(
+ foregroundWindowGroupId,
+ event );
+ }
+ }
+ else
+ {
+ __PHONELOG( EBasic, EPhoneUIView, "CPhoneApplicationExit::ExitApplicationL Application closing is NOT enabled" );
+
+ // If the application is not system and system has low memory, then
+ // stop the application.
+ if ( !wgName->IsSystem() && CElementBasic::IsLowMemory() )
+ {
+ __PHONELOG( EBasic, EPhoneUIView, "CPhoneApplicationExit::ExitApplicationL Close non-system app because of low memory" );
+ // Close application
+ TApaTask task( iWsSession );
+ task.SetWgId( foregroundWindowGroupId );
+ task.EndTask();
+ }
+ }
+
+ CleanupStack::PopAndDestroy( wgName );
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CheckApplicationClosingL
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::CheckApplicationClosingL(
+ const TUid& aUid )
+ {
+ ReadListsL();
+
+ return
+ IsIncludedToCloseListL( aUid ) && !IsIncludedToDontCloseListL( aUid );
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::IsIncludedToCloseListL
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::IsIncludedToCloseListL(
+ const TUid& aUid ) const
+ {
+ __PHONELOG( EBasic, EPhoneUIView, "CPhoneApplicationExit::IsIncludedToCloseList()" );
+
+ TBool result =
+ CheckListL(
+ iCloseList,
+ aUid );
+
+ __PHONELOG1( EBasic, EPhoneUIView, "CPhoneApplicationExit::IsIncludedToCloseList() result=%d", result );
+
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::IsIncludedToDontCloseListL
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::IsIncludedToDontCloseListL(
+ const TUid& aUid ) const
+ {
+ __PHONELOG( EBasic, EPhoneUIView, "CPhoneApplicationExit::IsIncludedToDontCloseList()" );
+
+ TBool result =
+ CheckListL(
+ iDontCloseList,
+ aUid );
+
+ __PHONELOG1( EBasic, EPhoneUIView, "CPhoneApplicationExit::IsIncludedToDontCloseList() result=%d", result );
+
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CheckListL
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::CheckListL(
+ const RPointerArray< CElement >& aTarget,
+ const TUid& aUid ) const
+ {
+ TBool result = EFalse;
+
+ const TInt count = aTarget.Count();
+
+ for ( TInt i = 0; i < count && !result; i++ )
+ {
+ result = aTarget[ i ]->AcceptL( aUid );
+ }
+
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::ReadListsL
+// -----------------------------------------------------------------------------
+//
+void CPhoneApplicationExit::ReadListsL()
+ {
+ if ( !iListsRead )
+ {
+ iCloseList.ResetAndDestroy();
+ iDontCloseList.ResetAndDestroy();
+
+ // Acquire buffer for reading operations.
+ HBufC* tempBuffer = HBufC::NewLC( KPhoneTemporaryBufferMaxLength );
+ tempBuffer->Des().Zero();
+ TPtr ptr( tempBuffer->Des() );
+
+ TInt err = KErrNone;
+ // Read "close" list.
+ err = CPhoneCenRepProxy::Instance()->GetString(
+ KCRUidTelPrivateVariation,
+ KTelAppsCloseList,
+ ptr );
+ if ( err == KErrNone )
+ {
+ BuildListL( iCloseList, ptr, ETrue );
+ }
+ if ( err == KErrNotFound )
+ {
+ // Not defined.
+ err = KErrNone;
+ }
+ User::LeaveIfError( err );
+
+ // Read "don't close" list.
+ err = CPhoneCenRepProxy::Instance()->GetString(
+ KCRUidTelPrivateVariation,
+ KTelAppsKeepList,
+ ptr );
+ if ( err == KErrNone )
+ {
+ BuildListL( iDontCloseList, ptr, EFalse );
+ }
+ if ( err == KErrNotFound )
+ {
+ // Not defined.
+ err = KErrNone;
+ }
+ User::LeaveIfError( err );
+
+ // By default, applications are closed on OOM.
+ if ( !iCloseList.Count() && !iDontCloseList.Count() )
+ {
+ CElement* element =
+ new ( ELeave ) CElementBasic(
+ CElementBasic::EExitWhenLowMemory );
+ CleanupStack::PushL( element );
+ User::LeaveIfError( iCloseList.Append( element ) );
+ CleanupStack::Pop( element );
+ }
+
+ CleanupStack::PopAndDestroy( tempBuffer );
+ iListsRead = ETrue;
+
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::BuildListL
+// -----------------------------------------------------------------------------
+//
+void CPhoneApplicationExit::BuildListL(
+ RPointerArray< CElement >& aTarget,
+ const TDesC& aSource,
+ TBool aOomAllowed )
+ {
+ aTarget.ResetAndDestroy();
+
+ TLex lexer( aSource );
+ lexer.SkipSpace();
+
+ TUid start;
+ TUid end;
+ TChar drive;
+
+ TInt length = lexer.Remainder().Length();
+ while ( length )
+ {
+ lexer.SkipSpace();
+
+ CElement* element = NULL;
+
+ if ( ParseString( lexer, KPhoneApplicationAnyApp ) )
+ {
+ element =
+ new ( ELeave ) CElementBasic(
+ CElementBasic::EExitAnyApp );
+ }
+ else if ( ParseString( lexer, KPhoneApplicationOom ) )
+ {
+ if ( aOomAllowed )
+ {
+ element =
+ new ( ELeave ) CElementBasic(
+ CElementBasic::EExitWhenLowMemory );
+ }
+ }
+ else if ( ParseDrive( lexer, drive ) )
+ {
+ element = new ( ELeave ) CElementDrive( drive );
+ }
+ else if ( ParseUid( lexer, start, end ) )
+ {
+
+ element = new ( ELeave ) CElementUid( start, end );
+ }
+ else
+ {
+ // No proceeding, stop.
+ length = 0;
+ }
+
+ if ( element )
+ {
+ CleanupStack::PushL( element );
+ User::LeaveIfError( aTarget.Append( element ) );
+ CleanupStack::Pop( element );
+ }
+
+ if ( length )
+ {
+ const TInt oldLength = length;
+ length = lexer.Remainder().Length();
+
+ if ( length == oldLength )
+ {
+ // No proceeding, stop.
+ length = 0;
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::ParseString
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::ParseString(
+ TLex& aLexer,
+ const TDesC& aString )
+ {
+ TBool result = EFalse;
+ TLexMark startMark;
+ aLexer.Mark( startMark );
+ const TInt length = aString.Length();
+
+ TInt i;
+ for ( i = 0;
+ i < length && ( aString[ i ] == TUint( aLexer.Peek() ) );
+ i++ )
+ {
+ aLexer.Inc();
+ }
+
+ result = ( ( i == length ) && CheckEnd( aLexer ) );
+
+ if ( !result )
+ {
+ aLexer.UnGetToMark( startMark );
+ }
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::ParseUid
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::ParseUid(
+ TLex& aLexer,
+ TUid& aUidStart,
+ TUid& aUidEnd )
+ {
+ TBool result = EFalse;
+ TLexMark startMark;
+
+ // Read first UID.
+ aLexer.Mark( startMark );
+ while ( aLexer.Peek().IsHexDigit() )
+ {
+ aLexer.Inc();
+ }
+ TPtrC token = aLexer.MarkedToken( startMark );
+ if ( token.Length() )
+ {
+ TUint uid = 0;
+ result = ( TLex( token ).Val( uid, EHex ) == KErrNone );
+ if ( result )
+ {
+ aUidStart.iUid = uid;
+ aUidEnd.iUid = uid;
+ }
+ }
+
+ if ( result )
+ {
+ TLexMark afterUid;
+ aLexer.Mark( afterUid );
+ aLexer.SkipSpace();
+
+ // Check range separator.
+ if ( aLexer.Peek() == KPhoneApplicationRangeSeparator )
+ {
+ // Now there must be another UID as well.
+ result = EFalse;
+ aLexer.Inc(); // skip separator character
+ aLexer.SkipSpace();
+
+ // Read second UID.
+ TLexMark mark;
+ aLexer.Mark( mark );
+ while ( aLexer.Peek().IsHexDigit() )
+ {
+ aLexer.Inc();
+ }
+
+ TPtrC token = aLexer.MarkedToken( mark );
+ if ( token.Length() )
+ {
+ TUint uid = 0;
+ result = ( TLex( token ).Val( uid, EHex ) == KErrNone );
+ if ( result )
+ {
+ result = CheckEnd( aLexer );
+ aUidEnd.iUid = uid;
+ }
+ }
+ }
+ else
+ {
+ // Only one UID, next must be space.
+ aLexer.UnGetToMark( afterUid );
+ result = CheckEnd( aLexer );
+ }
+ }
+
+ if ( !result )
+ {
+ aLexer.UnGetToMark( startMark );
+ }
+
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::ParseDrive
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::ParseDrive(
+ TLex& aLexer,
+ TChar& aChar )
+ {
+ TBool result = EFalse;
+ TChar ch = aLexer.Peek();
+
+ if ( ch.IsAlpha() )
+ {
+ aLexer.Inc();
+ if ( aLexer.Peek() == KPhoneApplicationDriveIdentifier )
+ {
+ aLexer.Inc();
+ aChar = ch;
+ result = CheckEnd( aLexer );
+ if ( !result )
+ {
+ aLexer.UnGet(); // drive identifier
+ aLexer.UnGet(); // drive letter
+ }
+ }
+ else
+ {
+ aLexer.UnGet(); // drive letter
+ }
+ }
+
+ return result;
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CheckEnd
+// -----------------------------------------------------------------------------
+//
+inline TBool CPhoneApplicationExit::CheckEnd( TLex& aLexer )
+ {
+ return ( aLexer.Eos() || aLexer.Peek().IsSpace() );
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::IsApplicationClosingEnabled
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::IsApplicationClosingEnabled() const
+ {
+ return CPhoneCenRepProxy::Instance()->IsTelephonyFeatureSupported(
+ KTelephonyLVFlagCloseApplications );
+ }
+
+// Implementation of CPhoneApplicationExit::CElementBasic.
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CElementBasic::CElementBasic
+// -----------------------------------------------------------------------------
+//
+CPhoneApplicationExit::CElementBasic::CElementBasic( TTypeOfElement aType ) :
+ iType( aType )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CElementBasic::IsLowMemory
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::CElementBasic::IsLowMemory()
+ {
+ // Fetch amount of free memory.
+ TMemoryInfoV1Buf memory;
+ UserHal::MemoryInfo( memory );
+ TInt freeRam = (TInt)( memory().iFreeRamInBytes );
+ TInt oomRamLowThreshold = 0;
+ /* MIGRATION NOTE - need new method to TelUtils for static get of one
+ value.
+ CRepository* cenRep = NULL;
+ TRAPD( error, cenRep = CRepository::NewL( KCRUidUiklaf ) );
+ if ( error == KErrNoMemory )
+ {
+ return ETrue;
+ }
+ else if ( error != KErrNone )
+ {
+ // Error; don't know OOM status.
+ return EFalse;
+ }
+ cenRep->Get( KUikOOMRamLowThreshold, oomRamLowThreshold );
+ delete cenRep;*/
+ return ( freeRam < oomRamLowThreshold );
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CElementBasic::AcceptL
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::CElementBasic::AcceptL(
+ const TUid& /*aUid*/ ) const
+ {
+ TBool result = EFalse;
+ switch ( iType )
+ {
+ case EExitAnyApp:
+ result = ETrue;
+ break;
+
+ case EExitWhenLowMemory:
+ result = IsLowMemory();
+ break;
+
+ default:
+ break;
+ }
+ return result;
+ }
+
+// Implementation of CPhoneApplicationExit::CElementUid.
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CElementUid::CElementUid
+// -----------------------------------------------------------------------------
+//
+CPhoneApplicationExit::CElementUid::CElementUid(
+ const TUid& aStart,
+ const TUid& aEnd ) :
+ iStart( aStart ),
+ iEnd( aEnd )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CElementUid::AcceptL
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::CElementUid::AcceptL( const TUid& aUid ) const
+ {
+ return ( iStart.iUid <= aUid.iUid && aUid.iUid <= iEnd.iUid );
+ }
+
+// Implementation of CPhoneApplicationExit::CElementDrive.
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CElementDrive::CElementDrive
+// -----------------------------------------------------------------------------
+//
+CPhoneApplicationExit::CElementDrive::CElementDrive( const TChar& aDrive ) :
+ iDrive( aDrive )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CElementDrive::AcceptL
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::CElementDrive::AcceptL( const TUid& aUid ) const
+ {
+ return CheckApplicationDriveL( aUid );
+ }
+
+// -----------------------------------------------------------------------------
+// CPhoneApplicationExit::CElementDrive::CheckApplicationDriveL
+// -----------------------------------------------------------------------------
+//
+TBool CPhoneApplicationExit::CElementDrive::CheckApplicationDriveL(
+ const TUid& aUid ) const
+ {
+ RApaLsSession session;
+ User::LeaveIfError( session.Connect() );
+ CleanupClosePushL( session );
+
+ TApaAppInfo* appInfo = new ( ELeave ) TApaAppInfo;
+ CleanupStack::PushL( appInfo );
+
+ TBool result = EFalse;
+ TInt count = KPhoneApplicationRetryCount;
+ while ( count )
+ {
+ TInt err = session.GetAppInfo( *appInfo, aUid );
+
+ if ( err == KErrNone )
+ {
+ count = 0;
+ result = ETrue;
+ }
+ else if ( err == KErrNotFound )
+ {
+ count = 0;
+ result = EFalse;
+ }
+ else
+ {
+ User::LeaveIfError( err );
+
+ // GetAppInfo may return positive value indicating that
+ // application information is not ready.
+ count--;
+ User::After( KPhoneApplicationRetryInterval );
+ }
+ }
+
+ if ( result )
+ {
+ result = EFalse;
+ if ( appInfo->iFullName.Length() )
+ {
+ // First character is drive
+ TChar drive( appInfo->iFullName[ 0 ] );
+ drive.UpperCase();
+
+ TChar targetDrive( iDrive );
+ targetDrive.UpperCase();
+
+ result = ( drive == targetDrive );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( appInfo );
+ CleanupStack::PopAndDestroy(); // CleanupClosePushL
+ return result;
+ }
+
+// End of File