phonebookengines/VirtualPhonebook/VPbkSimServer/src/CVPbkViewSubSession.cpp
author William Roberts <williamr@symbian.org>
Sun, 14 Mar 2010 13:08:38 +0000
branchCompilerCompatibility
changeset 6 c5deda9d60e3
parent 0 e686773b3f54
permissions -rw-r--r--
Automatic merge from PDK_3.0.h

/*
* Copyright (c) 2002-2007 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:  A sim store subsession class.
*
*/



// INCLUDE FILES
#include "CVPbkViewSubSession.h"

#include "VPbkSimServerCommon.h"
#include <RVPbkStreamedIntArray.h>
#include <MVPbkSimCntStore.h>
#include <MVPbkSimCntView.h>
#include <CVPbkSimContact.h>
#include <CVPbkSimFieldTypeFilter.h>
#include "VPbkSimServerOpCodes.h"
#include "SimServerErrors.h"
#include "SimServerInternal.h"
#include "CVPbkSimServerEventQueue.h"
#include <VPbkIPCPackage.h>
#include <MVPbkSimStoreOperation.h>
#include <s32mem.h> // RDesWriteStream
#include <badesca.h> // CDesCArray

// Debugging headers
#include <VPbkDebug.h>


// CONSTANTS

// This is some sensible limit for the checking the size of the
// sortarray.
const TInt KVPbkViewEventGranularity = 10;
const TInt KVPbkMaxViewEvents = 10 * KVPbkViewEventGranularity;
const TInt KGranularity( 2 );

// ============================= LOCAL FUNCTIONS ============================

namespace {

// --------------------------------------------------------------------------
// CompleteViewNotification
// --------------------------------------------------------------------------
//
void CompleteViewNotification( const RMessage2& aMsg, 
    TVPbkSimContactEventData& aEventData, TInt aResult )
    {    
    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
        "VPbkSimServer: complete view notification event %d data %d opdata %d"),
        aEventData.iEvent,aEventData.iData,aEventData.iOpData );
    TPckg<TVPbkSimContactEventData> pckg( aEventData );
    TInt result = aMsg.Write( KVPbkSlot0, pckg );
    if ( result != KErrNone )
        {
        VPbkSimSrvUtility::CompleteRequest( aMsg, result );
        }
    else
        {
        VPbkSimSrvUtility::CompleteRequest( aMsg, aResult );
        }
    }

// --------------------------------------------------------------------------
// Internalize find strings
// --------------------------------------------------------------------------
//   
MDesCArray* InternalizeFindStringsL( const RMessage2& aMessage )
    {
    CDesCArrayFlat* array = new(ELeave)CDesCArrayFlat( KGranularity );
    CleanupStack::PushL( array );
    
    TInt length = aMessage.GetDesLengthL( KVPbkSlot0 );
    if ( length > 0 )
        {
        HBufC8* data = HBufC8::NewLC( length );
        TPtr8 ptr = data->Des();
        aMessage.ReadL( KVPbkSlot0, ptr );
        
        RDesReadStream readStream( ptr );    
        CleanupClosePushL( readStream );
        
        const TInt count( readStream.ReadInt16L() );
        for ( TInt i(0); i < count; ++i )
            {
            TInt length( readStream.ReadInt16L() );
            HBufC* buffer = HBufC::NewLC( length );            
            TPtr ptrBuffer = buffer->Des();
            readStream.ReadL( ptrBuffer, length );
            array->AppendL( *buffer );
            CleanupStack::PopAndDestroy( buffer );                        
            }
        
        CleanupStack::PopAndDestroy(); // readStream
        CleanupStack::PopAndDestroy( data );
        }
    
    CleanupStack::Pop( array );
    return array;
    }

} // unnamed namespace

// ============================ MEMBER FUNCTIONS ============================

// --------------------------------------------------------------------------
// CVPbkViewSubSession::CVPbkViewSubSession
// C++ default constructor can NOT contain any code, that
// might leave.
// --------------------------------------------------------------------------
//
CVPbkViewSubSession::CVPbkViewSubSession( MVPbkSimCntStore& aStore ) :
        iStore( aStore )
    {
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::~CVPbkViewSubSession
// Destructor.
// --------------------------------------------------------------------------
//
CVPbkViewSubSession::~CVPbkViewSubSession()
    {
    AssertNoActiveAsyncRequests();
    delete iMatchOperation;
    delete iMatchingResults;
    delete iFindStrings;
    delete iEventQueue;
    CloseAndDestroyView();
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::NewL
// Two-phased constructor.
// --------------------------------------------------------------------------
//
CVPbkViewSubSession* CVPbkViewSubSession::NewL( const RMessage2& aMessage,
                                                MVPbkSimCntStore& aStore )
    {
    CVPbkViewSubSession* self = new( ELeave ) CVPbkViewSubSession( aStore );
    CleanupClosePushL( *self );
    self->ConstructL( aMessage );
    CleanupStack::Pop();
    return self;
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ConstructL
// Symbian 2nd phase constructor can leave.
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ConstructL( const RMessage2& aMessage )
    {
    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
        "CVPbkViewSubSession::ConstructL begin"));

    iEventQueue = CVPbkSimServerEventQueue::NewL(
        KVPbkViewEventGranularity, KVPbkMaxViewEvents);
        
    RVPbkSimFieldTypeArray sortOrder;
    CleanupClosePushL( sortOrder );
    VPbkSimSrvUtility::ReadFieldTypesL( sortOrder, aMessage, KVPbkSlot0 );

    TVPbkSimViewConstructionPolicy constructionPolicy = 
        static_cast<TVPbkSimViewConstructionPolicy>( aMessage.Int2() );
    
    // Read contact view name and filter from the separate package
    TInt length = aMessage.GetDesLengthL( KVPbkSlot1 );
    if ( length > 0 )
        {
        HBufC8* ipcData = HBufC8::NewLC( length );
        TPtr8 ptr = ipcData->Des();
        aMessage.ReadL( KVPbkSlot1, ptr );
        
        RDesReadStream readStream( ptr );
        readStream.PushL();

        HBufC* viewName = NULL;
        VPbkEngUtils::VPbkIPCPackage::InternalizeL( viewName, readStream );
        CleanupStack::PushL( viewName );

        HBufC8* filterBuffer = NULL;
        VPbkEngUtils::VPbkIPCPackage::InternalizeL
            ( filterBuffer, readStream );

        CVPbkSimFieldTypeFilter* filter = NULL;
        if ( filterBuffer && filterBuffer->Length() > 0 )
            {
            CleanupStack::PushL( filterBuffer );
			filter = new ( ELeave ) CVPbkSimFieldTypeFilter;
            CleanupStack::PushL( filter );

            // Internalize from stream
            TPtr8 filterPtr = filterBuffer->Des();
            filter->InternalizeL( filterPtr );

            CleanupStack::Pop( filter );
            CleanupStack::PopAndDestroy(); // filterBuffer
            }
       
        // Create a view (filter is taken)
        iView = iStore.CreateViewL(
        	sortOrder, constructionPolicy, *viewName, filter );
        
        CleanupStack::PopAndDestroy( viewName );
        CleanupStack::PopAndDestroy( &readStream );
        CleanupStack::PopAndDestroy( ipcData );
        }
    else
        {
        // Create an unamed non-filtered view
        iView = iStore.CreateViewL(
        	sortOrder, constructionPolicy, KNullDesC, NULL );
        }

    CleanupStack::PopAndDestroy(); // sortOrder
    iView->OpenL( *this );

    VPBK_DEBUG_PRINT(VPBK_DEBUG_STRING(
        "CVPbkViewSubSession::ConstructL end"));
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ServiceL
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ServiceL( const RMessage2& aMessage )
    {
    switch ( aMessage.Function() )
        {
        case EVPbkSimSrvViewEventNotification:
            {
            SaveViewEventNotification( aMessage );
            break;
            }
        case EVPbkSimSrvViewCount:
            {
            ReturnContactCountL( aMessage );
            break;
            }
        case EVPbkSimSrvGetViewContact:
            {   
            GetViewContactL( aMessage );
            break;
            }
        case EVPbkSimSrvChangeViewSortOrder:
            {
            ChangeSortOrderL( aMessage );
            break;
            }
        case EVPbkSimSrvFindViewIndex:
            {
            FindViewIndexL( aMessage );
            break;
            }
        case EVPbkSimSrvContactMatchingPrefix:
            {
            ContactMatchingPrefixL( aMessage );
            break;
            }
        case EVPbkSimSrvContactMathingResult:
            {
            ContactMatchingResultL( aMessage );
            break;
            }
        case EVPbkSimSrvViewSortOrderSize:
            {
            SortOrderSizeL( aMessage );
            break;
            }
        case EVPbkSimSrvViewSortOrder:
            {
            SortOrderL( aMessage );
            break;
            }
        default:
            {
            VPbkSimServer::PanicClient( aMessage, 
                VPbkSimServer::EInvalidOpCode );
            break;
            }
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::CancelRequestL
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::CancelRequestL( const RMessage2& aMessage )
    {
    TInt opCode = KErrUnknown;
    TPckg<TInt> pckg( opCode );
    aMessage.ReadL( KVPbkSlot0, pckg );

    switch ( opCode )
        {        
        case EVPbkSimSrvViewEventNotification:
            {
            CancelViewEventNotification();
            break;
            }
        case EVPbkSimSrvContactMatchingPrefix:
            {
            CancelContactMatching();
            break;
            }
        default:
            {
            VPbkSimServer::PanicClient( aMessage, 
                VPbkSimServer::EInvalidCancelOpCode );
            break;
            }
        }
    VPbkSimSrvUtility::CompleteRequest( aMessage, KErrNone );
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ViewReady
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ViewReady( MVPbkSimCntView& /*aView*/ )
    {
    TVPbkSimContactEventData event;
    event.iEvent = EVPbkSimViewOpen;
    event.iData = 0;
    event.iOpData = 0;
    HandleEvent( event );
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ViewError
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ViewError( MVPbkSimCntView& /*aView*/, TInt aError )
    {
    // If the view has an error then this subsession must not use it anymore
    
    // Complete the match request if it's active.
    CompleteAsyncContactMatching( aError );
    
    // Close the view
    CloseAndDestroyView();
    
    // Complete the view notification message.
    TVPbkSimContactEventData event;
    event.iEvent = EVPbkSimViewError;
    event.iData = aError;
    event.iOpData = 0;
    HandleEvent( event );
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ViewNotAvailable
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ViewNotAvailable( MVPbkSimCntView& /*aView*/ )
    {
    // Complete the match request if it's active.
    CompleteAsyncContactMatching( KErrCancel );
    
    TVPbkSimContactEventData event;
    event.iEvent = EVPbkSimViewNotAvailable;
    event.iData = 0;
    event.iOpData = 0;
    HandleEvent( event );
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ViewContactEvent
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ViewContactEvent( TEvent aEvent, TInt aIndex, 
    TInt aSimIndex )
    {
    TVPbkSimEvent viewEvent = EVPbkSimUnknown; 
    switch ( aEvent )
        {
        case EContactDeleted:
            {
            viewEvent = EVPbkSimContactDeleted;
            break;
            }
        case EContactAdded:
            {
            viewEvent = EVPbkSimContactAdded;
            break;
            }
        default:
            {
            // Do nothing
            break;
            }
        }

    TVPbkSimContactEventData event;
    event.iEvent = viewEvent;
    event.iData = aIndex;
    event.iOpData = (TInt16) aSimIndex;
    HandleEvent( event );
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ViewFindCompleted
// --------------------------------------------------------------------------
//    
void CVPbkViewSubSession::ViewFindCompleted( 
        MVPbkSimCntView& aSimCntView,
        const RVPbkStreamedIntArray& aSimIndexArray )
    {        
    TRAPD( result, ViewFindCompletedL( aSimCntView, aSimIndexArray ) );
    CompleteAsyncContactMatching( result );
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ViewFindError
// --------------------------------------------------------------------------
//    
void CVPbkViewSubSession::ViewFindError( 
        MVPbkSimCntView& /*aSimCntView*/, 
        TInt aError )    
    {
    // There was an error during match request. Complete the match request
    // with the error. View can still be used.
    CompleteAsyncContactMatching( aError );
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::SaveViewEventNotification
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::SaveViewEventNotification( 
    const RMessage2& aMessage )
    {
    // First check if the notification is already set
    if ( iNotificationMsg.Handle() )
        {
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrAlreadyExists );
        }
    // Second: check if there is an error waiting
    else if ( iErrorEvent.iEvent == EVPbkSimViewError )
        {
        CompleteViewNotification( aMessage, iErrorEvent, iErrorEvent.iData );
        ResetErrorEvent();
        }
    // Third: check if there is an event waiting
    else if ( !iEventQueue->IsEmpty() )
        {
        CompleteViewNotification( aMessage, iEventQueue->FirstEvent(), 
            KErrNone );
        iEventQueue->Pop();
        }   
    // Save notification message
    else
        {
        iNotificationMsg = aMessage;
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ReturnContactCount
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ReturnContactCountL( const RMessage2& aMessage )
    {
    if ( iView )
        {
        TInt count = iView->CountL();
        TPckg<TInt> pckg( count );
        aMessage.WriteL( KVPbkSlot0, pckg );
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrNone );    
        }
    else
        {
        // Client has ignored an error and still using the view.
        VPbkSimServer::PanicClient( aMessage,
            VPbkSimServer::ECVPbkViewSubSession_ReturnContactCountL );
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::GetViewContactL
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::GetViewContactL( const RMessage2& aMessage )
    {
    if ( iView )
        {
        TInt viewIndex = aMessage.Int0();
        TInt clientBufLength = aMessage.GetDesMaxLengthL( KVPbkSlot1 );

        MVPbkSimContact& cnt = iView->ContactAtL( viewIndex );
        const TDesC8& etelCnt = cnt.ETelContactL();
        if ( clientBufLength < etelCnt.Length() )
            {
            VPbkSimSrvUtility::CompleteRequest( aMessage, KErrOverflow );
            }
        else
            {
            aMessage.WriteL( KVPbkSlot1, etelCnt );
            VPbkSimSrvUtility::CompleteRequest( aMessage, KErrNone );
            }
        }
    else
        {
        // Client has ignored an error and still using the view.
        VPbkSimServer::PanicClient( aMessage,
            VPbkSimServer::ECVPbkViewSubSession_GetViewContactL );
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ChangeSortOrderL
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ChangeSortOrderL( const RMessage2& aMessage )
    {
    if ( iView )
        {
        RVPbkSimFieldTypeArray sortOrder;
        CleanupClosePushL( sortOrder );
        VPbkSimSrvUtility::ReadFieldTypesL( sortOrder, aMessage, KVPbkSlot0 );
        iView->ChangeSortOrderL( sortOrder );
        CleanupStack::PopAndDestroy(); //sortOrder 
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrNone );
        }
    else
        {
        // Client has ignored an error and still using the view.
        VPbkSimServer::PanicClient( aMessage,
            VPbkSimServer::ECVPbkViewSubSession_GetViewContactL );
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::FindViewIndexL
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::FindViewIndexL( const RMessage2& aMessage )
    {
    if ( iView )
        {
        TInt viewIndex = iView->MapSimIndexToViewIndexL( aMessage.Int0() );
        TPckg<TInt> pckg( viewIndex );
        aMessage.WriteL( KVPbkSlot1, pckg );
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrNone );
        }
    else
        {
        VPbkSimServer::PanicClient( aMessage,
            VPbkSimServer::ECVPbkViewSubSession_GetViewContactL );
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::CancelViewEventNotification
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::CancelViewEventNotification()
    {
    if ( iNotificationMsg.Handle() )
        {
        SetErrorEvent( KErrCancel );
        CompleteViewNotification( iNotificationMsg, iErrorEvent, KErrCancel );
        ResetErrorEvent();
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ContactMatchingPrefixL
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ContactMatchingPrefixL( const RMessage2& aMessage )
    {
    // First check if the matching is already set
    if ( iMatchingMsg.Handle() )
        {
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrAlreadyExists );
        
        __ASSERT_DEBUG( iFindStrings && iMatchOperation, 
            VPbkSimServer::PanicClient( aMessage,
            VPbkSimServer::ECVPbkViewSubSession_InvalidActiveMatchState));
        }    
    // Save matching message
    else
        {
        __ASSERT_DEBUG( !iFindStrings && !iMatchOperation, 
            VPbkSimServer::PanicClient( aMessage,
            VPbkSimServer::ECVPbkViewSubSession_InvalidNonActiveMatchState));
            
        iMatchingMsg = aMessage;
        iFindStrings = InternalizeFindStringsL( aMessage );
        iMatchOperation = iView->ContactMatchingPrefixL( *iFindStrings, *this );       
        }    
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::CancelContactMatching
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::CancelContactMatching()
    {
    CompleteAsyncContactMatching( KErrCancel );
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::CompleteAsyncContactMatching
// --------------------------------------------------------------------------
//    
void CVPbkViewSubSession::CompleteAsyncContactMatching( TInt aResult )
    {
    delete iMatchOperation;
    iMatchOperation = NULL;
    delete iFindStrings;
    iFindStrings = NULL;
            
    VPbkSimSrvUtility::CompleteRequest( iMatchingMsg, aResult );
    }
    
// --------------------------------------------------------------------------
// CVPbkViewSubSession::ContactMatchingResultL
// --------------------------------------------------------------------------
//    
void CVPbkViewSubSession::ContactMatchingResultL( 
        const RMessage2& aMessage )    
    {
    if ( iMatchingResults )
        {
        TPtr8 ptr = iMatchingResults->Des();    
        aMessage.WriteL( KVPbkSlot0, ptr );
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrNone );    
        }
    else
        {        
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrGeneral );    
        }    
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::SortOrderSizeL
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::SortOrderSizeL( const RMessage2& aMessage )
    {
    if ( iView )
        {
        TInt size = iView->SortOrderL().ExternalizedSize();
        TPckg<TInt> pckg( size );
        aMessage.WriteL( KVPbkSlot0, pckg );
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrNone );
        }
    else
        {
        // A view error has been occured.
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrAbort );
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::SortOrderL
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::SortOrderL( const RMessage2& aMessage )
    {
    if ( iView )
        {
        HBufC8* buf = ExternalizeArrayLC( iView->SortOrderL() );
        TPtr8 ptr( buf->Des() );
        // Leave KErrOverflow if too small buffer from client
        aMessage.WriteL( KVPbkSlot0, ptr );
        CleanupStack::PopAndDestroy( buf );
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrNone );
        }
    else
        {
        // A view error has been occured.
        VPbkSimSrvUtility::CompleteRequest( aMessage, KErrAbort );
        }
    }
    
// --------------------------------------------------------------------------
// CVPbkViewSubSession::HandleEvent
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::HandleEvent( TVPbkSimContactEventData& aEventData )
    {
    if ( iNotificationMsg.Handle() )
        {
        // There is a waiting notification message
        if ( aEventData.iEvent == EVPbkSimViewError )
            {
            // View is not in valid state anymore. Complete with error
            CompleteViewNotification( iNotificationMsg, aEventData, 
                aEventData.iData );
            }
        else
            {
            CompleteViewNotification( iNotificationMsg, aEventData, KErrNone );
            }
        }
    else
        {
        // Save the event to the queue
        if ( iEventQueue->IsFull() )
            {
            // Queue is full, set an error that will be returned when next
            // request comes.
            SetErrorEvent( KErrOverflow );
            }
        else
            {
            // Push the event to the queue for waiting notification message
            TInt result = iEventQueue->Push( aEventData );
            if ( result != KErrNone )
                {
                SetErrorEvent( result );
                }
            }
        }
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::SetErrorEvent
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::SetErrorEvent( TInt aError )
    {
    iErrorEvent.iEvent = EVPbkSimViewError;
    iErrorEvent.iData = aError;
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ResetErrorEvent
// --------------------------------------------------------------------------
//
void CVPbkViewSubSession::ResetErrorEvent()
    {
    iErrorEvent.iEvent = EVPbkSimUnknown;
    iErrorEvent.iData = 0;
    iErrorEvent.iOpData = 0;
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::ViewFindCompletedL
// --------------------------------------------------------------------------
//    
void CVPbkViewSubSession::ViewFindCompletedL( 
        MVPbkSimCntView& /*aSimCntView*/,
        const RVPbkStreamedIntArray& aSimIndexArray )
    {
    if ( iMatchingResults )
        {
        delete iMatchingResults;
        iMatchingResults = NULL;
        }
    
    iMatchingResults = HBufC8::NewL( aSimIndexArray.ExternalizedSize() );
    TPtr8 ptr = iMatchingResults->Des();
    RDesWriteStream stream( ptr );    
    CleanupClosePushL( stream );
    
    aSimIndexArray.ExternalizeL( stream );
    
    CleanupStack::PopAndDestroy(); //stream  
                
    TPckg<TInt> pckg( aSimIndexArray.ExternalizedSize() );
    iMatchingMsg.WriteL( KVPbkSlot1, pckg );        
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::CloseAndDestroyView
// --------------------------------------------------------------------------
//    
void CVPbkViewSubSession::CloseAndDestroyView()
    {
    if ( iView )
        {
        iView->Close( *this );
        }
    delete iView;
    iView = NULL;
    }

// --------------------------------------------------------------------------
// CVPbkViewSubSession::AssertNoActiveAsyncRequests
// --------------------------------------------------------------------------
//    
void CVPbkViewSubSession::AssertNoActiveAsyncRequests()
    {
    // Check that client has canceled the notification message.
    if ( iNotificationMsg.Handle() )
        {
        VPbkSimServer::PanicClient( iNotificationMsg,
            VPbkSimServer::ECVPbkViewSubSession_Destructor_EventMessage );
        }
    
    if ( iMatchingMsg.Handle() )
        {
        VPbkSimServer::PanicClient( iMatchingMsg,
            VPbkSimServer::ECVPbkViewSubSession_Destructor_Match );
        }
    }
//  End of File