phoneapp/phoneuiview/src/cphoneapplicationexit.cpp
changeset 0 5f000ab63145
--- /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